aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux
diff options
context:
space:
mode:
authorherbert <herbert.eiselt@highstreet-technologies.com>2019-12-14 01:05:47 +0100
committerHerbert Eiselt <herbert.eiselt@highstreet-technologies.com>2019-12-16 12:52:11 +0000
commite6d0d67fdbe3fc70c996c8df33bd65d3b151dfad (patch)
tree0d2da7d1da74c6ebca6b53039741617d35f65d96 /sdnr/wt/odlux
parent6b98928b7b1b0ebc28d2ef286e8c932fca67c305 (diff)
update odlux and featureaggregator
v2 update odlux and featureaggregator bundles Issue-ID: SDNC-1008 Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com> Change-Id: I0018d7bfa3a0e6896c1b210b539a574af9808e22 Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/odlux')
-rw-r--r--sdnr/wt/odlux/.gitignore7
-rw-r--r--sdnr/wt/odlux/LICENSE15
-rw-r--r--sdnr/wt/odlux/README.md260
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/package.json40
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/pom.xml155
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts25
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts40
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts33
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/index.html24
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/models/module.ts28
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx53
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/apiDemo/webpack.config.js139
-rw-r--r--sdnr/wt/odlux/apps/app-feature/pom.xml83
-rwxr-xr-xsdnr/wt/odlux/apps/app-installer/pom.xml155
-rw-r--r--sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts380
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts29
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts19
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts30
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts58
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts42
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/index.html27
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts19
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts142
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts44
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx77
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts38
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts25
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx464
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx47
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts1099
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java45
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/tsconfig.json38
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/webpack.config.js158
-rw-r--r--sdnr/wt/odlux/apps/connectApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/connectApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/connectApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts113
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts57
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts60
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts61
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx52
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx252
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx154
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx259
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts83
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts35
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts60
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts58
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/index.html27
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts27
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts1
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts22
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts36
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts25
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts1
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts36
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts22
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx56
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts208
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx111
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java45
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/connectApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/connectApp/webpack.config.js153
-rw-r--r--sdnr/wt/odlux/apps/demoApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/demoApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/demoApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts51
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx34
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts43
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts33
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts57
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/index.html25
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/models/author.ts37
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/plugin.tsx54
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts72
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx87
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx34
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java45
-rw-r--r--sdnr/wt/odlux/apps/demoApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/demoApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/demoApp/webpack.config.js134
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts45
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx36
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/index.html26
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/models/eventLogType.ts27
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx40
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx59
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/webpack.config.js155
-rw-r--r--sdnr/wt/odlux/apps/faultApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/faultApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/faultApp/pom.xml148
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts36
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts33
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts26
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts43
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx136
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx71
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts36
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts36
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts36
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts64
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts46
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts47
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/index.html25
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/models/fault.ts67
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts18
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx112
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts53
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx176
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java45
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/faultApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/faultApp/webpack.config.js152
-rw-r--r--sdnr/wt/odlux/apps/helpApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/helpApp/package.json45
-rw-r--r--sdnr/wt/odlux/apps/helpApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts78
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx80
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx77
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/components/tocEntry.tsx82
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts75
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/index.html29
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts42
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/plugin.tsx91
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts65
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts79
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx70
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx55
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/helpApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/helpApp/webpack.config.js170
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts45
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx36
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/index.html25
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts34
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx75
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx64
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx41
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/webpack.config.js156
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/package.json41
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts79
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx194
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts41
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts35
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/index.html26
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts33
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx44
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts72
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts45
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx226
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js154
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/package.json41
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/pom.xml148
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts58
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts154
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts114
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx393
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx220
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx107
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts36
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts43
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts120
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/index.html29
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts77
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx83
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts204
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx276
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx157
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/tsconfig.json38
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/tslint.json4
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/webpack.config.js158
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/package.json40
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts37
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src/index.html24
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx48
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java46
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/minimumApp/webpack.config.js136
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/.babelrc17
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/package.json43
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml147
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts78
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts78
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts32
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts29
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx469
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx133
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx133
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx134
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx136
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx134
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx136
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts37
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts60
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts38
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts56
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts40
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts105
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts38
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts38
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts38
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts38
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/index.html26
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts109
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts21
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts49
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts44
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts25
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts22
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts54
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts43
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts44
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts45
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts26
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts44
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx111
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts108
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx75
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts36
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx371
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java68
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml9
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java45
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/resources/test.js5
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json37
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js143
-rw-r--r--sdnr/wt/odlux/core/features/pom.xml57
-rwxr-xr-xsdnr/wt/odlux/core/installer/pom.xml99
-rw-r--r--sdnr/wt/odlux/core/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--sdnr/wt/odlux/core/model/pom.xml54
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java238
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java71
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/IndexOdlBundle.java22
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java141
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java30
-rw-r--r--sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java28
-rw-r--r--sdnr/wt/odlux/core/pom.xml35
-rw-r--r--sdnr/wt/odlux/core/provider/pom.xml108
-rw-r--r--sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java116
-rw-r--r--sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java71
-rw-r--r--sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/OdluxBundleLoaderImpl.java125
-rw-r--r--sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java88
-rw-r--r--sdnr/wt/odlux/core/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml39
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java66
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java46
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java57
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java104
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/resources/index.html24
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/resources/index2.html24
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/resources/odlux/index.html24
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/resources/odlux/index2.html24
-rw-r--r--sdnr/wt/odlux/core/provider/src/test/resources/simplelogger.properties38
-rw-r--r--sdnr/wt/odlux/framework/.babelrc17
-rw-r--r--sdnr/wt/odlux/framework/LICENSE13
-rw-r--r--sdnr/wt/odlux/framework/package.json49
-rw-r--r--sdnr/wt/odlux/framework/pom.xml163
-rw-r--r--sdnr/wt/odlux/framework/src/actions/authentication.ts26
-rw-r--r--sdnr/wt/odlux/framework/src/actions/errorActions.ts42
-rw-r--r--sdnr/wt/odlux/framework/src/actions/menuAction.ts31
-rw-r--r--sdnr/wt/odlux/framework/src/actions/navigationActions.ts64
-rw-r--r--sdnr/wt/odlux/framework/src/actions/snackbarActions.ts37
-rw-r--r--sdnr/wt/odlux/framework/src/actions/titleActions.ts27
-rw-r--r--sdnr/wt/odlux/framework/src/actions/websocketAction.ts8
-rw-r--r--sdnr/wt/odlux/framework/src/app.css6
-rw-r--r--sdnr/wt/odlux/framework/src/app.tsx108
-rw-r--r--sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg179
-rw-r--r--sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg.d.ts19
-rw-r--r--sdnr/wt/odlux/framework/src/common/event.ts81
-rw-r--r--sdnr/wt/odlux/framework/src/components/errorDisplay.tsx126
-rw-r--r--sdnr/wt/odlux/framework/src/components/logo.tsx98
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts54
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/index.tsx552
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx88
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx101
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx149
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/utilities.ts263
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/index.ts22
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx67
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx45
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx73
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/snackDisplay.tsx74
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx179
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx36
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx268
-rw-r--r--sdnr/wt/odlux/framework/src/components/navigationMenu.tsx142
-rw-r--r--sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx55
-rw-r--r--sdnr/wt/odlux/framework/src/components/titleBar.tsx208
-rw-r--r--sdnr/wt/odlux/framework/src/design/default.ts80
-rw-r--r--sdnr/wt/odlux/framework/src/favicon.icobin0 -> 1150 bytes
-rw-r--r--sdnr/wt/odlux/framework/src/flux/action.ts26
-rw-r--r--sdnr/wt/odlux/framework/src/flux/connect.ts161
-rw-r--r--sdnr/wt/odlux/framework/src/flux/middleware.ts107
-rw-r--r--sdnr/wt/odlux/framework/src/flux/store.ts98
-rw-r--r--sdnr/wt/odlux/framework/src/handlers/applicationRegistryHandler.ts31
-rw-r--r--sdnr/wt/odlux/framework/src/handlers/applicationStateHandler.ts108
-rw-r--r--sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts61
-rw-r--r--sdnr/wt/odlux/framework/src/handlers/navigationStateHandler.ts45
-rw-r--r--sdnr/wt/odlux/framework/src/index.dev.html28
-rw-r--r--sdnr/wt/odlux/framework/src/index.html24
-rw-r--r--sdnr/wt/odlux/framework/src/middleware/api.ts72
-rw-r--r--sdnr/wt/odlux/framework/src/middleware/logger.ts34
-rw-r--r--sdnr/wt/odlux/framework/src/middleware/navigation.ts79
-rw-r--r--sdnr/wt/odlux/framework/src/middleware/thunk.ts35
-rw-r--r--sdnr/wt/odlux/framework/src/models/applicationInfo.ts52
-rw-r--r--sdnr/wt/odlux/framework/src/models/authentication.ts58
-rw-r--r--sdnr/wt/odlux/framework/src/models/elasticSearch.ts56
-rw-r--r--sdnr/wt/odlux/framework/src/models/errorInfo.ts29
-rw-r--r--sdnr/wt/odlux/framework/src/models/iconDefinition.ts21
-rw-r--r--sdnr/wt/odlux/framework/src/models/index.ts18
-rw-r--r--sdnr/wt/odlux/framework/src/models/restService.ts48
-rw-r--r--sdnr/wt/odlux/framework/src/models/snackbarItem.ts20
-rw-r--r--sdnr/wt/odlux/framework/src/run.ts18
-rw-r--r--sdnr/wt/odlux/framework/src/services/applicationApi.ts61
-rw-r--r--sdnr/wt/odlux/framework/src/services/applicationManager.ts53
-rw-r--r--sdnr/wt/odlux/framework/src/services/authenticationService.ts53
-rw-r--r--sdnr/wt/odlux/framework/src/services/forceLogoutService.ts52
-rw-r--r--sdnr/wt/odlux/framework/src/services/index.ts21
-rw-r--r--sdnr/wt/odlux/framework/src/services/notificationService.ts190
-rw-r--r--sdnr/wt/odlux/framework/src/services/restAccessorService.ts93
-rw-r--r--sdnr/wt/odlux/framework/src/services/restService.ts105
-rw-r--r--sdnr/wt/odlux/framework/src/services/snackbarService.ts22
-rw-r--r--sdnr/wt/odlux/framework/src/store/applicationStore.ts73
-rw-r--r--sdnr/wt/odlux/framework/src/styles/att.ts46
-rw-r--r--sdnr/wt/odlux/framework/src/utilities/elasticSearch.ts78
-rw-r--r--sdnr/wt/odlux/framework/src/utilities/withComponents.ts37
-rw-r--r--sdnr/wt/odlux/framework/src/utilities/yangHelper.ts39
-rw-r--r--sdnr/wt/odlux/framework/src/views/about.tsx31
-rw-r--r--sdnr/wt/odlux/framework/src/views/frame.tsx118
-rw-r--r--sdnr/wt/odlux/framework/src/views/home.tsx27
-rw-r--r--sdnr/wt/odlux/framework/src/views/login.tsx210
-rw-r--r--sdnr/wt/odlux/framework/src/views/test.tsx878
-rw-r--r--sdnr/wt/odlux/framework/tsconfig.json39
-rw-r--r--sdnr/wt/odlux/framework/webpack.config.js203
-rw-r--r--sdnr/wt/odlux/framework/webpack.runner.js85
-rw-r--r--sdnr/wt/odlux/framework/webpack.vendor.js130
-rw-r--r--sdnr/wt/odlux/jest.json18
-rw-r--r--sdnr/wt/odlux/lerna.json12
-rw-r--r--sdnr/wt/odlux/package.json82
-rw-r--r--sdnr/wt/odlux/pom.xml63
-rw-r--r--sdnr/wt/odlux/yarn.lock11055
396 files changed, 40988 insertions, 0 deletions
diff --git a/sdnr/wt/odlux/.gitignore b/sdnr/wt/odlux/.gitignore
new file mode 100644
index 000000000..1577b0b91
--- /dev/null
+++ b/sdnr/wt/odlux/.gitignore
@@ -0,0 +1,7 @@
+package-lock.json
+npm
+yarn-error.log
+node/
+node_modules/
+dist/
+.vscode/
diff --git a/sdnr/wt/odlux/LICENSE b/sdnr/wt/odlux/LICENSE
new file mode 100644
index 000000000..c5487c33a
--- /dev/null
+++ b/sdnr/wt/odlux/LICENSE
@@ -0,0 +1,15 @@
+============LICENSE_START========================================================================
+ONAP : ccsdk feature sdnr wt
+=================================================================================================
+Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+=================================================================================================
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+in compliance with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software distributed under the License
+is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+or implied. See the License for the specific language governing permissions and limitations under
+the License.
+============LICENSE_END==========================================================================
diff --git a/sdnr/wt/odlux/README.md b/sdnr/wt/odlux/README.md
new file mode 100644
index 000000000..6e02db0e0
--- /dev/null
+++ b/sdnr/wt/odlux/README.md
@@ -0,0 +1,260 @@
+# Developing a ODLUX application
+
+## Prerequisites
+
+* Node: 8.10 or higher
+* Yarn: 1.12.3 or higher
+* Lerna: 3.10.7 or higher
+
+You can install these globally or let it be installed by maven due "mvn clean install"
+
+* Maven: 3 or higher
+* Java: 8 or higher
+
+## Dev-Environment Installation
+
+ * install NodeJS LTS https://nodejs.org/en/ or via packetmanager
+ * sudo npm install -g yarn
+ * sudo yarn global add lerna
+ * get framework from repository: git clone https://gerrit.onap.org/r/ccsdk/features
+ * in features/sdnr/wt/odlux you find a structure like this:
+ ```
+ odlux
+ |-apps
+ |-core
+ |-framework
+
+ ```
+ * go to features/sdnr/wt/odlux/apps and create your app:
+ ```
+ mvn archetype:generate -DarchetypeGroupId=org.onap.ccsdk.features.sdnr.wt \
+ -DarchetypeArtifactId=odlux-app-archetype \
+ -DgroupId=<groupId> \
+ -DartifactId=<artifactId> \
+ -Dversion=<version> \
+ -DappName=<applicationName>
+ ```
+
+ * your start folder for your web application is src/
+ * in src2/main/java are located the Java files and in src2/main/resources/ is the blueprint located
+ * with ```yarn start``` you can run your application due runtime in your application folder
+ * by default this will run on http://localhost:3100/index.html
+ * if you have added new dependencies you have to run ```lerna bootstrap``` in odlux/
+ * build your app for development version you can use ```yarn run build``` or ```yarn run build:dev```
+ * build for karaf with ```mvn clean install```
+
+
+## Including app into karaf environment
+
+ * copy maven repository files to karaf repository e.g.: ```cp ~/.m2/repository/path/of/groupId/artifactId $KARAF_HOME/system/path/of/groupId/```
+ * check if odlux-core is started in karaf console: ```feature:list | grep odlux```
+ * if not install: ```sdnr-wt-odlux-core-feature```
+ * start your app in karaf console: ```bundle:install -s mvn:<groupId>/<artifactId>/<version>```
+
+## Including into ONAP sdnc docker container
+
+ * add maven module to odlux/pom.xml
+ * add dependency to odlux/apps/app-feature/pom.xml and odlux/apps/app-installer/pom.xml
+ * build odlux/pom.xml
+ * this will automatically package your app into the packaged zip file of the installer
+
+## Details
+
+### Default menu positions
+
+ * from 0 for top to 999 for bottom.
+
+```
+0 Connect
+10 Fault
+20 Maintenance
+30 Configuration
+40 Protection
+50 Performance
+60 Security
+70 Inventory
+80 Topology
+90 Mediator
+100 Help
+```
+
+### blueprint.xml
+
+```
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="demoApp"/>
+ <property name="index" value="999"/>
+ </bean>
+</blueprint>
+```
+ * bundleName defines the applicationName => default javascript file: <applicationName>.js
+ * index defines the menu position.
+
+### MyOdluxBundle.java
+
+ * is just for getting access to the resources of its bundle (implemented because of OSGi access restrictions)
+
+### pom.xml
+
+```
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.2.1-SNAPSHOT</version>
+ <relativePath />
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-demoApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.8-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v8.10.0</nodeVersion>
+ <yarnVersion>v1.12.3</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package></Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>highstreet repo</id>
+ <url>https://cloud-highstreet-technologies.com/mvn/</url>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+</project>
+your
+```
+
+* a modified frontend-maven-plugin installs node, yarn and (optionally lerna) to compile the typescript sources to javascript. These will be build into the dist folder.
+
diff --git a/sdnr/wt/odlux/apps/apiDemo/.babelrc b/sdnr/wt/odlux/apps/apiDemo/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json
new file mode 100644
index 000000000..d6f74278b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/api-demo",
+ "version": "0.1.0",
+ "description": "A react based modular UI framework",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/pom.xml b/sdnr/wt/odlux/apps/apiDemo/pom.xml
new file mode 100644
index 000000000..11bf306f2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/pom.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-apiDemo</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-apiDemo</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts b/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
new file mode 100644
index 000000000..12fd3fcaf
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/actions/modulesSuccess.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { ModuleResult } from '../models/module';
+export class ModulesRequestSuccess extends Action {
+ constructor(public result: ModuleResult) {
+ super();
+ }
+}
+// error will be handled by the framework \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
new file mode 100644
index 000000000..36688b3a5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/apiDemoRootHandler.ts
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { moduleHandler, IModules } from './modulesHandler';
+
+export interface IApiDemoStoreState {
+ modules: IModules
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ apiDemo: IApiDemoStoreState
+ }
+}
+
+const actionHandlers = {
+ modules: moduleHandler
+};
+
+export const apiDemoRootHandler = combineActionHandler<IApiDemoStoreState>(actionHandlers);
+export default apiDemoRootHandler;
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
new file mode 100644
index 000000000..8777355db
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/handlers/modulesHandler.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { ModulesRequestSuccess } from '../actions/modulesSuccess';
+import { Module } from '../models/module';
+
+export type IModules = Module[]
+
+const modulesInit: IModules = [];
+
+export const moduleHandler: IActionHandler<IModules> = (state = modulesInit, action) => {
+ if (action instanceof ModulesRequestSuccess) {
+ return action.result.modules.module;
+ }
+
+ return state;
+};
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/index.html b/sdnr/wt/odlux/apps/apiDemo/src/index.html
new file mode 100644
index 000000000..c01df6b13
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>API Demo App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app","apiDemo"], function (app) {
+ app("./app.tsx")
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
new file mode 100644
index 000000000..abf86b76e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/models/module.ts
@@ -0,0 +1,28 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type Module = {
+ name: string;
+ revision: string;
+ namespace: string;
+}
+
+export type ModuleResult = {
+ modules: {
+ module: Module[]
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
new file mode 100644
index 000000000..6790ee929
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src/plugin.tsx
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faNewspaper } from '@fortawesome/free-solid-svg-icons';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import connect, { Connect } from '../../../framework/src/flux/connect';
+import { ApiAction } from '../../../framework/src/middleware/api'; // for RestConf
+
+import { apiDemoRootHandler } from './handlers/apiDemoRootHandler';
+import { ModulesRequestSuccess } from './actions/modulesSuccess';
+import { Module } from './models/module';
+
+type AppProps = RouteComponentProps & Connect & { modules: Module[], requestModules: () => void };
+
+const App = (props: AppProps ) => (
+ <>
+ <button onClick={ props.requestModules }>Load Modules</button>
+ <ul>{ props.modules.map((mod, ind) => (<li key={ ind }>{ mod.name }</li>)) }</ul>
+ </>
+);
+
+const FinalApp = withRouter(connect((state) => ({
+ modules: state.apiDemo.modules
+}), (dispatcher => ({
+ requestModules: () => { dispatcher.dispatch(new ApiAction('restconf/modules', ModulesRequestSuccess, true)) }
+})))(App));
+
+applicationManager.registerApplication({
+ name: "apiDemo",
+ icon: faNewspaper,
+ rootComponent: FinalApp,
+ rootActionHandler: apiDemoRootHandler,
+ menuEntry: "API Demo"
+});
+
diff --git a/sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..0877578e2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="apiDemo"/>
+ <property name="index" value="999"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/apiDemo/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..e2ffb596b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoader loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles() == 1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles() == 0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/apiDemo/src2/test/resources/test.js b/sdnr/wt/odlux/apps/apiDemo/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/apiDemo/tsconfig.json b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/apiDemo/webpack.config.js b/sdnr/wt/odlux/apps/apiDemo/webpack.config.js
new file mode 100644
index 000000000..1c699e15b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/apiDemo/webpack.config.js
@@ -0,0 +1,139 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ apiDemo: ["./plugin.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ // new CopyWebpackPlugin([{
+ // from: '../../../dist/**.*',
+ // to: path.resolve(__dirname, "dist")
+ // }]),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ })
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/restconf/**/*": {
+ target: "https://dlux.just-run.it",
+ secure: false,
+ changeOrigin: true
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/app-feature/pom.xml b/sdnr/wt/odlux/apps/app-feature/pom.xml
new file mode 100644
index 000000000..dd67901ab
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-feature/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.feature.sdnr.wt * ================================================================================
+ * Copyright (C) 2018 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved. * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); * you may
+ not use this file except in compliance with the License. * You may obtain
+ a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *
+ * Unless required by applicable law or agreed to in writing, software * distributed
+ under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES
+ OR CONDITIONS OF ANY KIND, either express or implied. * See the License for
+ the specific language governing permissions and * limitations under the License.
+ * ============LICENSE_END========================================================= -->
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-apps-feature</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>feature</packaging>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId} :: feature</name>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-maintenanceApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-performanceHistoryApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-eventLogApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-configurationApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sdnr/wt/odlux/apps/app-installer/pom.xml b/sdnr/wt/odlux/apps/app-installer/pom.xml
new file mode 100755
index 000000000..20871a4d2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-installer/pom.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-apps-installer</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <properties>
+ <application.name>sdnr-wt-odlux-apps</application.name>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>${application.name}-feature</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-apiDemo</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-minimumApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-maintenanceApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-performanceHistoryApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-eventLogApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-app-configurationApp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-nested-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>true</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <!--<includeArtifactIds>sdnr-wt-apigateway-provider,${application.name}</includeArtifactIds> -->
+ <!--<scope>provided</scope> -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..c4eb9aa25
--- /dev/null
+++ b/sdnr/wt/odlux/apps/app-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/sdnr/wt/odlux/apps/configurationApp/.babelrc b/sdnr/wt/odlux/apps/configurationApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/package.json b/sdnr/wt/odlux/apps/configurationApp/package.json
new file mode 100644
index 000000000..2985ba4fb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/configuration-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI for the configuration app.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/pom.xml b/sdnr/wt/odlux/apps/configurationApp/pom.xml
new file mode 100644
index 000000000..a4e067873
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-configurationApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-configurationApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
new file mode 100644
index 000000000..fc0665325
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -0,0 +1,380 @@
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { PushAction, ReplaceAction } from "../../../../framework/src/actions/navigationActions";
+
+import { restService } from "../services/restServices";
+import { YangParser } from "../yang/yangParser";
+import { Module } from "../models/yang";
+import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList } from "../models/uiModels";
+import { AddErrorInfoAction } from "../../../../framework/src/actions/errorActions";
+
+export class EnableValueSelector extends Action {
+ constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
+ super();
+ }
+}
+
+export class SetCollectingSelectionData extends Action {
+ constructor(public busy: boolean) {
+ super();
+ }
+}
+
+export class SetSelectedValue extends Action {
+ constructor(public value: any) {
+ super();
+ }
+}
+
+export class UpdateDeviceDescription extends Action {
+ constructor( public nodeId: string, public modules: { [name:string]: Module}, public views: ViewSpecification[]) {
+ super();
+ }
+}
+
+export class UpdatViewDescription extends Action {
+ constructor(public vPath: string, public view: ViewSpecification, public viewData: any, public displayAsList: boolean = false, public key?: string ) {
+ super();
+ }
+}
+
+export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState ) => {
+ const { configuration: { connectedNetworkElements : { rows }} } = getState();
+ dispatch(new SetCollectingSelectionData(true));
+ const networkElement = rows.find(r => r.nodeId === nodeId) || await restService.getMountedNetworkElementByMountId(nodeId);
+ if (!networkElement) {
+ console.error(new Error(`NetworkElement : [${nodeId}] does not exist.`));
+ return dispatch(new UpdateDeviceDescription("", { }, [ ]));
+ }
+
+ if (!networkElement.nodeDetails || !networkElement.nodeDetails.availableCapabilities) {
+ throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
+ }
+ const parser = new YangParser();
+
+ const capParser = /^\(.*\?revision=(\d{4}-\d{2}-\d{2})\)(\S+)$/i;
+ for (let i = 0; i < networkElement.nodeDetails.availableCapabilities.length; ++i){
+ const capRaw = networkElement.nodeDetails.availableCapabilities[i];
+ const capMatch = capRaw && capParser.exec(capRaw);
+ try {
+ capMatch && await parser.addCapability(capMatch[2], capMatch[1]);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+ parser.postProcess();
+
+ console.log(parser.modules, parser.views)
+
+ return dispatch(new UpdateDeviceDescription(nodeId, parser.modules, parser.views));
+}
+
+export const splitVPath = (vPath: string, vPathParser : RegExp): [string, string?][] => {
+ const pathParts: [string, string?][] = [];
+ let partMatch: RegExpExecArray | null;
+ if (vPath) do {
+ partMatch = vPathParser.exec(vPath);
+ if (partMatch) {
+ pathParts.push([partMatch[1], partMatch[2] || undefined]);
+ }
+ } while (partMatch)
+ return pathParts;
+}
+
+const getReferencedDataList = async (refPath: string, dataPath: string, modules: { [name: string]: Module }, views: ViewSpecification[]) => {
+ const pathParts = splitVPath(refPath, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property
+ let referencedModule = modules[pathParts[0][0]];
+
+ let dataMember: string;
+ let view: ViewSpecification;
+ let currentNS: string | null = null;
+ let dataUrls = [dataPath];
+ let data: any;
+
+ for (let i = 0; i < pathParts.length; ++i) {
+ const [pathPartNS, pathPart] = pathParts[i];
+ const namespace = pathPartNS != null ? (currentNS = pathPartNS) : currentNS;
+
+ const viewElement = i === 0
+ ? views[0].elements[`${referencedModule.name}:${pathPart}`]
+ : view!.elements[`${pathPart}`] || view!.elements[`${namespace}:${pathPart}`];
+
+ if (!viewElement) throw new Error(`Could not find ${pathPart} in ${refPath}`);
+ if (i < pathParts.length - 1) {
+ if (!isViewElementObjectOrList(viewElement)) {
+ throw Error(`Module: [${referencedModule.name}].[${viewElement.label}]. Viewelement is not list or object.`);
+ }
+ view = views[+viewElement.viewId];
+ const resultingDataUrls : string[] = [];
+ if (isViewElementList(viewElement)) {
+ for (let j = 0; j < dataUrls.length; ++j) {
+ const dataUrl = dataUrls[j];
+ const restResult = (await restService.getConfigData(dataUrl));
+ if (restResult.data == null || restResult.status < 200 || restResult.status > 299) {
+ const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
+ throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+ }
+
+ let dataRaw = restResult.data[dataMember!];
+ dataRaw = dataRaw instanceof Array
+ ? dataRaw[0]
+ : dataRaw;
+
+ data = dataRaw && dataRaw[viewElement.label] || [];
+ const keys: string[] = data.map((entry: { [key: string]: any } )=> entry[viewElement.key!]);
+ resultingDataUrls.push(...keys.map(key => `${dataUrl}/${viewElement.label.replace(/\//ig, "%2F")}/${key.replace(/\//ig, "%2F")}`));
+ }
+ dataMember = viewElement.label;
+ } else {
+ // just a member, not a list
+ const pathSegment = (i === 0
+ ? `/${referencedModule.name}:${viewElement.label.replace(/\//ig, "%2F")}`
+ : `/${viewElement.label.replace(/\//ig, "%2F")}`);
+ resultingDataUrls.push(...dataUrls.map(dataUrl => dataUrl + pathSegment));
+ dataMember = viewElement.label;
+ }
+ dataUrls = resultingDataUrls;
+ } else {
+ data = [];
+ for (let j = 0; j < dataUrls.length; ++j) {
+ const dataUrl = dataUrls[j];
+ const restResult = (await restService.getConfigData(dataUrl));
+ if (restResult.data == null || restResult.status < 200 || restResult.status > 299) {
+ const message = restResult.data && restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
+ throw new Error(`Server Error. Status: [${restResult.status}]\n${message || restResult.message || ''}`);
+ }
+ let dataRaw = restResult.data[dataMember!];
+ dataRaw = dataRaw instanceof Array
+ ? dataRaw[0]
+ : dataRaw;
+ data.push(dataRaw);
+ }
+ // BUG UUID ist nicht in den elements enthalten !!!!!!
+ const key = viewElement && viewElement.label || pathPart;
+ return {
+ view: view!,
+ data: data,
+ key: key,
+ };
+ }
+ }
+ return null;
+}
+
+const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification, viewData: any, displayAsList: boolean = false, key?: string): UpdatViewDescription =>{
+
+ // check if-feature | when | and resolve all references.
+ view = { ...view };
+ view.elements = Object.keys(view.elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+ const elm = view.elements[cur];
+ const key = defaultNS && cur.replace(new RegExp(`^${defaultNS}:`, "i"),"") || cur;
+ if (isViewElementReference(elm)) {
+ acc[key] = { ...(elm.ref(vPath) || elm), id: key };
+ } else {
+ acc[key] = { ...elm, id: key };
+ }
+ return acc;
+ }, {});
+ return new UpdatViewDescription(vPath, view, viewData, displayAsList, key);
+}
+
+export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+ const { configuration: { deviceDescription: { nodeId, modules, views } }, framework: { navigationState } } = getState();
+ let dataPath = `/restconf/config/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount`;
+ let viewSpecification: ViewSpecification = views[0];
+ let viewElement: ViewElement;
+
+ let dataMember: string;
+ let extractList: boolean = false;
+
+ let currentNS : string | null = null;
+ let defaultNS : string | null = null;
+
+ dispatch(new SetCollectingSelectionData(true));
+ try {
+ for (let ind = 0; ind < pathParts.length; ++ind) {
+ const [property, key] = pathParts[ind];
+ const namespaceInd = property && property.indexOf(":") || -1;
+ const namespace : string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+ if (ind === 0) { defaultNS = namespace };
+
+ viewElement = viewSpecification.elements[property];
+ if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+
+ if (viewElement.isList && !key) {
+ if (pathParts.length - 1 > ind) {
+ dispatch(new SetCollectingSelectionData(false));
+ throw new Error("No key for list [" + property + "]");
+ } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ // empty key is used for new element
+ if (viewElement && "viewId" in viewElement) viewSpecification = views[+viewElement.viewId];
+ const data = Object.keys(viewSpecification.elements).reduce<{ [name: string]: any }>((acc, cur) => {
+ const elm = viewSpecification.elements[cur];
+ if (elm.default) {
+ acc[elm.id] = elm.default || ""
+ }
+ return acc;
+ }, {});
+ return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, false, isViewElementList(viewElement!) && viewElement.key || undefined));
+ }
+ if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === "0") {
+ // check if there is a reference as key
+ const listSpecification = views[+viewElement.viewId];
+ const keyElement = viewElement.key && listSpecification.elements[viewElement.key];
+ if (keyElement && isViewElementReference(keyElement)) {
+ const refList = await getReferencedDataList(keyElement.referencePath, dataPath, modules, views);
+ if (!refList) {
+ throw new Error(`Could not find refList for [${keyElement.referencePath}].`);
+ }
+ if (!refList.key) {
+ throw new Error(`Key property not found for [${keyElement.referencePath}].`);
+ }
+ dispatch(new EnableValueSelector(refList.view, refList.data, refList.key, (refKey) => {
+ window.setTimeout(() => dispatch(new PushAction(`${vPath}[${refKey.replace(/\//ig, "%2F")}]`)));
+ }));
+ } else {
+ dispatch(new SetCollectingSelectionData(false));
+ throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ }
+ return;
+ }
+ extractList = true;
+ } else {
+ dataPath += `/${property}${key ? `/${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataMember = namespace === defaultNS
+ ? viewElement.label
+ : `${namespace}:${viewElement.label}`;
+ extractList = false;
+ }
+
+ if (viewElement && "viewId" in viewElement) viewSpecification = views[+viewElement.viewId];
+ }
+
+ let data: any = {};
+ if (viewSpecification && viewSpecification.id !== "0") {
+ const restResult = (await restService.getConfigData(dataPath));
+ if (!restResult.data) {
+ // special case: if this is a list without any response
+ if (extractList && restResult.status === 404) {
+ if (!isViewElementList(viewElement!)) {
+ throw new Error(`vPath: [${vPath}]. ViewElement has no key.`);
+ }
+ return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, [], extractList, viewElement.key));
+ }
+ throw new Error(`Did not get response from Server. Status: [${restResult.status}]`);
+ } else if (restResult.status < 200 || restResult.status > 299) {
+ const message = restResult.data.errors && restResult.data.errors.error && restResult.data.errors.error[0] && restResult.data.errors.error[0]["error-message"] || "";
+ throw new Error(`Server Error. Status: [${restResult.status}]\n${message}`);
+ } else {
+ data = restResult.data[dataMember!]; // extract dataMember
+ }
+
+ // extract the first element list[key]
+ data = data instanceof Array
+ ? data[0]
+ : data;
+
+ // extract the list -> key: list
+ data = extractList
+ ? data[viewElement!.label] || [] // if the list is empty, it does not exist
+ : data;
+ }
+
+ return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, extractList, isViewElementList(viewElement!) && viewElement.key || undefined));
+ // https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
+ // https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
+ } catch (error) {
+ history.back();
+ dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not process ${dataPath}` }));
+ dispatch(new SetCollectingSelectionData(false));
+ } finally {
+ return;
+ }
+}
+
+export const updateDataActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+ const { configuration: { deviceDescription: { nodeId, views } } } = getState();
+ let dataPath = `/restconf/config/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount`;
+ let viewSpecification: ViewSpecification = views[0];
+ let viewElement: ViewElement;
+ let dataMember: string;
+ let embedList: boolean = false;
+ let isNew: string | false = false;
+
+ let currentNS: string | null = null;
+ let defaultNS: string | null = null;
+
+ dispatch(new SetCollectingSelectionData(true));
+ try {
+ for (let ind = 0; ind < pathParts.length; ++ind) {
+ let [property, key] = pathParts[ind];
+ const namespaceInd = property && property.indexOf(":") || -1;
+ const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+ if (ind === 0) { defaultNS = namespace };
+ viewElement = viewSpecification.elements[property];
+ if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+
+ if (isViewElementList(viewElement) && !key) {
+ embedList = true;
+ if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
+ throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ }
+ if (pathParts.length - 1 > ind) {
+ dispatch(new SetCollectingSelectionData(false));
+ throw new Error("No key for list [" + property + "]");
+ } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ // handle new element
+ key = viewElement.key && String(data[viewElement.key]) || "";
+ isNew = key;
+ if (!key) {
+ dispatch(new SetCollectingSelectionData(false));
+ throw new Error("No value for key [" + viewElement.key +"] in list [" + property + "]");
+ }
+ }
+ }
+
+ dataPath += `/${property}${key ? `/${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataMember = viewElement.label;
+ embedList = false;
+
+ if (viewElement && "viewId" in viewElement) {
+ viewSpecification = views[+viewElement.viewId];
+ }
+ }
+
+ // embed the list -> key: list
+ data = embedList
+ ? { [viewElement!.label]: data }
+ : data;
+
+ // embed the first element list[key]
+ data = isNew
+ ? [data]
+ : data;
+
+ // do not extract root member (0)
+ if (viewSpecification && viewSpecification.id !== "0") {
+ const updateResult = await restService.setConfigData(dataPath, { [dataMember!]: data }); // extractDataMember
+ if (updateResult.status < 200 || updateResult.status > 299) {
+ const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
+ throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
+ }
+ }
+
+ return isNew
+ ? dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i,`[${isNew}]`)}`)) // navigate to new element
+ : dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, embedList, isViewElementList(viewElement!) && viewElement.key || undefined));
+ } catch (error) {
+ history.back();
+ dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not change ${dataPath}` }));
+ dispatch(new SetCollectingSelectionData(false));
+ } finally {
+ return;
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
new file mode 100644
index 000000000..04b63d39b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/configurationAppRootHandler.ts
@@ -0,0 +1,29 @@
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
+import { IDeviceDescriptionState, deviceDescriptionHandler } from "./deviceDescriptionHandler";
+import { IViewDescriptionState, viewDescriptionHandler } from "./viewDescriptionHandler";
+import { IValueSelectorState, valueSelectorHandler } from "./valueSelectorHandler";
+
+interface IConfigurationAppStoreState {
+ connectedNetworkElements: IConnectedNetworkElementsState; // used for ne selection
+ deviceDescription: IDeviceDescriptionState; // contains ui and device descriptions
+ viewDescription: IViewDescriptionState; // contains current ui description
+ valueSelector: IValueSelectorState;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ configuration: IConfigurationAppStoreState,
+ }
+}
+
+const actionHandlers = {
+ connectedNetworkElements: connectedNetworkElementsActionHandler,
+ deviceDescription: deviceDescriptionHandler,
+ viewDescription: viewDescriptionHandler,
+ valueSelector: valueSelectorHandler,
+};
+
+export const configurationAppRootHandler = combineActionHandler<IConfigurationAppStoreState>(actionHandlers);
+export default configurationAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
new file mode 100644
index 000000000..6a68242eb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
@@ -0,0 +1,19 @@
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+
+export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
+
+// create eleactic search material data fetch handler
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', { status: "Connected" });
+
+export const {
+ actionHandler: connectedNetworkElementsActionHandler,
+ createActions: createConnectedNetworkElementsActions,
+ createProperties: createConnectedNetworkElementsProperties,
+ reloadAction: connectedNetworkElementsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<NetworkElementConnection>(connectedNetworkElementsSearchHandler, appState => appState.configuration.connectedNetworkElements);
+ \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
new file mode 100644
index 000000000..3cc27aa95
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/deviceDescriptionHandler.ts
@@ -0,0 +1,30 @@
+import { Module } from "../models/yang";
+import { ViewSpecification } from "../models/uiModels";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { UpdateDeviceDescription } from "../actions/deviceActions";
+
+export interface IDeviceDescriptionState {
+ nodeId: string,
+ modules: {
+ [name: string]: Module
+ },
+ views: ViewSpecification[],
+}
+
+const deviceDescriptionStateInit: IDeviceDescriptionState = {
+ nodeId: "",
+ modules: {},
+ views: []
+};
+
+export const deviceDescriptionHandler: IActionHandler<IDeviceDescriptionState> = (state = deviceDescriptionStateInit, action) => {
+ if (action instanceof UpdateDeviceDescription) {
+ state = {
+ ...state,
+ nodeId: action.nodeId,
+ modules: action.modules,
+ views: action.views
+ };
+ }
+ return state;
+};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
new file mode 100644
index 000000000..c9e7dd2cc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
@@ -0,0 +1,58 @@
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { ViewSpecification } from "../models/uiModels";
+import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdatViewDescription } from "../actions/deviceActions";
+
+export interface IValueSelectorState {
+ collectingData: boolean;
+ keyProperty: string | undefined;
+ listSpecification: ViewSpecification | null;
+ listData: any[];
+ onValueSelected: (value: any) => void;
+}
+
+const nc = (val: React.SyntheticEvent) => { };
+const valueSelectorStateInit: IValueSelectorState = {
+ collectingData: false,
+ keyProperty: undefined,
+ listSpecification: null,
+ listData: [],
+ onValueSelected: nc,
+};
+
+export const valueSelectorHandler: IActionHandler<IValueSelectorState> = (state = valueSelectorStateInit, action) => {
+ if (action instanceof SetCollectingSelectionData) {
+ state = {
+ ...state,
+ collectingData: action.busy,
+ };
+ } else if (action instanceof EnableValueSelector) {
+ state = {
+ ...state,
+ collectingData: false,
+ keyProperty: action.keyProperty,
+ listSpecification: action.listSpecification,
+ onValueSelected: action.onValueSelected,
+ listData: action.listData,
+ };
+ } else if (action instanceof SetSelectedValue) {
+ state.keyProperty && state.onValueSelected(action.value[state.keyProperty]);
+ state = {
+ ...state,
+ collectingData: false,
+ keyProperty: undefined,
+ listSpecification: null,
+ onValueSelected: nc,
+ listData: [],
+ };
+ } else if (action instanceof UpdateDeviceDescription || action instanceof UpdatViewDescription) {
+ state = {
+ ...state,
+ collectingData: false,
+ keyProperty: undefined,
+ listSpecification: null,
+ onValueSelected: nc,
+ listData: [],
+ };
+ }
+ return state;
+};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
new file mode 100644
index 000000000..48155ee1e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
@@ -0,0 +1,42 @@
+import { IActionHandler } from "../../../../framework/src/flux/action";
+
+import { UpdatViewDescription } from "../actions/deviceActions";
+import { ViewSpecification } from "../models/uiModels";
+
+export interface IViewDescriptionState {
+ vPath: string | null;
+ keyProperty: string | undefined;
+ displayAsList: boolean;
+ viewSpecification: ViewSpecification;
+ viewData: any
+}
+
+const viewDescriptionStateInit: IViewDescriptionState = {
+ vPath: null,
+ keyProperty: undefined,
+ displayAsList: false,
+ viewSpecification: {
+ id: "empty",
+ canEdit: false,
+ parentView: "",
+ name: "emplty",
+ language: "en-US",
+ title: "empty",
+ elements: {}
+ },
+ viewData: null
+};
+
+export const viewDescriptionHandler: IActionHandler<IViewDescriptionState> = (state = viewDescriptionStateInit, action) => {
+ if (action instanceof UpdatViewDescription) {
+ state = {
+ ...state,
+ vPath: action.vPath,
+ keyProperty: action.key,
+ displayAsList: action.displayAsList,
+ viewSpecification: action.view,
+ viewData: action.viewData,
+ }
+ }
+ return state;
+};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/index.html b/sdnr/wt/odlux/apps/configurationApp/src/index.html
new file mode 100644
index 000000000..759b7b535
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Configuration App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "connectApp", "maintenanceApp", "configurationApp"], function (app, connectApp, maintenanceApp, configurationApp) {
+ connectApp.register();
+ configurationApp.register();
+ maintenanceApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
new file mode 100644
index 000000000..2575500a3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/networkElementConnection.ts
@@ -0,0 +1,19 @@
+export type NetworkElementConnection = {
+ id?: string;
+ nodeId: string;
+ host: string;
+ port: number;
+ username?: string;
+ password?: string;
+ isRequired?: boolean;
+ status?: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ coreModelCapability?: string;
+ deviceType?: string;
+ nodeDetails?: {
+ availableCapabilities: string[];
+ unavailableCapabilities: {
+ failureReason: string;
+ capability: string;
+ }[];
+ }
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
new file mode 100644
index 000000000..441d1281d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -0,0 +1,142 @@
+export type ViewElementBase = {
+ "id": string;
+ "label": string;
+ "config": boolean;
+ "ifFeature"?: string;
+ "when"?: string;
+ "mandatory"?: boolean;
+ "description"?: string;
+ "isList"?: boolean;
+ "default"?: string;
+ "status"?: "current" | "deprecated" | "obsolete",
+ "reference"?: string, // https://tools.ietf.org/html/rfc7950#section-7.21.4
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9.8
+export type ViewElementBinary = ViewElementBase & {
+ "uiType": "binary";
+ "length"?: number; // number of octets
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9.7.4
+export type ViewElementBits = ViewElementBase & {
+ "uiType": "bits";
+ "flags": {
+ [name: string]: number | undefined; // 0 - 4294967295
+ }
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9
+export type ViewElementString = ViewElementBase & {
+ "uiType": "string";
+ "pattern"?: string[];
+ "length"?: string;
+ "invertMatch"?: true;
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9.3
+export type ViewElementNumber = ViewElementBase & {
+ "uiType": "number";
+ "min"?: number;
+ "max"?: number;
+ "units"?: string;
+ "format"?: string;
+ "fDigits"?: number;
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9.5
+export type ViewElementBoolean = ViewElementBase & {
+ "uiType": "boolean";
+ "trueValue"?: string;
+ "falseValue"?: string;
+}
+
+// https://tools.ietf.org/html/rfc7950#section-9.6.4
+export type ViewElementSelection = ViewElementBase & {
+ "uiType": "selection";
+ "multiSelect"?: boolean
+ "options": {
+ "key": string;
+ "value": string;
+ "description"?: string,
+ "status"?: "current" | "deprecated" | "obsolete",
+ "reference"?: string,
+ }[];
+}
+
+// is a list if isList is true ;-)
+export type ViewElementObject = ViewElementBase & {
+ "uiType": "object";
+ "isList"?: false;
+ "viewId": string;
+}
+
+// Hint: read only lists do not need a key
+export type ViewElementList = (ViewElementBase & {
+ "uiType": "object";
+ "isList": true;
+ "viewId": string;
+ "key"?: string;
+});
+
+export type ViewElementReference = ViewElementBase & {
+ "uiType": "reference";
+ "referencePath": string;
+ "ref": (currentPath: string) => ViewElement | null;
+}
+
+export type ViewElement =
+ | ViewElementBits
+ | ViewElementBinary
+ | ViewElementString
+ | ViewElementNumber
+ | ViewElementBoolean
+ | ViewElementObject
+ | ViewElementList
+ | ViewElementSelection
+ | ViewElementReference;
+
+export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
+ return viewElement && viewElement.uiType === "string";
+}
+
+export const isViewElementNumber = (viewElement: ViewElement): viewElement is ViewElementNumber => {
+ return viewElement && viewElement.uiType === "number" ;
+}
+
+export const isViewElementBoolean = (viewElement: ViewElement): viewElement is ViewElementBoolean => {
+ return viewElement && viewElement.uiType === "boolean";
+}
+
+export const isViewElementObject = (viewElement: ViewElement): viewElement is ViewElementObject => {
+ return viewElement && viewElement.uiType === "object" && viewElement.isList === false;
+}
+
+export const isViewElementList = (viewElement: ViewElement): viewElement is ViewElementList => {
+ return viewElement && viewElement.uiType === "object" && viewElement.isList === true;
+}
+
+export const isViewElementObjectOrList = (viewElement: ViewElement): viewElement is ViewElementObject | ViewElementList => {
+ return viewElement && viewElement.uiType === "object";
+}
+
+export const isViewElementSelection = (viewElement: ViewElement): viewElement is ViewElementSelection => {
+ return viewElement && viewElement.uiType === "selection";
+}
+
+export const isViewElementReference = (viewElement: ViewElement): viewElement is ViewElementReference => {
+ return viewElement && viewElement.uiType === "reference";
+}
+
+export type ViewSpecification = {
+ "id": string;
+ "name": string;
+ "title"?: string;
+ "parentView"?: string;
+ "language": string;
+ "ifFeature"?: string;
+ "when"?: string;
+ "uses"?: string[];
+ "elements": { [name: string]: ViewElement };
+ readonly "canEdit": boolean;
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
new file mode 100644
index 000000000..57edf803f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/yang.ts
@@ -0,0 +1,44 @@
+import { ViewElement, ViewSpecification } from "./uiModels";
+
+export type Token = {
+ name: string;
+ value: string;
+ start: number;
+ end: number;
+}
+
+export type Statement = {
+ key: string;
+ arg?: string;
+ sub?: Statement[];
+}
+
+export type Identity = {
+ id: string,
+ label: string,
+ base?: string,
+ description?: string,
+ reference?: string,
+ children?: Identity[],
+ values?: Identity[],
+}
+
+export type Revision = {
+ description?: string,
+ reference?: string
+};
+
+export type Module = {
+ name: string;
+ namespace?: string;
+ prefix?: string;
+ identities: { [name: string]: Identity };
+ revisions: { [version: string]: Revision } ;
+ imports: { [prefix: string]: string };
+ features: { [feature: string]: { description?: string } };
+ typedefs: { [type: string]: ViewElement };
+ augments: { [path: string]: ViewSpecification[] };
+ groupings: { [group: string]: ViewSpecification };
+ views: { [view: string]: ViewSpecification };
+ elements: { [view: string]: ViewElement };
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
new file mode 100644
index 000000000..7fd3a97f9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/pluginConfiguration.tsx
@@ -0,0 +1,77 @@
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faAdjust } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import { configurationAppRootHandler } from "./handlers/configurationAppRootHandler";
+import { NetworkElementSelector } from "./views/networkElementSelector";
+
+import ConfigurationApplication from "./views/configurationApplication";
+import { updateNodeIdAsyncActionCreator, updateViewActionAsyncCreator } from "./actions/deviceActions";
+
+let currentNodeId: string | null | undefined = undefined;
+let currentVirtualPath: string | null | undefined = undefined;
+let lastUrl: string | undefined = undefined;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ // currentProblemsProperties: createCurrentProblemsProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ updateNodeId: (nodeId: string) => dispatcher.dispatch(updateNodeIdAsyncActionCreator(nodeId)),
+ updateView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
+});
+
+const ConfigurationApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ nodeId?: string, 0: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+ React.useEffect(() => {
+ return () => {
+ lastUrl = undefined;
+ currentNodeId = undefined;
+ currentVirtualPath = undefined;
+ }
+ },[]);
+ if (props.location.pathname !== lastUrl) {
+ // ensure the asynchronus update will only be called once per path
+ lastUrl = props.location.pathname;
+ window.setTimeout(async () => {
+
+ // check if the nodeId has changed
+ if (currentNodeId !== props.match.params.nodeId) {
+ currentNodeId = props.match.params.nodeId || undefined;
+ currentVirtualPath = null;
+ currentNodeId && await props.updateNodeId(currentNodeId);
+ }
+
+ if (currentVirtualPath !== props.match.params[0]) {
+ currentVirtualPath = props.match.params[0];
+ await props.updateView(currentVirtualPath);
+ }
+
+ });
+ }
+ return (
+ <ConfigurationApplication />
+ );
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+ <Switch>
+ <Route path={`${props.match.url}/:nodeId/*`} component={ ConfigurationApplicationRouteAdapter } />
+ <Route path={`${props.match.url}/:nodeId`} component={ ConfigurationApplicationRouteAdapter } />
+ <Route path={`${props.match.url}`} component={ NetworkElementSelector } />
+ <Redirect to={`${props.match.url}`} />
+ </Switch>
+));
+
+export function register() {
+ applicationManager.registerApplication({
+ name: "configuration",
+ icon: faAdjust,
+ rootComponent: App,
+ rootActionHandler: configurationAppRootHandler,
+ menuEntry: "Configuration"
+ });
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
new file mode 100644
index 000000000..061be05ec
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
@@ -0,0 +1,38 @@
+import { requestRest, requestRestExt } from "../../../../framework/src/services/restService";
+import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
+
+import { NetworkElementConnection } from "../models/networkElementConnection";
+
+class RestService {
+ public async getMountedNetworkElementByMountId(nodeId: string): Promise<NetworkElementConnection | null> {
+ // const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId;
+ // const connectedNetworkElement = await requestRest<NetworkElementConnection>(path, { method: "GET" });
+ // return connectedNetworkElement || null;
+
+ const path = "/restconf/operations/data-provider:read-network-element-connection-list";
+ const body = { "input": { "filter": [{ "property": "node-id", "filtervalue": nodeId }], "sortorder": [], "pagination": { "size": 1, "page": 1 } } };
+ const networkElementResult = await requestRest<{ output: { data: NetworkElementConnection[] } }>(path, { method: "POST", body: JSON.stringify(body) });
+ return networkElementResult && networkElementResult.output && networkElementResult.output.data &&
+ networkElementResult.output.data.map(obj => convertPropertyNames(obj, replaceHyphen))[0] || null;
+ }
+
+ /** Reads the config data by restconf path.
+ * @param path The restconf path to be used for read.
+ * @returns The data.
+ */
+ public getConfigData(path: string) {
+ return requestRestExt<{ [key: string]: any }>(path, { method: "GET" });
+ }
+
+ /** Updates or creates the config data by restconf path using data.
+ * @param path The restconf path to identify the note to update.
+ * @param data The data to be updated.
+ * @returns The written data.
+ */
+ public setConfigData(path: string, data: any) {
+ return requestRestExt<{ [key: string]: any }>(path, { method: "PUT", body: JSON.stringify(data) });
+ }
+ }
+
+export const restService = new RestService();
+export default restService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
new file mode 100644
index 000000000..17a4e43a7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
@@ -0,0 +1,25 @@
+type YangInfo = [string, (string | null | undefined)];
+
+const cache: { [path: string]: string } = {
+
+};
+
+class YangService {
+
+ public async getCapability(capability: string, version?: string) {
+ const url = `/yang-schema/${capability}${version ? `/${version}` : ""}`;
+
+ const cacheHit = cache[url];
+ if (cacheHit) return cacheHit;
+
+ const res = await fetch(url);
+ const yangFile = res.ok && await res.text();
+ if (yangFile !== false && yangFile !== null) {
+ cache[url] = yangFile;
+ }
+ return yangFile;
+ }
+}
+
+export const yangService = new YangService();
+export default yangService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
new file mode 100644
index 000000000..24a4af8b2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -0,0 +1,464 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from "../../../../framework/src/components/material-table";
+import { Loader } from "../../../../framework/src/components/material-ui/loader";
+
+import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator } from "../actions/deviceActions";
+import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection } from "../models/uiModels";
+
+import Fab from '@material-ui/core/Fab';
+import AddIcon from '@material-ui/icons/Add';
+import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
+import SaveIcon from '@material-ui/icons/Save';
+import EditIcon from '@material-ui/icons/Edit';
+import Tooltip from "@material-ui/core/Tooltip";
+import TextField from "@material-ui/core/TextField";
+import FormControl from "@material-ui/core/FormControl";
+import IconButton from "@material-ui/core/IconButton";
+import Button from "@material-ui/core/Button";
+import InputAdornment from "@material-ui/core/InputAdornment";
+import InputLabel from "@material-ui/core/InputLabel";
+import Select from "@material-ui/core/Select";
+import MenuItem from "@material-ui/core/MenuItem";
+import Breadcrumbs from "@material-ui/core/Breadcrumbs";
+import Link from "@material-ui/core/Link";
+import FormHelperText from '@material-ui/core/FormHelperText';
+
+const styles = (theme: Theme) => createStyles({
+ header: {
+ "display": "flex",
+ "justifyContent": "space-between",
+ },
+ leftButton: {
+ "justifyContent": "left"
+ },
+ outer: {
+ "flex": "1",
+ "heigh": "100%",
+ "display": "flex",
+ "alignItems": "center",
+ "justifyContent": "center",
+ },
+ inner: {
+
+ },
+ "icon": {
+ "marginRight": theme.spacing(0.5),
+ "width": 20,
+ "height": 20,
+ },
+ "fab": {
+ "margin": theme.spacing(1),
+ },
+ button: {
+ margin: 0,
+ padding: "6px 6px",
+ minWidth: 'unset'
+ },
+ readOnly: {
+ '& label.Mui-focused': {
+ color: 'green',
+ },
+ '& .MuiInput-underline:after': {
+ borderBottomColor: 'green',
+ },
+ '& .MuiOutlinedInput-root': {
+ '& fieldset': {
+ borderColor: 'red',
+ },
+ '&:hover fieldset': {
+ borderColor: 'yellow',
+ },
+ '&.Mui-focused fieldset': {
+ borderColor: 'green',
+ },
+ },
+ },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ collectingData: state.configuration.valueSelector.collectingData,
+ listKeyProperty: state.configuration.valueSelector.keyProperty,
+ listSpecification: state.configuration.valueSelector.listSpecification,
+ listData: state.configuration.valueSelector.listData,
+ vPath: state.configuration.viewDescription.vPath,
+ nodeId: state.configuration.deviceDescription.nodeId,
+ viewData: state.configuration.viewDescription.viewData,
+ viewSpecification: state.configuration.viewDescription.viewSpecification,
+ displayAsList: state.configuration.viewDescription.displayAsList,
+ keyProperty: state.configuration.viewDescription.keyProperty,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
+ onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
+});
+
+const SelectElementTable = MaterialTable as MaterialTableCtorType<{ [key: string]: any }>;
+
+type ConfigurationApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type ConfigurationApplicationComponentState = {
+ isNew: boolean;
+ editMode: boolean;
+ canEdit: boolean;
+ viewData: { [key: string]: any } | null;
+}
+
+const OldProps = Symbol("OldProps");
+class ConfigurationApplicationComponent extends React.Component<ConfigurationApplicationComponentProps, ConfigurationApplicationComponentState> {
+
+ /**
+ *
+ */
+ constructor (props: ConfigurationApplicationComponentProps) {
+ super(props);
+
+ this.state = {
+ isNew: false,
+ canEdit: false,
+ editMode: false,
+ viewData: null
+ }
+ }
+
+ static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
+
+ if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
+ const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
+ const state = {
+ ...prevState,
+ isNew: isNew,
+ editMode: isNew,
+ viewData: nextProps.viewData || null,
+ [OldProps]: nextProps,
+ }
+ return state;
+ }
+ return null;
+ }
+
+ private navigate = (path: string) => {
+ this.props.history.push(`${this.props.match.url}${path}`);
+ }
+
+ private changeValueFor = (property: string, value: any) => {
+ this.setState({
+ viewData: {
+ ...this.state.viewData,
+ [property]: value
+ }
+ });
+ }
+
+ private renderUIElement = (viewSpecification: ViewSpecification, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
+ const elements = viewSpecification.elements;
+ return (
+ Object.keys(elements).sort((a, b) => {
+ const vsA = elements[a];
+ const vsB = elements[b];
+ if (keyProperty) {
+ // if (vsA.label === vsB.label) return 0;
+ if (vsA.label === keyProperty) return -1;
+ if (vsB.label === keyProperty) return +1;
+ }
+
+ if (vsA.uiType === vsB.uiType) return 0;
+ if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+ if (vsA.uiType === "object") return +1;
+ return -1;
+ }).map(key => {
+ const uiElement = elements[key];
+ const isKey = (uiElement.label === keyProperty);
+ const canEdit = editMode && (isNew || (uiElement.config && !isKey));
+ if (isViewElementSelection(uiElement)) {
+ let error = ""
+ const value = String(viewData[uiElement.id]).toLowerCase();
+ if (uiElement.mandatory && !!value) {
+ error = "Error";
+ }
+ return (canEdit || viewData[uiElement.id] != null
+ ? (<FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
+ <Select
+ required={!!uiElement.mandatory}
+ error={!!error}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ value={(viewData[uiElement.id] || '').toString().toLowerCase()}
+ inputProps={{
+ name: uiElement.id,
+ id: `select-${uiElement.id}`,
+ }}
+ >
+ {uiElement.options.map(option => (<MenuItem key={option.key} title={option.description} value={option.value}>{option.key}</MenuItem>))}
+ </Select>
+ <FormHelperText>{error}</FormHelperText>
+ </FormControl>)
+ : null
+ );
+ } else if (isViewElementBoolean(uiElement)) {
+ let error = ""
+ const value = String(viewData[uiElement.id]).toLowerCase();
+ if (uiElement.mandatory && value !== "true" && value !== "false") {
+ error = "Error";
+ }
+ return (canEdit || viewData[uiElement.id] != null
+ ? (<FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <InputLabel htmlFor={`select-${uiElement.id}`} >{uiElement.label}</InputLabel>
+ <Select
+ required={!!uiElement.mandatory}
+ error={!!error}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
+ readOnly={!canEdit}
+ disabled={editMode && !canEdit}
+ value={value}
+ inputProps={{
+ name: uiElement.id,
+ id: `select-${uiElement.id}`,
+ }}
+ >
+ <MenuItem value={'true'}>{uiElement.trueValue || 'True'}</MenuItem>
+ <MenuItem value={'false'}>{uiElement.falseValue || 'False'}</MenuItem>
+
+ </Select>
+ <FormHelperText>{error}</FormHelperText>
+ </FormControl>)
+ : null
+ );
+ } else if (isViewElementString(uiElement)) {
+ return (
+ <Tooltip key={uiElement.id} title={uiElement.description || ''}>
+ <TextField InputProps={{ readOnly: !canEdit, disabled: editMode && !canEdit }} spellCheck={false} autoFocus margin="dense"
+ id={uiElement.id} label={isKey ? "🔑 " + uiElement.label : uiElement.label} type="text" value={viewData[uiElement.id] || ''}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
+ />
+ </Tooltip>
+ );
+ } else if (isViewElementNumber(uiElement)) {
+ return (
+ <Tooltip key={uiElement.id} title={uiElement.description || ''}>
+ <TextField InputProps={{ readOnly: !canEdit, disabled: editMode && !canEdit, startAdornment: uiElement.units != null ? <InputAdornment position="start">{uiElement.units}</InputAdornment> : undefined }} spellCheck={false} autoFocus margin="dense"
+ id={uiElement.id} label={uiElement.label} type="text" value={viewData[uiElement.id] == null ? '' : viewData[uiElement.id]}
+ style={{ width: 485, marginLeft: 20, marginRight: 20 }}
+ onChange={(e) => { this.changeValueFor(uiElement.id, e.target.value) }}
+ />
+ </Tooltip>
+ );
+ } else if (isViewElementObjectOrList(uiElement)) {
+ return (
+ <FormControl key={uiElement.id} style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
+ <Tooltip title={uiElement.description || ''}>
+ <Button className={this.props.classes.leftButton} color="secondary" disabled={this.state.editMode} onClick={() => {
+ this.navigate(`/${uiElement.id}`);
+ }}>{uiElement.label}</Button>
+ </Tooltip>
+ </FormControl>
+ );
+ } else {
+ if (process.env.NODE_ENV !== "production") {
+ console.error(`Unknown type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
+ }
+ return null;
+ }
+ })
+ );
+ };
+
+ private renderUIElementList(listSpecification: ViewSpecification, listKeyProperty: string, listData: { [key: string]: any }[]) {
+ const listElements = listSpecification.elements;
+
+ const navigate = (path: string) => {
+ this.props.history.push(`${this.props.match.url}${path}`);
+ };
+
+ const addNewElementAction = {
+ icon: AddIcon, tooltip: 'Add', onClick: () => {
+ navigate("[]"); // empty key means new element
+ }
+ };
+
+ const { classes } = this.props;
+
+ return (
+ <SelectElementTable idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
+ Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+ const elm = listElements[cur];
+ if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+ if (elm.label !== listKeyProperty) {
+ acc.push({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ } else {
+ acc.unshift({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ }
+ }
+ return acc;
+ }, []).concat([{
+ property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (row => {
+ return (
+ <Tooltip title={"Remove"} >
+ <IconButton className={classes.button} onClick={event => {
+
+ }} >
+ <RemoveIcon />
+ </IconButton>
+ </Tooltip>
+ )
+ })
+ }])
+ } onHandleClick={(ev, row) => {
+ ev.preventDefault();
+ navigate(`[${row[listKeyProperty]}]`);
+ }} ></SelectElementTable>
+ );
+ }
+
+ private renderBreadCrumps() {
+ const { editMode } = this.state;
+ const { viewSpecification, displayAsList } = this.props;
+ const { vPath, match: { url, path }, nodeId } = this.props;
+ const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+ let lastPath = `/configuration`;
+ let basePath = `/configuration/${nodeId}`;
+ return (
+ <div className={this.props.classes.header}>
+ <div>
+ <Breadcrumbs aria-label="breadcrumb">
+ <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
+ ev.preventDefault();
+ this.props.history.push(lastPath);
+ }}>Back</Link>
+ <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
+ ev.preventDefault();
+ this.props.history.push(`/configuration/${nodeId}`);
+ }}><span>{nodeId}</span></Link>
+ {
+ pathParts.map(([prop, key], ind) => {
+ const path = `${basePath}/${prop}`;
+ const keyPath = key && `${basePath}/${prop}[${key}]`;
+ const ret = (
+ <span key={ind}>
+ <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
+ ev.preventDefault();
+ this.props.history.push(path);
+ }}><span>{prop.replace(/^[^:]+:/, "")}</span></Link>
+ {
+ keyPath && <Link color="inherit" href="#" onClick={(ev: React.MouseEvent<HTMLElement>) => {
+ ev.preventDefault();
+ this.props.history.push(keyPath);
+ }}>{`[${key}]`}</Link> || null
+ }
+ </span>
+ );
+ lastPath = basePath;
+ basePath = keyPath || path;
+ return ret;
+ })
+ }
+ </Breadcrumbs>
+ </div>
+ { /* do not show edit if this is a list or it can't be edited */
+ !displayAsList && viewSpecification.canEdit && (<div>
+ <Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={() => {
+ if (this.state.editMode) {
+ this.props.onUpdateData(this.props.vPath!, this.state.viewData);
+ }
+ this.setState({ editMode: !editMode });
+ }}>
+ {editMode
+ ? <SaveIcon />
+ : <EditIcon />
+ }
+ </Fab>
+ </div> || null)
+ }
+ </div>
+ );
+ }
+
+ private renderValueSelector() {
+ const { listKeyProperty, listSpecification, listData, onValueSelected } = this.props;
+ if (!listKeyProperty || !listSpecification) {
+ throw new Error("ListKex ot view not specified.");
+ }
+
+ return (
+ <div>
+ <SelectElementTable idProperty={listKeyProperty} rows={listData} columns={
+ Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
+ const elm = listSpecification.elements[cur];
+ if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
+ if (elm.label !== listKeyProperty) {
+ acc.push({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ } else {
+ acc.unshift({ property: elm.label, type: elm.uiType === "number" ? ColumnType.numeric : ColumnType.text });
+ }
+ }
+ return acc;
+ }, [])
+ } onHandleClick={(ev, row) => { ev.preventDefault(); onValueSelected(row); }} ></SelectElementTable>
+ </div>
+ );
+ }
+
+ private renderValueEditor() {
+ const { keyProperty, displayAsList, viewSpecification } = this.props;
+ const { viewData, editMode, isNew } = this.state;
+
+ return (
+ <div>
+ { this.renderBreadCrumps() }
+ { displayAsList && viewData instanceof Array
+ ? this.renderUIElementList(viewSpecification, keyProperty!, viewData)
+ : this.renderUIElement(viewSpecification, viewData!, keyProperty, editMode, isNew)
+ }
+ </div >
+ );
+ }
+
+ private renderCollectingData() {
+ return (
+ <div className={this.props.classes.outer}>
+ <div className={this.props.classes.inner}>
+ <Loader />
+ <h3>Collecting Data ...</h3>
+ </div>
+ </div>
+ );
+ }
+
+ render() {
+ return this.props.collectingData || !this.state.viewData
+ ? this.renderCollectingData()
+ : this.props.listSpecification
+ ? this.renderValueSelector()
+ : this.renderValueEditor();
+ }
+}
+
+export const ConfigurationApplication = withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(ConfigurationApplicationComponent)));
+export default ConfigurationApplication; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
new file mode 100644
index 000000000..6fd5c8cf0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -0,0 +1,47 @@
+import * as React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { MaterialTable, MaterialTableCtorType, ColumnType } from "../../../../framework/src/components/material-table";
+import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "../../../configurationApp/src/handlers/connectedNetworkElementsHandler";
+
+import { NetworkElementConnection } from "../models/networkElementConnection";
+import { Tooltip, Button, IconButton } from "@material-ui/core";
+
+const mapProps = (state: IApplicationStoreState) => ({
+ connectedNetworkElementsProperties: createConnectedNetworkElementsProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ connectedNetworkElementsActions: createConnectedNetworkElementsActions(dispatcher.dispatch),
+});
+
+const ConnectedElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
+
+type NetworkElementSelectorComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
+
+class NetworkElementSelectorComponent extends React.Component<NetworkElementSelectorComponentProps> {
+
+ componentDidMount() {
+ this.props.connectedNetworkElementsActions.onRefresh();
+ }
+
+ render() {
+ return (
+ <ConnectedElementTable onHandleClick={(e, row) => { this.props.history.push(`${ this.props.match.path }/${row.nodeId}`) }} columns={[
+ { property: "nodeId", title: "Name", type: ColumnType.text },
+ { property: "isRequired", title: "Required ?", type: ColumnType.boolean },
+ { property: "host", title: "Host", type: ColumnType.text },
+ { property: "port", title: "Port", type: ColumnType.numeric },
+ { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+ { property: "deviceType", title: "Type", type: ColumnType.text },
+ ]} idProperty="id" {...this.props.connectedNetworkElementsActions} {...this.props.connectedNetworkElementsProperties} asynchronus >
+ </ConnectedElementTable>
+ );
+ }
+}
+
+export const NetworkElementSelector = withRouter(connect(mapProps, mapDispatch)(NetworkElementSelectorComponent));
+export default NetworkElementSelector;
+
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
new file mode 100644
index 000000000..c7ab5e4a3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -0,0 +1,1099 @@
+
+import { Token, Statement, Module, Identity } from "../models/yang";
+import { ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase, isViewElementReference } from "../models/uiModels";
+import { yangService } from "../services/yangService";
+
+export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
+ const pathParts: RegExpMatchArray[] = [];
+ let partMatch: RegExpExecArray | null;
+ if (vPath) do {
+ partMatch = vPathParser.exec(vPath);
+ if (partMatch) {
+ pathParts.push(partMatch);
+ }
+ } while (partMatch)
+ return pathParts;
+}
+
+class YangLexer {
+
+ private pos: number = 0;
+ private buf: string = "";
+
+ constructor(input: string) {
+ this.pos = 0;
+ this.buf = input;
+ }
+
+ private _optable: { [key: string]: string } = {
+ ';': 'SEMI',
+ '{': 'L_BRACE',
+ '}': 'R_BRACE',
+ };
+
+ private _isNewline(char: string): boolean {
+ return char === '\r' || char === '\n';
+ }
+
+ private _isWhitespace(char: string): boolean {
+ return char === ' ' || char === '\t' || this._isNewline(char);
+ }
+
+ private _isDigit(char: string): boolean {
+ return char >= '0' && char <= '9';
+ }
+
+ private _isAlpha(char: string): boolean {
+ return (char >= 'a' && char <= 'z') ||
+ (char >= 'A' && char <= 'Z')
+ }
+
+ private _isAlphanum(char: string): boolean {
+ return this._isAlpha(char) || this._isDigit(char) ||
+ char === '_' || char === '-' || char === '.';
+ }
+
+ private _skipNontokens() {
+ while (this.pos < this.buf.length) {
+ const char = this.buf.charAt(this.pos);
+ if (this._isWhitespace(char)) {
+ this.pos++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ private _processString(terminator: string | null): Token {
+ // this.pos points at the opening quote. Find the ending quote.
+ let end_index = this.pos + 1;
+ while (end_index < this.buf.length) {
+ const char = this.buf.charAt(end_index);
+ if (char === "\\") {
+ end_index += 2;
+ continue;
+ };
+ if (terminator === null && (this._isWhitespace(char) || this._optable[char] !== undefined) || char === terminator) {
+ break;
+ }
+ end_index++;
+ }
+
+ if (end_index >= this.buf.length) {
+ throw Error('Unterminated quote at ' + this.pos);
+ } else {
+ const start = this.pos + (terminator ? 1 : 0);
+ const end = end_index;
+ const tok = {
+ name: 'STRING',
+ value: this.buf.substring(start, end),
+ start,
+ end
+ };
+ this.pos = terminator ? end + 1 : end;
+ return tok;
+ }
+ }
+
+ private _processIdentifier(): Token {
+ let endpos = this.pos + 1;
+ while (endpos < this.buf.length &&
+ this._isAlphanum(this.buf.charAt(endpos))) {
+ endpos++;
+ }
+
+ const tok = {
+ name: 'IDENTIFIER',
+ value: this.buf.substring(this.pos, endpos),
+ start: this.pos,
+ end: endpos
+ };
+ this.pos = endpos;
+ return tok;
+ }
+
+ private _processNumber(): Token {
+ let endpos = this.pos + 1;
+ while (endpos < this.buf.length &&
+ this._isDigit(this.buf.charAt(endpos))) {
+ endpos++;
+ }
+
+ const tok = {
+ name: 'NUMBER',
+ value: this.buf.substring(this.pos, endpos),
+ start: this.pos,
+ end: endpos
+ };
+ this.pos = endpos;
+ return tok;
+ }
+
+ private _processLineComment() {
+ var endpos = this.pos + 2;
+ // Skip until the end of the line
+ while (endpos < this.buf.length && !this._isNewline(this.buf.charAt(endpos))) {
+ endpos++;
+ }
+ this.pos = endpos + 1;
+ }
+
+ private _processBlockComment() {
+ var endpos = this.pos + 2;
+ // Skip until the end of the line
+ while (endpos < this.buf.length && !((this.buf.charAt(endpos) === "/" && this.buf.charAt(endpos - 1) === "*"))) {
+ endpos++;
+ }
+ this.pos = endpos + 1;
+ }
+
+ public tokenize(): Token[] {
+ const result: Token[] = [];
+ this._skipNontokens();
+ while (this.pos < this.buf.length) {
+
+ const char = this.buf.charAt(this.pos);
+ const op = this._optable[char];
+
+ if (op !== undefined) {
+ result.push({ name: op, value: char, start: this.pos, end: ++this.pos });
+ } else if (this._isAlpha(char)) {
+ result.push(this._processIdentifier());
+ this._skipNontokens();
+ const peekChar = this.buf.charAt(this.pos);
+ if (this._optable[peekChar] === undefined) {
+ result.push((peekChar !== "'" && peekChar !== '"')
+ ? this._processString(null)
+ : this._processString(peekChar));
+ }
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === "/") {
+ this._processLineComment();
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === "*") {
+ this._processBlockComment();
+ } else {
+ throw Error('Token error at ' + this.pos + " " + this.buf[this.pos]);
+ }
+ this._skipNontokens();
+ }
+ return result;
+ }
+
+ public tokenize2(): Statement {
+ let stack: Statement[] = [{ key: "ROOT", sub: [] }];
+ let current: Statement | null = null;
+
+ this._skipNontokens();
+ while (this.pos < this.buf.length) {
+
+ const char = this.buf.charAt(this.pos);
+ const op = this._optable[char];
+
+ if (op !== undefined) {
+ if (op === "L_BRACE") {
+ current && stack.unshift(current);
+ current = null;
+ } else if (op === "R_BRACE") {
+ current = stack.shift() || null;
+ }
+ this.pos++;
+ } else if (this._isAlpha(char)) {
+ const key = this._processIdentifier().value;
+ this._skipNontokens();
+ let peekChar = this.buf.charAt(this.pos);
+ let arg = undefined;
+ if (this._optable[peekChar] === undefined) {
+ arg = (peekChar === '"' || peekChar === "'")
+ ? this._processString(peekChar).value
+ : this._processString(null).value;
+ }
+ do {
+ this._skipNontokens();
+ peekChar = this.buf.charAt(this.pos);
+ if (peekChar !== "+") break;
+ this.pos++;
+ this._skipNontokens();
+ peekChar = this.buf.charAt(this.pos);
+ arg += (peekChar === '"' || peekChar === "'")
+ ? this._processString(peekChar).value
+ : this._processString(null).value;
+ } while (true);
+ current = { key, arg, sub: [] };
+ stack[0].sub!.push(current);
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === "/") {
+ this._processLineComment();
+ } else if (char === '/' && this.buf.charAt(this.pos + 1) === "*") {
+ this._processBlockComment();
+ } else {
+ throw Error('Token error at ' + this.pos + " " + this.buf.slice(this.pos - 10, this.pos + 10));
+ }
+ this._skipNontokens();
+ }
+ if (stack[0].key !== "ROOT" || !stack[0].sub![0]) {
+ throw new Error("Internal Perser Error");
+ }
+ return stack[0].sub![0];
+ }
+}
+
+export class YangParser {
+ private _groupingsToResolve: (() => void)[] = [];
+ private _identityToResolve: (() => void)[] = [];
+
+ private _modules: { [name: string]: Module } = {};
+ private _views: ViewSpecification[] = [{
+ id: "0",
+ name: "root",
+ language: "en-US",
+ canEdit: false,
+ parentView: "0",
+ title: "root",
+ elements: {},
+ }];
+
+ constructor() {
+
+ }
+
+ public get modules() {
+ return this._modules;
+ }
+
+ public get views() {
+ return this._views;
+ }
+
+ public async addCapability(capability: string, version?: string) {
+ // do not add twice
+ if (this._modules[capability]) {
+ return;
+ }
+
+ const data = await yangService.getCapability(capability, version);
+ if (!data) {
+ throw new Error(`Could not load yang file for ${capability}.`);
+ }
+
+ const rootStatement = new YangLexer(data).tokenize2();
+
+ if (rootStatement.key !== "module") {
+ throw new Error(`Root element of ${capability} is not a module.`);
+ }
+ if (rootStatement.arg !== capability) {
+ throw new Error(`Root element capability ${rootStatement.arg} does not requested ${capability}.`);
+ }
+
+ const module = this._modules[capability] = {
+ name: rootStatement.arg,
+ revisions: {},
+ imports: {},
+ features: {},
+ identities: {},
+ augments: {},
+ groupings: {},
+ typedefs: {},
+ views: {},
+ elements: {}
+ };
+
+ await this.handleModule(module, rootStatement, capability);
+ }
+
+ private async handleModule(module: Module, rootStatement: Statement, capability: string) {
+
+ // extract namespace && prefix
+ module.namespace = this.extractValue(rootStatement, "namespace");
+ module.prefix = this.extractValue(rootStatement, "prefix");
+ if (module.prefix) {
+ module.imports[module.prefix] = capability;
+ }
+
+ // extract revisions
+ const revisions = this.extractNodes(rootStatement, "revision");
+ module.revisions = {
+ ...module.revisions,
+ ...revisions.reduce<{ [version: string]: { }}>((acc, version) => {
+ if (!version.arg) {
+ throw new Error(`Module [${module.name}] has a version w/o version number.`);
+ }
+ const description = this.extractValue(version, "description");
+ const reference = this.extractValue(version,"reference");
+ acc[version.arg] = {
+ description,
+ reference,
+ };
+ return acc;
+ }, {})
+ };
+
+ // extract features
+ const features = this.extractNodes(rootStatement, "feature");
+ module.features = {
+ ...module.features,
+ ...features.reduce<{ [version: string]: {} }>((acc, feature) => {
+ if (!feature.arg) {
+ throw new Error(`Module [${module.name}] has a feature w/o name.`);
+ }
+ const description = this.extractValue(feature, "description");
+ acc[feature.arg] = {
+ description,
+ };
+ return acc;
+ }, {})
+ };
+
+ // extract imports
+ const imports = this.extractNodes(rootStatement, "import");
+ module.imports = {
+ ...module.imports,
+ ...imports.reduce < { [key: string]: string }>((acc, imp) => {
+ const prefix = imp.sub && imp.sub.filter(s => s.key === "prefix");
+ if (!imp.arg) {
+ throw new Error(`Module [${module.name}] has an import with neither name nor prefix.`);
+ }
+ acc[prefix && prefix.length === 1 && prefix[0].arg || imp.arg] = imp.arg;
+ return acc;
+ }, {})
+ };
+
+ // import all required files
+ if (imports) for (let ind = 0; ind < imports.length; ++ind) {
+ await this.addCapability(imports[ind].arg!);
+ }
+
+ this.extractTypeDefinitions(rootStatement, module, "");
+
+ this.extractIdentites(rootStatement, 0, module, "");
+
+ const groupings = this.extractGroupings(rootStatement, 0, module, "");
+ this._views.push(...groupings);
+
+ const augments = this.extractAugments(rootStatement, 0, module, "");
+ this._views.push(...augments);
+
+ // the default for config on module level is config = true;
+ const [currentView, subViews] = this.extractSubViews(rootStatement, 0, module, "");
+ this._views.push(currentView, ...subViews);
+
+ // create the root elements for this module
+ module.elements = currentView.elements;
+ Object.keys(module.elements).forEach(key => {
+ const viewElement = module.elements[key];
+ if (!isViewElementObjectOrList(viewElement)) {
+ throw new Error(`Module: [${module}]. Only List or Object allowed on root level.`);
+ }
+ const viewIdIndex = Number(viewElement.viewId);
+ module.views[key] = this._views[viewIdIndex];
+ this._views[0].elements[key] = module.elements[key];
+ });
+ return module;
+ }
+
+ public postProcess() {
+ // process all groupings
+ // execute all post processes like resolving in propper order
+ this._groupingsToResolve.forEach(cb => {
+ try { cb(); } catch (error) {
+ console.warn(`Error resolving: [${error.message}]`);
+ }
+ });
+
+ // process all augmentations
+ Object.keys(this.modules).forEach(modKey => {
+ const module = this.modules[modKey];
+ Object.keys(module.augments).forEach(augKey => {
+ const augments = module.augments[augKey];
+ const viewSpec = this.resolveView(augKey);
+ if (!viewSpec) console.warn(`Could not find view to augment [${augKey}] in [${module.name}].`);
+ if (augments && viewSpec) {
+ augments.forEach(augment => Object.keys(augment.elements).forEach(key => {
+ const elm = augment.elements[key];
+ viewSpec.elements[key] = {
+ ...augment.elements[key],
+ when: elm.when ? `(${augment.when}) and (${elm.when})` : augment.when,
+ ifFeature: elm.ifFeature ? `(${augment.ifFeature}) and (${elm.ifFeature})` : augment.ifFeature,
+ };
+ }));
+ }
+ });
+ });
+
+ // process Identities
+ const traverseIdentity = (identities : Identity[]) => {
+ const result: Identity[] = [];
+ for (let identity of identities) {
+ if (identity.children && identity.children.length > 0) {
+ result.push(...traverseIdentity(identity.children));
+ } else {
+ result.push(identity);
+ }
+ }
+ return result;
+ }
+
+
+ const baseIdentites: Identity[] = [];
+ Object.keys(this.modules).forEach(modKey => {
+ const module = this.modules[modKey];
+ Object.keys(module.identities).forEach(idKey => {
+ const identity = module.identities[idKey];
+ if (identity.base != null) {
+ const base = this.resolveIdentity(identity.base, module);
+ base.children?.push(identity);
+ } else {
+ baseIdentites.push(identity);
+ }
+ });
+ });
+ baseIdentites.forEach(identity => {
+ identity.values = identity.children && traverseIdentity(identity.children) || [];
+ });
+
+ this._identityToResolve.forEach(cb => {
+ try { cb(); } catch (error) {
+ console.warn(error.message);
+ }
+ });
+ };
+
+
+ private _nextId = 1;
+ private get nextId() {
+ return this._nextId++;
+ }
+
+ private extractNodes(statement: Statement, key: string): Statement[] {
+ return statement.sub && statement.sub.filter(s => s.key === key) || [];
+ }
+
+ private extractValue(statement: Statement, key: string): string | undefined;
+ private extractValue(statement: Statement, key: string, parser: RegExp): RegExpExecArray | undefined;
+ private extractValue(statement: Statement, key: string, parser?: RegExp): string | RegExpExecArray | undefined {
+ const typeNodes = this.extractNodes(statement, key);
+ const rawValue = typeNodes.length > 0 && typeNodes[0].arg || undefined;
+ return parser
+ ? rawValue && parser.exec(rawValue) || undefined
+ : rawValue;
+ }
+
+ private extractTypeDefinitions(statement: Statement, module: Module, currentPath: string): void {
+ const typedefs = this.extractNodes(statement, "typedef");
+ typedefs && typedefs.forEach(def => {
+ if (! def.arg) {
+ throw new Error(`Module: [${module.name}]. Found typefed without name.`);
+ }
+ module.typedefs[def.arg] = this.getViewElement(def, module, 0, currentPath, false);
+ });
+ }
+
+ /** Handles Goupings like named Container */
+ private extractGroupings(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
+ const subViews: ViewSpecification[] = [];
+ const groupings = this.extractNodes(statement, "grouping");
+ if (groupings && groupings.length > 0) {
+ subViews.push(...groupings.reduce<ViewSpecification[]>((acc, cur) => {
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}][${currentPath}]. Found grouping without name.`);
+ }
+ const grouping = cur.arg;
+
+ // the default for config on module level is config = true;
+ const [currentView, subViews] = this.extractSubViews(cur, parentId, module, currentPath);
+ grouping && (module.groupings[grouping] = currentView);
+ acc.push(currentView, ...subViews);
+ return acc;
+ }, []));
+ }
+
+ return subViews;
+ }
+
+ /** Handles Augmants also like named Container */
+ private extractAugments(statement: Statement, parentId: number, module: Module, currentPath: string): ViewSpecification[] {
+ const subViews: ViewSpecification[] = [];
+ const augments = this.extractNodes(statement, "augment");
+ if (augments && augments.length > 0) {
+ subViews.push(...augments.reduce<ViewSpecification[]>((acc, cur) => {
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}][${currentPath}]. Found augment without path.`);
+ }
+ const augment = this.resolveReferencePath(cur.arg, module);
+
+ // the default for config on module level is config = true;
+ const [currentView, subViews] = this.extractSubViews(cur, parentId, module, currentPath);
+ if (augment) {
+ module.augments[augment] = module.augments[augment] || [];
+ module.augments[augment].push(currentView);
+ }
+ acc.push(currentView, ...subViews);
+ return acc;
+ }, []));
+ }
+
+ return subViews;
+ }
+
+ /** Handles Identities */
+ private extractIdentites(statement: Statement, parentId: number, module: Module, currentPath: string) {
+ const identities = this.extractNodes(statement, "identity");
+ module.identities = identities.reduce<{ [name: string]: Identity }>((acc, cur) => {
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}][${currentPath}]. Found identiy without name.`);
+ }
+ acc[cur.arg] = {
+ id: `${module.name}:${cur.arg}`,
+ label: cur.arg,
+ base: this.extractValue(cur, "base"),
+ description: this.extractValue(cur, "description"),
+ reference: this.extractValue(cur, "reference"),
+ children: []
+ }
+ return acc;
+ }, {});
+ }
+
+ private extractSubViews(statement: Statement, parentId: number, module: Module, currentPath: string): [ViewSpecification, ViewSpecification[]] {
+ const subViews: ViewSpecification[] = [];
+ const currentId = this.nextId;
+ let elements: ViewElement[] = [];
+
+ const configValue = this.extractValue(statement, "config");
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+
+ // extract conditions
+ const ifFeature = this.extractValue(statement, "if-feature");
+ const whenCondition = this.extractValue(statement, "when");
+
+ // extract all container
+ const container = this.extractNodes(statement, "container");
+ if (container && container.length > 0) {
+ subViews.push(...container.reduce<ViewSpecification[]>((acc, cur) => {
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}]. Found container without name.`);
+ }
+ const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
+ elements.push({
+ id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
+ label: cur.arg,
+ uiType: "object",
+ viewId: currentView.id,
+ config: config
+ });
+ acc.push(currentView, ...subViews);
+ return acc;
+ }, []));
+ }
+
+ // process all lists
+ // a list is a list of containers with the leafs contained in the list
+ const lists = this.extractNodes(statement, "list");
+ if (lists && lists.length > 0) {
+ subViews.push(...lists.reduce<ViewSpecification[]>((acc, cur) => {
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}]. Found list without name.`);
+ }
+ const key = this.extractValue(cur, "key") || undefined;
+ if (config && !key) {
+ throw new Error(`Module: [${module.name}]. Found configurable list without key.`);
+ }
+ const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
+ elements.push({
+ id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
+ label: cur.arg,
+ isList: true,
+ uiType: "object",
+ viewId: currentView.id,
+ key: key,
+ config: config
+ });
+ acc.push(currentView, ...subViews);
+ return acc;
+ }, []));
+ }
+
+ // process all leaf-lists
+ // a leaf-list is a list of some type
+ const leafLists = this.extractNodes(statement, "leaf-list");
+ if (leafLists && leafLists.length > 0) {
+ elements.push(...leafLists.reduce<ViewElement[]>((acc, cur) => {
+ const element = this.getViewElement(cur, module, parentId, currentPath, true);
+ element && acc.push(element);
+ return acc;
+ }, []));
+ }
+
+ // process all leafs
+ // a leaf is mainly a property of an object
+ const leafs = this.extractNodes(statement, "leaf");
+ if (leafs && leafs.length > 0) {
+ elements.push(...leafs.reduce<ViewElement[]>((acc, cur) => {
+ const element = this.getViewElement(cur, module, parentId, currentPath, false);
+ element && acc.push(element);
+ return acc;
+ }, []));
+ }
+
+
+ const choiceStms = this.extractNodes(statement, "choice");
+ if (choiceStms && choiceStms.length > 0) {
+ for (let i = 0; i < choiceStms.length; ++i) {
+ const cases = this.extractNodes(choiceStms[i], "case");
+ console.warn(`Choice found ${choiceStms[i].arg}::${cases.map(c => c.arg).join(";")}`, choiceStms[i]);
+ }
+ }
+
+ const rpcs = this.extractNodes(statement, "rpc");
+ if (rpcs && rpcs.length > 0) {
+ // todo:
+ }
+
+ if (!statement.arg) {
+ throw new Error(`Module: [${module.name}]. Found statement without name.`);
+ }
+
+ const viewSpec: ViewSpecification = {
+ id: String(currentId),
+ parentView: String(parentId),
+ name: statement.arg,
+ title: statement.arg,
+ language: "en-us",
+ canEdit: false,
+ ifFeature: ifFeature,
+ when: whenCondition,
+ elements: elements.reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+ acc[cur.id] = cur;
+ return acc;
+ }, {}),
+ };
+
+ // evaluate canEdit depending on all conditions
+ Object.defineProperty(viewSpec, "canEdit", {
+ get: () => {
+ return Object.keys(viewSpec.elements).some(key => {
+ const elm = viewSpec.elements[key];
+ return (!isViewElementObjectOrList(elm) && elm.config);
+ });
+ }
+ });
+
+ // merge in all uses references and resolve groupings
+ const usesRefs = this.extractNodes(statement, "uses");
+ if (usesRefs && usesRefs.length > 0) {
+
+ viewSpec.uses = (viewSpec.uses || []);
+ for (let i = 0; i < usesRefs.length; ++i) {
+ const groupingName = usesRefs[i].arg;
+ if (!groupingName) {
+ throw new Error(`Module: [${module.name}]. Found an uses statement without a grouping name.`);
+ }
+
+ viewSpec.uses.push(this.resolveReferencePath(groupingName, module));
+
+ this._groupingsToResolve.push(() => {
+ const groupingViewSpec = this.resolveGrouping(groupingName, module);
+ if (groupingViewSpec) {
+ Object.keys(groupingViewSpec.elements).forEach(key => {
+ const elm = groupingViewSpec.elements[key];
+ viewSpec.elements[key] = {
+ ...groupingViewSpec.elements[key],
+ when: elm.when ? `(${groupingViewSpec.when}) and (${elm.when})` : groupingViewSpec.when,
+ ifFeature: elm.ifFeature ? `(${groupingViewSpec.ifFeature}) and (${elm.ifFeature})` : groupingViewSpec.ifFeature,
+ };
+ });
+ }
+ });
+ }
+ }
+
+ return [viewSpec, subViews];
+ }
+
+ /** Extracts the UI View from the type in the cur statement. */
+ private getViewElement(cur: Statement, module: Module, parentId: number, currentPath: string, isList: boolean): ViewElement {
+
+ const type = this.extractValue(cur, "type");
+ const defaultVal = this.extractValue(cur, "default") || undefined;
+ const description = this.extractValue(cur, "description") || undefined;
+ const rangeMatch = this.extractValue(cur, "range", /^(\d+)\.\.(\d+)/) || undefined;
+
+ const configValue = this.extractValue(cur, "config");
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+
+ const mandatory = this.extractValue(cur, "mandatory") === "true" || false;
+
+ if (!cur.arg) {
+ throw new Error(`Module: [${module.name}]. Found element without name.`);
+ }
+
+ if (!type) {
+ throw new Error(`Module: [${module.name}].[${cur.arg}]. Found element without type.`);
+ }
+
+ const element: ViewElementBase = {
+ id: parentId === 0 ? `${module.name}:${cur.arg}`: cur.arg,
+ label: cur.arg,
+ config: config,
+ mandatory: mandatory,
+ isList: isList,
+ default: defaultVal,
+ description: description
+ };
+
+ if (type === "string") {
+ return ({
+ ...element,
+ uiType: "string",
+ pattern: this.extractNodes(this.extractNodes(cur, "type")[0]!, "pattern").map(p => p.arg!).filter(p => !!p),
+ });
+ } else if (type === "boolean") {
+ return ({
+ ...element,
+ uiType: "boolean"
+ });
+ } else if (type === "uint8") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +255,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "uint16") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +65535,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "uint32") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +4294967295,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "uint64") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "int8") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : -128,
+ max: rangeMatch ? Number(rangeMatch[1]) : +127,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "int16") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : -32768,
+ max: rangeMatch ? Number(rangeMatch[1]) : +32767,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "int32") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : -2147483648,
+ max: rangeMatch ? Number(rangeMatch[1]) : +2147483647,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "int64") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ });
+ } else if (type === "decimal16") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
+ });
+ } else if (type === "decimal32") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
+ });
+ } else if (type === "decimal64") {
+ return ({
+ ...element,
+ uiType: "number",
+ min: rangeMatch ? Number(rangeMatch[0]) : 0,
+ max: rangeMatch ? Number(rangeMatch[1]) : +18446744073709551615,
+ units: this.extractValue(cur, "units") || undefined,
+ format: this.extractValue(cur, "format") || undefined,
+ fDigits: Number(this.extractValue(this.extractNodes(cur, "type")[0]!, "fraction-digits")) || -1
+ });
+ } else if (type === "enumeration") {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const enumNodes = this.extractNodes(typeNode, "enum");
+ return ({
+ ...element,
+ uiType: "selection",
+ options: enumNodes.reduce<{ key: string; value: string; description?: string }[]>((acc, enumNode) => {
+ if (!enumNode.arg) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found option without name.`);
+ }
+ const ifClause = this.extractValue(enumNode, "if-feature");
+ const value = this.extractValue(enumNode, "value");
+ const enumOption = {
+ key: enumNode.arg,
+ value: value != null ? value : enumNode.arg,
+ description: this.extractValue(enumNode, "description") || undefined
+ };
+ // todo: ❗ handle the if clause ⚡
+ acc.push(enumOption);
+ return acc;
+ }, [])
+ });
+ } else if (type === "leafref") {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const vPath = this.extractValue(typeNode, "path");
+ if (!vPath) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found leafref without path.`);
+ }
+ const refPath = this.resolveReferencePath(vPath, module);
+ const resolve = this.resolveReference.bind(this);
+ const res : ViewElement = {
+ ...element,
+ uiType: "reference",
+ referencePath: refPath,
+ ref(this: ViewElement, currentPath: string) {
+ const resolved = resolve(refPath, currentPath);
+ return resolved && {
+ ...resolved,
+ id: this.id,
+ label: this.label,
+ config: this.config,
+ mandatory: this.mandatory,
+ isList: this.isList,
+ default: this.default,
+ description: this.description,
+ } as ViewElement;
+ }
+ };
+ return res;
+ } else if (type === "identityref") {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const base = this.extractValue(typeNode, "base");
+ if (!base) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found identityref without base.`);
+ }
+ const res: ViewElement = {
+ ...element,
+ uiType: "selection",
+ options: []
+ };
+ this._identityToResolve.push(() => {
+ const identity : Identity = this.resolveIdentity(base, module);
+ if (!identity) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Could not resolve identity [${base}].`);
+ }
+ if (!identity.values || identity.values.length === 0) {
+ throw new Error(`Identity: [${base}] has no values.`);
+ }
+ res.options = identity.values.map(val => ({
+ key: val.id,
+ value: val.id,
+ description: val.description
+ }));
+ });
+ return res ;
+ } else if (type === "empty") {
+ // todo: ❗ handle empty ⚡
+ /* 9.11. The empty Built-In Type
+ The empty built-in type represents a leaf that does not have any
+ value, it conveys information by its presence or absence. */
+ console.warn(`found type: empty in [${module.name}][${currentPath}][${element.label}]`);
+ return {
+ ...element,
+ uiType: "string",
+ };
+ } else if (type === "union") {
+ // todo: ❗ handle union ⚡
+ /* 9.12. The union Built-In Type */
+ console.warn(`found type: union in [${module.name}][${currentPath}][${element.label}]`);
+ return {
+ ...element,
+ uiType: "string",
+ };
+ } else if (type === "bits") {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const bitNodes = this.extractNodes(typeNode, "bit");
+ return {
+ ...element,
+ uiType: "bits",
+ flags: bitNodes.reduce<{[name: string]: number | undefined; }>((acc, bitNode) => {
+ if (!bitNode.arg) {
+ throw new Error(`Module: [${module.name}][${currentPath}][${cur.arg}]. Found bit without name.`);
+ }
+ const ifClause = this.extractValue(bitNode, "if-feature");
+ const pos = Number(this.extractValue(bitNode, "position"));
+ acc[bitNode.arg] = pos === pos ? pos : undefined;
+ return acc;
+ }, {})
+ };
+ } else if (type === "binary") {
+ const typeNode = this.extractNodes(cur, "type")[0]!;
+ const length = Number(this.extractValue(typeNode, "length"));
+ return {
+ ...element,
+ uiType: "binary",
+ length: length === length ? length : undefined
+ };
+ } else {
+ // not a build in type, have to resolve type
+ const typeRef = this.resolveType(type, module);
+ if (typeRef == null) console.error(new Error(`Could not resolve type ${type} in [${module.name}][${currentPath}].`));
+ return ({
+ ...typeRef,
+ ...element,
+ description: description
+ }) as ViewElement;
+ }
+ }
+
+ private resolveReferencePath(vPath: string, module: Module) {
+ const vPathParser = /(?:(?:([^\/\:]+):)?([^\/]+))/g // 1 = opt: namespace / 2 = property
+ return vPath.replace(vPathParser, (_, ns, property) => {
+ const nameSpace = ns && module.imports[ns] || module.name;
+ return `${nameSpace}:${property}`;
+ });
+ }
+
+
+ private resolveReference(vPath: string, currentPath: string) {
+ const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+ let element : ViewElement | null = null;
+ let moduleName = "";
+
+ const vPathParts = splitVPath(vPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }));
+ const resultPathParts = !vPath.startsWith("/")
+ ? splitVPath(currentPath, vPathParser).map(p => ({ ns: p[1], property: p[2], ind: p[3] }))
+ : [];
+
+ for (let i = 0; i < vPathParts.length; ++i){
+ const vPathPart = vPathParts[i];
+ if (vPathPart.property === "..") {
+ resultPathParts.pop();
+ } else if (vPathPart.property !== ".") {
+ resultPathParts.push(vPathPart);
+ }
+ }
+
+ // resolve element by path
+ for (let j = 0; j < resultPathParts.length;++j){
+ const pathPart = resultPathParts[j];
+ if (j===0) {
+ moduleName = pathPart.ns;
+ const rootModule = this._modules[moduleName];
+ if (!rootModule) throw new Error("Could not resolve module [" + moduleName +"].\r\n" + vPath);
+ element = rootModule.elements[`${pathPart.ns}:${pathPart.property}`];
+ } else if (element && isViewElementObjectOrList(element)) {
+ const view: ViewSpecification = this._views[+element.viewId];
+ if (moduleName !== pathPart.ns) {
+ moduleName = pathPart.ns;
+ element = view.elements[`${moduleName}:${pathPart.property}`];
+ } else {
+ element = view.elements[pathPart.property] || view.elements[`${moduleName}:${pathPart.property}`];
+ }
+ } else {
+ throw new Error("Could not resolve reference.\r\n" + vPath);
+ }
+ if (!element) throw new Error("Could not resolve path [" + pathPart.property + "] in ["+ currentPath +"] \r\n" + vPath);
+ }
+
+ return element;
+ }
+
+ private resolveView(vPath: string) {
+ const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g // 1 = opt: namespace / 2 = property / 3 = opt: indexPath
+ let element: ViewElement | null = null;
+ let partMatch: RegExpExecArray | null;
+ let view: ViewSpecification | null = null;
+ let moduleName = "";
+ if (vPath) do {
+ partMatch = vPathParser.exec(vPath);
+ if (partMatch) {
+ if (element === null) {
+ moduleName = partMatch[1]!;
+ const rootModule = this._modules[moduleName];
+ if (!rootModule) return null;
+ element = rootModule.elements[`${moduleName}:${partMatch[2]!}`];
+ } else if (isViewElementObjectOrList(element)) {
+ view = this._views[+element.viewId];
+ if (moduleName !== partMatch[1]) {
+ moduleName = partMatch[1];
+ element = view.elements[`${moduleName}:${partMatch[2]}`];
+ } else {
+ element = view.elements[partMatch[2]];
+ }
+ } else {
+ return null;
+ }
+ if (!element) return null;
+ }
+ } while (partMatch)
+ return element && isViewElementObjectOrList(element) && this._views[+element.viewId] || null;
+ }
+
+ private resolveType(type: string, module: Module) {
+ const collonInd = type.indexOf(":");
+ const preFix = collonInd > -1 ? type.slice(0, collonInd) : "";
+ const typeName = collonInd > -1 ? type.slice(collonInd + 1) : type;
+
+ const res = preFix
+ ? this._modules[module.imports[preFix]].typedefs[typeName]
+ : module.typedefs[typeName];
+ return res;
+ }
+
+ private resolveGrouping(grouping: string, module: Module) {
+ const collonInd = grouping.indexOf(":");
+ const preFix = collonInd > -1 ? grouping.slice(0, collonInd) : "";
+ const groupingName = collonInd > -1 ? grouping.slice(collonInd + 1) : grouping;
+
+ return preFix
+ ? this._modules[module.imports[preFix]].groupings[groupingName]
+ : module.groupings[groupingName];
+
+ }
+
+ private resolveIdentity(identity: string, module: Module) {
+ const collonInd = identity.indexOf(":");
+ const preFix = collonInd > -1 ? identity.slice(0, collonInd) : "";
+ const identityName = collonInd > -1 ? identity.slice(collonInd + 1) : identity;
+
+ return preFix
+ ? this._modules[module.imports[preFix]].identities[identityName]
+ : module.identities[identityName];
+
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/configurationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/configurationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..48f7dde3d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="configurationApp"/>
+ <property name="index" value="30"/>
+ </bean>
+</blueprint>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/configurationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..edf68e096
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/configurationApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/configurationApp/tsconfig.json b/sdnr/wt/odlux/apps/configurationApp/tsconfig.json
new file mode 100644
index 000000000..b0c9b424d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/tsconfig.json
@@ -0,0 +1,38 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "node",
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/configurationApp/webpack.config.js b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
new file mode 100644
index 000000000..6a5c5d55e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/configurationApp/webpack.config.js
@@ -0,0 +1,158 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ configurationApp: ["./pluginConfiguration.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/yang-schema/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/websocket": {
+ target: "http://10.20.6.29:48181",
+ ws: true,
+ changeOrigin: false,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/.babelrc b/sdnr/wt/odlux/apps/connectApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json
new file mode 100644
index 000000000..04653d520
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/connect-app",
+ "version": "0.1.1",
+ "description": "A react based modular UI to display network connect data from a database.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/pom.xml b/sdnr/wt/odlux/apps/connectApp/pom.xml
new file mode 100644
index 000000000..f52fa1111
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-connectApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-connectApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
new file mode 100644
index 000000000..bf4778b5b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/commonNetworkElementsActions.ts
@@ -0,0 +1,113 @@
+// update action erstellen, die unterscheiden kann, ob die eine oder die andere Ansicht gerade aktive ist und diese katualisiert.
+// Diese action wird dann bei jeder aktualisierung in den anderen Actions und bei eintreffen von notifikationen verwendet.
+
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { networkElementsReloadAction } from '../handlers/networkElementsHandler';
+import { connectionStatusLogReloadAction } from '../handlers/connectionStatusLogHandler';
+
+import { PanelId } from '../models/panelId';
+import { guiCutThrough } from '../models/guiCutTrough';
+import connectService from '../services/connectService';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+
+export class SetPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
+
+export class AddWebUriList extends Action {
+ constructor(public element: guiCutThrough[], public knownElements: string[]) {
+ super();
+ }
+}
+
+export class RemoveWebUri extends Action {
+ constructor(public element: string) {
+ super();
+ }
+}
+
+export const removeWebUriAction = (nodeId: string) => {
+ return new RemoveWebUri(nodeId);
+}
+
+let isBusy = false;
+export const findWebUrisForGuiCutThroughAsyncAction = (dispatcher: Dispatch) => (networkElements: NetworkElementConnection[], knownElements: string[]) => {
+
+ // keep method from executing simultanously; state not used because change of iu isn't needed
+ if (isBusy)
+ return;
+ isBusy = true;
+
+ const nodeIds = networkElements.map(element => { return element.id as string });
+
+ if (knownElements.length > 0) {
+
+ let elementsToSearch: string[] = [];
+
+ nodeIds.forEach(element => {
+ // find index of nodeId
+ const index = knownElements.indexOf(element);
+
+ // if element dosen't exist, add it to list
+ if (index === -1) {
+ elementsToSearch.push(element)
+ }
+ });
+
+ // if new elements were found, search for weburi
+ if (elementsToSearch.length > 0) {
+ const foundWebUris = connectService.getAllWebUriExtensionsForNetworkElementListAsync(elementsToSearch);
+ foundWebUris.then(result => {
+ dispatcher(new AddWebUriList(result, elementsToSearch));
+ isBusy = false;
+ })
+
+ } else {
+ isBusy = false;
+ }
+
+ } else {
+ connectService.getAllWebUriExtensionsForNetworkElementListAsync(nodeIds).then(result => {
+ dispatcher(new AddWebUriList(result, nodeIds));
+ isBusy = false;
+ })
+ }
+}
+
+export const setPanelAction = (panelId: PanelId) => {
+ return new SetPanelAction(panelId);
+}
+
+export const updateCurrentViewAsyncAction = () => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const { connect: { currentOpenPanel } } = getState();
+ if (currentOpenPanel === "NetworkElements") {
+ return dispatch(networkElementsReloadAction);
+ }
+ else {
+ return dispatch(connectionStatusLogReloadAction);
+ }
+};
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
new file mode 100644
index 000000000..4ae28aab2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/infoNetworkElementActions.ts
@@ -0,0 +1,57 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { TopologyNode } from '../models/topologyNetconf';
+import { connectService } from '../services/connectService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load all element Yang capabilities.
+ */
+export class LoadAllElementInfoAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to update element Yang capabilities.
+ */
+export class AllElementInfoLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ * @param elementInfo The information of the element which is returned.
+ */
+ constructor(public elementInfo: TopologyNode | null, public error?: string) {
+ super();
+ }
+}
+
+/**
+ * Represents an asynchronous thunk action to load all yang capabilities.
+ */
+export const loadAllInfoElementAsync = (nodeId: string) => (dispatch: Dispatch) => {
+ dispatch(new LoadAllElementInfoAction());
+ connectService.infoNetworkElement(nodeId).then(info => {
+ dispatch(new AllElementInfoLoadedAction(info));
+ }, error => {
+ dispatch(new AllElementInfoLoadedAction(null, error));
+ });
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
new file mode 100644
index 000000000..84e73ae5a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { connectService } from '../services/connectService';
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an action crator for a async thunk action to mount a network element. */
+export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkElementConnection) => (dispatch: Dispatch) => {
+ return connectService.mountNetworkElement(networkElement).then((success) => {
+ if (success) {
+ dispatch(updateCurrentViewAsyncAction());
+ dispatch(new AddSnackbarNotification({ message: `Requesting mount [${networkElement.nodeId}]`, options: { variant: 'info' } }))
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'warning' } }));
+ }
+ }).catch(error => {
+ dispatch(new AddSnackbarNotification({ message: `Failed to mount [${networkElement.nodeId}]`, options: { variant: 'error' } }));
+ console.error(error);
+ });
+};
+
+/** Represents an action crator for a async thunk action to unmount a network element. */
+export const unmountNetworkElementAsyncActionCreator = (nodeId: string) => (dispatch: Dispatch) => {
+ return connectService.unmountNetworkElement(nodeId).then((success) => {
+ if (success) {
+ dispatch(updateCurrentViewAsyncAction());
+ dispatch(new AddSnackbarNotification({ message: `Requesting unmount [${nodeId}]`, options: { variant: 'info' } }));
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'warning' } }));
+ }
+ }).catch(error => {
+ dispatch(new AddSnackbarNotification({ message: `Failed to unmount [${nodeId}]`, options: { variant: 'error' } }));
+ console.error(error);
+ });
+};
+
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
new file mode 100644
index 000000000..1a86f94b1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { connectService } from '../services/connectService';
+import { updateCurrentViewAsyncAction } from './commonNetworkElementsActions';
+import { unmountNetworkElementAsyncActionCreator } from './mountedNetworkElementsActions';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an async thunk action creator to add an element to the network elements. */
+export const addNewNetworkElementAsyncActionCreator = (element: NetworkElementConnection) => async (dispatch: Dispatch) => {
+ const res = await connectService.createNetworkElement({ ...element });
+ dispatch(updateCurrentViewAsyncAction());
+ dispatch(new AddSnackbarNotification({ message: `Successfully added [${element.nodeId}]`, options: { variant: 'success' } }));
+};
+
+/** Represents an async thunk action creator to edit network element. */
+export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
+ const connectionStatus: ConnectionStatus[] = await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne)) || [];
+ const currentConnectionStatus = connectionStatus[0].status;
+ if (currentConnectionStatus === "Disconnected") {
+ const res = await connectService.deleteNetworkElement(element);
+ }
+ else {
+ const res = await connectService.updateNetworkElement(element);
+ }
+ dispatch(updateCurrentViewAsyncAction());
+ dispatch(new AddSnackbarNotification({ message: `Successfully modified [${element.id}]`, options: { variant: 'success' } }));
+};
+
+
+/** Represents an async thunk action creator to delete an element from network elements. */
+export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
+ const res = await connectService.deleteNetworkElement(element);
+ await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id));
+ dispatch(updateCurrentViewAsyncAction());
+};
+
+
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
new file mode 100644
index 000000000..4e5ca65e1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -0,0 +1,52 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+import { createConnectionStatusLogActions, createConnectionStatusLogProperties } from '../handlers/connectionStatusLogHandler';
+import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ connectionStatusLogProperties: createConnectionStatusLogProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch),
+});
+
+const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<NetworkElementConnectionLog>;
+
+type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
+
+class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps> {
+ render(): JSX.Element {
+ return (
+ <ConnectionStatusTable tableId="connection-status-table" columns={[
+ { property: "timestamp", title: "Time", type: ColumnType.text },
+ { property: "nodeId", title: "Node Name", type: ColumnType.text },
+ { property: "status", title: "Connection status", type: ColumnType.text },
+ ]} idProperty="id" {...this.props.connectionStatusLogActions} {...this.props.connectionStatusLogProperties} >
+ </ConnectionStatusTable>
+ );
+ };
+}
+
+export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent);
+export default ConnectionStatusLog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
new file mode 100644
index 000000000..1e1f11523
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -0,0 +1,252 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import {
+ editNetworkElementAsyncActionCreator,
+ addNewNetworkElementAsyncActionCreator,
+ removeNetworkElementAsyncActionCreator
+} from '../actions/networkElementsActions';
+
+import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
+import { NetworkElementConnection, UpdateNetworkElement } from '../models/networkElementConnection';
+import { removeWebUriAction } from '../actions/commonNetworkElementsActions';
+
+export enum EditNetworkElementDialogMode {
+ None = "none",
+ EditNetworkElement = "editNetworkElement",
+ RemoveNetworkElement = "removeNetworkElement",
+ AddNewNetworkElement = "addNewNetworkElement",
+ MountNetworkElement = "mountNetworkElement",
+ UnmountNetworkElement = "unmountNetworkElement",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ addNewNetworkElement: async (element: NetworkElementConnection) => {
+ await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element));
+ await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element));
+ },
+ mountNetworkElement: (element: NetworkElementConnection) => dispatcher.dispatch(mountNetworkElementAsyncActionCreator(element)),
+ unmountNetworkElement: (element: NetworkElementConnection) => {
+ dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId));
+ },
+ editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => {
+ await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
+ await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
+ },
+ removeNetworkElement: (element: UpdateNetworkElement) => {
+ dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
+ dispatcher.dispatch(removeWebUriAction(element.id));
+ }
+});
+
+type DialogSettings = {
+ dialogTitle: string,
+ dialogDescription: string,
+ applyButtonText: string,
+ cancelButtonText: string,
+ enableMountIdEditor: boolean,
+ enableUsernameEditor: boolean,
+ enableExtendedEditor: boolean,
+}
+
+const settings: { [key: string]: DialogSettings } = {
+ [EditNetworkElementDialogMode.None]: {
+ dialogTitle: "",
+ dialogDescription: "",
+ applyButtonText: "",
+ cancelButtonText: "",
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ },
+
+ [EditNetworkElementDialogMode.AddNewNetworkElement]: {
+ dialogTitle: "Add new network element",
+ dialogDescription: "Add this new network element:",
+ applyButtonText: "Add network element",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: true,
+ enableUsernameEditor: true,
+ enableExtendedEditor: true,
+ },
+ [EditNetworkElementDialogMode.MountNetworkElement]: {
+ dialogTitle: "Mount network element",
+ dialogDescription: "mount this network element:",
+ applyButtonText: "mount network element",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ },
+ [EditNetworkElementDialogMode.UnmountNetworkElement]: {
+ dialogTitle: "Unmount network element",
+ dialogDescription: "unmount this network element:",
+ applyButtonText: "Unmount network element",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ },
+ [EditNetworkElementDialogMode.EditNetworkElement]: {
+ dialogTitle: "Modify the network elements",
+ dialogDescription: "Modify this network element",
+ applyButtonText: "Modify",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableUsernameEditor: true,
+ enableExtendedEditor: false,
+ },
+ [EditNetworkElementDialogMode.RemoveNetworkElement]: {
+ dialogTitle: "Remove network element",
+ dialogDescription: "Do you really want to remove this network element:",
+ applyButtonText: "Remove network element",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableUsernameEditor: false,
+ enableExtendedEditor: false,
+ }
+}
+
+type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: EditNetworkElementDialogMode;
+ initialNetworkElement: NetworkElementConnection;
+ onClose: () => void;
+};
+
+type EditNetworkElementDialogComponentState = NetworkElementConnection;
+
+class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
+ constructor(props: EditNetworkElementDialogComponentProps) {
+ super(props);
+
+ this.state = {
+ nodeId: this.props.initialNetworkElement.nodeId,
+ isRequired: false,
+ host: this.props.initialNetworkElement.host,
+ port: this.props.initialNetworkElement.port,
+ };
+ }
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ return (
+ <Dialog open={this.props.mode !== EditNetworkElementDialogMode.None}>
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
+ <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="netconfport" label="NetConf port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} onChange={(event) => { this.setState({ port: +event.target.value }); }} />
+ {setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
+ {setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="password" label="Password" aria-label="password" type="password" fullWidth value={this.state.password} onChange={(event) => { this.setState({ password: event.target.value }); }} /> || null}
+ <FormControl fullWidth disabled={!setting.enableUsernameEditor}>
+ <InputLabel htmlFor="active">Required</InputLabel>
+ <Select value={this.state.isRequired || false} onChange={(event) => {
+ this.setState({ isRequired: event.target.value as any as boolean });
+ }} inputProps={{ name: 'required', id: 'required' }} fullWidth >
+ <MenuItem value={true as any as string} >True</MenuItem>
+ <MenuItem value={false as any as string} >False</MenuItem>
+ </Select>
+ </FormControl>
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={(event) => {
+ this.onApply({
+ isRequired: this.state.isRequired,
+ id: this.state.nodeId,
+ nodeId: this.state.nodeId,
+ host: this.state.host,
+ port: this.state.port,
+ username: this.state.username,
+ password: this.state.password,
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }} > {setting.applyButtonText} </Button>
+ <Button onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ private onApply = (element: NetworkElementConnection) => {
+ this.props.onClose && this.props.onClose();
+ let updateElement: UpdateNetworkElement = {
+ id: this.state.nodeId
+ }
+ switch (this.props.mode) {
+ case EditNetworkElementDialogMode.AddNewNetworkElement:
+ element && this.props.addNewNetworkElement(element);
+ break;
+ case EditNetworkElementDialogMode.MountNetworkElement:
+ element && this.props.mountNetworkElement(element);
+ break;
+ case EditNetworkElementDialogMode.UnmountNetworkElement:
+ element && this.props.unmountNetworkElement(element);
+ break;
+ case EditNetworkElementDialogMode.EditNetworkElement:
+ if (this.props.initialNetworkElement.isRequired !== this.state.isRequired)
+ updateElement.isRequired = this.state.isRequired;
+ if (this.props.initialNetworkElement.username !== this.state.username)
+ updateElement.username = this.state.username;
+ if (this.props.initialNetworkElement.password !== this.state.password)
+ updateElement.password = this.state.password;
+ element && this.props.editNetworkElement(updateElement, element);
+ break;
+ case EditNetworkElementDialogMode.RemoveNetworkElement:
+ element && this.props.removeNetworkElement(updateElement);
+ break;
+ }
+ };
+
+ private onCancel = () => {
+ this.props.onClose && this.props.onClose();
+ }
+
+ static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } {
+ if (props.initialNetworkElement !== state._initialNetworkElement) {
+ state = {
+ ...state,
+ ...props.initialNetworkElement,
+ _initialNetworkElement: props.initialNetworkElement,
+ };
+ }
+ return state;
+ }
+}
+
+export const EditNetworkElementDialog = connect(undefined, mapDispatch)(EditNetworkElementDialogComponent);
+export default EditNetworkElementDialog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
new file mode 100644
index 000000000..ea9d419ec
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
@@ -0,0 +1,154 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import { AvailableCapabilities } from '../models/yangCapabilitiesType'
+
+export enum InfoNetworkElementDialogMode {
+ None = "none",
+ InfoNetworkElement = "infoNetworkElement"
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+});
+
+type DialogSettings = {
+ dialogTitle: string,
+ dialogDescription: string,
+ cancelButtonText: string,
+}
+
+const settings: { [key: string]: DialogSettings } = {
+ [InfoNetworkElementDialogMode.None]: {
+ dialogTitle: "",
+ dialogDescription: "",
+ cancelButtonText: "",
+ },
+ [InfoNetworkElementDialogMode.InfoNetworkElement]: {
+ dialogTitle: "Yang capabilities of the network element",
+ dialogDescription: "Available capabilities of the network element",
+ cancelButtonText: "Cancel",
+ }
+}
+
+type InfoNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: InfoNetworkElementDialogMode;
+ initialNetworkElement: NetworkElementConnection;
+ onClose: () => void;
+};
+
+type InfoNetworkElementDialogComponentState = NetworkElementConnection;
+
+class InfoNetworkElementDialogComponent extends React.Component<InfoNetworkElementDialogComponentProps, InfoNetworkElementDialogComponentState> {
+ constructor(props: InfoNetworkElementDialogComponentProps) {
+ super(props);
+
+ this.state = {
+ nodeId: this.props.initialNetworkElement.nodeId,
+ isRequired: false,
+ host: this.props.initialNetworkElement.host,
+ port: this.props.initialNetworkElement.port,
+ };
+ }
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ const availableCapabilities = this.props.state.connect.elementInfo.elementInfo["netconf-node-topology:available-capabilities"]["available-capability"];
+ let yangCapabilities: AvailableCapabilities[] = [];
+
+ availableCapabilities.forEach(value => {
+ const capabilty = value.capability;
+ const indexRevision = capabilty.indexOf("revision=");
+ const indexModule = capabilty.indexOf(")", indexRevision);
+ if (indexRevision > 0 && indexModule > 0) {
+ yangCapabilities.push({
+ module: capabilty.substr(indexModule + 1),
+ revision: capabilty.substr(indexRevision + 9, 10)
+ });
+ }
+ });
+
+ return (
+ <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None}>
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription + " " + this.state.nodeId}
+ </DialogContentText>
+ <Table >
+ <TableHead>
+ <TableRow>
+ <TableCell align="right">S.No</TableCell>
+ <TableCell >Module</TableCell>
+ <TableCell >Revision</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {yangCapabilities.map((yang, index) => (
+ <TableRow>
+ <TableCell>{index + 1}</TableCell>
+ <TableCell>{yang.module}</TableCell>
+ <TableCell>{yang.revision}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ private onCancel = () => {
+ this.props.onClose();
+ }
+
+ static getDerivedStateFromProps(props: InfoNetworkElementDialogComponentProps, state: InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): InfoNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } {
+ if (props.initialNetworkElement !== state._initialNetworkElement) {
+ state = {
+ ...state,
+ ...props.initialNetworkElement,
+ _initialNetworkElement: props.initialNetworkElement,
+ };
+ }
+ return state;
+ }
+}
+
+export const InfoNetworkElementDialog = connect(undefined, mapDispatch)(InfoNetworkElementDialogComponent);
+export default InfoNetworkElementDialog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
new file mode 100644
index 000000000..0f4b0e8ff
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -0,0 +1,259 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+import * as React from 'react';
+import { Theme, createStyles, withStyles, WithStyles } from '@material-ui/core/styles';
+
+import AddIcon from '@material-ui/icons/Add';
+import LinkIcon from '@material-ui/icons/Link';
+import LinkOffIcon from '@material-ui/icons/LinkOff';
+import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
+import EditIcon from '@material-ui/icons/Edit';
+import Info from '@material-ui/icons/Info';
+import ComputerIcon from '@material-ui/icons/Computer';
+
+import Button from '@material-ui/core/Button';
+import IconButton from '@material-ui/core/IconButton';
+import Tooltip from '@material-ui/core/Tooltip';
+
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { connect, Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+import { createNetworkElementsActions, createNetworkElementsProperties } from '../handlers/networkElementsHandler';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import EditNetworkElementDialog, { EditNetworkElementDialogMode } from './editNetworkElementDialog';
+
+import InfoNetworkElementDialog, { InfoNetworkElementDialogMode } from './infoNetworkElementDialog';
+import { loadAllInfoElementAsync } from '../actions/infoNetworkElementActions';
+import { TopologyNode } from '../models/topologyNetconf';
+
+const styles = (theme: Theme) => createStyles({
+ connectionStatusConnected: {
+ color: 'darkgreen',
+ },
+ connectionStatusConnecting: {
+ color: 'blue',
+ },
+ connectionStatusDisconnected: {
+ color: 'red',
+ },
+ button: {
+ margin: 0,
+ padding: "6px 6px",
+ minWidth: 'unset'
+ },
+ spacer: {
+ marginLeft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ display: "inline"
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ networkElementsProperties: createNetworkElementsProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ networkElementsActions: createNetworkElementsActions(dispatcher.dispatch),
+ navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+ networkElementInfo: async (nodeId: string) => await dispatcher.dispatch(loadAllInfoElementAsync(nodeId)),
+});
+
+type NetworkElementsListComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
+type NetworkElementsListComponentState = {
+ networkElementToEdit: NetworkElementConnection,
+ networkElementEditorMode: EditNetworkElementDialogMode,
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode,
+ elementInfo: TopologyNode | null
+}
+
+const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false };
+
+const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
+
+export class NetworkElementsListComponent extends React.Component<NetworkElementsListComponentProps, NetworkElementsListComponentState> {
+
+ constructor(props: NetworkElementsListComponentProps) {
+ super(props);
+
+ this.state = {
+ networkElementToEdit: emptyRequireNetworkElement,
+ networkElementEditorMode: EditNetworkElementDialogMode.None,
+ elementInfo: null,
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None
+ };
+ }
+
+ // private navigationCreator
+
+ render(): JSX.Element {
+ const { classes } = this.props;
+ const { networkElementToEdit } = this.state;
+ const addRequireNetworkElementAction = {
+ icon: AddIcon, tooltip: 'Add', onClick: () => {
+ this.setState({
+ networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
+ networkElementToEdit: emptyRequireNetworkElement,
+ });
+ }
+ };
+ let counter = 0;
+ return (
+ <>
+ <NetworkElementTable tableId="network-element-table" customActionButtons={[addRequireNetworkElementAction]} columns={[
+ { property: "nodeId", title: "Node Name", type: ColumnType.text },
+ { property: "isRequired", title: "Required", type: ColumnType.boolean },
+ { property: "status", title: "Connection Status", type: ColumnType.text },
+ { property: "host", title: "Host", type: ColumnType.text },
+ { property: "port", title: "Port", type: ColumnType.numeric },
+ { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+ { property: "deviceType", title: "Type", type: ColumnType.text },
+ {
+ property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => {
+ counter++;
+ return (
+ <>
+ <div className={classes.spacer}>
+ {
+ rowData.webUri && <Tooltip title={"Web Client"} ><IconButton aria-label={"web-client-button-" + counter} className={classes.button} onClick={event => { console.log(rowData); window.open(rowData.webUri, "_blank") }}><ComputerIcon /></IconButton></Tooltip>
+ }
+ <Tooltip title={"Mount"} >
+ <IconButton aria-label={"mount-button-" + counter} className={classes.button} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} >
+ <LinkIcon /></IconButton>
+ </Tooltip>
+ <Tooltip title={"Unmount"} >
+ <IconButton aria-label={"unmount-button-" + counter} className={classes.button} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} >
+ <LinkOffIcon /></IconButton>
+ </Tooltip>
+ <Tooltip title={"Info"} ><IconButton aria-label={"info-button-" + counter} className={classes.button} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} >
+ <Info /></IconButton>
+ </Tooltip>
+ <Tooltip title={"Edit"} ><IconButton aria-label={"edit-button-" + counter} className={classes.button} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)} ><EditIcon /></IconButton></Tooltip>
+ <Tooltip title={"Remove"} ><IconButton aria-label={"remove-button-" + counter} className={classes.button} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /></IconButton></Tooltip>
+ </div>
+ <div className={classes.spacer}>
+ <Tooltip title={"Inventory"} ><Button aria-label={"inventory-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("inventory", rowData)} >I</Button></Tooltip>
+ </div>
+ <div className={classes.spacer}>
+ <Tooltip title={"Fault"} ><Button aria-label={"fault-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("fault", rowData)} >F</Button></Tooltip>
+ <Tooltip title={"Configure"} ><Button aria-label={"configure-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("configuration", rowData)} >C</Button></Tooltip>
+ <Tooltip title={"Accounting "} ><Button className={classes.button} onClick={this.navigateToApplicationHandlerCreator("accounting", rowData)} disabled={true} >A</Button></Tooltip>
+ <Tooltip title={"Performance"} ><Button aria-label={"performance-button-" + counter} className={classes.button} onClick={this.navigateToApplicationHandlerCreator("performanceHistory", rowData)}>P</Button></Tooltip>
+ <Tooltip title={"Security"} ><Button className={classes.button} onClick={this.navigateToApplicationHandlerCreator("security", rowData)} disabled={true} >S</Button></Tooltip>
+ </div>
+ </>
+ )
+ }
+ },
+ ]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus >
+ </NetworkElementTable>
+ <EditNetworkElementDialog
+ initialNetworkElement={networkElementToEdit}
+ mode={this.state.networkElementEditorMode}
+ onClose={this.onCloseEditNetworkElementDialog}
+ />
+ <InfoNetworkElementDialog
+ initialNetworkElement={networkElementToEdit}
+ mode={this.state.infoNetworkElementEditorMode}
+ onClose={this.onCloseInfoNetworkElementDialog}
+ />
+ </>
+ );
+ };
+
+ public componentDidMount() {
+ this.props.networkElementsActions.onRefresh();
+ }
+
+ private onOpenRemoveNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ this.setState({
+ networkElementToEdit: element,
+ networkElementEditorMode: EditNetworkElementDialogMode.RemoveNetworkElement
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ private onOpenEditNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ this.setState({
+ networkElementToEdit: {
+ nodeId: element.nodeId,
+ isRequired: element.isRequired,
+ host: element.host,
+ port: element.port,
+ username: element.username,
+ password: element.password,
+ },
+ networkElementEditorMode: EditNetworkElementDialogMode.EditNetworkElement
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ private onOpenUnmountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ this.setState({
+ networkElementToEdit: element,
+ networkElementEditorMode: EditNetworkElementDialogMode.UnmountNetworkElement
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ private onOpenMountdNetworkElementsDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ this.setState({
+ networkElementToEdit: element,
+ networkElementEditorMode: EditNetworkElementDialogMode.MountNetworkElement
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ private onOpenInfoNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
+ this.props.networkElementInfo(element.nodeId);
+ this.setState({
+ networkElementToEdit: element,
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.InfoNetworkElement,
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ private onCloseEditNetworkElementDialog = () => {
+ this.setState({
+ networkElementEditorMode: EditNetworkElementDialogMode.None,
+ networkElementToEdit: emptyRequireNetworkElement,
+ });
+ }
+ private onCloseInfoNetworkElementDialog = () => {
+ this.setState({
+ infoNetworkElementEditorMode: InfoNetworkElementDialogMode.None,
+ networkElementToEdit: emptyRequireNetworkElement,
+ });
+ }
+
+ private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementConnection) => (event: React.MouseEvent<HTMLElement>) => {
+ this.props.navigateToApplication(applicationName, element.nodeId);
+ event.preventDefault();
+ event.stopPropagation();
+ }
+}
+
+export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent));
+export default NetworkElementsList; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
new file mode 100644
index 000000000..1440599fd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
@@ -0,0 +1,83 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+import { INetworkElementsState, networkElementsActionHandler } from './networkElementsHandler';
+import { IConnectionStatusLogState, connectionStatusLogActionHandler } from './connectionStatusLogHandler';
+import { IInfoNetworkElementsState, infoNetworkElementsActionHandler } from './infoNetworkElementHandler';
+import { SetPanelAction, AddWebUriList, RemoveWebUri } from '../actions/commonNetworkElementsActions';
+import { PanelId } from '../models/panelId';
+import { guiCutThrough } from '../models/guiCutTrough';
+
+export interface IConnectAppStoreState {
+ networkElements: INetworkElementsState;
+ connectionStatusLog: IConnectionStatusLogState;
+ currentOpenPanel: PanelId;
+ elementInfo: IInfoNetworkElementsState;
+ guiCutThrough: guiCutThroughState;
+}
+
+const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+}
+
+interface guiCutThroughState {
+ availableWebUris: guiCutThrough[];
+ knownElements: string[];
+}
+
+const guiCutThroughHandler: IActionHandler<guiCutThroughState> = (state = { availableWebUris: [], knownElements: [] }, action) => {
+ if (action instanceof AddWebUriList) {
+ let knownElements: string[];
+ let availableWebUris: guiCutThrough[];
+
+ knownElements = state.knownElements.concat(action.knownElements);
+
+ availableWebUris = state.availableWebUris.concat(action.element);
+
+ state = { availableWebUris: availableWebUris, knownElements: knownElements }
+
+ } else if (action instanceof RemoveWebUri) {
+ const nodeId = action.element;
+ const webUris = state.availableWebUris.filter(item => item.nodeId !== nodeId);
+ const knownElements = state.knownElements.filter(item => item !== nodeId);
+ state = { knownElements: knownElements, availableWebUris: webUris };
+ }
+ return state;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ connect: IConnectAppStoreState
+ }
+}
+
+const actionHandlers = {
+ networkElements: networkElementsActionHandler,
+ connectionStatusLog: connectionStatusLogActionHandler,
+ currentOpenPanel: currentOpenPanelHandler,
+ elementInfo: infoNetworkElementsActionHandler,
+ guiCutThrough: guiCutThroughHandler
+};
+
+export const connectAppRootHandler = combineActionHandler<IConnectAppStoreState>(actionHandlers);
+export default connectAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
new file mode 100644
index 000000000..6863ec33b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusLogHandler.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnectionLog } from '../models/networkElementConnectionLog';
+export interface IConnectionStatusLogState extends IExternalTableState<NetworkElementConnectionLog> { }
+
+// create eleactic search material data fetch handler
+const connectionStatusLogSearchHandler = createSearchDataHandler<NetworkElementConnectionLog>('connectionlog');
+
+export const {
+ actionHandler: connectionStatusLogActionHandler,
+ createActions: createConnectionStatusLogActions,
+ createProperties: createConnectionStatusLogProperties,
+ reloadAction: connectionStatusLogReloadAction,
+
+ // set value action, to change a value
+} = createExternal<NetworkElementConnectionLog>(connectionStatusLogSearchHandler, appState => appState.connect.connectionStatusLog);
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
new file mode 100644
index 000000000..d67a81ec4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/infoNetworkElementHandler.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllElementInfoLoadedAction, LoadAllElementInfoAction } from '../actions/infoNetworkElementActions';
+
+import { TopologyNode } from '../models/topologyNetconf';
+
+export interface IInfoNetworkElementsState {
+ elementInfo: TopologyNode;
+ busy: boolean;
+}
+
+const infoNetworkElementsStateInit: IInfoNetworkElementsState = {
+ elementInfo: {
+ "node-id": "",
+ "netconf-node-topology:available-capabilities": {
+ "available-capability": []
+ }
+ },
+ busy: false
+};
+
+export const infoNetworkElementsActionHandler: IActionHandler<IInfoNetworkElementsState> = (state = infoNetworkElementsStateInit, action) => {
+ if (action instanceof LoadAllElementInfoAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+ } else if (action instanceof AllElementInfoLoadedAction) {
+ if (!action.error && action.elementInfo) {
+ state = {
+ ...state,
+ elementInfo: action.elementInfo,
+ busy: false
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
new file mode 100644
index 000000000..78c7000d2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/handlers/networkElementsHandler.ts
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+import connectService from '../services/connectService';
+import { requestRest } from '../../../../framework/src/services/restService';
+export interface INetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
+
+// create eleactic search material data fetch handler
+const networkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection');
+
+export const {
+ actionHandler: networkElementsActionHandler,
+ createActions: createNetworkElementsActions,
+ createProperties: createNetworkElementsProperties,
+ reloadAction: networkElementsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<NetworkElementConnection>(networkElementsSearchHandler, appState => {
+
+ const webUris = appState.connect.guiCutThrough.availableWebUris;
+ if (appState.connect.networkElements.rows && webUris.length > 0) {
+
+ appState.connect.networkElements.rows.forEach(element => {
+
+ if (element.status === "Connected") {
+ const webUri = webUris.find(item => item.nodeId === element.id as string);
+ if (webUri) {
+ element.webUri = webUri.webUri;
+ element.isWebUriUnreachable = false;
+ }
+ else {
+ element.isWebUriUnreachable = true
+ }
+ }
+ });
+ }
+
+ return appState.connect.networkElements
+});
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/index.html b/sdnr/wt/odlux/apps/connectApp/src/index.html
new file mode 100644
index 000000000..9c8a2063e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <link rel="stylesheet" href="./vendor.css">
+ <title>connectApp</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "connectApp", "faultApp", "inventoryApp", "configurationApp"], function (app, connectApp, faultApp, inventoryApp, configurationApp) {
+ connectApp.register();
+ faultApp.register();
+ inventoryApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
new file mode 100644
index 000000000..df43c217a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusLog.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type ConnectionStatusLogType = {
+ _id: string;
+ elementStatus: string;
+ timeStamp: string;
+ objectId: string;
+ type: string;
+ newValue: string;
+}
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
new file mode 100644
index 000000000..4b443bac8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/guiCutTrough.ts
@@ -0,0 +1 @@
+export type guiCutThrough = { webUri: string, nodeId: string } \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
new file mode 100644
index 000000000..39278a8e1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementBase.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type NetworkElementBaseType = {
+ mountId: string,
+ host: string,
+ port: number,
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
new file mode 100644
index 000000000..4c2dc9b09
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -0,0 +1,36 @@
+export type NetworkElementConnection = {
+ id?: string;
+ nodeId: string;
+ isRequired: boolean;
+ host: string;
+ port: number;
+ username?: string;
+ password?: string;
+ webUri?: string;
+ isWebUriUnreachable?: boolean;
+ status?: "Connected" | "mounted" | "unmounted" | "Connecting" | "Disconnected" | "idle";
+ coreModelCapability?: string;
+ deviceType?: string;
+ nodeDetails?: {
+ availableCapabilites: {
+ capabilityOrigin: string;
+ capability: string;
+ }[];
+ unavailableCapabilities: {
+ failureReason: string;
+ capability: string;
+ }[];
+ }
+}
+
+
+export type UpdateNetworkElement = {
+ id: string;
+ isRequired?: boolean;
+ username?: string;
+ password?: string;
+}
+
+export type ConnectionStatus = {
+ status: string
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
new file mode 100644
index 000000000..a1535cbe5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnectionLog.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnectionLog = {
+ id: string;
+ nodeId: string;
+ status: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ timestamp: string;
+}
+
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
new file mode 100644
index 000000000..b51412055
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/panelId.ts
@@ -0,0 +1 @@
+export type PanelId = null | "NetworkElements" | "ConnectionStatusLog"; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
new file mode 100644
index 000000000..694009d1b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/topologyNetconf.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export interface AvailableCapability {
+ "capability-origin": string;
+ capability: string;
+}
+
+export interface NetconfNodeTopologyAvailableCapabilities {
+ "available-capability": AvailableCapability[];
+}
+
+export interface TopologyNode {
+ "node-id": string;
+ "netconf-node-topology:available-capabilities": NetconfNodeTopologyAvailableCapabilities;
+}
+
+export interface Topology {
+ "topology-id": string;
+ node: TopologyNode[];
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
new file mode 100644
index 000000000..230468287
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/yangCapabilitiesType.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type AvailableCapabilities = {
+ module: string,
+ revision: string
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
new file mode 100644
index 000000000..f711c440c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { faPlug } from '@fortawesome/free-solid-svg-icons';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
+
+import connectAppRootHandler from './handlers/connectAppRootHandler';
+import ConnectApplication from './views/connectView';
+
+import { AddSnackbarNotification } from '../../../framework/src/actions/snackbarActions';
+import { updateCurrentViewAsyncAction } from './actions/commonNetworkElementsActions';
+
+type ObjectNotification = {
+ counter: string;
+ nodeName: string;
+ objectId: string;
+ timeStamp: string;
+}
+
+export function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: "connect",
+ icon: faPlug,
+ rootComponent: ConnectApplication,
+ rootActionHandler: connectAppRootHandler,
+ menuEntry: "Connect"
+ });
+
+ // subscribe to the websocket notifications
+ subscribe<ObjectNotification & IFormatedMessage>(["ObjectCreationNotification", "ObjectDeletionNotification", "AttributeValueChangedNotification"], (msg => {
+ const store = applicationApi.applicationStore;
+ if (msg && msg.notifType === "ObjectCreationNotification" && store) {
+ store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg.objectId}]`, options: { variant: 'info' } }));
+ } else if (msg && (msg.notifType === "ObjectDeletionNotification" || msg.notifType === "AttributeValueChangedNotification") && store) {
+ store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg.objectId}]`, options: { variant: 'info' } }));
+ }
+ store && store.dispatch(updateCurrentViewAsyncAction());
+ }));
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
new file mode 100644
index 000000000..7a410f4ae
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
@@ -0,0 +1,208 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { requestRest } from '../../../../framework/src/services/restService';
+import { NetworkElementConnection, ConnectionStatus, UpdateNetworkElement } from '../models/networkElementConnection';
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { Topology, TopologyNode } from '../models/topologyNetconf';
+import { guiCutThrough } from '../models/guiCutTrough';
+
+/**
+* Represents a web api accessor service for all Network Elements actions.
+*/
+class ConnectService {
+
+ /**
+ * Inserts a network elements.
+ */
+ public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
+ const path = `/restconf/operations/data-provider:create-network-element-connection`;
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Updates a network element.
+ */
+ public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const path = `/restconf/operations/data-provider:update-network-element-connection`;
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ input: element }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /**
+ * Deletes a network element.
+ */
+ public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
+ const query = {
+ "id": element.id
+ };
+ const path = `/restconf/operations/data-provider:delete-network-element-connection`;
+ const result = await requestRest<NetworkElementConnection>(path, {
+ method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase))
+ });
+ return result || null;
+ }
+
+ /** Mounts network element. */
+ public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
+ const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + networkElement.nodeId;
+ const mountXml = [
+ '<node xmlns="urn:TBD:params:xml:ns:yang:network-topology">',
+ `<node-id>${networkElement.nodeId}</node-id>`,
+ `<host xmlns="urn:opendaylight:netconf-node-topology">${networkElement.host}</host>`,
+ `<port xmlns="urn:opendaylight:netconf-node-topology">${networkElement.port}</port>`,
+ `<username xmlns="urn:opendaylight:netconf-node-topology">${networkElement.username}</username>`,
+ `<password xmlns="urn:opendaylight:netconf-node-topology">${networkElement.password}</password>`,
+ ' <tcp-only xmlns="urn:opendaylight:netconf-node-topology">false</tcp-only>',
+
+ ' <!-- non-mandatory fields with default values, you can safely remove these if you do not wish to override any of these values-->',
+ ' <reconnect-on-changed-schema xmlns="urn:opendaylight:netconf-node-topology">false</reconnect-on-changed-schema>',
+ ' <connection-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">20000</connection-timeout-millis>',
+ ' <max-connection-attempts xmlns="urn:opendaylight:netconf-node-topology">100</max-connection-attempts>',
+ ' <between-attempts-timeout-millis xmlns="urn:opendaylight:netconf-node-topology">2000</between-attempts-timeout-millis>',
+ ' <sleep-factor xmlns="urn:opendaylight:netconf-node-topology">1.5</sleep-factor>',
+
+ ' <!-- keepalive-delay set to 0 turns off keepalives-->',
+ ' <keepalive-delay xmlns="urn:opendaylight:netconf-node-topology">120</keepalive-delay>',
+ '</node>'].join('');
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ body: mountXml
+ });
+ // expect an empty answer
+ return result !== null;
+ } catch {
+ return false;
+ }
+ };
+
+ /** Unmounts a network element by its id. */
+ public async unmountNetworkElement(nodeId: string): Promise<boolean> {
+ const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + nodeId;
+
+ try {
+ const result = await requestRest<string>(path, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'application/xml',
+ 'Accept': 'application/xml'
+ },
+ });
+ // expect an empty answer
+ return result !== null;
+
+ } catch {
+ return false;
+ }
+ };
+
+ /** Yang capabilities of the selected network elements. */
+ public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
+ const path = 'restconf/operational/network-topology:network-topology/topology/topology-netconf/node/' + nodeId;
+ const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
+
+ return topologyRequestPomise && topologyRequestPomise.then(result => {
+ return result && result.node && result.node[0] || null;
+ });
+ }
+
+ /**
+ * Get the connection state of the network element.
+ */
+ public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
+ const path = `/restconf/operations/data-provider:read-network-element-connection-list`;
+ const query = {
+ "input": {
+ "filter": [{
+ "property": "node-id",
+ "filtervalue": element
+ }],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ }
+ const result = await requestRest<Result<ConnectionStatus>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result.output && result.output.data && result.output.data.map(ne => ({
+ status: ne.status
+ })) || null;
+ }
+
+ public async getWebUriExtensionForNetworkElementAsync(ne: string) {
+ const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + ne + '/yang-ext:mount/core-model:network-element';
+ try {
+ const result = await requestRest<any>(path, { method: "GET" });
+
+ if (result['network-element'].extension) {
+ const webUri = result['network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+ if (webUri) {
+ return webUri.value as string;
+ }
+ }
+ } catch (error) {
+ console.log(ne + ' unrechable: ' + error)
+ }
+
+ return undefined;
+
+ }
+
+ public getAllWebUriExtensionsForNetworkElementListAsync(ne: string[]) {
+
+ let promises: any[] = [];
+ let webUris: guiCutThrough[] = []
+
+ ne.forEach(nodeId => {
+ const path = 'restconf/config/network-topology:network-topology/topology/topology-netconf/node/' + nodeId + '/yang-ext:mount/core-model:network-element';
+
+ // add search request to array
+ promises.push(requestRest<any>(path, { method: "GET" })
+ .then(result => {
+
+ if (result['network-element'] && result['network-element'].extension) {
+ const webUri = result['network-element'].extension.find((item: any) => item['value-name'] === "webUri")
+ if (webUri) {
+ webUris.push({ webUri: webUri.value, nodeId: nodeId });
+ }
+ }
+ })
+ .catch(error => console.log("network element is unreachable: " + error)))
+
+ })
+
+ // wait until all promises are done and return weburis
+ return Promise.all(promises).then(result => { return webUris });
+ }
+
+}
+export const connectService = new ConnectService();
+export default connectService;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
new file mode 100644
index 000000000..aa3391c47
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -0,0 +1,111 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { Panel } from '../../../../framework/src/components/material-ui';
+import { networkElementsReloadAction, createNetworkElementsActions } from '../handlers/networkElementsHandler';
+import { connectionStatusLogReloadAction, createConnectionStatusLogActions } from '../handlers/connectionStatusLogHandler';
+
+import { NetworkElementsList } from '../components/networkElements';
+import { ConnectionStatusLog } from '../components/connectionStatusLog';
+import { setPanelAction, findWebUrisForGuiCutThroughAsyncAction } from '../actions/commonNetworkElementsActions';
+import { PanelId } from '../models/panelId';
+import { NetworkElementConnection } from 'models/networkElementConnection';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ panelId: state.connect.currentOpenPanel,
+ user: state.framework.authenticationState.user,
+ netWorkElements: state.connect.networkElements,
+ availableGuiCutroughs: state.connect.guiCutThrough
+});
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+ networkElementsActions: createNetworkElementsActions(dispatcher.dispatch),
+ connectionStatusLogActions: createConnectionStatusLogActions(dispatcher.dispatch),
+ onLoadNetworkElements: () => {
+ dispatcher.dispatch(networkElementsReloadAction);
+ },
+ loadWebUris: findWebUrisForGuiCutThroughAsyncAction(dispatcher.dispatch),
+ onLoadConnectionStatusLog: () => {
+ dispatcher.dispatch(connectionStatusLogReloadAction);
+ },
+ switchActivePanel: (panelId: PanelId) => {
+ dispatcher.dispatch(setPanelAction(panelId));
+ }
+});
+
+type ConnectApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatcher>;
+
+class ConnectApplicationComponent extends React.Component<ConnectApplicationComponentProps>{
+
+ componentDidUpdate = () => {
+ // search for guicutthroughs after networkelements were found
+ const networkElements = this.props.netWorkElements;
+ const guiCuttrough = this.props.availableGuiCutroughs;
+
+ if (networkElements.rows.length > 0 && networkElements.total !== guiCuttrough.knownElements.length) {
+ this.props.loadWebUris(networkElements.rows, guiCuttrough.knownElements);
+ }
+ }
+
+ private onTogglePanel = (panelId: PanelId) => {
+ const nextActivePanel = panelId === this.props.panelId ? null : panelId;
+ this.props.switchActivePanel(nextActivePanel);
+
+ switch (nextActivePanel) {
+ case 'NetworkElements':
+ this.props.onLoadNetworkElements();
+ break;
+ case 'ConnectionStatusLog':
+ this.props.onLoadConnectionStatusLog();
+ break;
+ case null:
+ // do nothing if all panels are closed
+ break;
+ default:
+ console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView");
+ break;
+ }
+
+ };
+
+ render(): JSX.Element {
+ const { panelId } = this.props;
+
+ return (
+ <>
+ <Panel activePanel={panelId} panelId={'NetworkElements'} onToggle={this.onTogglePanel} title={"Network Elements"}>
+ <NetworkElementsList />
+ </Panel>
+ <Panel activePanel={panelId} panelId={'ConnectionStatusLog'} onToggle={this.onTogglePanel} title={"Connection Status Log"}>
+ <ConnectionStatusLog />
+ </Panel>
+ </>
+ );
+ };
+ public componentDidMount() {
+ this.onTogglePanel("NetworkElements");
+ this.props.networkElementsActions.onToggleFilter();
+ this.props.connectionStatusLogActions.onToggleFilter();
+ }
+}
+
+export const ConnectApplication = (connect(mapProps, mapDispatcher)(ConnectApplicationComponent));
+export default ConnectApplication; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..adc9b777b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="connectApp"/>
+ <property name="index" value="0"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..edf68e096
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/tsconfig.json b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/connectApp/webpack.config.js b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
new file mode 100644
index 000000000..6d70b04b0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/connectApp/webpack.config.js
@@ -0,0 +1,153 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ connectApp: ["./pluginConnect.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/websocket": {
+ target: "http://10.20.6.29:28181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/.babelrc b/sdnr/wt/odlux/apps/demoApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json
new file mode 100644
index 000000000..f692d69ed
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/demo-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI framework",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/pom.xml b/sdnr/wt/odlux/apps/demoApp/pom.xml
new file mode 100644
index 000000000..8cffb9e7a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-demoApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-demoApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
new file mode 100644
index 000000000..f75075192
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/actions/authorActions.ts
@@ -0,0 +1,51 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
+
+import { IAuthor } from '../models/author';
+import { authorService } from '../services/authorService';
+
+export class ApplicationBaseAction extends Action { }
+
+
+export class LoadAllAuthorsAction extends ApplicationBaseAction {
+ constructor() {
+ super();
+ }
+}
+
+// in React Action is most times a Message
+export class AllAuthorsLoadedAction extends ApplicationBaseAction {
+ constructor(public authors: IAuthor[] | null, public error?: string) {
+ super();
+
+ }
+}
+
+export const loadAllAuthorsAsync = (dispatch: Dispatch) => {
+ dispatch(new LoadAllAuthorsAction());
+ authorService.getAllAuthors().then(authors => {
+ dispatch(new AllAuthorsLoadedAction(authors));
+ }, error => {
+ dispatch(new AllAuthorsLoadedAction(null, error));
+ dispatch(new AddErrorInfoAction(error));
+ });
+}
+
diff --git a/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
new file mode 100644
index 000000000..b47fa4507
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/components/counter.tsx
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+export class Counter extends React.Component<{}, { counter: number }> {
+ constructor(props: {}) {
+ super(props);
+
+ this.state = {
+ counter: 0
+ };
+ }
+
+ render() {
+ return (
+ <button onClick={ () => this.setState({ counter: this.state.counter + 1 }) }>{ this.state.counter }</button>
+ )
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
new file mode 100644
index 000000000..9ff8450c8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/demoAppRootHandler.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { listAuthorsHandler, IListAuthors } from './listAuthorsHandler';
+import { editAuthorHandler, IEditAuthor } from './editAuthorHandler';
+
+export interface IDemoAppStoreState {
+ listAuthors: IListAuthors;
+ editAuthor: IEditAuthor;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ demo: IDemoAppStoreState
+ }
+}
+
+const actionHandlers = {
+ listAuthors: listAuthorsHandler,
+ editAuthor: editAuthorHandler,
+};
+
+export const demoAppRootHandler = combineActionHandler <IDemoAppStoreState>(actionHandlers);
+export default demoAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
new file mode 100644
index 000000000..34b533cb1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/editAuthorHandler.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IAuthor } from '../models/author';
+export interface IEditAuthor {
+ author: IAuthor | null;
+ isDirty: boolean;
+}
+
+const editAuthorInit: IEditAuthor = {
+ author: null,
+ isDirty: false
+};
+
+export const editAuthorHandler: IActionHandler<IEditAuthor> = (state = editAuthorInit, action) => {
+ return state;
+};
diff --git a/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
new file mode 100644
index 000000000..ca2b6d3c6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/handlers/listAuthorsHandler.ts
@@ -0,0 +1,57 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IAuthor } from '../models/author';
+import { LoadAllAuthorsAction, AllAuthorsLoadedAction } from '../actions/authorActions';
+
+export interface IListAuthors {
+ authors: IAuthor[];
+ busy: boolean;
+}
+
+const listAuthorsInit: IListAuthors = {
+ authors: [],
+ busy: false
+};
+
+export const listAuthorsHandler: IActionHandler<IListAuthors> = (state = listAuthorsInit, action) => {
+ if (action instanceof LoadAllAuthorsAction) {
+
+ state = {
+ ...state,
+ busy: true
+ };
+
+ } else if (action instanceof AllAuthorsLoadedAction) {
+ if (!action.error && action.authors) {
+ state = {
+ ...state,
+ authors: action.authors,
+ busy: false
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/index.html b/sdnr/wt/odlux/apps/demoApp/src/index.html
new file mode 100644
index 000000000..e85bcbb03
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>Demo App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app","demoApp"], function (app, demoApp) {
+ demoApp.register();
+ app("./app.tsx");
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src/models/author.ts b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
new file mode 100644
index 000000000..0aaa308a2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/models/author.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents an author.
+ */
+export interface IAuthor {
+ /**
+ * Defines the unique id of the autor.
+ */
+ id: number;
+
+ /**
+ * Defines the first name of this author.
+ */
+ firstName: string;
+
+ /**
+ * Defines the last name of this author.
+ */
+ lastName: string;
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
new file mode 100644
index 000000000..4d67c28ac
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/plugin.tsx
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faAddressBook, faRegistered } from '@fortawesome/free-solid-svg-icons';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import connect, { Connect } from '../../../framework/src/flux/connect';
+
+import { demoAppRootHandler } from './handlers/demoAppRootHandler';
+
+import AuthorsList from './views/authorsList';
+import EditAuthor from './views/editAuthor';
+
+import { Counter } from './components/counter';
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+ <Switch>
+ <Route exact path={ `${ props.match.path }/authors` } component={AuthorsList} />
+ <Route path={ `${ props.match.path }/authors/:authorId` } component={EditAuthor } />
+ <Redirect to={ `${ props.match.path }/authors` } />
+ </Switch>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: "demo",
+ icon: faAddressBook,
+ rootComponent: FinalApp,
+ rootActionHandler: demoAppRootHandler,
+ exportedComponents: { counter: Counter },
+ menuEntry: "Demo"
+ });
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
new file mode 100644
index 000000000..13e4b316c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/services/authorService.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IAuthor } from '../models/author';
+
+import * as $ from 'jquery';
+
+const base_url = 'https://api.mfico.de/v1/authors';
+
+/**
+ * Represents a web api accessor service for all author related actions.
+ */
+class AuthorService {
+
+ /**
+ * Gets all known authors from the backend.
+ * @returns A promise of the type array of @see {@link IAuthor} containing all known authors.
+ */
+ public getAllAuthors(): Promise<IAuthor[]> {
+ return new Promise((resolve: (value: IAuthor[]) => void, reject: (err: any) => void) => {
+ $.ajax({ method: "GET", url: base_url })
+ .then((data) => { resolve(data); }, (err) => { reject(err) });
+ });
+ }
+
+ /**
+ * Gets an author by its id from the backend.
+ * @returns A promise of the type @see {@link IAuthor} containing the author to get.
+ */
+ public getAuthorById(id: string | number): Promise<IAuthor> {
+ return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
+ $.ajax({ method: "GET", url: base_url + "/" + id })
+ .then((data) => { resolve(data); }, (err) => { reject(err) });
+ });
+ }
+
+
+/**
+ * Saves the given author to the backend api.
+ * @returns A promise of the type @see {@link IAuthor} containing the autor returned by the backend api.
+ */
+ public saveAuthor(author: IAuthor): Promise<IAuthor> {
+ return new Promise((resolve: (value: IAuthor) => void, reject: (err: any) => void) => {
+ // simulate server save
+ window.setTimeout(() => {
+ if (Math.random() > 0.8) {
+ reject("Could not save author.");
+ } else {
+ resolve(author);
+ }
+ }, 800); // simulate a short network delay
+ });
+ }
+}
+
+// return as a singleton
+export const authorService = new AuthorService();
+export default authorService;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
new file mode 100644
index 000000000..3d0651b49
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/authorsList.tsx
@@ -0,0 +1,87 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import Paper from '@material-ui/core/Paper'; // means border
+
+import connect from '../../../../framework/src/flux/connect';
+
+import { loadAllAuthorsAsync } from '../actions/authorActions';
+import { IAuthor } from '../models/author';
+
+interface IAuthorsListProps {
+ authors: IAuthor[],
+ busy: boolean,
+ onLoadAllAuthors: () => void
+}
+
+class AuthorsListComponent extends React.Component<RouteComponentProps & IAuthorsListProps> {
+
+ render(): JSX.Element {
+ const { authors, busy } = this.props;
+ return (
+ <Paper>
+ <Table >
+ <TableHead>
+ <TableRow>
+ <TableCell align="right">Id</TableCell>
+ <TableCell >First Name</TableCell>
+ <TableCell >Last Name</TableCell>
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {authors.map(author => (
+ <TableRow key={author.id} onClick={(e) => this.editAuthor(author)}>
+ <TableCell>{author.id}</TableCell>
+ <TableCell>{author.firstName}</TableCell>
+ <TableCell>{author.lastName}</TableCell>
+ </TableRow>
+ ))}
+ </TableBody>
+ </Table>
+ </Paper>
+ );
+ };
+
+ public componentDidMount() {
+ this.props.onLoadAllAuthors();
+ }
+
+ private editAuthor = (author: IAuthor) => {
+ author && this.props.history.push(this.props.match.path + '/' + author.id);
+ };
+}
+
+export const AuthorsList = withRouter(
+ connect(
+ ({ demo: state }) => ({
+ authors: state.listAuthors.authors,
+ busy: state.listAuthors.busy
+ }),
+ (dispatcher) => ({
+ onLoadAllAuthors: () => {
+ dispatcher.dispatch(loadAllAuthorsAsync)
+ }
+ }))(AuthorsListComponent));
+export default AuthorsList;
diff --git a/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
new file mode 100644
index 000000000..92f671234
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src/views/editAuthor.tsx
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+type EditAuthorProps = RouteComponentProps<{ authorId: string}>;
+
+class EditAuthorComponent extends React.Component<EditAuthorProps> {
+ render(): JSX.Element {
+ return (
+ <div>
+ <h2>Edit Author { this.props.match.params.authorId }</h2>
+ </div>
+ )
+ }
+}
+
+export const EditAuthor = withRouter(EditAuthorComponent);
+export default EditAuthor; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..91f6002ac
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="demoApp"/>
+ <property name="index" value="999"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/demoApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..edf68e096
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/demoApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/demoApp/tsconfig.json b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/demoApp/webpack.config.js b/sdnr/wt/odlux/apps/demoApp/webpack.config.js
new file mode 100644
index 000000000..61dd8f6f6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/demoApp/webpack.config.js
@@ -0,0 +1,134 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ demoApp: ["./plugin.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/api": {
+ target: "http://localhost:3001",
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/.babelrc b/sdnr/wt/odlux/apps/eventLogApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/package.json b/sdnr/wt/odlux/apps/eventLogApp/package.json
new file mode 100644
index 000000000..2594debc1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/eventlog-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to display event log from a database.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Sai Neetha Phulmali",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/pom.xml b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
new file mode 100644
index 000000000..9e369ee62
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-eventLogApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-eventLogApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts b/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts
new file mode 100644
index 000000000..6e2d40efd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogAppRootHandler.ts
@@ -0,0 +1,45 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// ** do not remove **
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { IEventLogState, eventLogActionHandler } from './eventLogHandler';
+
+
+export interface IEventLogAppStateState {
+ logEntries: IEventLogState
+}
+
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ eventLog: IEventLogAppStateState;
+ }
+}
+
+const actionHandlers = {
+ logEntries: eventLogActionHandler
+};
+
+export const EventLogAppRootHandler = combineActionHandler<IEventLogAppStateState>(actionHandlers);
+export default EventLogAppRootHandler;
+
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx
new file mode 100644
index 000000000..300a8f7b3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/handlers/eventLogHandler.tsx
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { EventLogType } from '../models/eventLogType';
+
+export interface IEventLogState extends IExternalTableState<EventLogType> { }
+
+// create eleactic search material data fetch handler
+const eventLogSearchHandler = createSearchDataHandler<EventLogType>("eventlog");
+
+export const {
+ actionHandler: eventLogActionHandler,
+ createActions: createEventLogActions,
+ createProperties: createEventLogProperties,
+ reloadAction: eventLogReloadAction,
+
+ // set value action, to change a value
+} = createExternal<EventLogType>(eventLogSearchHandler, appState => appState.eventLog.logEntries);
+
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/index.html b/sdnr/wt/odlux/apps/eventLogApp/src/index.html
new file mode 100644
index 000000000..8027509e6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>EventLog App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app","connectApp", "eventLogApp"], function (app, connectApp, eventLogApp) {
+ connectApp.register();
+ eventLogApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/models/eventLogType.ts b/sdnr/wt/odlux/apps/eventLogApp/src/models/eventLogType.ts
new file mode 100644
index 000000000..7c68e6497
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/models/eventLogType.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+export type EventLogType = {
+ nodeId: string;
+ counter: number;
+ timestamp: string;
+ objectId: string;
+ attributeName: string;
+ newValue: string;
+ sourceType: string;
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx
new file mode 100644
index 000000000..a2edb436f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/pluginEventLog.tsx
@@ -0,0 +1,40 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { faBookOpen } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { EventLog } from './views/eventLog';
+import eventLogAppRootHandler from './handlers/eventLogAppRootHandler';
+
+const App : React.SFC = (props) => {
+ return <EventLog />
+};
+
+export function register() {
+ applicationManager.registerApplication({
+ name: "eventLog",
+ icon: faBookOpen,
+ rootActionHandler: eventLogAppRootHandler,
+ rootComponent: App,
+ menuEntry: "EventLog"
+ });
+}
+
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
new file mode 100644
index 000000000..535de1f1d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
@@ -0,0 +1,59 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+import { EventLogType } from '../models/eventLogType';
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { createEventLogProperties, createEventLogActions } from "../handlers/eventLogHandler";
+
+const EventLogTable = MaterialTable as MaterialTableCtorType<EventLogType & {_id: string}>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ eventLogProperties: createEventLogProperties(state),
+ eventLog: state.eventLog.logEntries
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ eventLogActions: createEventLogActions(dispatcher.dispatch)
+});
+
+class EventLogComponent extends React.Component<Connect<typeof mapProps, typeof mapDispatch>> {
+ render() {
+ return <EventLogTable title="Event Log" idProperty="_id" columns={[
+ { property: "nodeId", title: "Node Name" },
+ { property: "counter", title: "Counter" },
+ { property: "timestamp", title: "Timestamp" },
+ { property: "objectId", title: "Object ID" },
+ { property: "attributeName", title: "Attribute Name" },
+ { property: "newValue", title: "Message" },
+ { property: "sourceType", title: "Source" }
+ ]} {...this.props.eventLogActions} {...this.props.eventLogProperties} >
+ </EventLogTable>
+ }
+
+ componentDidMount() {
+ this.props.eventLogActions.onToggleFilter();
+ this.props.eventLogActions.onHandleRequestSort("node-id");
+ }
+}
+
+export const EventLog = connect(mapProps, mapDispatch)(EventLogComponent);
+export default EventLog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/eventLogApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/eventLogApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..cb2d0626a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="eventLogApp"/>
+ <property name="index" value="75"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/eventLogApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..e2ffb596b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoader loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles() == 1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles() == 0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/eventLogApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json b/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js b/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js
new file mode 100644
index 000000000..a67a34074
--- /dev/null
+++ b/sdnr/wt/odlux/apps/eventLogApp/webpack.config.js
@@ -0,0 +1,155 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ eventLogApp: ["./pluginEventLog.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://localhost:28181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://localhost:28181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://localhost:28181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://localhost:28181",
+ secure: false
+ },
+ "/websocket/": {
+ target: "http://localhost:28181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/.babelrc b/sdnr/wt/odlux/apps/faultApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json
new file mode 100644
index 000000000..909626303
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/fault-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to demo the fault management.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/pom.xml b/sdnr/wt/odlux/apps/faultApp/pom.xml
new file mode 100644
index 000000000..973c1061f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-faultApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-faultApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
new file mode 100644
index 000000000..ba1a24822
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+import { clearStuckAlarms } from "../services/faultStatusService"
+import { Dispatch } from "../../../../framework/src/flux/store";
+import { FaultApplicationBaseAction } from "./notificationActions";
+
+export class AreStuckAlarmsCleared extends FaultApplicationBaseAction {
+ constructor(public isBusy: boolean) {
+ super();
+ }
+}
+
+
+export const clearStuckAlarmAsyncAction = (dispatcher: Dispatch) => async (nodeNames: string[]) => {
+ dispatcher(new AreStuckAlarmsCleared(true))
+ const result = await clearStuckAlarms(nodeNames).catch(error => { console.error(error); return undefined });
+ dispatcher(new AreStuckAlarmsCleared(false))
+ return result;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts
new file mode 100644
index 000000000..584e7cd8b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/notificationActions.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+
+import { FaultAlarmNotification } from '../models/fault';
+
+export class FaultApplicationBaseAction extends Action { }
+
+
+export class AddFaultNotificationAction extends FaultApplicationBaseAction {
+ constructor(public fault:FaultAlarmNotification) {
+ super();
+ }
+}
+
+export class ResetFaultNotificationsAction extends FaultApplicationBaseAction {
+
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
new file mode 100644
index 000000000..f032c139a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { PanelId } from '../models/panelId';
+
+export class SetPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
new file mode 100644
index 000000000..8a3633243
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { FaultApplicationBaseAction } from './notificationActions';
+import { getFaultStateFromDatabase } from '../services/faultStatusService';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+
+export class SetFaultStatusAction extends FaultApplicationBaseAction {
+ constructor (public criticalFaults: number, public majorFaults: number, public minorFaults: number, public warnings: number) {
+ super();
+ }
+}
+
+
+export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch ) => {
+ const result = await getFaultStateFromDatabase().catch(_=>null);
+ if (result) {
+ const statusAction = new SetFaultStatusAction(
+ result["Critical"] || 0,
+ result["Major"] || 0,
+ result["Minor"] || 0,
+ result["Warning"] || 0
+ );
+ dispatch(statusAction);
+ return;
+ }
+ dispatch(new SetFaultStatusAction(0, 0, 0, 0));
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
new file mode 100644
index 000000000..3b8b9b684
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx
@@ -0,0 +1,136 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+import { DialogContent, DialogActions, Button, Dialog, DialogTitle, DialogContentText } from '@material-ui/core';
+import { currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
+import { clearStuckAlarmAsyncAction } from '../actions/clearStuckAlarmsAction';
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+
+export enum ClearStuckAlarmsDialogMode {
+ None = "none",
+ Show = "show"
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ clearStuckAlarmsAsync: clearStuckAlarmAsyncAction(dispatcher.dispatch),
+ reloadCurrentProblemsAction: () => dispatcher.dispatch(currentProblemsReloadAction)
+})
+
+type clearStuckAlarmsProps = Connect<typeof undefined, typeof mapDispatch> & {
+ numberDevices: Number,
+ mode: ClearStuckAlarmsDialogMode,
+ stuckAlarms: string[]
+ onClose: () => void
+}
+
+type ClearStuckAlarmsState = {
+ clearAlarmsSuccessful: boolean,
+ errormessage: string,
+ unclearedAlarms: string[]
+}
+
+class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsProps, ClearStuckAlarmsState>{
+ constructor(props: clearStuckAlarmsProps) {
+ super(props);
+ this.state = { clearAlarmsSuccessful: true, errormessage: '', unclearedAlarms: [] }
+ }
+
+ onClose = (event: React.MouseEvent) => {
+ event.stopPropagation();
+ event.preventDefault();
+ this.props.onClose();
+ }
+
+ onRefresh = async (event: React.MouseEvent) => {
+ event.stopPropagation();
+ event.preventDefault();
+ const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms);
+
+ if (result) {
+ if (result.output.nodenames) {
+ if (result.output.nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared
+ const undeletedAlarm = this.props.stuckAlarms.filter(item => !result.output.nodenames.includes(item))
+ const error = "The alarms of the following devices couldn't be refreshed: ";
+ this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm })
+ return;
+ }
+ }
+ }
+ else { //show errormessage if no devices were cleared
+ this.setState({ clearAlarmsSuccessful: false, errormessage: "Alarms couldn't be refreshed.", unclearedAlarms: [] })
+ return;
+ }
+
+ this.props.reloadCurrentProblemsAction();
+ this.props.onClose();
+ }
+
+ onOk = (event: React.MouseEvent) => {
+
+ event.stopPropagation();
+ event.preventDefault();
+ if (this.state.unclearedAlarms.length > 0)
+ this.props.reloadCurrentProblemsAction();
+ this.props.onClose();
+ }
+
+ render() {
+ console.log(this.props.stuckAlarms);
+ const device = this.props.numberDevices > 1 ? 'devices' : 'device'
+ const defaultMessage = "Are you sure you want to refresh all alarms for " + this.props.numberDevices + " " + device + "?"
+ const message = this.state.clearAlarmsSuccessful ? defaultMessage : this.state.errormessage;
+
+ const defaultTitle = "Refresh Confirmation"
+ const title = this.state.clearAlarmsSuccessful ? defaultTitle : 'Refresh Result';
+
+ return (
+ <Dialog open={this.props.mode !== ClearStuckAlarmsDialogMode.None}>
+ <DialogTitle>{title}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {message}
+ </DialogContentText>
+ {
+ this.state.unclearedAlarms.map(item =>
+ <DialogContentText>
+ {item}
+ </DialogContentText>
+ )
+ }
+ </DialogContent>
+ <DialogActions>
+ {
+ this.state.clearAlarmsSuccessful &&
+ <>
+ <Button onClick={this.onRefresh}>Yes</Button>
+ <Button onClick={this.onClose}>No</Button>
+ </>
+ }
+
+ {
+ !this.state.clearAlarmsSuccessful && <Button onClick={this.onOk}>Ok</Button>
+ }
+ </DialogActions>
+ </Dialog>
+ )
+ }
+}
+
+const ClearStuckAlarmsDialog = connect(undefined, mapDispatch)(ClearStuckAlarmsDialogComponent)
+export default ClearStuckAlarmsDialog;
diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
new file mode 100644
index 000000000..1ec463f47
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/components/faultStatus.tsx
@@ -0,0 +1,71 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import connect, { Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import Typography from '@material-ui/core/Typography';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+const styles = (theme: Theme) => createStyles({
+ icon: {
+ marginLeft: 8,
+ marginRight: 8
+ },
+ critical: {
+ color: "red"
+ },
+ major: {
+ color: "orange"
+ },
+ minor: {
+ color: "#f7f700"
+ },
+ warning: {
+ color: "#428bca"
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ faultStatus: state.fault.faultStatus,
+});
+
+
+type FaultStatusComponentProps = & WithStyles<typeof styles> & Connect<typeof mapProps>;
+
+class FaultStatusComponent extends React.Component<FaultStatusComponentProps> {
+ render(): JSX.Element {
+ const { classes, faultStatus } = this.props;
+
+ return (
+ <Typography variant="body1" color="inherit" >
+ Alarm Status: <FontAwesomeIcon className={`${classes.icon} ${classes.critical}`} icon={faExclamationTriangle} /> { faultStatus.critical } |
+ <FontAwesomeIcon className={`${classes.icon} ${classes.major}`} icon={faExclamationTriangle} /> { faultStatus.major } |
+ <FontAwesomeIcon className={`${classes.icon} ${classes.minor}`} icon={faExclamationTriangle} /> { faultStatus.minor } |
+ <FontAwesomeIcon className={`${classes.icon} ${classes.warning}`} icon={faExclamationTriangle} /> { faultStatus.warning } |
+ </Typography>
+ );
+ };
+}
+
+export const FaultStatus = withStyles(styles)(connect(mapProps)(FaultStatusComponent));
+export default FaultStatus; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
new file mode 100644
index 000000000..31b8259b2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/alarmLogEntriesHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface IAlarmLogEntriesState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const alarmLogEntriesSearchHandler = createSearchDataHandler< Fault>('faultlog');
+
+export const {
+ actionHandler: alarmLogEntriesActionHandler,
+ createActions: createAlarmLogEntriesActions,
+ createProperties: createAlarmLogEntriesProperties,
+ reloadAction: alarmLogEntriesReloadAction,
+
+ // set value action, to change a value
+} = createExternal<Fault>(alarmLogEntriesSearchHandler, appState => appState.fault.alarmLogEntries);
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
new file mode 100644
index 000000000..14634b4c4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/clearStuckAlarmsHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IActionHandler } from "../../../../framework/src/flux/action"
+import { AreStuckAlarmsCleared } from "../actions/clearStuckAlarmsAction";
+
+export interface IStuckAlarms {
+ areAlarmsCleared: boolean
+}
+
+const initialState: IStuckAlarms = {
+ areAlarmsCleared: false
+}
+
+export const stuckAlarmHandler: IActionHandler<IStuckAlarms> = (state = initialState, action) => {
+ if (action instanceof AreStuckAlarmsCleared) {
+ state = { ...state, areAlarmsCleared: action.isBusy }
+ }
+
+ return state;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
new file mode 100644
index 000000000..3698a2798
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/currentProblemsHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { Fault } from '../models/fault';
+
+export interface ICurrentProblemsState extends IExternalTableState<Fault> { }
+
+// create eleactic search data fetch handler
+const currentProblemsSearchHandler = createSearchDataHandler<Fault>('faultcurrent');
+
+export const {
+ actionHandler: currentProblemsActionHandler,
+ createActions: createCurrentProblemsActions,
+ createProperties: createCurrentProblemsProperties,
+ reloadAction: currentProblemsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<Fault>(currentProblemsSearchHandler, appState => appState.fault.currentProblems);
+
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
new file mode 100644
index 000000000..dddb4a247
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// ** do not remove **
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler';
+import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler';
+import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { IFaultStatus, faultStatusHandler } from './faultStatusHandler';
+import { stuckAlarmHandler } from './clearStuckAlarmsHandler';
+
+export interface IFaultAppStoreState {
+ currentProblems: ICurrentProblemsState;
+ faultNotifications: IFaultNotifications;
+ alarmLogEntries: IAlarmLogEntriesState;
+ currentOpenPanel: string | null;
+ faultStatus: IFaultStatus;
+}
+
+const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ fault: IFaultAppStoreState;
+ }
+}
+
+const actionHandlers = {
+ currentProblems: currentProblemsActionHandler,
+ faultNotifications: faultNotificationsHandler,
+ alarmLogEntries: alarmLogEntriesActionHandler,
+ currentOpenPanel: currentOpenPanelHandler,
+ faultStatus: faultStatusHandler,
+ stuckAlarms: stuckAlarmHandler
+};
+
+export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers);
+export default faultAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
new file mode 100644
index 000000000..1c76a4b1a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetFaultStatusAction } from "../actions/statusActions";
+
+export interface IFaultStatus {
+ critical: number,
+ major: number,
+ minor: number,
+ warning: number
+}
+
+const faultStatusInit: IFaultStatus = {
+ critical: 0,
+ major: 0,
+ minor: 0,
+ warning: 0
+};
+
+export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
+ if (action instanceof SetFaultStatusAction) {
+ state = {
+ critical: action.criticalFaults,
+ major: action.majorFaults,
+ minor: action.minorFaults,
+ warning: action.warnings
+ }
+ }
+
+ return state;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
new file mode 100644
index 000000000..aa92d2a1c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/notificationsHandler.ts
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { AddFaultNotificationAction, ResetFaultNotificationsAction } from '../actions/notificationActions';
+import { FaultAlarmNotification } from '../models/fault';
+
+export interface IFaultNotifications {
+ faults: FaultAlarmNotification[];
+ since: Date;
+}
+
+const faultNotoficationsInit: IFaultNotifications = {
+ faults: [],
+ since: new Date()
+};
+
+export const faultNotificationsHandler: IActionHandler<IFaultNotifications> = (state = faultNotoficationsInit, action) => {
+ if (action instanceof AddFaultNotificationAction) {
+ state = {
+ ...state,
+ faults: [...state.faults, action.fault]
+ };
+ } else if (action instanceof ResetFaultNotificationsAction){
+ state = {
+ ...state,
+ faults: [],
+ since: new Date()
+ };
+ }
+
+ return state;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/index.html b/sdnr/wt/odlux/apps/faultApp/src/index.html
new file mode 100644
index 000000000..cd315f0b7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Minimal App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "faultApp" ], function (app, faultApp) {
+ faultApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
new file mode 100644
index 000000000..c65734437
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type Fault = {
+ id: string;
+ nodeId: string;
+ counter: number;
+ timestamp: string;
+ objectId: string;
+ problem: string;
+ severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical';
+ type: string;
+ sourceType: string;
+}
+
+export type FaultAlarmNotification = {
+ id: string;
+ nodeName: string;
+ counter: number;
+ timeStamp: string;
+ objectId: string;
+ problem: string;
+ severity: null | 'Warning' | 'Minor' | 'Major' | 'Critical';
+ type: string;
+ sourceType: string;
+}
+
+/**
+ * Fault status return type
+ */
+export type FaultsReturnType = {
+ criticals: number,
+ majors: number,
+ minors: number,
+ warnings: number
+};
+
+export type FaultType = {
+ Critical: number,
+ Major: number,
+ Minor: number,
+ Warning: number
+};
+
+export type Faults = {
+ faults: FaultsReturnType
+};
+
+export type DeletedStuckAlarms = {
+ output: {
+ nodenames: string[]
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
new file mode 100644
index 000000000..186aa53d9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/models/panelId.ts
@@ -0,0 +1,18 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type PanelId = null | "CurrentProblem" | "AlarmNotifications" | "AlarmLog"; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
new file mode 100644
index 000000000..02dde90f7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
@@ -0,0 +1,112 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { faBell } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { subscribe, IFormatedMessage } from '../../../framework/src/services/notificationService';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+
+import { faultAppRootHandler } from './handlers/faultAppRootHandler';
+import { FaultApplication } from "./views/faultApplication";
+
+import { FaultAlarmNotification } from "./models/fault";
+import { PanelId } from "./models/panelId";
+
+import { SetPanelAction } from "./actions/panelChangeActions";
+import { AddFaultNotificationAction } from "./actions/notificationActions";
+
+import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from "./handlers/currentProblemsHandler";
+import { FaultStatus } from "./components/faultStatus";
+import { refreshFaultStatusAsyncAction } from "./actions/statusActions";
+
+let currentMountId: string | undefined = undefined;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ currentProblemsProperties: createCurrentProblemsProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch, true),
+ setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId))
+});
+
+const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+ if (currentMountId !== props.match.params.mountId) {
+ // route parameter has changed
+ currentMountId = props.match.params.mountId || undefined;
+ // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+ window.setTimeout(() => {
+ if (currentMountId) {
+ props.setCurrentPanel("CurrentProblem");
+ props.currentProblemsActions.onFilterChanged("nodeId", currentMountId);
+ props.currentProblemsProperties.showFilter; // || (props.currentProblemsActions.onToggleFilter());
+ props.currentProblemsActions.onRefresh();
+ }
+ });
+ }
+ return (
+ <FaultApplication />
+ )
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+ <Switch>
+ <Route path={ `${ props.match.path }/:mountId?` } component={ FaultApplicationRouteAdapter } />
+ <Redirect to={ `${ props.match.path }` } />
+ </Switch>
+));
+
+export function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: "fault",
+ icon: faBell,
+ rootComponent: App,
+ rootActionHandler: faultAppRootHandler,
+ statusBarElement: FaultStatus,
+ menuEntry: "Fault"
+ });
+
+ // subscribe to the websocket notifications
+ subscribe<FaultAlarmNotification & IFormatedMessage>("ProblemNotification", (fault => {
+ const store = applicationApi && applicationApi.applicationStore;
+ if (fault && store) {
+ store.dispatch(new AddFaultNotificationAction(fault));
+ }
+ }));
+
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(currentProblemsReloadAction);
+ });
+
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(refreshFaultStatusAsyncAction);
+ });
+ window.setInterval(() => {
+ applicationApi.applicationStoreInitialized.then(store => {
+ store.dispatch(refreshFaultStatusAsyncAction);
+ });
+ }, 15000);
+
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
new file mode 100644
index 000000000..d3409e095
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from "../../../../framework/src/services/restService";
+import { Result, PostResponse } from "../../../../framework/src/models/elasticSearch";
+import { FaultType, Faults, DeletedStuckAlarms } from "../models/fault";
+
+
+export const getFaultStateFromDatabase = async (): Promise<FaultType | null> => {
+ const path = 'restconf/operations/data-provider:read-status';
+ const result = await requestRest<Result<Faults>>(path, { method: "POST" });
+
+ let faultType: FaultType = {
+ Critical: 0,
+ Major: 0,
+ Minor: 0,
+ Warning: 0
+ }
+ let faults: Faults[] | null = null;
+
+ if (result && result.output && result.output.data) {
+ faults = result.output.data;
+ faultType = {
+ Critical: faults[0].faults.criticals,
+ Major: faults[0].faults.majors,
+ Minor: faults[0].faults.minors,
+ Warning: faults[0].faults.warnings
+ }
+ }
+
+ return faultType;
+}
+
+export const clearStuckAlarms = async (nodeNames: string[]) => {
+ const path = 'restconf/operations/devicemanager:clear-current-fault-by-nodename'
+ const result = await requestRest<DeletedStuckAlarms>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) })
+ return result;
+
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
new file mode 100644
index 000000000..fd1c48ac5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -0,0 +1,176 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
+
+import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { Panel } from '../../../../framework/src/components/material-ui';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { Fault, FaultAlarmNotification } from '../models/fault';
+import { PanelId } from '../models/panelId';
+
+import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
+import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { Tooltip, IconButton } from '@material-ui/core';
+import RefreshIcon from '@material-ui/icons/Refresh';
+import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ activePanel: state.fault.currentOpenPanel,
+ currentProblemsProperties: createCurrentProblemsProperties(state),
+ faultNotifications: state.fault.faultNotifications,
+ alarmLogEntriesProperties: createAlarmLogEntriesProperties(state)
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch),
+ alarmLogEntriesActions: createAlarmLogEntriesActions(dispatcher.dispatch),
+ reloadCurrentProblems: () => dispatcher.dispatch(currentProblemsReloadAction),
+ reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
+ setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+});
+
+type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
+
+type FaultApplicationState = {
+ clearAlarmDialogMode: ClearStuckAlarmsDialogMode,
+ stuckAlarms: string[]
+}
+
+
+const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
+const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
+
+
+class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState>{
+
+ /**
+ *
+ */
+ constructor(props: FaultApplicationComponentProps) {
+ super(props);
+ this.state = { clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] }
+ }
+
+ onDialogClose = () => {
+ this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.None, stuckAlarms: [] })
+ }
+
+ onDialogOpen = () => {
+ const stuckAlarms = [...new Set(this.props.currentProblemsProperties.rows.map(item => item.nodeId))];
+ this.setState({ clearAlarmDialogMode: ClearStuckAlarmsDialogMode.Show, stuckAlarms: stuckAlarms })
+ }
+
+
+
+ render(): JSX.Element {
+
+ const refreshButton = {
+ icon: RefreshIcon, tooltip: 'Clear stuck alarms', onClick: this.onDialogOpen
+ };
+ const areFaultsAvailable = this.props.currentProblemsProperties.rows && this.props.currentProblemsProperties.rows.length > 0
+ const customAction = areFaultsAvailable ? [refreshButton] : [];
+
+ const { activePanel } = this.props;
+
+ const onTogglePanel = (panelId: PanelId) => {
+ const nextActivePanel = panelId === this.props.activePanel ? null : panelId;
+ this.props.setCurrentPanel(nextActivePanel);
+
+ switch (nextActivePanel) {
+ case 'CurrentProblem':
+ this.props.reloadCurrentProblems();
+ break;
+ case 'AlarmLog':
+ this.props.reloadAlarmLogEntries();
+ break;
+ case 'AlarmNotifications':
+ case null:
+ default:
+ // nothing to do
+ break;
+ }
+ };
+
+ return (
+ <>
+ <Panel activePanel={activePanel} panelId={'CurrentProblem'} onToggle={onTogglePanel} title={'Current Problem List'}>
+ <FaultTable idProperty={'id'} customActionButtons={customAction} columns={[
+ { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: "timestamp", type: ColumnType.text, title: "Time Stamp" },
+ { property: "nodeId", title: "Node Name", type: ColumnType.text },
+ { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" },
+ { property: "objectId", title: "Object Id", type: ColumnType.text },
+ { property: "problem", title: "Alarm Type", type: ColumnType.text },
+ { property: "severity", title: "Severity", type: ColumnType.text, width: "140px" },
+ ]} {...this.props.currentProblemsProperties} {...this.props.currentProblemsActions} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={'AlarmNotifications'} onToggle={onTogglePanel} title={`Alarm Notifications ${this.props.faultNotifications.faults.length} since ${this.props.faultNotifications.since}`}>
+ <FaultAlarmNotificationTable rows={this.props.faultNotifications.faults} asynchronus columns={[
+ { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: "timeStamp", title: "Time Stamp" },
+ { property: "nodeName", title: "Node Name" },
+ { property: "counter", title: "Count", width: "100px" },
+ { property: "objectId", title: "Object Id" },
+ { property: "problem", title: "Alarm Type" },
+ { property: "severity", title: "Severity", width: "140px" },
+ ]} idProperty={'id'} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={'AlarmLog'} onToggle={onTogglePanel} title={'Alarm Log'}>
+ <FaultTable idProperty={'id'} columns={[
+ { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+ { property: "timestamp", title: "Time Stamp" },
+ { property: "nodeId", title: "Node Name" },
+ { property: "counter", title: "Count", type: ColumnType.numeric, width: "100px" },
+ { property: "objectId", title: "Object Id" },
+ { property: "problem", title: "Alarm Type" },
+ { property: "severity", title: "Severity", width: "140px" },
+ { property: "sourceType", title: "Source", width: "140px" },
+ ]} {...this.props.alarmLogEntriesProperties} {...this.props.alarmLogEntriesActions} />
+ </Panel>
+ {
+ this.state.clearAlarmDialogMode !== ClearStuckAlarmsDialogMode.None && <ClearStuckAlarmsDialog mode={this.state.clearAlarmDialogMode} numberDevices={this.state.stuckAlarms.length} stuckAlarms={this.state.stuckAlarms} onClose={this.onDialogClose} />
+
+ }
+
+ </>
+ );
+ };
+
+ public componentDidMount() {
+ this.props.alarmLogEntriesActions.onToggleFilter();
+ this.props.currentProblemsActions.onToggleFilter();
+ }
+ private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
+ return (
+ <FontAwesomeIcon icon={faExclamationTriangle} />
+ );
+ };
+
+}
+
+export const FaultApplication = withRouter(connect(mapProps, mapDisp)(FaultApplicationComponent));
+export default FaultApplication;
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..e7c262bc0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="faultApp"/>
+ <property name="index" value="10"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/faultApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..edf68e096
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/faultApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/tsconfig.json b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/faultApp/webpack.config.js b/sdnr/wt/odlux/apps/faultApp/webpack.config.js
new file mode 100644
index 000000000..66926edfb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/webpack.config.js
@@ -0,0 +1,152 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ faultApp: ["./pluginFault.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ })
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:28181/",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:28181/",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:28181/",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:28181/",
+ secure: false
+ },
+ "/websocket/": {
+ target: "http://10.20.6.29:28181/",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/.babelrc b/sdnr/wt/odlux/apps/helpApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/package.json b/sdnr/wt/odlux/apps/helpApp/package.json
new file mode 100644
index 000000000..1f106ab65
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "@odlux/help-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI providing the help functionaliy.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*",
+ "marked": "0.6.0",
+ "@types/marked": "0.6.0",
+ "highlight.js": "9.13.1",
+ "@types/highlight.js": "9.12.3",
+ "github-markdown-css": "2.10.0"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/pom.xml b/sdnr/wt/odlux/apps/helpApp/pom.xml
new file mode 100644
index 000000000..8180a68df
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-helpApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-helpApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts b/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts
new file mode 100644
index 000000000..3cebfd61d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/actions/helpActions.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { TocTreeNode } from '../models/tocNode';
+import helpService from '../services/helpService';
+
+export class LoadTocAction extends Action {
+ constructor() {
+ super();
+
+ }
+}
+
+export class TocLoadedAction extends Action {
+ constructor(public toc?: TocTreeNode[], error?: string) {
+ super();
+
+ }
+}
+
+export const requestTocAsyncAction = async (dispatch: Dispatch) => {
+ dispatch(new LoadTocAction);
+ try {
+ const toc = await helpService.getTableOfContents();
+ if (toc) {
+ dispatch(new TocLoadedAction(toc));
+ } else {
+ dispatch(new TocLoadedAction(undefined, "Could not load TOC."));
+ }
+ } catch (err) {
+ dispatch(new TocLoadedAction(undefined, err));
+ }
+}
+
+export class LoadDocumentAction extends Action {
+ constructor() {
+ super();
+
+ }
+}
+
+export class DocumentLoadedAction extends Action {
+ constructor(public document?: string, public documentPath?: string, error?: string) {
+ super();
+
+ }
+}
+
+export const requestDocumentAsyncActionCreator = (path: string) => async (dispatch: Dispatch) => {
+ dispatch(new LoadDocumentAction);
+ try {
+ const doc = await helpService.getDocument(path);
+ if (doc) {
+ dispatch(new DocumentLoadedAction(doc, path));
+ } else {
+ dispatch(new DocumentLoadedAction(undefined, undefined, "Could not load document."));
+ }
+ } catch (err) {
+ dispatch(new DocumentLoadedAction(undefined, undefined, err));
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx
new file mode 100644
index 000000000..140935715
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/helpStatus.tsx
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import connect, { Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import Typography from '@material-ui/core/Typography';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
+import { withRouter, RouteComponentProps } from 'react-router';
+
+const styles = (theme: Theme) => createStyles({
+ icon: {
+ marginLeft: 8,
+ marginRight: 8
+ },
+ disabled: {
+ color: theme.palette.grey[400]
+ },
+ link: {
+ cursor: "pointer",
+ '&:hover': {
+ textDecoration: "underline"
+ }
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ appId: state.framework.applicationState.appId,
+ toc: state.help.toc
+});
+
+
+type HelpStatusComponentProps = & RouteComponentProps & WithStyles<typeof styles> & Connect<typeof mapProps>;
+
+class HelpStatusComponent extends React.Component<HelpStatusComponentProps> {
+ render() {
+ const { classes, history, toc, appId } = this.props;
+ const rootNode = toc && toc.find(t => t.id === "sdnr");
+ const helpNode = appId
+ ? rootNode && rootNode.nodes && rootNode.nodes.find(n => n.id === appId || n.id === appId + "App")
+ : rootNode;
+ return helpNode
+ ? (
+ <Typography variant="body1" color="inherit" className={classes.link} onClick={(event) => { event.stopPropagation(); history.push(`/help/${helpNode.uri}`) }} >
+ <FontAwesomeIcon className={classes.icon} icon={faQuestionCircle} />
+ Help
+ </Typography>
+ )
+ : (
+ <Typography variant="body1" className={classes.disabled}>
+ <FontAwesomeIcon className={classes.icon} icon={faQuestionCircle} />
+ Help
+ </Typography>
+ );
+ };
+
+}
+
+export const HelpStatus = withRouter(withStyles(styles)(connect(mapProps)(HelpStatusComponent) as any) as any);
+export default HelpStatus; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx
new file mode 100644
index 000000000..a7137836e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/markdown.tsx
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import * as marked from 'marked';
+import * as hljs from 'highlight.js';
+
+type MarkdownComponentProps = {
+ text: string;
+ className?: string;
+ markedOptions?: marked.MarkedOptions;
+ style?: React.CSSProperties
+}
+
+const defaultRenderer = new marked.Renderer();
+defaultRenderer.link = (href, title, text) => (
+ `<a target="_blank" rel="noopener noreferrer" href="${ href }" title="${ title }">${ text }</a>`
+);
+
+
+class MarkdownComponent extends React.Component<MarkdownComponentProps> {
+ constructor(props: MarkdownComponentProps) {
+ super(props);
+
+ const markedOptions: marked.MarkedOptions = {
+ gfm: true,
+ tables: true,
+ breaks: false,
+ pedantic: false,
+ sanitize: true,
+ smartLists: true,
+ smartypants: false,
+ langPrefix: 'hljs ',
+ ...(this.props.markedOptions || {}),
+ highlight: (code, lang) => {
+ if (!!(lang && hljs.getLanguage(lang))) {
+ return hljs.highlight(lang, code).value;
+ }
+ return code;
+ }
+ };
+
+ marked.setOptions(markedOptions);
+ }
+ render() {
+ const { text, className, style } = this.props;
+
+
+ const html = (marked(text || '', { renderer: this.props.markedOptions && this.props.markedOptions.renderer || defaultRenderer }));
+
+ return (
+ <div
+ dangerouslySetInnerHTML={ { __html: html } }
+ className={ className }
+ style={ style }
+ />
+ );
+ }
+}
+
+export const Markdown = MarkdownComponent;
+
diff --git a/sdnr/wt/odlux/apps/helpApp/src/components/tocEntry.tsx b/sdnr/wt/odlux/apps/helpApp/src/components/tocEntry.tsx
new file mode 100644
index 000000000..fc7b8dff5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/components/tocEntry.tsx
@@ -0,0 +1,82 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react"
+import { TocTreeNode } from "../models/tocNode"
+import { Typography, Link, makeStyles, Theme, createStyles } from "@material-ui/core"
+
+const useStyles = makeStyles((theme: Theme) =>
+ createStyles({
+ link: {
+ color: "blue",
+ },
+ sublink: {
+ margin: theme.spacing(1),
+ color: "blue",
+ },
+ container: {
+ display: "flex",
+ flexDirection: "row",
+ flexWrap: "wrap",
+ }
+ }),
+);
+
+type tocEntryProps = {
+ label: string,
+ overviewUri: string,
+ nodes?: TocTreeNode[],
+ loadDocument(uri: string): any
+}
+
+const TocEntry: React.FunctionComponent<tocEntryProps> = (props) => {
+ const classes = useStyles();
+ const areNodesEmpty = !props.nodes || props.nodes.length === 0
+
+ const navigate = (event: React.SyntheticEvent, uri: string) => {
+ event.preventDefault();
+ event.stopPropagation();
+ props.loadDocument(uri);
+ }
+
+ return (<div>
+ {
+ areNodesEmpty ? <Typography variant="h6">
+ <Link onClick={(event: any) => navigate(event, props.overviewUri)} className={classes.link}> {props.label}</Link>
+ </Typography> :
+ <>
+ <Typography variant="h6">
+ {props.label}
+ </Typography>
+ <div className={classes.container}>
+ <Typography variant="body1">
+ <Link onClick={(event: any) => navigate(event, props.overviewUri)} className={classes.sublink}>Overview</Link>
+ </Typography>
+ {props.nodes !== undefined && props.nodes.map((item, index) =>
+ <Typography variant="body1" key={index + 'x' + item.id}>
+ <Link onClick={(event: any) => navigate(event, item.uri)} className={classes.sublink}>{item.label}</Link>
+ </Typography>
+ )}
+ </div>
+ </>
+ }
+ </div >)
+}
+
+
+export default TocEntry; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
new file mode 100644
index 000000000..cc6a98488
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/handlers/helpAppRootHandler.ts
@@ -0,0 +1,75 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { TocTreeNode } from 'models/tocNode';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { LoadTocAction, TocLoadedAction, LoadDocumentAction, DocumentLoadedAction } from '../actions/helpActions';
+
+export interface IHelpAppStoreState {
+ busy: boolean;
+ toc: TocTreeNode[] | undefined;
+ content: string | undefined;
+ currentPath: string | undefined;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ help: IHelpAppStoreState
+ }
+}
+
+const helpAppStoreStatcurrentPatheInit: IHelpAppStoreState = {
+ busy: false,
+ toc: undefined,
+ content: undefined,
+ currentPath: undefined
+};
+
+export const helpAppRootHandler: IActionHandler<IHelpAppStoreState> = (state = helpAppStoreStatcurrentPatheInit, action) => {
+ if (action instanceof LoadTocAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+ } else if (action instanceof TocLoadedAction) {
+ state = {
+ ...state,
+ busy: false,
+ toc: action.toc
+ };
+ } else if (action instanceof LoadDocumentAction) {
+ state = {
+ ...state,
+ busy: true
+ };
+ } else if (action instanceof DocumentLoadedAction) {
+ state = {
+ ...state,
+ busy: false,
+ content: action.document,
+ currentPath: action.documentPath
+ };
+ }
+
+ return state;
+}
+
+
+export default helpAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/helpApp/src/index.html b/sdnr/wt/odlux/apps/helpApp/src/index.html
new file mode 100644
index 000000000..2344708c8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Minimal App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "helpApp"], function (app, helpApp) {
+ //connectApp.register();
+ //faultApp.register();
+ //configurationApp.register();
+ //maintenanceApp.register();
+ helpApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts b/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts
new file mode 100644
index 000000000..dbefeec77
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/models/tocNode.ts
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type VersionInfo = {
+ label: string,
+ path: string,
+ date: string
+}
+
+export type TocNode = {
+ label: string;
+ versions: {
+ [versionKey: string]: VersionInfo,
+ current: VersionInfo
+ };
+ nodes?: TocNodeCollection;
+}
+
+export type TocNodeCollection = { [tocNodeKey: string]: TocNode };
+
+
+export type TocTreeNode = {
+ id: string;
+ label: string;
+ uri: string;
+ nodes?: TocTreeNode[];
+ disabled?: boolean;
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
new file mode 100644
index 000000000..50a264b15
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/plugin.tsx
@@ -0,0 +1,91 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faFirstAid } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { requestTocAsyncAction, requestDocumentAsyncActionCreator } from "./actions/helpActions";
+import { helpAppRootHandler } from './handlers/helpAppRootHandler';
+
+import { HelpApplication } from './views/helpApplication';
+import { HelpStatus } from "./components/helpStatus";
+
+import '!style-loader!css-loader!highlight.js/styles/default.css';
+import HelpTocApp from "./views/helpTocApp";
+
+const mapProps = (state: IApplicationStoreState) => ({
+
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ requestDocument: (path: string) => {
+ dispatcher.dispatch(requestDocumentAsyncActionCreator(path));
+ }
+});
+
+let currentHelpPath: string | undefined = undefined;
+
+const HelpApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ '0'?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+
+ if (currentHelpPath !== props.match.params["0"]) {
+ // route parameter has changed
+ currentHelpPath = props.match.params["0"] || undefined;
+ // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+ window.setTimeout(() => {
+ if (currentHelpPath) {
+ props.requestDocument(currentHelpPath);
+ }
+ });
+ }
+
+ return (
+ <HelpApplication />
+ )
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+ <Switch>
+ <Route exact path={`${props.match.path}/`} component={HelpTocApp} />
+ <Route path={`${props.match.path}/*`} component={HelpApplicationRouteAdapter} />
+ <Route path={`${props.match.path}`} component={HelpTocApp} />
+ </Switch>
+));
+
+export async function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: "help",
+ icon: faFirstAid,
+ rootComponent: App,
+ rootActionHandler: helpAppRootHandler,
+ statusBarElement: HelpStatus,
+ menuEntry: "Help",
+ //subMenuEntry: SubMenuEntry
+ });
+
+ // start the initial toc request after the application store is initalized
+ const store = await applicationApi.applicationStoreInitialized;
+ store.dispatch(requestTocAsyncAction);
+
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts b/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts
new file mode 100644
index 000000000..c8b247832
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/services/helpService.ts
@@ -0,0 +1,65 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from '../../../../framework/src/services/restService';
+import { TocTreeNode, TocNodeCollection } from '../models/tocNode';
+
+class HelpService {
+
+ private tocNodeCollection: TocTreeNode[] | null = null;
+ private documents: { [path: string]: string | null } = {};
+
+ public async getDocument(path: string): Promise<string | null> {
+ // check if the result is allready in the cache
+ if (this.documents[path]) return Promise.resolve(this.documents[path]);
+
+ // request the document
+ const result = await requestRest<string>(`/help/${path}`.replace(/\/{2,}/i, '/'));
+ if (result) {
+ this.documents[path] = result;
+ }
+ return this.documents[path] || null;
+ }
+
+ public async getTableOfContents(): Promise<TocTreeNode[] | null> {
+ // check if the result is allready in the cache
+ if (this.tocNodeCollection) return Promise.resolve(this.tocNodeCollection);
+
+ // request the table of contents
+ const result = await requestRest<TocNodeCollection>('/help/?meta', undefined, false);
+ if (result !== null) {
+ const mapNodesCollection = (col: TocNodeCollection): TocTreeNode[] => {
+ return Object.keys(col).reduce<TocTreeNode[]>((acc, key) => {
+ const current = col[key];
+ acc.push({
+ id: key,
+ label: current.label,
+ uri: current.versions.current.path,
+ nodes: current.nodes && mapNodesCollection(current.nodes) || undefined
+ });
+ return acc;
+ }, []);
+ }
+
+ this.tocNodeCollection = result && mapNodesCollection(result);
+ }
+ return this.tocNodeCollection || null;
+ }
+}
+
+export const helpService = new HelpService();
+export default helpService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts b/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts
new file mode 100644
index 000000000..412bdfb1e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/utilities/path.ts
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export const resolvePath = (...paths: string[]): string => {
+ function resolve(pathA: string, pathB: string) {
+ // ‘a’ => ['a']
+ // 'a/b' => ['a', 'b']
+ // '/a/b' => ['', 'a', 'b']
+ // '/a/b/' => ['', 'a', 'b', '']
+ const pathBParts = pathB.split('/');
+ if (pathBParts[0] === '') {
+ return pathBParts.join('/');
+ }
+ const pathAParts = pathA.split('/');
+ const aLastIndex = pathAParts.length - 1;
+ if (pathAParts[aLastIndex] !== '') {
+ pathAParts[aLastIndex] = '';
+ }
+
+ let part: string;
+ let i = 0;
+ while (typeof (part = pathBParts[i]) === 'string') {
+ switch (part) {
+ case '..':
+ pathAParts.pop();
+ pathAParts.pop();
+ pathAParts.push('');
+ break;
+ case '.':
+ pathAParts.pop();
+ pathAParts.push('');
+ break;
+ default:
+ pathAParts.pop();
+ pathAParts.push(part);
+ pathAParts.push('');
+ break;
+ }
+ i++;
+ }
+ if (pathBParts[pathBParts.length - 1] !== '') pathAParts.pop();
+ return pathAParts.join('/');
+ }
+
+ let i = 0;
+ let path: string;
+ let r = location.pathname;
+
+ const urlRegex = /^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i;
+ const multiSlashReg = /\/\/+/g;
+
+ while (typeof (path = paths[i]) === 'string') {
+ debugger;
+ const matches = path && path.match(urlRegex);
+ if (matches || !i) {
+ r = path;
+ } else {
+ path = path.replace(multiSlashReg, '/');
+ r = resolve(r, path);
+ }
+ i++;
+ }
+
+ return r;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
new file mode 100644
index 000000000..b4de26d50
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
@@ -0,0 +1,70 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import * as marked from 'marked';
+
+import { resolvePath } from '../utilities/path';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect } from '../../../../framework/src/flux/connect';
+
+import { Markdown } from "../components/markdown";
+
+import '!style-loader!css-loader!github-markdown-css/github-markdown.css'
+
+const mapProps = (state: IApplicationStoreState) => ({
+ content: state.help.content,
+ currentPath: state.help.currentPath
+});
+
+type HelpApplicationComponentProps = Connect<typeof mapProps>;
+
+class HelpApplicationComponent extends React.Component<HelpApplicationComponentProps> {
+
+ /**
+ * Initializes a new instance.
+ */
+ constructor(props: HelpApplicationComponentProps) {
+ super(props);
+
+ this.renderer = new marked.Renderer();
+
+ this.renderer.link = (href: string, title: string, text: string) => {
+ // check if href is rel or abs
+ const absUrlMatch = href.trim().match(/^https?:\/\//i);
+ return `<a href="${absUrlMatch ? href : resolvePath('#/help/', this.props.currentPath || '/', href)}" title="${title}" >${text}</a>`
+ };
+
+ this.renderer.image = (href: string, title: string) => {
+ return `<img src="${resolvePath('/help/', this.props.currentPath || '/', href)}" alt="${title}" />`
+ };
+
+ }
+
+ render(): JSX.Element {
+ return this.props.content ? (
+ <Markdown text={this.props.content} markedOptions={{ renderer: this.renderer }} className="markdown-body"
+ style={{ maxWidth: "960px", margin: "1.5em auto" }} />
+ ) : (<h2>Loading ...</h2>)
+ }
+
+ private renderer: marked.Renderer;
+}
+
+export const HelpApplication = connect(mapProps)(HelpApplicationComponent);
+export default HelpApplication; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
new file mode 100644
index 000000000..65d4609e2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import connect, { Connect, IDispatcher } from "../../../../framework/src/flux/connect";
+
+import { NavigateToApplication } from "../../../../framework/src/actions/navigationActions";
+import * as React from 'react'
+import { FunctionComponent } from "react";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import TocEntry from "../components/tocEntry";
+import { Typography } from "@material-ui/core";
+
+const mapProps = (state: IApplicationStoreState) => ({
+ helpToc: state.help.toc,
+})
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ requestDocument: (uri: string) => dispatcher.dispatch(new NavigateToApplication("help", uri))
+});
+
+const HelpTocComponent: FunctionComponent<Connect<typeof mapProps, typeof mapDisp>> = (props) => {
+
+ return (
+ <div>
+ <Typography style={{ marginBottom: '30px' }} variant="h5">
+ Help &amp; FAQ
+ </Typography>
+ <Typography style={{ marginBottom: '30px' }} variant="body1">
+ On our Help site, you can find general information about SDN-R, detailed information about our applications, frequently asked questions and a list of used abbreviations.
+ </Typography>
+ {
+ props.helpToc && props.helpToc.map((item, index) => <TocEntry key={index} overviewUri={item.uri} nodes={item.nodes} label={item.label} loadDocument={props.requestDocument} />)
+ }
+ </div>
+ )
+}
+
+export const HelpTocApp = connect(mapProps, mapDisp)(HelpTocComponent)
+
+export default HelpTocApp; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..a0e3dac11
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="helpApp"/>
+ <property name="index" value="100"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/helpApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..d0fbe63c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/helpApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/helpApp/tsconfig.json b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/helpApp/webpack.config.js b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
new file mode 100644
index 000000000..14ab528a7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/helpApp/webpack.config.js
@@ -0,0 +1,170 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const autoprefixer = require('autoprefixer');
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ helpApp: ["./plugin.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }, {
+ test: /\.css$/,
+ use: [{
+ loader: 'style-loader'
+ }, {
+ loader: 'css-loader',
+ options: {
+ modules: true,
+ localIdentName: env !== "release" ? '[name]_[local]_[hash:base64:5]' : '[hash]'
+ }
+ }, {
+ loader: 'postcss-loader',
+ options: {
+ plugins: () => [autoprefixer]
+ }
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/websocket/": {
+ target: "http://10.20.6.29:48181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/.babelrc b/sdnr/wt/odlux/apps/inventoryApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json
new file mode 100644
index 000000000..9e004c112
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/inventory-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to display network inventory data from a database.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/pom.xml b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
new file mode 100644
index 000000000..081f070fc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-inventoryApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-inventoryApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
new file mode 100644
index 000000000..786f6d0c5
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
@@ -0,0 +1,45 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// ** do not remove **
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+import { IInventoryElementsState, inventoryElementsActionHandler } from './inventoryElementsHandler';
+
+
+export interface IInventoryAppStateState {
+ inventoryElements: IInventoryElementsState
+}
+
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ inventory: IInventoryAppStateState;
+ }
+}
+
+const actionHandlers = {
+ inventoryElements: inventoryElementsActionHandler
+};
+
+export const inventoryAppRootHandler = combineActionHandler<IInventoryAppStateState>(actionHandlers);
+export default inventoryAppRootHandler;
+
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx
new file mode 100644
index 000000000..a65319efa
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { InventoryType } from '../models/inventory';
+
+export interface IInventoryElementsState extends IExternalTableState<InventoryType> { }
+
+// create eleactic search material data fetch handler
+const inventoryElementsSearchHandler = createSearchDataHandler<InventoryType>("inventory");
+
+export const {
+ actionHandler: inventoryElementsActionHandler,
+ createActions: createInventoryElementsActions,
+ createProperties: createInventoryElementsProperties,
+ reloadAction: inventoryElementsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<InventoryType>(inventoryElementsSearchHandler, appState => appState.inventory.inventoryElements);
+
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/index.html b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
new file mode 100644
index 000000000..0cdb9e93b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>Inventory App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "inventoryApp"], function (app, inventoryApp) {
+ inventoryApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
new file mode 100644
index 000000000..9d747415f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+export type InventoryType = {
+ treeLevel: number;
+ parentUuid: string;
+ nodeId: string;
+ uuid: string;
+ containedHolder?: (string)[] | null;
+ manufacturerName?: string ;
+ manufacturerIdentifier: string;
+ serial: string;
+ date: string;
+ version: string;
+ description: string;
+ partTypeId: string;
+ modelIdentifier: string;
+ typeName: string;
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
new file mode 100644
index 000000000..ad53285cb
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
@@ -0,0 +1,75 @@
+/**
+* ============LICENSE_START========================================================================
+* ONAP : ccsdk feature sdnr wt odlux
+* =================================================================================================
+* Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+* =================================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software distributed under the License
+* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+* or implied. See the License for the specific language governing permissions and limitations under
+* the License.
+* ============LICENSE_END==========================================================================
+*/
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+import { faShoppingBag } from '@fortawesome/free-solid-svg-icons'; // select app icon
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+
+import { Dashboard } from './views/dashboard';
+import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
+
+import { createInventoryElementsProperties, createInventoryElementsActions, inventoryElementsReloadAction } from "./handlers/inventoryElementsHandler";
+
+let currentMountId: string | undefined = undefined;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ inventoryProperties: createInventoryElementsProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ inventoryActions: createInventoryElementsActions(dispatcher.dispatch, true)
+});
+
+const InventoryApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
+ if (currentMountId !== props.match.params.mountId) {
+ currentMountId = props.match.params.mountId || undefined;
+ window.setTimeout(() => {
+ if (currentMountId) {
+ props.inventoryActions.onFilterChanged("nodeId", currentMountId);
+ props.inventoryProperties.showFilter;
+ props.inventoryActions.onRefresh();
+ }
+ });
+ }
+ return (
+ <Dashboard />
+ )
+});
+
+const App = withRouter((props: RouteComponentProps) => (
+ <Switch>
+ <Route path={`${props.match.path}/:mountId?`} component={InventoryApplicationRouteAdapter} />
+ <Redirect to={`${props.match.path}`} />
+ </Switch>
+));
+
+export function register() {
+ applicationManager.registerApplication({
+ name: "inventory",
+ icon: faShoppingBag,
+ rootActionHandler: inventoryAppRootHandler,
+ rootComponent: App,
+ menuEntry: "Inventory"
+ });
+}
+
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
new file mode 100644
index 000000000..bd182ed5d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+import { InventoryType } from '../models/inventory';
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
+
+const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & {_id: string}>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ inventoryElementsProperties: createInventoryElementsProperties(state),
+ inventoryElements: state.inventory.inventoryElements
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch)
+});
+
+class DashboardComponent extends React.Component<Connect<typeof mapProps, typeof mapDispatch>> {
+ render() {
+ return <InventoryTable title="Inventory" idProperty="_id" columns={[
+ { property: "nodeId", title: "Node Name" },
+ { property: "manufacturerIdentifier", title: "Manufacturer" },
+ { property: "parentUuid", title: "Parent" },
+ { property: "uuid", title: "Name" },
+ { property: "serial", title: "Serial" },
+ { property: "version", title: "Version" },
+ { property: "date", title: "Date" },
+ { property: "description", title: "Description" },
+ { property: "partTypeId", title: "Part Type Id" },
+ { property: "modelIdentifier", title: "Model Identifier" },
+ { property: "typeName", title: "Type" },
+ { property: "treeLevel", title: "Containment Level" },
+ ]} {...this.props.inventoryElementsActions} {...this.props.inventoryElementsProperties} >
+ </InventoryTable>
+ }
+
+ componentDidMount() {
+ this.props.inventoryElementsActions.onToggleFilter();
+ this.props.inventoryElementsActions.onHandleRequestSort("node-id");
+ }
+}
+
+export const Dashboard = connect(mapProps, mapDispatch)(DashboardComponent);
+export default Dashboard; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
new file mode 100644
index 000000000..f03b30cdd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/detail.tsx
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Button from '@material-ui/core/Button';
+import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; // infra for styling
+
+const styles = (theme: Theme) => createStyles({
+ warnButton: {
+ backgroundColor: theme.palette.primary.dark
+ }
+});
+
+type DetailProps = RouteComponentProps<{ id: string }> & WithStyles<typeof styles>;
+
+export const Detail = withStyles( styles )( withRouter( (props: DetailProps) => (
+ <div>
+ <h1>Detail {props.match.params.id}</h1>
+ <p>This are the information about {props.staticContext}.</p>
+ <Button color={"secondary"} variant={"contained"}>Start</Button>
+ <Button className={ props.classes.warnButton } variant={"contained"}>Stop</Button>
+ </div>
+)));
+
+export default Detail; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..f0bf05483
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="inventoryApp"/>
+ <property name="index" value="70"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/inventoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..d0fbe63c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/inventoryApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
new file mode 100644
index 000000000..426763803
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
@@ -0,0 +1,156 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ inventoryApp: ["./pluginInventory.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+
+ "/oauth2/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
+ "/websocket/": {
+ target: "http://localhost:48181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/.babelrc b/sdnr/wt/odlux/apps/maintenanceApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/package.json b/sdnr/wt/odlux/apps/maintenanceApp/package.json
new file mode 100644
index 000000000..96f9f7d2b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@odlux/maintenance-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI for the maintenance app.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*",
+ "@odlux/connect-app": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/pom.xml b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
new file mode 100644
index 000000000..be6e2ea6e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-maintenanceApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-maintenanceApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
new file mode 100644
index 000000000..162d94367
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/actions/maintenenceActions.ts
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+
+import { maintenenceService } from '../services/maintenenceService';
+import { maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
+
+export class BaseAction extends Action { }
+
+export class LoadAllMainteneceEntriesAction extends BaseAction { }
+
+export class AllMainteneceEntriesLoadedAction extends BaseAction {
+
+ constructor (public maintenenceEntries: MaintenenceEntry[] | null, error?:string) {
+ super();
+
+ }
+}
+
+
+export class UpdateMaintenanceEntry extends BaseAction {
+ constructor(public maintenenceEntry: MaintenenceEntry) {
+ super();
+ }
+}
+
+/** Represents an async thunk action creator to add an element to the maintenence entries. */
+export const addOrUpdateMaintenenceEntryAsyncActionCreator = (entry: MaintenenceEntry) => (dispatch: Dispatch) => {
+ maintenenceService.writeMaintenenceEntry(entry).then(result => {
+ result && window.setTimeout(() => {
+ // dispatch(loadAllMountedNetworkElementsAsync);
+ dispatch(new UpdateMaintenanceEntry(entry));
+ dispatch(new AddSnackbarNotification({ message: `Successfully ${result && result.created ? "created" : "updated"} maintenance settings for [${entry.nodeId}]`, options: { variant: 'success' } }));
+ }, 900);
+ dispatch(maintenanceEntriesReloadAction)
+ });
+};
+
+/** Represents an async thunk action creator to delete an element from the maintenence entries. */
+export const removeFromMaintenenceEntrysAsyncActionCreator = (entry: MaintenenceEntry) => (dispatch: Dispatch) => {
+ maintenenceService.deleteMaintenenceEntry(entry).then(result => {
+ result && window.setTimeout(() => {
+ dispatch(new UpdateMaintenanceEntry({
+ [spoofSymbol]: true,
+ _id: entry._id,
+ nodeId: entry.nodeId,
+ description: "",
+ start: "",
+ end: "",
+ active: false
+ }));
+ dispatch(new AddSnackbarNotification({ message: `Successfully removed [${entry.nodeId}]`, options: { variant: 'success' } }));
+ }, 900);
+ dispatch(maintenanceEntriesReloadAction)
+ });
+};
+
+// Hint: since there is no notification of changed required network elements, this code is not aware of changes caused outiside of this browser. \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
new file mode 100644
index 000000000..e0cd51493
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
@@ -0,0 +1,194 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import {
+ addOrUpdateMaintenenceEntryAsyncActionCreator,
+ removeFromMaintenenceEntrysAsyncActionCreator
+} from '../actions/maintenenceActions';
+
+import { MaintenenceEntry } from '../models/maintenenceEntryType';
+import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+
+export enum EditMaintenenceEntryDialogMode {
+ None = "none",
+ AddMaintenenceEntry = "addMaintenenceEntry",
+ EditMaintenenceEntry = "editMaintenenceEntry",
+ RemoveMaintenenceEntry = "removeMaintenenceEntry"
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ addOrUpdateMaintenenceEntry: (entry: MaintenenceEntry) => {
+ dispatcher.dispatch(addOrUpdateMaintenenceEntryAsyncActionCreator(entry));
+ },
+ removeMaintenenceEntry: (entry: MaintenenceEntry) => {
+ dispatcher.dispatch(removeFromMaintenenceEntrysAsyncActionCreator(entry));
+ },
+});
+
+type DialogSettings = {
+ dialogTitle: string,
+ dialogDescription: string,
+ applyButtonText: string,
+ cancelButtonText: string,
+ enableMountIdEditor: boolean,
+ enableTimeEditor: boolean,
+}
+
+const settings: { [key: string]: DialogSettings } = {
+ [EditMaintenenceEntryDialogMode.None]: {
+ dialogTitle: "",
+ dialogDescription: "",
+ applyButtonText: "",
+ cancelButtonText: "",
+ enableMountIdEditor: false,
+ enableTimeEditor: false,
+ },
+ [EditMaintenenceEntryDialogMode.AddMaintenenceEntry]: {
+ dialogTitle: "Add new maintenence entry",
+ dialogDescription: "",
+ applyButtonText: "Add",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: true,
+ enableTimeEditor: true,
+ },
+ [EditMaintenenceEntryDialogMode.EditMaintenenceEntry]: {
+ dialogTitle: "Edit maintenence entry",
+ dialogDescription: "",
+ applyButtonText: "Save",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableTimeEditor: true,
+ },
+ [EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry]: {
+ dialogTitle: "Remove maintenence entry",
+ dialogDescription: "",
+ applyButtonText: "Remove",
+ cancelButtonText: "Cancel",
+ enableMountIdEditor: false,
+ enableTimeEditor: false,
+ },
+}
+
+type EditMaintenenceEntryDIalogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: EditMaintenenceEntryDialogMode;
+ initialMaintenenceEntry: MaintenenceEntry;
+ onClose: () => void;
+};
+
+type EditMaintenenceEntryDIalogComponentState = MaintenenceEntry;
+
+class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenceEntryDIalogComponentProps, EditMaintenenceEntryDIalogComponentState> {
+ constructor (props: EditMaintenenceEntryDIalogComponentProps) {
+ super(props);
+
+ this.state = {
+ ...this.props.initialMaintenenceEntry
+ };
+ }
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ return (
+ <Dialog open={this.props.mode !== EditMaintenenceEntryDialogMode.None}>
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ <TextField disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ <TextField disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="start" label="Start (Local DateTime)" type="datetime-local" fullWidth value={this.state.start} onChange={(event) => { this.setState({ start: event.target.value }); }} />
+ <TextField disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="end" label="End (Local DateTime)" type="datetime-local" fullWidth value={this.state.end} onChange={(event) => { this.setState({ end: event.target.value }); }} />
+ <FormControl fullWidth disabled={!setting.enableTimeEditor}>
+ <InputLabel htmlFor="active">Active</InputLabel>
+ <Select value={ this.state.active || false } onChange={(event) => {
+ this.setState({ active: event.target.value as any as boolean });
+ }} inputProps={{ name: 'active', id: 'active' }} fullWidth >
+ <MenuItem value={true as any as string}>active</MenuItem>
+ <MenuItem value={false as any as string}>not active</MenuItem>
+ </Select>
+ </FormControl>
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={(event) => {
+ this.onApply({
+ _id: this.state._id || this.state.nodeId,
+ nodeId: this.state.nodeId,
+ description: this.state.description,
+ start: this.state.start,
+ end: this.state.end,
+ active: this.state.active
+ });
+ event.preventDefault();
+ event.stopPropagation();
+ }} > {setting.applyButtonText} </Button>
+ <Button onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ private onApply = (entry: MaintenenceEntry) => {
+ this.props.onClose && this.props.onClose();
+ switch (this.props.mode) {
+ case EditMaintenenceEntryDialogMode.AddMaintenenceEntry:
+ entry && this.props.addOrUpdateMaintenenceEntry(entry);
+ break;
+ case EditMaintenenceEntryDialogMode.EditMaintenenceEntry:
+ entry && this.props.addOrUpdateMaintenenceEntry(entry);
+ break;
+ case EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry:
+ entry && this.props.removeMaintenenceEntry(entry);
+ break;
+ }
+ };
+
+
+ private onCancel = () => {
+ this.props.onClose && this.props.onClose();
+ }
+
+ static getDerivedStateFromProps(props: EditMaintenenceEntryDIalogComponentProps, state: EditMaintenenceEntryDIalogComponentState & { _initialMaintenenceEntry: MaintenenceEntry }): EditMaintenenceEntryDIalogComponentState & { _initialMaintenenceEntry: MaintenenceEntry } {
+ if (props.initialMaintenenceEntry !== state._initialMaintenenceEntry) {
+ state = {
+ ...state,
+ ...props.initialMaintenenceEntry,
+ _initialMaintenenceEntry: props.initialMaintenenceEntry,
+ };
+ }
+ return state;
+ }
+
+}
+
+export const EditMaintenenceEntryDIalog = connect(undefined, mapDispatch)(EditMaintenenceEntryDIalogComponent);
+export default EditMaintenenceEntryDIalog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
new file mode 100644
index 000000000..71b4bf70d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenanceAppRootHandler.ts
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { IMaintenanceEntriesState, maintenanceEntriesActionHandler } from './maintenenceEntriesHandler';
+
+export interface IMaintenanceAppStoreState {
+ maintenenceEntries : IMaintenanceEntriesState
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ maintenance: IMaintenanceAppStoreState
+ }
+}
+
+const actionHandlers = {
+ maintenenceEntries: maintenanceEntriesActionHandler
+};
+
+export const maintenanceAppRootHandler = combineActionHandler<IMaintenanceAppStoreState>(actionHandlers);
+export default maintenanceAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts
new file mode 100644
index 000000000..445541889
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/handlers/maintenenceEntriesHandler.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { MaintenenceEntry } from '../models/maintenenceEntryType';
+export interface IMaintenanceEntriesState extends IExternalTableState<MaintenenceEntry> { }
+
+// create eleactic search material data fetch handler
+const maintenanceEntriesSearchHandler = createSearchDataHandler<MaintenenceEntry>('maintenance');
+
+export const {
+ actionHandler: maintenanceEntriesActionHandler,
+ createActions: createmaintenanceEntriesActions,
+ createProperties: createmaintenanceEntriesProperties,
+ reloadAction: maintenanceEntriesReloadAction,
+
+ // set value action, to change a value
+} = createExternal<MaintenenceEntry>(maintenanceEntriesSearchHandler, appState => appState.maintenance.maintenenceEntries);
+
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/index.html b/sdnr/wt/odlux/apps/maintenanceApp/src/index.html
new file mode 100644
index 000000000..c84aecee1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Minimal App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app","connectApp", "maintenanceApp"], function (app, connectApp, maintenanceApp) {
+ connectApp.register();
+ maintenanceApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
new file mode 100644
index 000000000..989bfbdc3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/models/maintenenceEntryType.ts
@@ -0,0 +1,33 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+/** Represents the elestic search db type for maintenence enrties */
+
+
+export const spoofSymbol = Symbol("Spoof");
+
+/** Represents the type for an maintenence entry. */
+export type MaintenenceEntry = {
+ _id: string;
+ nodeId: string;
+ description?: string,
+ end: string,
+ start: string
+ active: boolean
+ [spoofSymbol]?: boolean;
+}
+
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
new file mode 100644
index 000000000..e6ab977b3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/pluginMaintenance.tsx
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import * as React from "react";
+
+import { faLock } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { maintenanceAppRootHandler } from './handlers/maintenanceAppRootHandler';
+
+import MaintenenceView from "./views/maintenenceView";
+
+const App : React.SFC = (props) => {
+ return <MaintenenceView />
+};
+
+export function register() {
+ applicationManager.registerApplication({
+ name: "maintenance",
+ icon: faLock,
+ rootComponent: App,
+ rootActionHandler: maintenanceAppRootHandler,
+ menuEntry: "Maintenance"
+ });
+}
+
+
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
new file mode 100644
index 000000000..daa6082d7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/services/maintenenceService.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from '../../../../framework/src/services/restService';
+import { Result, HitEntry, PostResponse, DeleteResponse } from '../../../../framework/src/models/elasticSearch';
+
+import { MaintenenceEntry } from '../models/maintenenceEntryType';
+import { convertToLocaleString, convertToGMTString, convertToISODateString } from '../utils/timeUtils';
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+
+
+export const maintenenceEntryDatabasePath = "mwtn/maintenancemode";
+
+/**
+ * Represents a web api accessor service for all maintenence entries related actions.
+ */
+class MaintenenceService {
+
+ /**
+ * Adds or updates one maintenence entry to the backend.
+ */
+ public async writeMaintenenceEntry(maintenenceEntry: MaintenenceEntry): Promise<PostResponse | null> {
+ const path = `/restconf/operations/data-provider:create-maintenance`;
+
+ const query = {
+ "id": maintenenceEntry._id,
+ "node-id": maintenenceEntry.nodeId,
+ "active": maintenenceEntry.active,
+ "description": maintenenceEntry.description,
+ "end": convertToISODateString(maintenenceEntry.end),
+ "start": convertToISODateString(maintenenceEntry.start)
+ };
+
+ const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
+ return result || null;
+ }
+
+ /**
+ * Deletes one maintenence entry by its mountId from the backend.
+ */
+ public async deleteMaintenenceEntry(maintenenceEntry: MaintenenceEntry): Promise<(DeleteResponse) | null> {
+ const path = `/restconf/operations/data-provider:delete-maintenance`;
+
+ const query = {
+ "id": maintenenceEntry._id,
+ "node-id": maintenenceEntry.nodeId,
+ "active": maintenenceEntry.active,
+ "description": maintenenceEntry.description,
+ "end": convertToISODateString(maintenenceEntry.end),
+ "start": convertToISODateString(maintenenceEntry.start)
+ };
+ const result = await requestRest<DeleteResponse>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
+ return result || null;
+ }
+}
+
+export const maintenenceService = new MaintenenceService();
+export default maintenenceService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts b/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
new file mode 100644
index 000000000..676be1a38
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/utils/timeUtils.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export function convertToGMTString(dateString: string): string {
+ const date = new Date(dateString);
+ const pad = (n: number) => (n < 10) ? '0' + n : n;
+
+ return date.getUTCFullYear() +
+ '-' + pad(date.getUTCMonth() + 1) +
+ '-' + pad(date.getUTCDate()) +
+ 'T' + pad(date.getUTCHours()) +
+ ':' + pad(date.getUTCMinutes()) +
+ '+00:00';
+}
+
+export function convertToLocaleString(rawDate: string| number): string {
+ const date = new Date(rawDate);
+ const pad = (n: number) => (n < 10) ? '0' + n : n;
+
+ return date.getFullYear() +
+ '-' + pad(date.getMonth() + 1) +
+ '-' + pad(date.getDate()) +
+ 'T' + pad(date.getHours()) +
+ ':' + pad(date.getMinutes());
+}
+
+export function convertToISODateString(rawDate: string| number): string {
+ const date = new Date(rawDate);
+ const displayDate = date.toISOString();
+ return displayDate.replace(/\.[0-9]{2}/, '.');
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
new file mode 100644
index 000000000..3b7879351
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
@@ -0,0 +1,226 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
+
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import AddIcon from '@material-ui/icons/Add';
+import EditIcon from '@material-ui/icons/Edit';
+import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
+
+import Button from '@material-ui/core/Button';
+import IconButton from '@material-ui/core/IconButton';
+
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
+
+import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog';
+import { convertToLocaleString } from '../utils/timeUtils';
+import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
+
+const styles = (theme: Theme) => createStyles({
+ button: {
+ margin: 0,
+ padding: "6px 6px",
+ minWidth: 'unset'
+ },
+ spacer: {
+ marginLeft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ display: "inline"
+ }
+});
+
+const MaintenenceEntriesTable = MaterialTable as MaterialTableCtorType<MaintenenceEntry>;
+
+const mapProps = (state: IApplicationStoreState) => ({
+ maintenanceEntriesProperties: createmaintenanceEntriesProperties(state)
+});
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+ maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch),
+ onLoadMaintenanceEntries: async () => {
+ await dispatcher.dispatch(maintenanceEntriesReloadAction)
+ }
+});
+
+const emptyMaintenenceEntry: MaintenenceEntry = {
+ _id: '',
+ nodeId: '',
+ description: '',
+ start: convertToLocaleString(new Date().valueOf()),
+ end: convertToLocaleString(new Date().valueOf()),
+ active: false,
+};
+
+type MaintenenceViewComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof styles> & {
+
+}
+
+type MaintenenceViewComponentState = {
+ maintenenceEntryToEdit: MaintenenceEntry;
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode;
+}
+
+class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentProps, MaintenenceViewComponentState> {
+
+ constructor(props: MaintenenceViewComponentProps) {
+ super(props);
+
+ this.state = {
+ maintenenceEntryToEdit: emptyMaintenenceEntry,
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+ };
+
+ }
+
+ render() {
+ const { classes } = this.props;
+ const addMaintenenceEntryAction = {
+ icon: AddIcon, tooltip: 'Add', onClick: () => {
+ const startTime = (new Date().valueOf());
+ const endTime = startTime;
+ this.setState({
+ maintenenceEntryToEdit: {
+ ...emptyMaintenenceEntry,
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
+ },
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry
+ });
+ }
+ };
+ const now = new Date().valueOf();
+ return (
+ <>
+ <MaintenenceEntriesTable title={"Maintenance"} customActionButtons={[addMaintenenceEntryAction]} columns={
+ [
+ { property: "nodeId", title: "Node Name", type: ColumnType.text },
+ {
+ property: "notifications", title: "Notification", width: 50, align: "center", type: ColumnType.custom, customControl: ({ rowData }) => (
+ rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && <FontAwesomeIcon icon={faBan} /> || null
+ )
+ },
+ { property: "active", title: "Activation State", type: ColumnType.boolean, labels: { "true": "active", "false": "not active" }, },
+ { property: "start", title: "Start Date (UTC)", type: ColumnType.text },
+ { property: "end", title: "End Date (UTC)", type: ColumnType.text },
+ {
+ property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => (
+ <>
+ <div className={classes.spacer}>
+ <Tooltip title={"1h from now"} ><Button className={classes.button} onClick={(event) => this.onOpenPlus1hEditMaintenenceEntryDialog(event, rowData)} >+1h</Button></Tooltip>
+ <Tooltip title={"8h from now"} ><Button className={classes.button} onClick={(event) => this.onOpenPlus8hEditMaintenenceEntryDialog(event, rowData)} >+8h</Button></Tooltip>
+ </div>
+ <div className={classes.spacer}>
+ <Tooltip title={"Edit"} ><IconButton className={classes.button} onClick={(event) => this.onOpenEditMaintenenceEntryDialog(event, rowData)} ><EditIcon /></IconButton></Tooltip>
+ <Tooltip title={"Remove"} ><IconButton disabled={!!rowData[spoofSymbol]} className={classes.button} onClick={(event) => this.onOpenRemoveMaintenenceEntryDialog(event, rowData)} ><RemoveIcon /></IconButton></Tooltip>
+ </div>
+ </>
+ )
+ },
+ ]
+ } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus > </MaintenenceEntriesTable>
+ <EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenenceEntryEditorMode}
+ onClose={this.onCloseEditMaintenenceEntryDialog} />
+ </>
+ );
+ }
+
+ public componentDidMount() {
+ this.props.maintenanceEntriesActions.onRefresh();
+ this.props.onLoadMaintenanceEntries();
+ }
+
+ private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ event.preventDefault();
+ event.stopPropagation();
+ const startTime = (new Date().valueOf());
+ const endTime = startTime + (1 * 60 * 60 * 1000);
+ this.setState({
+ maintenenceEntryToEdit: {
+ ...entry,
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
+ },
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ });
+ }
+
+ private onOpenPlus8hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ event.preventDefault();
+ event.stopPropagation();
+ const startTime = (new Date().valueOf());
+ const endTime = startTime + (8 * 60 * 60 * 1000);
+ this.setState({
+ maintenenceEntryToEdit: {
+ ...entry,
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
+ },
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ });
+ }
+
+ private onOpenEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ event.preventDefault();
+ event.stopPropagation();
+ const startTime = (new Date().valueOf());
+ const endTime = startTime;
+ this.setState({
+ maintenenceEntryToEdit: {
+ ...entry,
+ ...(entry.start && endTime)
+ ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) }
+ : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }
+ },
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
+ });
+ }
+
+ private onOpenRemoveMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
+ event.preventDefault();
+ event.stopPropagation();
+ const startTime = (new Date().valueOf());
+ const endTime = startTime;
+ this.setState({
+ maintenenceEntryToEdit: {
+ ...entry,
+ ...(entry.start && endTime)
+ ? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) }
+ : { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }
+ },
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.RemoveMaintenenceEntry
+ });
+ }
+
+ private onCloseEditMaintenenceEntryDialog = () => {
+ this.setState({
+ maintenenceEntryToEdit: emptyMaintenenceEntry,
+ maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.None,
+ });
+ }
+}
+
+export const MaintenenceView = withStyles(styles)(connect(mapProps, mapDispatcher)(MaintenenceViewComponent));
+export default MaintenenceView; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/maintenanceApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/maintenanceApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..2dd79d781
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="maintenanceApp"/>
+ <property name="index" value="20" />
+ </bean>
+</blueprint>
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/maintenanceApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..d0fbe63c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/maintenanceApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json b/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js b/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js
new file mode 100644
index 000000000..e6d968564
--- /dev/null
+++ b/sdnr/wt/odlux/apps/maintenanceApp/webpack.config.js
@@ -0,0 +1,154 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ maintenanceApp: ["./pluginMaintenance.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/websocket/": {
+ target: "http://10.20.6.29:28181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/.babelrc b/sdnr/wt/odlux/apps/mediatorApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json
new file mode 100644
index 000000000..718d2fd03
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@odlux/mediator-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to demo the mediator possible app.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
new file mode 100644
index 000000000..bc3355a39
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-mediatorApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
new file mode 100644
index 000000000..3f56b05e1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/avaliableMediatorServersActions.ts
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+
+import { MediatorServer } from '../models/mediatorServer';
+import { avaliableMediatorServersReloadAction } from '../handlers/avaliableMediatorServersHandler';
+import mediatorService from '../services/mediatorService';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+/** Represents an async thunk action that will add a server to the avaliable mediator servers. */
+export const addAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+ mediatorService.insertMediatorServer(server).then(_ => {
+ window.setTimeout(() => {
+ dispatch(avaliableMediatorServersReloadAction);
+ dispatch(new AddSnackbarNotification({ message: `Successfully added [${ server.name }]`, options: { variant: 'success' } }));
+ }, 900);
+ });
+ };
+
+ /** Represents an async thunk action that will add a server to the avaliable mediator servers. */
+export const updateAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+ mediatorService.updateMediatorServer(server).then(_ => {
+ window.setTimeout(() => {
+ dispatch(avaliableMediatorServersReloadAction);
+ dispatch(new AddSnackbarNotification({ message: `Successfully updated [${ server.name }]`, options: { variant: 'success' } }));
+ }, 900);
+ });
+};
+
+ /** Represents an async thunk action that will delete a server from the avaliable mediator servers. */
+ export const removeAvaliableMediatorServerAsyncActionCreator = (server: MediatorServer) => (dispatch: Dispatch) => {
+ mediatorService.deleteMediatorServer(server).then(_ => {
+ window.setTimeout(() => {
+ dispatch(avaliableMediatorServersReloadAction);
+ dispatch(new AddSnackbarNotification({ message: `Successfully removed [${ server.name }]`, options: { variant: 'success' } }));
+ }, 900);
+ });
+ };
+ \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
new file mode 100644
index 000000000..516515ab2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorConfigActions.ts
@@ -0,0 +1,154 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import mediatorService from '../services/mediatorService';
+import { MediatorConfig, MediatorConfigResponse } from '../models/mediatorServer';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+export class SetMediatorBusyByName extends BaseAction {
+ constructor(public name: string, public isBusy: boolean) {
+ super();
+ }
+}
+
+export class AddMediatorConfig extends BaseAction {
+ constructor(public mediatorConfig: MediatorConfigResponse) {
+ super();
+ }
+}
+
+export class UpdateMediatorConfig extends BaseAction {
+ constructor(public name: string, public mediatorConfig: MediatorConfigResponse) {
+ super();
+ }
+}
+
+export class RemoveMediatorConfig extends BaseAction {
+ constructor(public name: string) {
+ super();
+ }
+}
+
+
+export const startMediatorByNameAsyncActionCreator = (name: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ dispatch(new SetMediatorBusyByName(name, true));
+ const { mediator: { mediatorServerState: { id } } } = getState();
+ if (id) {
+ mediatorService.startMediatorByName(id, name).then(msg => {
+ dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+ // since there is no notification, a timeout will be need here
+ window.setTimeout(() => {
+ mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+ if (config) {
+ dispatch(new UpdateMediatorConfig(name, config));
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+ }
+ dispatch(new SetMediatorBusyByName(name, false));
+ });
+ }, 2100);
+ });
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+ dispatch(new SetMediatorBusyByName(name, false));
+ }
+};
+
+export const stopMediatorByNameAsyncActionCreator = (name: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ dispatch(new SetMediatorBusyByName(name, true));
+ const { mediator: { mediatorServerState: { id } } } = getState();
+ if (id) {
+ mediatorService.stopMediatorByName(id, name).then(msg => {
+ dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+ // since there is no notification, a timeout will be need here
+ window.setTimeout(() => {
+ mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+ if (config) {
+ dispatch(new UpdateMediatorConfig(name, config));
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+ }
+ dispatch(new SetMediatorBusyByName(name, false));
+ });
+ }, 2100);
+ });
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+ dispatch(new SetMediatorBusyByName(name, false));
+ }
+};
+
+export const addMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const { Name: name } = config;
+ const { mediator: { mediatorServerState: { id } } } = getState();
+ if (id) {
+ mediatorService.createMediatorConfig(id, config).then(msg => {
+ dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+ // since there is no notification, a timeout will be need here
+ window.setTimeout(() => {
+ mediatorService.getMediatorServerConfigByName(id, name).then(config => {
+ if (config) {
+ dispatch(new AddMediatorConfig(config));
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: reading mediator config for ${name}.`, options: { variant: 'error' } }));
+ }
+ });
+ }, 2100);
+ });
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+ }
+};
+
+export const updateMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch) => {
+ // currently not supported be backend
+};
+
+export const removeMediatorConfigAsyncActionCreator = (config: MediatorConfig) => (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const { Name: name } = config;
+ const { mediator: { mediatorServerState: { id } } } = getState();
+ if (id) {
+ mediatorService.deleteMediatorConfigByName(id, name).then(msg => {
+ dispatch(new AddSnackbarNotification({ message: msg + ' ' + name, options: { variant: 'info' } }));
+ // since there is no notification, a timeout will be need here
+ window.setTimeout(() => {
+ mediatorService.getMediatorServerConfigByName(id, config.Name).then(config => {
+ if (!config) {
+ dispatch(new RemoveMediatorConfig(name));
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: deleting mediator config for ${name}.`, options: { variant: 'error' } }));
+ }
+ });
+ }, 2100);
+ });
+ } else {
+ dispatch(new AddSnackbarNotification({ message: `Error: currently no mediator server selected.`, options: { variant: 'error' } }));
+ dispatch(new SetMediatorBusyByName(name, false));
+ }
+};
+
+
+
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
new file mode 100644
index 000000000..79e46df0e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts
@@ -0,0 +1,114 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { MediatorServerVersionInfo, MediatorConfig, MediatorConfigResponse, MediatorServerDevice } from '../models/mediatorServer';
+import mediatorService from '../services/mediatorService';
+import { AddSnackbarNotification } from '../../../../framework/src/actions/snackbarActions';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+/** Represents the base action. */
+export class BaseAction extends Action { }
+
+export class SetMediatorServerBusy extends BaseAction {
+ constructor(public isBusy: boolean) {
+ super();
+ }
+}
+
+export class SetMediatorServerInfo extends BaseAction {
+ /**
+ * Initializes a new instance of this class.
+ */
+ constructor(public id: string | null, public name: string | null, public url: string | null) {
+ super();
+
+ }
+}
+
+export class SetMediatorServerVersion extends BaseAction {
+ /**
+ * Initializes a new instance of this class.
+ */
+ constructor(public versionInfo: MediatorServerVersionInfo | null) {
+ super();
+
+ }
+}
+
+export class SetAllMediatorServerConfigurations extends BaseAction {
+ /**
+ * Initializes a new instance of this class.
+ */
+ constructor(public allConfigurations: MediatorConfigResponse[] | null) {
+ super();
+
+ }
+}
+
+export class SetMediatorServerSupportedDevices extends BaseAction {
+ /**
+ * Initializes a new instance of this class.
+ */
+ constructor(public devices: MediatorServerDevice[] | null) {
+ super();
+
+ }
+}
+
+export class SetMediatorServerReachable extends BaseAction {
+ constructor(public isReachable: boolean) {
+ super();
+ }
+}
+
+export const initializeMediatorServerAsyncActionCreator = (serverId: string) => (dispatch: Dispatch) => {
+ dispatch(new SetMediatorServerBusy(true));
+ mediatorService.getMediatorServerById(serverId).then(mediatorServer => {
+ if (!mediatorServer) {
+ dispatch(new SetMediatorServerBusy(false));
+ dispatch(new AddSnackbarNotification({ message: `Error loading mediator server [${serverId}]`, options: { variant: 'error' } }));
+ dispatch(new NavigateToApplication("mediator"));
+ return;
+ }
+
+ dispatch(new SetMediatorServerInfo(mediatorServer.id, mediatorServer.name, mediatorServer.url));
+
+ Promise.all([
+ mediatorService.getMediatorServerAllConfigs(mediatorServer.id),
+ mediatorService.getMediatorServerSupportedDevices(mediatorServer.id),
+ mediatorService.getMediatorServerVersion(mediatorServer.id)
+ ]).then(([configurations, supportedDevices, versionInfo]) => {
+ if (configurations === null && supportedDevices === null && versionInfo === null) {
+ dispatch(new SetMediatorServerReachable(false));
+ } else {
+ dispatch(new SetMediatorServerReachable(true));
+ }
+ dispatch(new SetAllMediatorServerConfigurations(configurations));
+ dispatch(new SetMediatorServerSupportedDevices(supportedDevices));
+ dispatch(new SetMediatorServerVersion(versionInfo));
+ dispatch(new SetMediatorServerBusy(false));
+ }).catch(error => {
+ dispatch(new SetMediatorServerReachable(false));
+ dispatch(new SetMediatorServerBusy(false));
+ });
+ });
+};
+
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
new file mode 100644
index 000000000..bcbccccd7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx
@@ -0,0 +1,393 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme, createStyles, WithStyles, withStyles, Typography, FormControlLabel, Checkbox } from '@material-ui/core';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Select from '@material-ui/core/Select';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import Tabs from '@material-ui/core/Tabs';
+import Tab from '@material-ui/core/Tab';
+
+import Fab from '@material-ui/core/Fab';
+import AddIcon from '@material-ui/icons/Add';
+import DeleteIcon from '@material-ui/icons/Delete';
+import IconButton from '@material-ui/core/IconButton';
+
+import { addMediatorConfigAsyncActionCreator, updateMediatorConfigAsyncActionCreator, removeMediatorConfigAsyncActionCreator } from '../actions/mediatorConfigActions';
+import { MediatorConfig, ODLConfig } from '../models/mediatorServer';
+import FormControl from '@material-ui/core/FormControl';
+import InputLabel from '@material-ui/core/InputLabel';
+import MenuItem from '@material-ui/core/MenuItem';
+
+import { Panel } from '../../../../framework/src/components/material-ui/panel';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ display: 'flex',
+ flexDirection: 'column',
+ flex: '1',
+ },
+ fab: {
+ position: 'absolute',
+ bottom: theme.spacing(1),
+ right: theme.spacing(1),
+ },
+ title: {
+ fontSize: 14,
+ },
+ center: {
+ flex: "1",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ alignInOneLine: {
+ display: 'flex',
+ flexDirection: 'row'
+ },
+ left: {
+ marginRight: theme.spacing(1),
+ },
+ right: {
+ marginLeft: 0,
+ }
+});
+
+const TabContainer: React.SFC = ({ children }) => {
+ return (
+ <div style={{ width: "430px", height: "530px", position: "relative", display: 'flex', flexDirection: 'column' }}>
+ {children}
+ </div>
+ );
+}
+
+export enum EditMediatorConfigDialogMode {
+ None = "none",
+ AddMediatorConfig = "addMediatorConfig",
+ EditMediatorConfig = "editMediatorConfig",
+ RemoveMediatorConfig = "removeMediatorConfig",
+}
+
+const mapProps = (state: IApplicationStoreState) => ({
+ supportedDevices: state.mediator.mediatorServerState.supportedDevices
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ addMediatorConfig: (config: MediatorConfig) => {
+ dispatcher.dispatch(addMediatorConfigAsyncActionCreator(config));
+ },
+ updateMediatorConfig: (config: MediatorConfig) => {
+ dispatcher.dispatch(updateMediatorConfigAsyncActionCreator(config));
+ },
+ removeMediatorConfig: (config: MediatorConfig) => {
+ dispatcher.dispatch(removeMediatorConfigAsyncActionCreator(config));
+ },
+});
+
+type DialogSettings = {
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ readonly: boolean;
+ readonlyName: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+ [EditMediatorConfigDialogMode.None]: {
+ dialogTitle: "",
+ dialogDescription: "",
+ applyButtonText: "",
+ cancelButtonText: "",
+ readonly: true,
+ readonlyName: true,
+ },
+ [EditMediatorConfigDialogMode.AddMediatorConfig]: {
+ dialogTitle: "Add Mediator Configuration",
+ dialogDescription: "",
+ applyButtonText: "Add",
+ cancelButtonText: "Cancel",
+ readonly: false,
+ readonlyName: false,
+ },
+ [EditMediatorConfigDialogMode.EditMediatorConfig]: {
+ dialogTitle: "Edit Mediator Configuration",
+ dialogDescription: "",
+ applyButtonText: "Update",
+ cancelButtonText: "Cancel",
+ readonly: false,
+ readonlyName: true,
+ },
+ [EditMediatorConfigDialogMode.RemoveMediatorConfig]: {
+ dialogTitle: "Remove Mediator Configuration",
+ dialogDescription: "",
+ applyButtonText: "Remove",
+ cancelButtonText: "Cancel",
+ readonly: true,
+ readonlyName: true,
+ },
+};
+
+type EditMediatorConfigDialogComponentProps = WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch> & {
+ mode: EditMediatorConfigDialogMode;
+ mediatorConfig: MediatorConfig;
+ onClose: () => void;
+};
+
+type EditMediatorConfigDialogComponentState = MediatorConfig & { activeTab: number; activeOdlConfig: string, forceAddOdlConfig: boolean, isOdlConfigHostnameEmpty: boolean };
+
+class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConfigDialogComponentProps, EditMediatorConfigDialogComponentState> {
+ constructor(props: EditMediatorConfigDialogComponentProps) {
+ super(props);
+
+ this.state = {
+ ...this.props.mediatorConfig,
+ activeTab: 0,
+ activeOdlConfig: "",
+ forceAddOdlConfig: false,
+ isOdlConfigHostnameEmpty: false
+ };
+ }
+
+ private odlConfigValueChangeHandlerCreator = <THtmlElement extends HTMLElement, TKey extends keyof ODLConfig>(index: number, property: TKey, mapValue: (event: React.ChangeEvent<THtmlElement>) => any) => (event: React.ChangeEvent<THtmlElement>) => {
+ event.stopPropagation();
+ event.preventDefault();
+ this.setState({
+ ODLConfig: [
+ ...this.state.ODLConfig.slice(0, index),
+ { ...this.state.ODLConfig[index], [property]: mapValue(event) },
+ ...this.state.ODLConfig.slice(index + 1)
+ ]
+ });
+ }
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+ const { classes } = this.props;
+ return (
+ <Dialog open={this.props.mode !== EditMediatorConfigDialogMode.None}>
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ <Tabs value={this.state.activeTab} indicatorColor="secondary" textColor="secondary" onChange={(event, value) => this.setState({ activeTab: value })} >
+ <Tab label="Config" />
+ <Tab label="ODL AutoConnect" />
+ </Tabs>
+ {this.state.activeTab === 0 ? <TabContainer >
+ <TextField disabled={setting.readonly || setting.readonlyName} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.Name} onChange={(event) => { this.setState({ Name: event.target.value }); }} />
+ <FormControl fullWidth disabled={setting.readonly}>
+ <InputLabel htmlFor="deviceType">Device</InputLabel>
+ <Select value={this.state.DeviceType} onChange={(event, value) => {
+ const device = this.props.supportedDevices.find(device => device.id === event.target.value);
+ if (device) {
+ this.setState({
+ DeviceType: device.id,
+ NeXMLFile: device.xml
+ });
+ } else {
+ this.setState({
+ DeviceType: -1,
+ NeXMLFile: ""
+ });
+ }
+ }} inputProps={{ name: 'deviceType', id: 'deviceType' }} fullWidth >
+ <MenuItem value={-1}><em>None</em></MenuItem>
+ {this.props.supportedDevices.map(device => (<MenuItem key={device.id} value={device.id} >{`${device.vendor} - ${device.device} (${device.version || '0.0.0'}) `}</MenuItem>))}
+ </Select>
+ </FormControl>
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ipAddress" label="Device IP" type="text" fullWidth value={this.state.DeviceIp} onChange={(event) => { this.setState({ DeviceIp: event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="devicePort" label="Device SNMP Port" type="number" fullWidth value={this.state.DevicePort || ""} onChange={(event) => { this.setState({ DevicePort: +event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="trapsPort" label="TrapsPort" type="number" fullWidth value={this.state.TrapPort || ""} onChange={(event) => { this.setState({ TrapPort: +event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncUser" label="Netconf User" type="text" fullWidth value={this.state.NcUsername} onChange={(event) => { this.setState({ NcUsername: event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncPassword" label="Netconf Password" type="password" fullWidth value={this.state.NcPassword} onChange={(event) => { this.setState({ NcPassword: event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} autoFocus margin="dense" id="ncPort" label="Netconf Port" type="number" fullWidth value={this.state.NcPort || ""} onChange={(event) => { this.setState({ NcPort: +event.target.value }); }} />
+ </TabContainer> : null}
+ {this.state.activeTab === 1 ? <TabContainer >
+ {this.state.ODLConfig && this.state.ODLConfig.length > 0
+ ? this.state.ODLConfig.map((cfg, ind) => {
+ const panelId = `panel-${ind}`;
+ const deleteButton = (<IconButton onClick={() => {
+ this.setState({
+ ODLConfig: [
+ ...this.state.ODLConfig.slice(0, ind),
+ ...this.state.ODLConfig.slice(ind + 1)
+ ]
+ });
+ }} ><DeleteIcon /></IconButton>)
+ return (
+ <Panel title={cfg.Server && `${cfg.User ? `${cfg.User}@` : ''}${cfg.Protocol}://${cfg.Server}:${cfg.Port}` || "new odl config"} key={panelId} panelId={panelId} activePanel={this.state.activeOdlConfig} customActionButtons={[deleteButton]}
+ onToggle={(id) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); console.log("activeOdlConfig " + id); this.hideHostnameErrormessage(id) }} >
+ <div className={classes.alignInOneLine}>
+ <FormControl className={classes.left} margin={"dense"} >
+ <InputLabel htmlFor={`protocol-${ind}`}>Protocoll</InputLabel>
+ <Select value={cfg.Protocol} onChange={(e, v) => this.odlConfigValueChangeHandlerCreator(ind, "Protocol", e => v)} inputProps={{ name: `protocol-${ind}`, id: `protocol-${ind}` }} fullWidth >
+ <MenuItem value={"http"}>http</MenuItem>
+ <MenuItem value={"https"}>https</MenuItem>
+ </Select>
+ </FormControl>
+ <TextField className={classes.left} spellCheck={false} margin="dense" id="hostname" label="Hostname" type="text" value={cfg.Server} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Server", e => e.target.value)} />
+ <TextField className={classes.right} style={{ maxWidth: "65px" }} spellCheck={false} margin="dense" id="port" label="Port" type="number" value={cfg.Port || ""} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Port", e => +e.target.value)} />
+ </div>
+ {
+ this.state.isOdlConfigHostnameEmpty &&
+ <Typography component={"div"} className={classes.left} color="error" gutterBottom>Please add a hostname.</Typography>
+ }
+ <div className={classes.alignInOneLine}>
+ <TextField className={classes.left} spellCheck={false} margin="dense" id="username" label="Username" type="text" value={cfg.User} onChange={this.odlConfigValueChangeHandlerCreator(ind, "User", e => e.target.value)} />
+ <TextField className={classes.right} spellCheck={false} margin="dense" id="password" label="Password" type="password" value={cfg.Password} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Password", e => e.target.value)} />
+ </div>
+ <div className={classes.alignInOneLine}>
+ <FormControlLabel className={classes.right} control={<Checkbox checked={cfg.Trustall} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Trustall", e => e.target.checked)} />} label="Trustall" />
+ </div>
+ </Panel>
+ );
+ })
+ : (this.state.forceAddOdlConfig ?
+ <div className={classes.center} >
+ <Typography component={"div"} className={classes.title} color="error" gutterBottom>Please add at least one ODL auto connect configuration.</Typography>
+ </div>
+ :
+ <div className={classes.center} >
+ <Typography component={"div"} className={classes.title} color="textSecondary" gutterBottom>Please add an ODL auto connect configuration.</Typography>
+ </div>
+ )
+ }
+ <Fab className={classes.fab} color="primary" aria-label="Add" onClick={() => this.setState({
+ ODLConfig: [...this.state.ODLConfig, { Server: '', Port: 8181, Protocol: 'https', User: 'admin', Password: 'admin', Trustall: false }]
+ })} > <AddIcon /> </Fab>
+
+ </TabContainer> : null}
+
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={(event) => { this.addConfig(event) }} > {setting.applyButtonText} </Button>
+ <Button onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ this.resetPanel();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ private addConfig = (event: any) => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.state.ODLConfig.length === 0) {
+ this.setState({ activeTab: 1, forceAddOdlConfig: true });
+ }
+ else
+ if (this.state.ODLConfig.length > 0) {
+ for (let i = 0; i <= this.state.ODLConfig.length; i++) {
+ if (this.isHostnameEmpty(i)) {
+ this.setState({ activeOdlConfig: 'panel-' + i })
+ this.setState({ isOdlConfigHostnameEmpty: true })
+ return;
+ }
+ }
+
+ this.onApply(Object.keys(this.state).reduce<MediatorConfig & { [kex: string]: any }>((acc, key) => {
+ // do not copy additional state properties
+ if (key !== "activeTab" && key !== "activeOdlConfig" && key !== "isOdlConfigHostnameEmpty"
+ && key !== "forceAddOdlConfig" && key !== "_initialMediatorConfig") acc[key] = (this.state as any)[key];
+ return acc;
+ }, {} as MediatorConfig));
+ this.resetPanel();
+ }
+ }
+
+ private resetPanel = () => {
+ this.setState({ forceAddOdlConfig: false, isOdlConfigHostnameEmpty: false, activeTab: 0 });
+ }
+
+
+ private hideHostnameErrormessage = (panelId: string | null) => {
+
+ if (panelId) {
+ let id = Number(panelId.split('-')[1]);
+ if (!this.isHostnameEmpty(id)) {
+ this.setState({ isOdlConfigHostnameEmpty: false })
+ }
+ }
+ }
+
+ private isHostnameEmpty = (id: number) => {
+
+ const element = this.state.ODLConfig[id];
+ if (element) {
+ if (!element.Server) {
+ return true;
+ }
+ else {
+ return false
+ }
+
+ } else {
+ return null;
+ }
+ }
+
+ private onApply = (config: MediatorConfig) => {
+ this.props.onClose && this.props.onClose();
+ switch (this.props.mode) {
+ case EditMediatorConfigDialogMode.AddMediatorConfig:
+ config && this.props.addMediatorConfig(config);
+ break;
+ case EditMediatorConfigDialogMode.EditMediatorConfig:
+ config && this.props.updateMediatorConfig(config);
+ break;
+ case EditMediatorConfigDialogMode.RemoveMediatorConfig:
+ config && this.props.removeMediatorConfig(config);
+ break;
+ }
+ };
+
+ private onCancel = () => {
+ this.props.onClose && this.props.onClose();
+ }
+
+ static getDerivedStateFromProps(props: EditMediatorConfigDialogComponentProps, state: EditMediatorConfigDialogComponentState & { _initialMediatorConfig: MediatorConfig }): EditMediatorConfigDialogComponentState & { _initialMediatorConfig: MediatorConfig } {
+ if (props.mediatorConfig !== state._initialMediatorConfig) {
+ state = {
+ ...state,
+ ...props.mediatorConfig,
+ _initialMediatorConfig: props.mediatorConfig,
+ };
+ }
+ return state;
+ }
+}
+
+export const EditMediatorConfigDialog = withStyles(styles)(connect(mapProps, mapDispatch)(EditMediatorConfigDialogComponent));
+export default EditMediatorConfigDialog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
new file mode 100644
index 000000000..882a6b37e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
@@ -0,0 +1,220 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import Button from '@material-ui/core/Button';
+import TextField from '@material-ui/core/TextField';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+
+import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
+
+import { addAvaliableMediatorServerAsyncActionCreator, removeAvaliableMediatorServerAsyncActionCreator, updateAvaliableMediatorServerAsyncActionCreator } from '../actions/avaliableMediatorServersActions';
+import { MediatorServer } from '../models/mediatorServer';
+import { Typography } from '@material-ui/core';
+
+export enum EditMediatorServerDialogMode {
+ None = "none",
+ AddMediatorServer = "addMediatorServer",
+ EditMediatorServer = "editMediatorServer",
+ RemoveMediatorServer = "removeMediatorServer",
+}
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ addMediatorServer: (element: MediatorServer) => {
+ dispatcher.dispatch(addAvaliableMediatorServerAsyncActionCreator(element));
+ },
+ updateMediatorServer: (element: MediatorServer) => {
+ dispatcher.dispatch(updateAvaliableMediatorServerAsyncActionCreator(element));
+ },
+ removeMediatorServer: (element: MediatorServer) => {
+ dispatcher.dispatch(removeAvaliableMediatorServerAsyncActionCreator(element));
+ },
+});
+
+type DialogSettings = {
+ dialogTitle: string;
+ dialogDescription: string;
+ applyButtonText: string;
+ cancelButtonText: string;
+ readonly: boolean;
+};
+
+const settings: { [key: string]: DialogSettings } = {
+ [EditMediatorServerDialogMode.None]: {
+ dialogTitle: "",
+ dialogDescription: "",
+ applyButtonText: "",
+ cancelButtonText: "",
+ readonly: true,
+ },
+ [EditMediatorServerDialogMode.AddMediatorServer]: {
+ dialogTitle: "Add Mediator Server",
+ dialogDescription: "",
+ applyButtonText: "Add",
+ cancelButtonText: "Cancel",
+ readonly: false,
+ },
+ [EditMediatorServerDialogMode.EditMediatorServer]: {
+ dialogTitle: "Edit Mediator Server",
+ dialogDescription: "",
+ applyButtonText: "Update",
+ cancelButtonText: "Cancel",
+ readonly: false,
+ },
+ [EditMediatorServerDialogMode.RemoveMediatorServer]: {
+ dialogTitle: "Remove Mediator Server",
+ dialogDescription: "",
+ applyButtonText: "Remove",
+ cancelButtonText: "Cancel",
+ readonly: true,
+ },
+};
+
+type EditMediatorServerDialogComponentProps = Connect<undefined, typeof mapDispatch> & {
+ mode: EditMediatorServerDialogMode;
+ mediatorServer: MediatorServer;
+ onClose: () => void;
+};
+
+const urlRegex = RegExp("^https?://");
+
+type EditMediatorServerDialogComponentState = MediatorServer & { errorMessage: string[] };
+
+class EditMediatorServerDialogComponent extends React.Component<EditMediatorServerDialogComponentProps, EditMediatorServerDialogComponentState> {
+ constructor(props: EditMediatorServerDialogComponentProps) {
+ super(props);
+
+ this.state = {
+ ...this.props.mediatorServer,
+ errorMessage: []
+ };
+ }
+
+ areFieldsValid = () => {
+ return this.state.name.trim().length > 0 && this.state.url.trim().length > 0 && urlRegex.test(this.state.url);
+ }
+
+ createErrorMessages = () => {
+
+ let messages = [];
+ if (this.state.name.trim().length === 0 && this.state.url.trim().length === 0) {
+ messages.push("The server name and the url must not be empty.")
+ }
+ else
+ if (this.state.url.trim().length === 0) {
+ messages.push("The server url must not be empty.")
+
+ } else if (this.state.name.trim().length === 0) {
+ messages.push("The server name must not be empty.")
+ }
+
+ if (!urlRegex.test(this.state.url)) {
+ if (messages.length > 0) {
+ return messages.concat(["The server url must start with 'http(s)://'."])
+ } else {
+ return ["The server url must start with 'http(s)://'."]
+ }
+ }
+
+ return messages;
+ }
+
+
+
+ render(): JSX.Element {
+ const setting = settings[this.props.mode];
+
+ return (
+ <Dialog open={this.props.mode !== EditMediatorServerDialogMode.None}>
+ <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle>
+ <DialogContent>
+ <DialogContentText>
+ {setting.dialogDescription}
+ </DialogContentText>
+ {/* <TextField disabled spellCheck={false} autoFocus margin="dense" id="id" label="Id" type="text" fullWidth value={ this.state._id } onChange={(event)=>{ this.setState({_id: event.target.value}); } } /> */}
+ <TextField disabled={setting.readonly} spellCheck={false} margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.name} onChange={(event) => { this.setState({ name: event.target.value }); }} />
+ <TextField disabled={setting.readonly} spellCheck={false} margin="dense" id="url" label="Url" type="text" fullWidth value={this.state.url} onChange={(event) => { this.setState({ url: event.target.value }); }} />
+
+ <Typography id="errorMessage" component={"div"} color="error">{this.state.errorMessage.map((error, index) => <div key={index}>{error}</div>)}</Typography>
+
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={(event) => {
+
+ if (this.areFieldsValid()) {
+ this.setState({ errorMessage: [] })
+ this.onApply({
+ id: this.state.id,
+ name: this.state.name,
+ url: this.state.url
+ });
+ } else {
+ const errorMessage = this.createErrorMessages()
+ this.setState({ errorMessage: errorMessage })
+ }
+
+ event.preventDefault();
+ event.stopPropagation();
+ }} > {setting.applyButtonText} </Button>
+ <Button onClick={(event) => {
+ this.onCancel();
+ event.preventDefault();
+ event.stopPropagation();
+ }} color="secondary"> {setting.cancelButtonText} </Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+ private onApply = (element: MediatorServer) => {
+ this.props.onClose && this.props.onClose();
+ switch (this.props.mode) {
+ case EditMediatorServerDialogMode.AddMediatorServer:
+ element && this.props.addMediatorServer(element);
+ break;
+ case EditMediatorServerDialogMode.EditMediatorServer:
+ element && this.props.updateMediatorServer(element);
+ break;
+ case EditMediatorServerDialogMode.RemoveMediatorServer:
+ element && this.props.removeMediatorServer(element);
+ break;
+ }
+ };
+
+ private onCancel = () => {
+ this.props.onClose && this.props.onClose();
+ }
+
+ static getDerivedStateFromProps(props: EditMediatorServerDialogComponentProps, state: EditMediatorServerDialogComponentState & { _initialMediatorServer: MediatorServer }): EditMediatorServerDialogComponentState & { _initialMediatorServer: MediatorServer } {
+ if (props.mediatorServer !== state._initialMediatorServer) {
+ state = {
+ ...state,
+ ...props.mediatorServer,
+ _initialMediatorServer: props.mediatorServer,
+ };
+ }
+ return state;
+ }
+}
+
+export const EditMediatorServerDialog = connect(undefined, mapDispatch)(EditMediatorServerDialogComponent);
+export default EditMediatorServerDialog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
new file mode 100644
index 000000000..fd8a2496a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+import { Dialog, DialogTitle, DialogContent, DialogActions, TextField, DialogContentText, Checkbox, Button, FormControlLabel, FormGroup } from '@material-ui/core';
+import { IApplicationState } from '../../../../framework/src/handlers/applicationStateHandler';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect } from '../../../../framework/src/flux/connect';
+import { MediatorConfigResponse } from 'models/mediatorServer';
+import { Panel } from '../../../../framework/src/components/material-ui/panel';
+
+export enum MediatorInfoDialogMode {
+ None = "none",
+ ShowDetails = "showDetails"
+}
+
+const mapProps = (state: IApplicationStoreState) => ({ supportedDevices: state.mediator.mediatorServerState.supportedDevices })
+
+type ShowMediatorInfoDialogComponentProps = Connect<typeof mapProps, undefined> &
+{
+ config: MediatorConfigResponse,
+ mode: MediatorInfoDialogMode,
+ onClose: () => void
+}
+
+type ShowMediatorInfoDialogComponentState = {
+ status: string,
+ devicetype: string,
+ activeOdlConfig: string
+}
+
+/*
+Displays all values of a mediator server
+*/
+class ShowMediatorInfoDialogComponent extends React.Component<ShowMediatorInfoDialogComponentProps, ShowMediatorInfoDialogComponentState> {
+
+ constructor(props: ShowMediatorInfoDialogComponentProps) {
+ super(props);
+ if (this.props.config) {
+ let deviceType = props.supportedDevices.find(element => element.id === this.props.config.DeviceType)
+
+ this.state = {
+ status: props.config.pid > 0 ? "Running" : "Stopped",
+ devicetype: deviceType != undefined ? deviceType.device : 'none',
+ activeOdlConfig: ''
+ }
+ }
+ }
+
+ onClose = (event: React.MouseEvent) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.props.onClose();
+ }
+
+ render() {
+ return (
+ <Dialog open={this.props.mode !== MediatorInfoDialogMode.None} onBackdropClick={this.props.onClose} >
+ <DialogTitle>{this.props.config.Name}</DialogTitle>
+ <DialogContent>
+ <TextField disabled margin="dense" id="deviceIp" label="Device IP" fullWidth defaultValue={this.props.config.DeviceIp} />
+ <TextField disabled margin="dense" id="deviceport" label="Device Port" fullWidth defaultValue={this.props.config.DevicePort} />
+ <TextField disabled margin="dense" id="status" label="Status" fullWidth defaultValue={this.state.status} />
+ <TextField disabled margin="dense" id="deviceType" label="Device Type" fullWidth defaultValue={this.state.devicetype} />
+ <TextField disabled margin="dense" id="ncPort" label="Netconf Port" fullWidth defaultValue={this.props.config.NcPort} />
+ <FormGroup>
+ <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNCConnected}></Checkbox>} label="Netconf Connection" />
+ <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNeConnected}></Checkbox>} label="Network Element Connection" />
+ <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.fwactive}></Checkbox>} label="Firewall active" />
+ </FormGroup>
+ {
+ this.props.config.ODLConfig.map((element, index) =>
+ <Panel title={"ODL config " + (this.props.config.ODLConfig.length > 1 ? index + 1 : '')} key={index} panelId={'panel-' + index} activePanel={this.state.activeOdlConfig} onToggle={(id: string) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); }}>
+ <TextField disabled margin="dense" defaultValue={element.Protocol + '://' + element.Server} label="Server" />
+ <TextField disabled margin="dense" defaultValue={element.Port} label="Port" />
+ <FormControlLabel control={<Checkbox disabled checked={element.Trustall} />} label="Trustall" />
+ </Panel>
+ )
+ }
+
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={this.onClose}>Close</Button>
+ </DialogActions>
+ </Dialog>
+ )
+ }
+
+}
+
+export const ShowMediatorInfoDialog = connect(mapProps)(ShowMediatorInfoDialogComponent)
+export default ShowMediatorInfoDialog; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
new file mode 100644
index 000000000..c22252d20
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/avaliableMediatorServersHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal,IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { MediatorServer } from '../models/mediatorServer';
+import { mediatorServerResourcePath } from '../services/mediatorService';
+
+export interface IAvaliableMediatorServersState extends IExternalTableState<MediatorServer> { }
+
+// create eleactic search material data fetch handler
+const avaliableMediatorServersSearchHandler = createSearchDataHandler<MediatorServer>(mediatorServerResourcePath);
+
+export const {
+ actionHandler: avaliableMediatorServersActionHandler,
+ createActions: createAvaliableMediatorServersActions,
+ createProperties: createAvaliableMediatorServersProperties,
+ reloadAction: avaliableMediatorServersReloadAction,
+
+ // set value action, to change a value
+} = createExternal<MediatorServer>(avaliableMediatorServersSearchHandler, appState => appState.mediator.avaliableMediatorServers); \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
new file mode 100644
index 000000000..2642ec8cd
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorAppRootHandler.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { IAvaliableMediatorServersState, avaliableMediatorServersActionHandler } from './avaliableMediatorServersHandler' ;
+import { MediatorServerState, mediatorServerHandler } from './mediatorServerHandler';
+
+export interface IMediatorAppStoreState {
+ avaliableMediatorServers: IAvaliableMediatorServersState,
+ mediatorServerState: MediatorServerState,
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ mediator: IMediatorAppStoreState
+ }
+}
+
+const actionHandlers = {
+ avaliableMediatorServers: avaliableMediatorServersActionHandler,
+ mediatorServerState: mediatorServerHandler,
+};
+
+export const mediatorAppRootHandler = combineActionHandler<IMediatorAppStoreState>(actionHandlers);
+export default mediatorAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
new file mode 100644
index 000000000..246634cbe
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts
@@ -0,0 +1,120 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { XmlFileInfo, MediatorConfig, BusySymbol, MediatorConfigResponse, MediatorServerDevice } from "../models/mediatorServer";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetMediatorServerVersion, SetMediatorServerInfo, SetAllMediatorServerConfigurations, SetMediatorServerBusy, SetMediatorServerSupportedDevices, SetMediatorServerReachable } from "../actions/mediatorServerActions";
+import { SetMediatorBusyByName, UpdateMediatorConfig, AddMediatorConfig, RemoveMediatorConfig } from "../actions/mediatorConfigActions";
+
+export type MediatorServerState = {
+ busy: boolean;
+ name: string | null;
+ url: string | null;
+ id: string | null;
+ serverVersion: string | null;
+ mediatorVersion: string | null;
+ nexmls: XmlFileInfo[];
+ configurations: MediatorConfigResponse[];
+ supportedDevices: MediatorServerDevice[];
+ isReachable: boolean;
+}
+
+const mediatorServerInit: MediatorServerState = {
+ busy: false,
+ name: null,
+ url: null,
+ id: null,
+ serverVersion: null,
+ mediatorVersion: null,
+ nexmls: [],
+ configurations: [],
+ supportedDevices: [],
+ isReachable: true
+}
+
+export const mediatorServerHandler: IActionHandler<MediatorServerState> = (state = mediatorServerInit, action) => {
+ if (action instanceof SetMediatorServerBusy) {
+ state = {
+ ...state,
+ busy: action.isBusy
+ };
+ } else if (action instanceof SetMediatorServerInfo) {
+ state = {
+ ...state,
+ name: action.name,
+ url: action.url,
+ id: action.id,
+ };
+ } else if (action instanceof SetMediatorServerVersion) {
+ state = {
+ ...state,
+ serverVersion: action.versionInfo && action.versionInfo.server,
+ mediatorVersion: action.versionInfo && action.versionInfo.mediator,
+ nexmls: action.versionInfo && [...action.versionInfo.nexmls] || [],
+ };
+ } else if (action instanceof SetAllMediatorServerConfigurations) {
+ state = {
+ ...state,
+ configurations: action.allConfigurations && action.allConfigurations.map(config => ({ ...config, busy: false })) || [],
+ };
+ } else if (action instanceof SetMediatorServerSupportedDevices) {
+ state = {
+ ...state,
+ supportedDevices: action.devices || [],
+ };
+ } else if (action instanceof SetMediatorBusyByName) {
+ const index = state.configurations.findIndex(config => config.Name === action.name);
+ if (index > -1) state = {
+ ...state,
+ configurations: [
+ ...state.configurations.slice(0, index),
+ { ...state.configurations[index], [BusySymbol]: action.isBusy },
+ ...state.configurations.slice(index + 1)
+ ]
+ };
+ } else if (action instanceof AddMediatorConfig) {
+ state = {
+ ...state,
+ configurations: [
+ ...state.configurations,
+ action.mediatorConfig
+ ]
+ };
+ } else if (action instanceof UpdateMediatorConfig) {
+ const index = state.configurations.findIndex(config => config.Name === action.name);
+ if (index > -1) state = {
+ ...state,
+ configurations: [
+ ...state.configurations.slice(0, index),
+ { ...action.mediatorConfig, [BusySymbol]: state.configurations[index][BusySymbol] },
+ ...state.configurations.slice(index + 1)
+ ]
+ };
+ } else if (action instanceof RemoveMediatorConfig) {
+ const index = state.configurations.findIndex(config => config.Name === action.name);
+ if (index > -1) state = {
+ ...state,
+ configurations: [
+ ...state.configurations.slice(0, index),
+ ...state.configurations.slice(index + 1)
+ ]
+ };
+ } else if( action instanceof SetMediatorServerReachable){
+ state = {...state, isReachable: action.isReachable}
+ }
+ return state;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/index.html b/sdnr/wt/odlux/apps/mediatorApp/src/index.html
new file mode 100644
index 000000000..95bf9ec6b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Mediator App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "mediatorApp" ,"connectApp","inventoryApp","faultApp","helpApp"], function (app, mediatorApp, connectApp,inventoryApp,faultApp,helpApp) {
+ mediatorApp.register();
+ connectApp.register();
+ inventoryApp.register();
+ faultApp.register();
+ helpApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts
new file mode 100644
index 000000000..6ab6db8b3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts
@@ -0,0 +1,77 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type MediatorServer = {
+ id: string;
+ name: string;
+ url: string;
+}
+
+export type XmlFileInfo = {
+ filename: string;
+ version: string;
+}
+
+export type MediatorServerVersionInfo = {
+ mediator: string;
+ server: string;
+ nexmls: XmlFileInfo[];
+}
+
+export type ODLConfig = {
+ User: string;
+ Password: string;
+ Port: number;
+ Protocol: "http" | "https";
+ Server: string;
+ Trustall: boolean;
+};
+
+export const BusySymbol = Symbol("Busy");
+
+export type MediatorConfig = {
+ Name: string;
+ DeviceIp: string;
+ DevicePort: number;
+ DeviceType: number;
+ TrapPort: number;
+ NcUsername: string;
+ NcPassword: string;
+ NcPort: number;
+ NeXMLFile: string;
+ ODLConfig: ODLConfig[];
+}
+
+export type MediatorConfigResponse = MediatorConfig & {
+ IsNCConnected: boolean;
+ IsNeConnected: boolean;
+ autorun: boolean;
+ fwactive: boolean;
+ islocked: boolean;
+ ncconnections:{}[];
+ pid: number;
+ // extended properties
+ [BusySymbol]: boolean;
+}
+
+export type MediatorServerDevice = {
+ id: number; // DeviceType
+ device: string;
+ vendor: string;
+ version: string;
+ xml: string; // NeXMLFile
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
new file mode 100644
index 000000000..5ffd0124b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/plugin.tsx
@@ -0,0 +1,83 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faGlobe } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+
+import { mediatorAppRootHandler } from './handlers/mediatorAppRootHandler';
+import { avaliableMediatorServersReloadAction } from "./handlers/avaliableMediatorServersHandler";
+
+import { MediatorApplication } from "./views/mediatorApplication";
+import { MediatorServerSelection } from "./views/mediatorServerSelection";
+import { initializeMediatorServerAsyncActionCreator } from "./actions/mediatorServerActions";
+
+let currentMediatorServerId: string | undefined = undefined;
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ loadMediatorServer : (mediatorServerId: string) => dispatcher.dispatch(initializeMediatorServerAsyncActionCreator(mediatorServerId)),
+});
+
+const MediatorServerRouteAdapter = connect(undefined, mapDisp)((props: RouteComponentProps<{ mediatorServerId: string }> & Connect<undefined, typeof mapDisp>) => {
+ if (currentMediatorServerId !== props.match.params.mediatorServerId) {
+ // route parameter has changed
+ currentMediatorServerId = props.match.params.mediatorServerId || undefined;
+ // Hint: This timeout is need, since it is not recommended to change the state while rendering is in progress !
+ window.setTimeout(() => {
+ if (currentMediatorServerId) {
+ props.loadMediatorServer(currentMediatorServerId);
+ }
+ });
+ }
+ return (
+ <MediatorApplication />
+ )
+});
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+ <Switch>
+ <Route exact path={ `${ props.match.path }` } component={ MediatorServerSelection } />
+ <Route path={ `${ props.match.path }/:mediatorServerId` } component={ MediatorServerRouteAdapter } />
+ <Redirect to={ `${ props.match.path }` } />
+ </Switch>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+ const applicationApi = applicationManager.registerApplication({
+ name: "mediator",
+ icon: faGlobe,
+ rootComponent: FinalApp,
+ rootActionHandler: mediatorAppRootHandler,
+ menuEntry: "Mediator"
+ });
+
+ // prefetch all avaliable mediator servers
+ applicationApi.applicationStoreInitialized.then(applicationStore => {
+ applicationStore.dispatch(avaliableMediatorServersReloadAction)
+ });
+};
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts
new file mode 100644
index 000000000..aee086689
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts
@@ -0,0 +1,204 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as $ from 'jquery';
+
+import { requestRest, formEncode } from '../../../../framework/src/services/restService';
+import { MediatorServer, MediatorServerVersionInfo, MediatorConfig, MediatorServerDevice, MediatorConfigResponse } from '../models/mediatorServer';
+import { PostResponse, DeleteResponse, Result } from '../../../../framework/src/models';
+
+export const mediatorServerResourcePath = "mediator-server";
+
+type MediatorServerResponse<TData> = { code: number, data: TData };
+type IndexableMediatorServer = MediatorServer & { [key: string]: any; };
+
+/**
+ * Represents a web api accessor service for all mediator server actions.
+ */
+class MediatorService {
+ /**
+ * Inserts data into the mediator servers table.
+ */
+ public async insertMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> {
+ const path = `/restconf/operations/data-provider:create-mediator-server`;
+
+ const data = {
+ "url": server.url,
+ "name": server.name
+ }
+
+ const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+ return result || null;
+ }
+
+ /**
+ * Updates data into the mediator servers table.
+ */
+ public async updateMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> {
+ const path = `/restconf/operations/data-provider:update-mediator-server`;
+
+ const data = {
+ "id": server.id,
+ "url": server.url,
+ "name": server.name
+ }
+
+ const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+ return result || null;
+ }
+
+ /**
+ * Deletes data from the mediator servers table.
+ */
+ public async deleteMediatorServer(server: MediatorServer): Promise<DeleteResponse | null> {
+ const path = `/restconf/operations/data-provider:delete-mediator-server`;
+
+ const data = {
+ "id": server.id,
+ }
+
+ const result = await requestRest<DeleteResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+ return result || null;
+ }
+
+ public async getMediatorServerById(serverId: string): Promise<MediatorServer | null> {
+ const path = `/restconf/operations/data-provider:read-mediator-server-list`;
+
+ const data = { "filter": [{ "property": "id", "filtervalue": serverId }] }
+
+
+ const result = await requestRest<Result<MediatorServer>>(path, { method: "POST", body: JSON.stringify({ input: data }) });
+
+ if (result && result.output.data[0]) {
+ const firstResult = result.output.data[0];
+
+ return {
+ id: firstResult.id,
+ name: firstResult.name,
+ url: firstResult.url
+ }
+ }
+ else {
+ return null;
+ }
+ }
+
+ // https://cloud-highstreet-technologies.com/wiki/doku.php?id=att:ms:api
+
+ private async accassMediatorServer<TData = {}>(mediatorServerId: string, task: string, data?: {}): Promise<MediatorServerResponse<TData> | null> {
+ const path = `ms/${mediatorServerId}/api/'?task=${task}`;
+ const result = (await requestRest<string>(path, {
+ method: data ? "POST" : "GET",
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ body: data ? formEncode({
+ ...data,
+ ...{ task: task }
+ }) : null
+ }, true)) || null;
+
+ return result ? JSON.parse(result) as { code: number, data: TData } : null;
+ }
+ /*
+ private accassMediatorServer<TData = {}>(mediatorServerId: string, task: string, data?: {}): Promise<MediatorServerResponse<TData> | null> {
+ const path = `ms/${mediatorServerId}/api/?task=${task}`;
+ return new Promise<{ code: number, data: TData }>((resolve, reject) => {
+ $.ajax({
+ method: data ? 'POST' : 'GET',
+ url: path,
+ data: { ...{ task: task }, ...data },
+ //contentType: 'application/json'
+ }).then((result: any) => {
+ if (typeof result === "string") {
+ resolve(JSON.parse(result));
+ } else {
+ resolve(result);
+ };
+ });
+ });
+ }*/
+
+ public async getMediatorServerVersion(mediatorServerId: string): Promise<MediatorServerVersionInfo | null> {
+ const result = await this.accassMediatorServer<MediatorServerVersionInfo>(mediatorServerId, 'version');
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async getMediatorServerAllConfigs(mediatorServerId: string): Promise<MediatorConfigResponse[] | null> {
+ const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerId, 'getconfig');
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async getMediatorServerConfigByName(mediatorServerId: string, name: string): Promise<MediatorConfigResponse | null> {
+ const result = await this.accassMediatorServer<MediatorConfigResponse[]>(mediatorServerId, `getconfig&name=${name}`);
+ if (result && result.code === 1 && result.data && result.data.length === 1) return result.data[0];
+ return null;
+ }
+
+ public async getMediatorServerSupportedDevices(mediatorServerId: string): Promise<MediatorServerDevice[] | null> {
+ const result = await this.accassMediatorServer<MediatorServerDevice[]>(mediatorServerId, 'getdevices');
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async startMediatorByName(mediatorServerId: string, name: string): Promise<string | null> {
+ const result = await this.accassMediatorServer<string>(mediatorServerId, `start&name=${name}`);
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async stopMediatorByName(mediatorServerId: string, name: string): Promise<string | null> {
+ const result = await this.accassMediatorServer<string>(mediatorServerId, `stop&name=${name}`);
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async createMediatorConfig(mediatorServerId: string, config: MediatorConfig): Promise<string | null> {
+ const result = await this.accassMediatorServer<string>(mediatorServerId, 'create', { config: JSON.stringify(config) });
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async updateMediatorConfigByName(mediatorServerId: string, config: MediatorConfig): Promise<string | null> {
+ const result = await this.accassMediatorServer<string>(mediatorServerId, 'update', { config: JSON.stringify(config) });
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async deleteMediatorConfigByName(mediatorServerId: string, name: string): Promise<string | null> {
+ const result = await this.accassMediatorServer<string>(mediatorServerId, `delete&name=${name}`);
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async getMediatorServerFreeNcPorts(mediatorServerId: string, limit?: number): Promise<number[] | null> {
+ const result = await this.accassMediatorServer<number[]>(mediatorServerId, 'getncports', { limit });
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+
+ public async getMediatorServerFreeSnmpPorts(mediatorServerId: string, limit?: number): Promise<number[] | null> {
+ const result = await this.accassMediatorServer<number[]>(mediatorServerId, 'getsnmpports', { limit });
+ if (result && result.code === 1) return result.data;
+ return null;
+ }
+}
+
+export const mediatorService = new MediatorService;
+export default mediatorService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
new file mode 100644
index 000000000..945e13507
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -0,0 +1,276 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { Theme, createStyles, WithStyles, withStyles, Tooltip } from '@material-ui/core';
+
+import AddIcon from '@material-ui/icons/Add';
+import IconButton from '@material-ui/core/IconButton';
+import EditIcon from '@material-ui/icons/Edit';
+import DeleteIcon from '@material-ui/icons/Delete';
+import InfoIcon from '@material-ui/icons/Info';
+import StartIcon from '@material-ui/icons/PlayArrow';
+import StopIcon from '@material-ui/icons/Stop';
+
+import CircularProgress from '@material-ui/core/CircularProgress'
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/mediatorServer';
+import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog';
+import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions';
+import mediatorService from '../services/mediatorService';
+import { ShowMediatorInfoDialog, MediatorInfoDialogMode } from '../components/showMeditaorInfoDialog'
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ display: 'flex',
+ flexDirection: 'column',
+ flex: '1',
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 300,
+ },
+ button: {
+ margin: 0,
+ padding: "6px 6px",
+ minWidth: 'unset'
+ },
+ spacer: {
+ marginLeft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ display: "inline"
+ },
+ progress: {
+ flex: '1 1 100%',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ pointerEvents: 'none'
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ serverName: state.mediator.mediatorServerState.name,
+ serverUrl: state.mediator.mediatorServerState.url,
+ serverId: state.mediator.mediatorServerState.id,
+ serverVersion: state.mediator.mediatorServerState.serverVersion,
+ mediatorVersion: state.mediator.mediatorServerState.mediatorVersion,
+ configurations: state.mediator.mediatorServerState.configurations,
+ supportedDevices: state.mediator.mediatorServerState.supportedDevices,
+ busy: state.mediator.mediatorServerState.busy,
+ isReachable: state.mediator.mediatorServerState.isReachable
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ startMediator: (name: string) => dispatcher.dispatch(startMediatorByNameAsyncActionCreator(name)),
+ stopMediator: (name: string) => dispatcher.dispatch(stopMediatorByNameAsyncActionCreator(name)),
+});
+
+const emptyMediatorConfig: MediatorConfig = {
+ Name: "",
+ DeviceIp: "127.0.0.1",
+ DevicePort: 161,
+ NcUsername: "admin",
+ NcPassword: "admin",
+ DeviceType: -1,
+ NcPort: 4020,
+ TrapPort: 10020,
+ NeXMLFile: "",
+ ODLConfig: []
+};
+
+const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>;
+const MediatorServerUnreachableTable = MaterialTable as MaterialTableCtorType<{ Name: string, status: string, ipAdress: string, device: string, actions: string }>
+
+type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+ busy: boolean,
+ mediatorConfigToEdit: MediatorConfig,
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode,
+ mediatorShowInfoMode: MediatorInfoDialogMode,
+ mediatorConfigToDisplay: MediatorConfigResponse | null
+}
+
+class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> {
+
+ constructor(props: MediatorApplicationComponentProps) {
+ super(props);
+
+ this.state = {
+ busy: false,
+ mediatorConfigToEdit: emptyMediatorConfig,
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
+ mediatorShowInfoMode: MediatorInfoDialogMode.None,
+ mediatorConfigToDisplay: null
+ }
+ }
+
+ render() {
+ const { classes } = this.props;
+
+ const renderActions = (rowData: MediatorConfigResponse) => (
+ <>
+ <div className={classes.spacer}>
+ <Tooltip title={"Start"} >
+ <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
+ <StartIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.startMediator(rowData.Name); }} />
+ </IconButton>
+ </Tooltip>
+ <Tooltip title={"Stop"} >
+ <IconButton disabled={rowData[BusySymbol]} className={classes.button}>
+ <StopIcon onClick={(event) => { event.preventDefault(); event.stopPropagation(); this.props.stopMediator(rowData.Name); }} />
+ </IconButton>
+ </Tooltip>
+ </div>
+ <div className={classes.spacer}>
+ <Tooltip title={"Info"} ><IconButton className={classes.button} onClick={(event) => { this.onOpenInfoDialog(event, rowData) }}><InfoIcon /></IconButton></Tooltip>
+ </div>
+ <div className={classes.spacer}>
+ {process.env.NODE_ENV === "development" ? <Tooltip title={"Edit"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}><EditIcon /></IconButton></Tooltip> : null}
+ <Tooltip title={"Remove"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenRemoveConfigutationDialog(event, rowData)}><DeleteIcon /></IconButton></Tooltip>
+ </div>
+ </>
+ );
+
+ const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', onClick: this.onOpenAddConfigurationDialog };
+
+ return (
+ <div className={classes.root}>
+ {this.props.busy || this.state.busy
+ ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div>
+ :
+
+ this.props.isReachable ?
+
+ <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
+ { property: "Name", title: "Mediator", type: ColumnType.text },
+ { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
+ { property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
+ {
+ property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => {
+ const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType);
+ return (
+ <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span>
+ )
+ }
+ },
+ { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) },
+ ]} />
+ :
+ <MediatorServerUnreachableTable title={this.props.serverName || ''} idProperty={"Name"} disableFilter={true} disableSorting={true} enableSelection={false} rows={[{ Name: '', status: "Mediator server not found.", ipAdress: '', device: '', actions: '' }]} columns={[
+ { property: "Name", title: "Mediator", type: ColumnType.text },
+ { property: "status", title: "Status", type: ColumnType.text },
+ { property: "ipAdress", title: "IP Adress", type: ColumnType.text },
+ { property: "device", title: "Device", type: ColumnType.text },
+ { property: "actions", title: "Actions", type: ColumnType.text },
+
+ ]} />
+ }
+
+ <EditMediatorConfigDialog
+ mediatorConfig={this.state.mediatorConfigToEdit}
+ mode={this.state.mediatorConfigEditorMode}
+ onClose={this.onCloseEditMediatorConfigDialog} />
+
+ {
+
+ this.state.mediatorShowInfoMode != MediatorInfoDialogMode.None &&
+ <ShowMediatorInfoDialog
+ config={this.state.mediatorConfigToDisplay as MediatorConfigResponse}
+ mode={this.state.mediatorShowInfoMode}
+ onClose={this.onCloseInfoDialog} />
+ }
+ </div>
+ );
+ }
+
+ private onOpenInfoDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfigResponse) => {
+ event.stopPropagation();
+ event.preventDefault();
+ this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.ShowDetails, mediatorConfigToDisplay: configEntry })
+ }
+
+ private onCloseInfoDialog = () => {
+ this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.None, mediatorConfigToDisplay: null })
+ }
+
+ private onOpenAddConfigurationDialog = () => {
+ // Tries to determine a free port for netconf listener and snpm listener
+ // it it could not determine free ports the dialog will open any way
+ // those ports should not be configured from the fontend, furthermore
+ // the backend should auto configure them and tell the user the result
+ // after the creation process.
+ this.setState({
+ busy: true,
+ });
+ this.props.serverId && Promise.all([
+ mediatorService.getMediatorServerFreeNcPorts(this.props.serverId, 1),
+ mediatorService.getMediatorServerFreeSnmpPorts(this.props.serverId, 1),
+ ]).then(([freeNcPorts, freeSnmpPorts]) => {
+ if (freeNcPorts && freeSnmpPorts && freeNcPorts.length > 0 && freeSnmpPorts.length > 0) {
+ this.setState({
+ busy: false,
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
+ mediatorConfigToEdit: {
+ ...emptyMediatorConfig,
+ NcPort: freeNcPorts[0],
+ TrapPort: freeSnmpPorts[0],
+ },
+ });
+ } else {
+ this.setState({
+ busy: false,
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.AddMediatorConfig,
+ mediatorConfigToEdit: { ...emptyMediatorConfig },
+ });
+ }
+ })
+
+ }
+
+ private onOpenEditConfigurationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.setState({
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.EditMediatorConfig,
+ mediatorConfigToEdit: configEntry,
+ });
+ }
+
+ private onOpenRemoveConfigutationDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfig) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.setState({
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.RemoveMediatorConfig,
+ mediatorConfigToEdit: configEntry,
+ });
+ }
+
+ private onCloseEditMediatorConfigDialog = () => {
+ this.setState({
+ mediatorConfigEditorMode: EditMediatorConfigDialogMode.None,
+ mediatorConfigToEdit: emptyMediatorConfig,
+ });
+ }
+}
+
+export const MediatorApplication = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorApplicationComponent));
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
new file mode 100644
index 000000000..a5b34a2dc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -0,0 +1,157 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { WithStyles, withStyles, createStyles, Theme, Tooltip } from '@material-ui/core';
+
+import AddIcon from '@material-ui/icons/Add';
+import IconButton from '@material-ui/core/IconButton';
+import EditIcon from '@material-ui/icons/Edit';
+import DeleteIcon from '@material-ui/icons/Delete';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import MaterialTable, { MaterialTableCtorType, ColumnType } from '../../../../framework/src/components/material-table';
+
+import { createAvaliableMediatorServersProperties, createAvaliableMediatorServersActions } from '../handlers/avaliableMediatorServersHandler';
+
+import { MediatorServer } from '../models/mediatorServer';
+import EditMediatorServerDialog, { EditMediatorServerDialogMode } from '../components/editMediatorServerDialog';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+const MediatorServersTable = MaterialTable as MaterialTableCtorType<MediatorServer>;
+
+const styles = (theme: Theme) => createStyles({
+ button: {
+ margin: 0,
+ padding: "6px 6px",
+ minWidth: 'unset',
+ },
+ spacer: {
+ marginLeft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ display: "inline",
+ },
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ mediatorServersProperties: createAvaliableMediatorServersProperties(state),
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ mediatorServersActions: createAvaliableMediatorServersActions(dispatcher.dispatch),
+ selectMediatorServer: (mediatorServerId: string) => mediatorServerId && dispatcher.dispatch(new NavigateToApplication("mediator", mediatorServerId)),
+});
+
+const emptyMediatorServer: MediatorServer = {
+ id: "",
+ name: "",
+ url: ""
+};
+
+type MediatorServerSelectionComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>;
+
+type MediatorServerSelectionComponentState = {
+ mediatorServerToEdit: MediatorServer,
+ mediatorServerEditorMode: EditMediatorServerDialogMode
+}
+
+class MediatorServerSelectionComponent extends React.Component<MediatorServerSelectionComponentProps, MediatorServerSelectionComponentState> {
+
+ constructor(props: MediatorServerSelectionComponentProps) {
+ super(props);
+
+ this.state = {
+ mediatorServerEditorMode: EditMediatorServerDialogMode.None,
+ mediatorServerToEdit: emptyMediatorServer,
+ }
+ }
+
+ render() {
+ const { classes } = this.props;
+
+ const addMediatorServerActionButton = {
+ icon: AddIcon, tooltip: 'Add', onClick: () => {
+ this.setState({
+ mediatorServerEditorMode: EditMediatorServerDialogMode.AddMediatorServer,
+ mediatorServerToEdit: emptyMediatorServer,
+ });
+ }
+ };
+ return (
+ <>
+ <MediatorServersTable title={"Mediator"} customActionButtons={[addMediatorServerActionButton]} idProperty={"id"}
+ {...this.props.mediatorServersActions} {...this.props.mediatorServersProperties} columns={[
+ { property: "name", title: "Name", type: ColumnType.text },
+ { property: "url", title: "Url", type: ColumnType.text },
+ {
+ property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => (
+ <div className={classes.spacer}>
+ <Tooltip title={"Edit"} ><IconButton className={classes.button} onClick={event => { this.onEditMediatorServer(event, rowData); }}><EditIcon /></IconButton></Tooltip>
+ <Tooltip title={"Remove"} ><IconButton className={classes.button} onClick={event => { this.onRemoveMediatorServer(event, rowData); }}><DeleteIcon /></IconButton></Tooltip>
+ </div>
+ )
+ }
+ ]} onHandleClick={this.onSelectMediatorServer} />
+ <EditMediatorServerDialog
+ mediatorServer={this.state.mediatorServerToEdit}
+ mode={this.state.mediatorServerEditorMode}
+ onClose={this.onCloseEditMediatorServerDialog} />
+ </>
+ );
+ }
+
+ public componentDidMount() {
+ this.props.mediatorServersActions.onToggleFilter();
+ }
+
+ private onSelectMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.props.selectMediatorServer(server && server.id);
+
+ }
+
+ private onEditMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.setState({
+ mediatorServerEditorMode: EditMediatorServerDialogMode.EditMediatorServer,
+ mediatorServerToEdit: server,
+ });
+ }
+
+ private onRemoveMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.setState({
+ mediatorServerEditorMode: EditMediatorServerDialogMode.RemoveMediatorServer,
+ mediatorServerToEdit: server,
+ });
+ }
+
+ private onCloseEditMediatorServerDialog = () => {
+ this.setState({
+ mediatorServerEditorMode: EditMediatorServerDialogMode.None,
+ mediatorServerToEdit: emptyMediatorServer,
+ });
+ }
+}
+
+
+export const MediatorServerSelection = withStyles(styles)(connect(mapProps, mapDispatch)(MediatorServerSelectionComponent));
+export default MediatorServerSelection; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..c11492bc4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="mediatorApp"/>
+ <property name="index" value="90"/>
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/mediatorApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..d0fbe63c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/mediatorApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
new file mode 100644
index 000000000..b0c9b424d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/tsconfig.json
@@ -0,0 +1,38 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "node",
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/mediatorApp/tslint.json b/sdnr/wt/odlux/apps/mediatorApp/tslint.json
new file mode 100644
index 000000000..b5143e92c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/tslint.json
@@ -0,0 +1,4 @@
+{
+ "rules":{
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
new file mode 100644
index 000000000..3efe2d015
--- /dev/null
+++ b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js
@@ -0,0 +1,158 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ mediatorApp: ["./plugin.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/database/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/restconf/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/help/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/ms/": {
+ target: "http://10.20.6.29:28181",
+ secure: false
+ },
+ "/websocket": {
+ target: "http://10.20.6.29:28181",
+ ws: true,
+ changeOrigin: true,
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/.babelrc b/sdnr/wt/odlux/apps/minimumApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/package.json b/sdnr/wt/odlux/apps/minimumApp/package.json
new file mode 100644
index 000000000..d9b18a3ce
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@odlux/minimum-app",
+ "version": "0.1.0",
+ "description": "A react based modular UI to demo the minimum possible app.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/pom.xml b/sdnr/wt/odlux/apps/minimumApp/pom.xml
new file mode 100644
index 000000000..dc9507c9b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-minimumApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-minimumApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
new file mode 100644
index 000000000..463ad21e2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/handlers/minimumAppRootHandler.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+export interface IMinimumAppStoreState {
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ minimum: IMinimumAppStoreState
+ }
+}
+
+const actionHandlers = {
+};
+
+export const minimumAppRootHandler = combineActionHandler<IMinimumAppStoreState>(actionHandlers);
+export default minimumAppRootHandler;
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/index.html b/sdnr/wt/odlux/apps/minimumApp/src/index.html
new file mode 100644
index 000000000..58865edc1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css"> -->
+ <title>Minimal App</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "minimumApp"], function (app) {
+ app("./app.tsx")
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
new file mode 100644
index 000000000..3095ba783
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src/plugin.tsx
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// app configuration and main entry point for the app
+
+import * as React from "react";
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+
+import { faLock } from '@fortawesome/free-solid-svg-icons'; // select app icon
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+import connect, { Connect } from '../../../framework/src/flux/connect';
+
+import { minimumAppRootHandler } from './handlers/minimumAppRootHandler';
+
+type AppProps = RouteComponentProps & Connect;
+
+const App = (props: AppProps) => (
+ <div>Start your app here!!</div>
+);
+
+const FinalApp = withRouter(connect()(App));
+
+export function register() {
+ applicationManager.registerApplication({
+ name: "minimum",
+ icon: faLock,
+ rootComponent: FinalApp,
+ rootActionHandler: minimumAppRootHandler,
+ menuEntry: "Minimum"
+ });
+}
+
+
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..4c8ed1343
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="minimumApp"/>
+ <property name="index" value="999" />
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/minimumApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..d0fbe63c0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/minimumApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/minimumApp/tsconfig.json b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/minimumApp/webpack.config.js b/sdnr/wt/odlux/apps/minimumApp/webpack.config.js
new file mode 100644
index 000000000..64a534464
--- /dev/null
+++ b/sdnr/wt/odlux/apps/minimumApp/webpack.config.js
@@ -0,0 +1,136 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ minimumApp: ["./plugin.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/api": {
+ target: "http://localhost:3001",
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/.babelrc b/sdnr/wt/odlux/apps/performanceHistoryApp/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
new file mode 100644
index 000000000..1e6adf7c3
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "@odlux/performancehistory-app",
+ "version": "0.1.1",
+ "description": "A react based modular UI to display performance history data from a database.",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "build": "webpack --env release --config webpack.config.js",
+ "build:dev": "webpack --env debug --config webpack.config.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Sai Neetha Phulmali",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@odlux/framework": "*",
+ "@odlux/connect-app": "*",
+ "react-chartjs-2": "2.7.6",
+ "chart.js": "2.8.0"
+ },
+ "peerDependencies": {
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
new file mode 100644
index 000000000..b6ede0c36
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-app-performanceHistoryApp</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>sdnr-wt-odlux-app-performanceHistoryApp</name>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src2/main/java</sourceDirectory>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>src2/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.model.*,com.opensymphony.*</Import-Package>
+ <Private-Package/>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ <resource>
+ <directory>src2/main/resources</directory>
+ </resource>
+ <resource>
+ <directory>src2/test/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
new file mode 100644
index 000000000..9637fec81
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/deviceListActions.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { DeviceListType } from '../models/deviceListType';
+import { PerformanceHistoryService } from '../services/performanceHistoryService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load all devices.
+ */
+export class LoadAllDeviceListAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to update all devices.
+ */
+export class AllDeviceListLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ *
+ * @param deviceList All the distinct devices from the performance history database.
+ */
+ constructor(public deviceList: DeviceListType[] | null, public error?: string) {
+ super();
+ }
+}
+
+/**
+ * Represents an asynchronous thunk action to load all devices.
+ */
+export const loadAllDeviceListAsync = async (dispatch: Dispatch) => {
+ dispatch(new LoadAllDeviceListAction());
+ const deviceListFromPerfHistory: DeviceListType[] = await PerformanceHistoryService.getDeviceListfromPerf15minHistory().then(ne => (ne)) || [];
+ const deviceListFromPerf24History: DeviceListType[] = await PerformanceHistoryService.getDeviceListfromPerf24hHistory().then(ne => (ne)) || [];
+ deviceListFromPerf24History.forEach(deviceList24h => {
+ if (deviceListFromPerfHistory.findIndex(deviceList15min => deviceList15min.nodeId === deviceList24h.nodeId) < 0) {
+ deviceListFromPerfHistory.push(deviceList24h);
+ };
+ });
+ return deviceListFromPerfHistory && dispatch(new AllDeviceListLoadedAction(deviceListFromPerfHistory));
+};
+
+/**
+ * Represents an action causing the store to update mountId.
+ */
+export class UpdateMountId extends BaseAction {
+ constructor(public nodeId?: string) {
+ super();
+ }
+}
+
+/**
+ * Represents an asynchronous thunk action to load updated mountId.
+ */
+export const updateMountIdActionCreator = (nodeId: string) => async (dispatch: Dispatch) => {
+ return dispatch(new UpdateMountId(nodeId));
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
new file mode 100644
index 000000000..2741d889a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { LtpIds } from '../models/availableLtps';
+import { PerformanceHistoryService } from '../services/performanceHistoryService';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+/**
+ * Represents an action causing the store to load available ltps.
+ */
+export class LoadAllAvailableLtpsAction extends BaseAction { }
+
+/**
+ * Represents an action causing the store to update available ltps.
+ */
+export class AllAvailableLtpsLoadedAction extends BaseAction {
+ /**
+ * Initialize this instance.
+ * @param availableLtps The available ltps which are returned from the database.
+ */
+ constructor(public availableLtps: LtpIds[] | null, public error?: string) {
+ super();
+ }
+}
+
+
+/**
+ * Represents an asynchronous thunk action to load available distinctLtps by networkElement from the database and set the returned first Ltp as default.
+ * @param networkElement The network element sent to database to get its available distinct Ltps.
+ * @param selectedTimePeriod The time period selected sent to database to get the distinct Ltps of the selected network element.
+ * @param selectedLtp The Ltp which is selected in the dropdown.
+ * @param selectFirstLtp The function to get the first ltp returned from the database to be selected as default on selection upon network element.
+ * @param resetLtp The function to verify if the selected ltp is also available in the selected time period database else reset the Ltp dropdown to select.
+ */
+export const loadDistinctLtpsbyNetworkElementAsync = (networkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => (dispatch: Dispatch) => {
+ dispatch(new LoadAllAvailableLtpsAction());
+ PerformanceHistoryService.getDistinctLtpsFromDatabase(networkElement, selectedTimePeriod).then(distinctLtps => {
+ if (distinctLtps) {
+ const ltps = getDistinctLtps(distinctLtps, selectedLtp, selectFirstLtp, resetLtp);
+ dispatch(new AllAvailableLtpsLoadedAction(ltps));
+ }
+ }).catch(error => {
+ dispatch(new AllAvailableLtpsLoadedAction(null, error));
+ });
+};
+
+const getDistinctLtps = (distinctLtps: LtpIds[], selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => {
+ let ltpNotSelected: boolean = true;
+ selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
+ distinctLtps.forEach((value: LtpIds) => {
+ if (value.key === selectedLtp) {
+ ltpNotSelected = false;
+ }
+ });
+ resetLtp && resetLtp(ltpNotSelected);
+ return distinctLtps;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts
new file mode 100644
index 000000000..8b77cb3b0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/panelChangeActions.ts
@@ -0,0 +1,32 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { PanelId } from '../models/panelId';
+
+/**
+ * Represents an action causing the store to update the panel.
+ */
+export class SetPanelAction extends Action {
+ /**
+ * Initialize this instance.
+ * @param panelId Action to set the current panel by its Id.
+ */
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
new file mode 100644
index 000000000..a069af13c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/timeChangeAction.ts
@@ -0,0 +1,29 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../../../../framework/src/flux/action';
+import { PmDataInterval } from '../models/performanceDataType';
+
+export class TimeChangeAction extends Action {
+ /**
+ * Initialize this instance.
+ * @param time Action to set the time interval in dropdown.
+ */
+ constructor(public time: PmDataInterval) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
new file mode 100644
index 000000000..09d3accd4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
@@ -0,0 +1,469 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { AdaptiveModulationDataType, AdaptiveModulationDatabaseDataType } from '../models/adaptiveModulationDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createAdaptiveModulationProperties, createAdaptiveModulationActions } from '../handlers/adaptiveModulationHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ adaptiveModulationProperties: createAdaptiveModulationProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch),
+});
+
+type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType<AdaptiveModulationDataType>;
+
+/**
+ * The Component which gets the adaptiveModulation data from the database based on the selected time period.
+ */
+class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.adaptiveModulationProperties;
+ const actions = this.props.adaptiveModulationActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+ const adaptiveModulationColumns: ColumnModel<AdaptiveModulationDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }];
+
+ chartPagedData.datasets.forEach(ds => {
+ adaptiveModulationColumns.push(addColumnLabels<AdaptiveModulationDataType>(ds.name, ds.columnLabel));
+ });
+
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <AdaptiveModulationTable idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for Adaptive modulation according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+
+ private getChartDataValues = (rows: AdaptiveModulationDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "time2StatesS",
+ label: "QAM2S",
+ borderColor: '#62a309fc',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2S",
+ }, {
+ name: "time2States",
+ label: "QAM2",
+ borderColor: '#62a309fc',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2",
+ }, {
+ name: "time2StatesL",
+ label: "QAM2L",
+ borderColor: '#62a309fc',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2L",
+ }, {
+ name: "time4StatesS",
+ label: "QAM4S",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4S",
+ }, {
+ name: "time4States",
+ label: "QAM4",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4",
+ }, {
+ name: "time4StatesL",
+ label: "QAM4L",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4L",
+ }, {
+ name: "time16StatesS",
+ label: "QAM16S",
+ borderColor: '#9b15e2',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM16S",
+ }, {
+ name: "time16States",
+ label: "QAM16",
+ borderColor: '#9b15e2',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM16",
+ }, {
+ name: "time16StatesL",
+ label: "QAM16L",
+ borderColor: '#9b15e2',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM16L",
+ }, {
+ name: "time32StatesS",
+ label: "QAM32S",
+ borderColor: '#2704f5f0',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM32S",
+ }, {
+ name: "time32States",
+ label: "QAM32",
+ borderColor: '#2704f5f0',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM32",
+ }, {
+ name: "time32StatesL",
+ label: "QAM32L",
+ borderColor: '#2704f5f0',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM32L",
+ }, {
+ name: "time64StatesS",
+ label: "QAM64S",
+ borderColor: '#347692',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM64S",
+ }, {
+ name: "time64States",
+ label: "QAM64",
+ borderColor: '#347692',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM64",
+ }, {
+ name: "time64StatesL",
+ label: "QAM64L",
+ borderColor: '#347692',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM64L",
+ }, {
+ name: "time128StatesS",
+ label: "QAM128S",
+ borderColor: '#885e22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM128S",
+ }, {
+ name: "time128States",
+ label: "QAM128",
+ borderColor: '#885e22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM128",
+ }, {
+ name: "time128StatesL",
+ label: "QAM128L",
+ borderColor: '#885e22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM128L",
+ }, {
+ name: "time256StatesS",
+ label: "QAM256S",
+ borderColor: '#de07807a',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM256S",
+ }, {
+ name: "time256States",
+ label: "QAM256",
+ borderColor: '#de07807a',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM256",
+ }, {
+ name: "time256StatesL",
+ label: "QAM256L",
+ borderColor: '#de07807a',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM256L",
+ }, {
+ name: "time512StatesS",
+ label: "QAM512S",
+ borderColor: '#8fdaacde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM512S",
+ }, {
+ name: "time512States",
+ label: "QAM512",
+ borderColor: '#8fdaacde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM512",
+ }, {
+
+ name: "time512StatesL",
+ label: "QAM512L",
+ borderColor: '#8fdaacde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM512L",
+ }, {
+
+ name: "time1024StatesS",
+ label: "QAM1024S",
+ borderColor: '#435b22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM1024S",
+ }, {
+
+ name: "time1024States",
+ label: "QAM1024",
+ borderColor: '#435b22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM1024",
+ }, {
+
+ name: "time1024StatesL",
+ label: "QAM1024L",
+ borderColor: '#435b22',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM1024L",
+ }, {
+ name: "time2048StatesS",
+ label: "QAM2048S",
+ borderColor: '#e87a5b',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2048S",
+ }, {
+ name: "time2048States",
+ label: "QAM2048",
+ borderColor: '#e87a5b',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2048",
+ }, {
+ name: "time2048StatesL",
+ label: "QAM2048L",
+ borderColor: '#e87a5b',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM2048L",
+ }, {
+ name: "time4096StatesS",
+ label: "QAM4096S",
+ borderColor: '#5be878',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4096S",
+ }, {
+ name: "time4096States",
+ label: "QAM4096",
+ borderColor: '#5be878',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4096",
+ }, {
+ name: "time4096StatesL",
+ label: "QAM4096L",
+ borderColor: '#5be878',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM4096L",
+ }, {
+ name: "time8192StatesS",
+ label: "QAM8192s",
+ borderColor: '#cb5be8',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM8192S",
+ }, {
+ name: "time8192States",
+ label: "QAM8192",
+ borderColor: '#cb5be8',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM8192",
+ }, {
+ name: "time8192StatesL",
+ label: "QAM8192L",
+ borderColor: '#cb5be8',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "QAM8192L",
+ }
+ ];
+
+ _rows.forEach(row => {
+ row.time2StatesS = row.performanceData.time2StatesS
+ row.time2States = row.performanceData.time2States;
+ row.time2StatesL = row.performanceData.time2StatesL;
+ row.time4StatesS = row.performanceData.time4StatesS
+ row.time4States = row.performanceData.time4States;
+ row.time4StatesL = row.performanceData.time4StatesL;
+ row.time16StatesS = row.performanceData.time16StatesS;
+ row.time16States = row.performanceData.time16States;
+ row.time16StatesL = row.performanceData.time16StatesL;
+ row.time32StatesS = row.performanceData.time32StatesS;
+ row.time32States = row.performanceData.time32States;
+ row.time32StatesL = row.performanceData.time32StatesL;
+ row.time64StatesS = row.performanceData.time64StatesS;
+ row.time64States = row.performanceData.time64States;
+ row.time64StatesL = row.performanceData.time64StatesL;
+ row.time128StatesS = row.performanceData.time128StatesS;
+ row.time128States = row.performanceData.time128States;
+ row.time128StatesL = row.performanceData.time128StatesL;
+ row.time256StatesS = row.performanceData.time256StatesS;
+ row.time256States = row.performanceData.time256States;
+ row.time256StatesL = row.performanceData.time256StatesL;
+ row.time512StatesS = row.performanceData.time512StatesS;
+ row.time512States = row.performanceData.time512States;
+ row.time512StatesL = row.performanceData.time512StatesL;
+ row.time1024StatesS = row.performanceData.time1024StatesS;
+ row.time1024States = row.performanceData.time1024States;
+ row.time1024StatesL = row.performanceData.time1024StatesL;
+ row.time2048StatesS = row.performanceData.time2048StatesS;
+ row.time2048States = row.performanceData.time2048States;
+ row.time2048StatesL = row.performanceData.time2048StatesL;
+ row.time4096StatesS = row.performanceData.time4096StatesS;
+ row.time4096States = row.performanceData.time4096States;
+ row.time4096StatesL = row.performanceData.time4096StatesL;
+ row.time8192StatesS = row.performanceData.time8192StatesS;
+ row.time8192States = row.performanceData.time8192States;
+ row.time8192StatesL = row.performanceData.time8192StatesL;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof AdaptiveModulationDataType] as string,
+ y: row.performanceData[ds.name as keyof AdaptiveModulationDatabaseDataType] as string
+ });
+ });
+ });
+
+ return {
+ datasets: datasets
+ };
+ }
+}
+const AdaptiveModulation = withRouter(connect(mapProps, mapDisp)(AdaptiveModulationComponent));
+export default AdaptiveModulation;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
new file mode 100644
index 000000000..267e00bbe
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
@@ -0,0 +1,133 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, MaterialTableCtorType, ColumnModel } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { CrossPolarDiscriminationDataType, CrossPolarDiscriminationDatabaseDataType } from '../models/crossPolarDiscriminationDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createCrossPolarDiscriminationProperties, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch),
+});
+
+type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<CrossPolarDiscriminationDataType>;
+
+/**
+ * The Component which gets the crossPolarDiscrimination data from the database based on the selected time period.
+ */
+class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.crossPolarDiscriminationProperties;
+ const actions = this.props.crossPolarDiscriminationActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+
+ const cpdColumns: ColumnModel<CrossPolarDiscriminationDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ cpdColumns.push(addColumnLabels<CrossPolarDiscriminationDataType>(ds.name, ds.columnLabel));
+ });
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <CrossPolarDiscriminationTable idProperty={"_id"} columns={cpdColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for CPD according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+ private getChartDataValues = (rows: CrossPolarDiscriminationDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "xpdMin",
+ label: "xpd-min",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "CPD (min)[db]"
+ }, {
+ name: "xpdAvg",
+ label: "xpd-avg",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "CPD (avg)[db]"
+ }, {
+ name: "xpdMax",
+ label: "xpd-max",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "CPD (max)[db]"
+ }];
+
+ _rows.forEach(row => {
+ row.xpdMin = row.performanceData.xpdMin;
+ row.xpdAvg = row.performanceData.xpdAvg;
+ row.xpdMax = row.performanceData.xpdMax;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof CrossPolarDiscriminationDataType] as string,
+ y: row.performanceData[ds.name as keyof CrossPolarDiscriminationDatabaseDataType] as string
+ });
+ });
+ });
+ return {
+ datasets: datasets
+ };
+ }
+}
+const CrossPolarDiscrimination = withRouter(connect(mapProps, mapDisp)(CrossPolarDiscriminationComponent));
+export default CrossPolarDiscrimination;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
new file mode 100644
index 000000000..c58c49c9e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
@@ -0,0 +1,133 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { PerformanceDataType, PerformanceDatabaseDataType } from '../models/performanceDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createPerformanceDataProperties, createPerformanceDataActions } from '../handlers/performanceDataHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ performanceDataProperties: createPerformanceDataProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ performanceDataActions: createPerformanceDataActions(dispatcher.dispatch),
+});
+
+type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceDataType>;
+
+/**
+ * The Component which gets the performance data from the database based on the selected time period.
+ */
+class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.performanceDataProperties;
+ const actions = this.props.performanceDataActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+ const performanceColumns: ColumnModel<PerformanceDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ performanceColumns.push(addColumnLabels<PerformanceDataType>(ds.name, ds.columnLabel));
+ });
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <PerformanceDataTable idProperty={"_id"} columns={performanceColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for PerformanceData according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+ private getChartDataValues = (rows: PerformanceDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "es",
+ label: "es",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "ES"
+ }, {
+ name: "ses",
+ label: "ses",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "SES"
+ }, {
+ name: "unavailability",
+ label: "unavailability",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Unavailability"
+ }];
+
+ _rows.forEach(row => {
+ row.es = row.performanceData.es;
+ row.ses = row.performanceData.ses;
+ row.unavailability = row.performanceData.unavailability;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof PerformanceDataType] as string,
+ y: row.performanceData[ds.name as keyof PerformanceDatabaseDataType] as string
+ });
+ });
+ });
+
+ return {
+ datasets: datasets
+ };
+ }
+}
+
+const PerformanceData = withRouter(connect(mapProps, mapDisp)(PerformanceDataComponent));
+export default PerformanceData;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
new file mode 100644
index 000000000..55bc39860
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
@@ -0,0 +1,134 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { ReceiveLevelDataType,ReceiveLevelDatabaseDataType } from '../models/receiveLevelDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createReceiveLevelProperties, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ receiveLevelProperties: createReceiveLevelProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch),
+});
+
+type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDataType>;
+
+/**
+ * The Component which gets the receiveLevel data from the database based on the selected time period.
+ */
+class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.receiveLevelProperties;
+ const actions = this.props.receiveLevelActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+ const receiveLevelColumns: ColumnModel<ReceiveLevelDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ receiveLevelColumns.push(addColumnLabels<ReceiveLevelDataType>(ds.name, ds.columnLabel));
+ });
+
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <ReceiveLevelTable idProperty={"_id"} columns={receiveLevelColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for ReceiveLevel according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+ private getChartDataValues = (rows: ReceiveLevelDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "rxLevelMin",
+ label: "rx-level-min",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rx min"
+ }, {
+ name: "rxLevelAvg",
+ label: "rx-level-avg",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rx avg"
+ }, {
+ name: "rxLevelMax",
+ label: "rx-level-max",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rx max"
+ }];
+
+ _rows.forEach(row => {
+ row.rxLevelMin = row.performanceData.rxLevelMin;
+ row.rxLevelAvg = row.performanceData.rxLevelAvg;
+ row.rxLevelMax = row.performanceData.rxLevelMax;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof ReceiveLevelDataType] as string,
+ y: row.performanceData[ds.name as keyof ReceiveLevelDatabaseDataType] as string
+ });
+ });
+ });
+ return {
+ datasets: datasets
+ };
+ }
+}
+
+const ReceiveLevel = withRouter(connect(mapProps, mapDisp)(ReceiveLevelComponent));
+export default ReceiveLevel;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
new file mode 100644
index 000000000..42aa007a9
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
@@ -0,0 +1,136 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { SignalToInterferenceDataType, SignalToInterferenceDatabaseDataType } from '../models/signalToInteferenceDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createSignalToInterferenceProperties, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ signalToInterferenceProperties: createSignalToInterferenceProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch),
+});
+
+type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalToInterferenceDataType>;
+
+/**
+ * The Component which gets the signal to interference data from the database based on the selected time period.
+ */
+class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.signalToInterferenceProperties;
+ const actions = this.props.signalToInterferenceActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+
+ const sinrColumns: ColumnModel<SignalToInterferenceDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ sinrColumns.push(addColumnLabels<SignalToInterferenceDataType>(ds.name, ds.columnLabel));
+ });
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <SignalToInterferenceTable idProperty={"_id"} columns={sinrColumns} {...properties} {...actions}
+ />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for SINR according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+
+ private getChartDataValues = (rows: SignalToInterferenceDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "snirMin",
+ label: "snir-min",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "SINR (min)[db]"
+ }, {
+ name: "snirAvg",
+ label: "snir-avg",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "SINR (avg)[db]"
+ }, {
+ name: "snirMax",
+ label: "snir-max",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "SINR (max)[db]"
+ }];
+
+ _rows.forEach(row => {
+ row.snirMin = row.performanceData.snirMin;
+ row.snirAvg = row.performanceData.snirAvg;
+ row.snirMax = row.performanceData.snirMax;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof SignalToInterferenceDataType] as string,
+ y: row.performanceData[ds.name as keyof SignalToInterferenceDatabaseDataType] as string
+ });
+ });
+ });
+ return {
+ datasets: datasets
+ };
+ }
+}
+
+const SignalToInterference = withRouter(connect(mapProps, mapDisp)(SignalToInterferenceComponent));
+export default SignalToInterference;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
new file mode 100644
index 000000000..256911c2d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
@@ -0,0 +1,134 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { TemperatureDataType, TemperatureDatabaseDataType } from '../models/temperatureDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createTemperatureProperties, createTemperatureActions } from '../handlers/temperatureHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ temperatureProperties: createTemperatureProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ temperatureActions: createTemperatureActions(dispatcher.dispatch),
+});
+
+type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+};
+
+const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataType>;
+
+/**
+ * The Component which gets the temperature data from the database based on the selected time period.
+ */
+class TemperatureComponent extends React.Component<TemperatureComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.temperatureProperties;
+ const actions = this.props.temperatureActions;
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+ const temperatureColumns: ColumnModel<TemperatureDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ temperatureColumns.push(addColumnLabels<TemperatureDataType>(ds.name, ds.columnLabel));
+ });
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <TemperatureTable idProperty={"_id"} columns={temperatureColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for Temperature according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+
+ private getChartDataValues = (rows: TemperatureDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "rfTempMin",
+ label: "rf-temp-min",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rf Temp Min[deg C]"
+ }, {
+ name: "rfTempAvg",
+ label: "rf-temp-avg",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rf Temp Avg[deg C]"
+ }, {
+ name: "rfTempMax",
+ label: "rf-temp-max",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Rf Temp Max[deg C]"
+ }];
+
+ _rows.forEach(row => {
+ row.rfTempMin = row.performanceData.rfTempMin;
+ row.rfTempAvg = row.performanceData.rfTempAvg;
+ row.rfTempMax = row.performanceData.rfTempMax;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof TemperatureDataType] as string,
+ y: row.performanceData[ds.name as keyof TemperatureDatabaseDataType] as string
+ });
+ });
+ });
+ return {
+ datasets: datasets
+ };
+ }
+}
+
+const Temperature = withRouter(connect(mapProps, mapDisp)(TemperatureComponent));
+export default Temperature;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
new file mode 100644
index 000000000..635cbf103
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
@@ -0,0 +1,136 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+
+import { TransmissionPowerDataType, TransmissionPowerDatabaseDataType } from '../models/transmissionPowerDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createTransmissionPowerProperties, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ transmissionPowerProperties: createTransmissionPowerProperties(state),
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch),
+});
+
+type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
+ selectedTimePeriod: string
+}
+
+const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<TransmissionPowerDataType>;
+
+/**
+ * The Component which gets the transmission power data from the database based on the selected time period.
+ */
+class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps>{
+ render(): JSX.Element {
+ const properties = this.props.transmissionPowerProperties
+ const actions = this.props.transmissionPowerActions
+
+ const chartPagedData = this.getChartDataValues(properties.rows);
+
+ const transmissionColumns: ColumnModel<TransmissionPowerDataType>[] = [
+ { property: "radioSignalId", title: "Radio signal", type: ColumnType.text },
+ { property: "scannerId", title: "Scanner ID", type: ColumnType.text },
+ { property: "timeStamp", title: "End Time", type: ColumnType.text },
+ {
+ property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
+ const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
+ return <div >{suspectIntervalFlag} </div>
+ }
+ }
+ ];
+
+ chartPagedData.datasets.forEach(ds => {
+ transmissionColumns.push(addColumnLabels<TransmissionPowerDataType>(ds.name, ds.columnLabel));
+ });
+
+ return (
+ <>
+ {lineChart(chartPagedData)}
+ <TransmissionPowerTable idProperty={"_id"} columns={transmissionColumns} {...properties} {...actions} />
+ </>
+ );
+ };
+
+ /**
+ * This function gets the performance values for TransmissionPower according on the chartjs dataset structure
+ * which is to be sent to the chart.
+ */
+
+ private getChartDataValues = (rows: TransmissionPowerDataType[]): IDataSetsObject => {
+ const _rows = [...rows];
+ sortDataByTimeStamp(_rows);
+
+ const datasets: IDataSet[] = [{
+ name: "txLevelMin",
+ label: "tx-level-min",
+ borderColor: '#0e17f3de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Tx min"
+ }, {
+ name: "txLevelAvg",
+ label: "tx-level-avg",
+ borderColor: '#08edb6de',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Tx avg"
+ }, {
+ name: "txLevelMax",
+ label: "tx-level-max",
+ borderColor: '#b308edde',
+ bezierCurve: false,
+ lineTension: 0,
+ fill: false,
+ data: [],
+ columnLabel: "Tx max"
+ }];
+
+ _rows.forEach(row => {
+ row.txLevelMin = row.performanceData.txLevelMin;
+ row.txLevelAvg = row.performanceData.txLevelAvg;
+ row.txLevelMax = row.performanceData.txLevelMax;
+ datasets.forEach(ds => {
+ ds.data.push({
+ x: row["timeStamp" as keyof TransmissionPowerDataType] as string,
+ y: row.performanceData[ds.name as keyof TransmissionPowerDatabaseDataType] as string
+ });
+ });
+ });
+ return {
+ datasets: datasets
+ };
+ }
+}
+
+const TransmissionPower = withRouter(connect(mapProps, mapDisp)(TransmissionPowerComponent));
+export default TransmissionPower;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
new file mode 100644
index 000000000..3548bf4dc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { AdaptiveModulationDataType } from '../models/adaptiveModulationDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IAdaptiveModulationState extends IExternalTableState<AdaptiveModulationDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Adaptive modulation from historicalperformance database.
+ */
+const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, null)
+export const {
+ actionHandler: adaptiveModulationActionHandler,
+ createActions: createAdaptiveModulationActions,
+ createProperties: createAdaptiveModulationProperties,
+ createPreActions: createAdaptiveModulationPreActions,
+ reloadAction: adaptiveModulationReloadAction,
+} = createExternal<AdaptiveModulationDataType>(adaptiveModulationSearchHandler, appState => appState.performanceHistory.adaptiveModulation);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
new file mode 100644
index 000000000..b3b284b42
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
@@ -0,0 +1,60 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import {
+ AllAvailableLtpsLoadedAction,
+ LoadAllAvailableLtpsAction,
+} from '../actions/ltpAction';
+
+import { LtpIds } from '../models/availableLtps';
+
+export interface IAvailableLtpsState {
+ distinctLtps: LtpIds[];
+ busy: boolean;
+}
+
+const ltpListStateInit: IAvailableLtpsState = {
+ distinctLtps: [],
+ busy: false
+};
+
+export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
+ if (action instanceof LoadAllAvailableLtpsAction) {
+
+ state = {
+ ...state,
+ busy: true
+ };
+
+ } else if (action instanceof AllAvailableLtpsLoadedAction) {
+ if (!action.error && action.availableLtps) {
+ state = {
+ ...state,
+ distinctLtps: action.availableLtps,
+ busy: false
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
new file mode 100644
index 000000000..1e6c6d0a6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { CrossPolarDiscriminationDataType } from '../models/crossPolarDiscriminationDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ICrossPolarDiscriminationState extends IExternalTableState<CrossPolarDiscriminationDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for CPD from historicalperformance database.
+ */
+const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, null)
+
+export const {
+ actionHandler: crossPolarDiscriminationActionHandler,
+ createActions: createCrossPolarDiscriminationActions,
+ createProperties: createCrossPolarDiscriminationProperties,
+ createPreActions: createCrossPolarDiscriminationPreActions,
+ reloadAction: crossPolarDiscriminationReloadAction,
+} = createExternal<CrossPolarDiscriminationDataType>(crossPolarDiscriminationSearchHandler, appState => appState.performanceHistory.crossPolarDiscrimination);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
new file mode 100644
index 000000000..b3c0db446
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/deviceListActionHandler.ts
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { AllDeviceListLoadedAction, LoadAllDeviceListAction } from '../actions/deviceListActions';
+import { DeviceListType } from '../models/deviceListType';
+
+export interface IDeviceListState {
+ deviceList: DeviceListType[];
+ busy: boolean;
+}
+
+const deviceListStateInit: IDeviceListState = {
+ deviceList: [],
+ busy: false
+};
+
+export const deviceListActionHandler: IActionHandler<IDeviceListState> = (state = deviceListStateInit, action) => {
+ if (action instanceof LoadAllDeviceListAction) {
+
+ state = {
+ ...state,
+ busy: true
+ };
+
+ } else if (action instanceof AllDeviceListLoadedAction) {
+ if (!action.error && action.deviceList) {
+ state = {
+ ...state,
+ deviceList: action.deviceList,
+ busy: false
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
+ }
+ }
+ return state;
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
new file mode 100644
index 000000000..131566367
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
@@ -0,0 +1,40 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as moment from 'moment';
+
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { PerformanceDataType } from '../models/performanceDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IPerformanceDataState extends IExternalTableState<PerformanceDataType> { }
+
+/**
+* Creates elastic search material data fetch handler for performance data from historicalperformance15min database.
+*/
+const performanceDataSearchHandler = createSearchDataHandler<PerformanceDataType>(getFilter, null);
+
+export const {
+ actionHandler: performanceDataActionHandler,
+ createActions: createPerformanceDataActions,
+ createProperties: createPerformanceDataProperties,
+ createPreActions: createPerformanceDataPreActions,
+ reloadAction: performanceDataReloadAction
+} = createExternal<PerformanceDataType>(performanceDataSearchHandler, appState => appState.performanceHistory.performanceData);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
new file mode 100644
index 000000000..c33f10a7e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
@@ -0,0 +1,105 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+// main state handler
+
+import { combineActionHandler } from '../../../../framework/src/flux/middleware';
+
+// ** do not remove **
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { IActionHandler } from '../../../../framework/src/flux/action';
+
+import { IConnectAppStoreState } from '../../../connectApp/src/handlers/connectAppRootHandler';
+import { IPerformanceDataState, performanceDataActionHandler } from './performanceDataHandler';
+import { IReceiveLevelState, receiveLevelActionHandler } from './receiveLevelHandler';
+import { ITransmissionPowerState, transmissionPowerActionHandler } from './transmissionPowerHandler';
+import { IAdaptiveModulationState, adaptiveModulationActionHandler } from './adaptiveModulationHandler';
+import { ITemperatureState, temperatureActionHandler } from './temperatureHandler';
+import { ISignalToInterferenceState, signalToInterferenceActionHandler } from './signalToInterferenceHandler';
+import { ICrossPolarDiscriminationState, crossPolarDiscriminationActionHandler } from './crossPolarDiscriminationHandler';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { IDeviceListState, deviceListActionHandler } from './deviceListActionHandler';
+import { IAvailableLtpsState, availableLtpsActionHandler } from './availableLtpsActionHandler';
+import { PmDataInterval } from '../models/performanceDataType';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import { UpdateMountId } from '../actions/deviceListActions';
+
+export interface IPerformanceHistoryStoreState {
+ nodeId: string;
+ networkElements: IDeviceListState;
+ ltps: IAvailableLtpsState;
+ performanceData: IPerformanceDataState;
+ receiveLevel: IReceiveLevelState;
+ transmissionPower: ITransmissionPowerState;
+ adaptiveModulation: IAdaptiveModulationState;
+ temperature: ITemperatureState;
+ signalToInterference: ISignalToInterferenceState;
+ crossPolarDiscrimination: ICrossPolarDiscriminationState;
+ currentOpenPanel: string | null;
+ pmDataIntervalType: PmDataInterval;
+}
+
+const mountIdHandler: IActionHandler<string> = (state = "", action) => {
+ if (action instanceof UpdateMountId) {
+ state = "";
+ if (action.nodeId) {
+ state = action.nodeId;
+ }
+ }
+ return state;
+}
+
+
+const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+}
+
+const currentPMDataIntervalHandler: IActionHandler<PmDataInterval> = (state = PmDataInterval.pmInterval15Min, action) => {
+ if (action instanceof TimeChangeAction) {
+ state = action.time;
+ }
+ return state;
+}
+
+declare module '../../../../framework/src/store/applicationStore' {
+ interface IApplicationStoreState {
+ performanceHistory: IPerformanceHistoryStoreState;
+ connect: IConnectAppStoreState;
+ }
+}
+
+const actionHandlers = {
+ nodeId: mountIdHandler,
+ networkElements: deviceListActionHandler,
+ ltps: availableLtpsActionHandler,
+ performanceData: performanceDataActionHandler,
+ receiveLevel: receiveLevelActionHandler,
+ transmissionPower: transmissionPowerActionHandler,
+ adaptiveModulation: adaptiveModulationActionHandler,
+ temperature: temperatureActionHandler,
+ signalToInterference: signalToInterferenceActionHandler,
+ crossPolarDiscrimination: crossPolarDiscriminationActionHandler,
+ currentOpenPanel: currentOpenPanelHandler,
+ pmDataIntervalType: currentPMDataIntervalHandler
+};
+
+const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
+export default performanceHistoryRootHandler;
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
new file mode 100644
index 000000000..91595cc58
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { ReceiveLevelDataType } from '../models/receiveLevelDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface IReceiveLevelState extends IExternalTableState<ReceiveLevelDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for receiveLevel from historicalperformance database.
+ */
+const receiveLevelSearchHandler = createSearchDataHandler<ReceiveLevelDataType>(getFilter, null);
+
+export const {
+ actionHandler: receiveLevelActionHandler,
+ createActions: createReceiveLevelActions,
+ createProperties: createReceiveLevelProperties,
+ createPreActions: createReceiveLevelPreActions,
+ reloadAction: receiveLevelReloadAction,
+} = createExternal<ReceiveLevelDataType>(receiveLevelSearchHandler, appState => appState.performanceHistory.receiveLevel);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
new file mode 100644
index 000000000..e0f804086
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { SignalToInterferenceDataType } from '../models/signalToInteferenceDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ISignalToInterferenceState extends IExternalTableState<SignalToInterferenceDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for SINR from historicalperformance database.
+ */
+const signalToInterferenceSearchHandler = createSearchDataHandler<SignalToInterferenceDataType>(getFilter, null);
+
+export const {
+ actionHandler: signalToInterferenceActionHandler,
+ createActions: createSignalToInterferenceActions,
+ createProperties: createSignalToInterferenceProperties,
+ createPreActions: createSignalToInterferencePreActions,
+ reloadAction: signalToInterferenceReloadAction,
+} = createExternal<SignalToInterferenceDataType>(signalToInterferenceSearchHandler, appState => appState.performanceHistory.signalToInterference);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
new file mode 100644
index 000000000..0a6c73a1c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { TemperatureDataType } from '../models/temperatureDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ITemperatureState extends IExternalTableState<TemperatureDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Temperature from historicalperformance database.
+ */
+const temperatureSearchHandler = createSearchDataHandler< TemperatureDataType>(getFilter, null);
+
+export const {
+ actionHandler: temperatureActionHandler,
+ createActions: createTemperatureActions,
+ createProperties: createTemperatureProperties,
+ createPreActions: createTemperaturePreActions,
+ reloadAction: temperatureReloadAction,
+} = createExternal<TemperatureDataType>(temperatureSearchHandler, appState => appState.performanceHistory.temperature);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
new file mode 100644
index 000000000..32bef817d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
@@ -0,0 +1,38 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { TransmissionPowerDataType } from '../models/transmissionPowerDataType';
+import { getFilter } from '../utils/tableUtils';
+
+export interface ITransmissionPowerState extends IExternalTableState<TransmissionPowerDataType> { }
+
+/**
+ * Creates elastic search material data fetch handler for Transmission power from historicalperformance database.
+ */
+const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, null)
+
+export const {
+ actionHandler: transmissionPowerActionHandler,
+ createActions: createTransmissionPowerActions,
+ createProperties: createTransmissionPowerProperties,
+ createPreActions: createTransmissionPowerPreActions,
+ reloadAction: transmissionPowerReloadAction,
+} = createExternal<TransmissionPowerDataType>(transmissionPowerSearchHandler, appState => appState.performanceHistory.transmissionPower);
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/index.html b/sdnr/wt/odlux/apps/performanceHistoryApp/src/index.html
new file mode 100644
index 000000000..8cb775be2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>PM History Application</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app", "connectApp", "performanceHistoryApp"], function (app, connectApp, performanceHistoryApp) {
+ connectApp.register();
+ performanceHistoryApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts
new file mode 100644
index 000000000..adb0bcd6f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts
@@ -0,0 +1,109 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the License); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents Adaptive Modulation data fields of the performance history table.
+ */
+export type AdaptiveModulationDatabaseDataType = {
+ _id: string ;
+ time2StatesS: number;
+ time2States: number;
+ time2StatesL: number;
+ time4StatesS: number;
+ time4States: number;
+ time4StatesL: number;
+ time16StatesS: number;
+ time16States: number;
+ time16StatesL: number;
+ time32StatesS: number;
+ time32States: number;
+ time32StatesL: number;
+ time64StatesS: number;
+ time64States: number;
+ time64StatesL: number;
+ time128StatesS: number;
+ time128States: number;
+ time128StatesL: number;
+ time256StatesS: number;
+ time256States: number;
+ time256StatesL: number;
+ time512StatesS: number;
+ time512States: number;
+ time512StatesL: number;
+ time1024StatesS: number;
+ time1024States: number;
+ time1024StatesL: number;
+ time2048StatesS: number;
+ time2048States: number;
+ time2048StatesL: number;
+ time4096StatesS: number;
+ time4096States: number;
+ time4096StatesL: number;
+ time8192StatesS: number;
+ time8192States: number;
+ time8192StatesL: number;
+};
+
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type AdaptiveModulationDataType = {
+ performanceData: AdaptiveModulationDatabaseDataType;
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ time2StatesS: number;
+ time2States: number;
+ time2StatesL: number;
+ time4StatesS: number;
+ time4States: number;
+ time4StatesL: number;
+ time16StatesS: number;
+ time16States: number;
+ time16StatesL: number;
+ time32StatesS: number;
+ time32States: number;
+ time32StatesL: number;
+ time64StatesS: number;
+ time64States: number;
+ time64StatesL: number;
+ time128StatesS: number;
+ time128States: number;
+ time128StatesL: number;
+ time256StatesS: number;
+ time256States: number;
+ time256StatesL: number;
+ time512StatesS: number;
+ time512States: number;
+ time512StatesL: number;
+ time1024StatesS: number;
+ time1024States: number;
+ time1024StatesL: number;
+ time2048StatesS: number;
+ time2048States: number;
+ time2048StatesL: number;
+ time4096StatesS: number;
+ time4096States: number;
+ time4096StatesL: number;
+ time8192StatesS: number;
+ time8192States: number;
+ time8192StatesL: number;
+} & { _id: string }; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
new file mode 100644
index 000000000..dc6c7bc16
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+ export type LtpIds = {
+ key : string
+ }
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
new file mode 100644
index 000000000..53039faa2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export interface IData {
+ x: string;
+ y: string;
+}
+
+/**
+ * Structure of chartjs dataset with the chart properties.
+ */
+export interface IDataSet {
+ name: string,
+ label: string,
+ lineTension: 0,
+ bezierCurve: boolean;
+ fill: boolean,
+ borderColor: string,
+ data: IData[],
+ columnLabel: string
+}
+
+/**
+ * Structure of chartjs dataset which is sent to the chart.
+ */
+export interface IDataSetsObject {
+ datasets: IDataSet[]
+}
+
+/**
+ * Interface used by chart for sorting on time-stamp
+ */
+export interface ITimeStamp {
+ timeStamp: string;
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
new file mode 100644
index 000000000..8adb16f45
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type CrossPolarDiscriminationDatabaseDataType = {
+ _id: string;
+ xpdMin: number;
+ xpdAvg: number;
+ xpdMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type CrossPolarDiscriminationDataType = {
+ performanceData: CrossPolarDiscriminationDatabaseDataType
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ xpdMin: number;
+ xpdAvg: number;
+ xpdMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
new file mode 100644
index 000000000..db8f2d71e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/deviceListType.ts
@@ -0,0 +1,25 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents all the distinct devices from the performance history data.
+ */
+
+export type DeviceListType = {
+ nodeId: string;
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts
new file mode 100644
index 000000000..5889a64c8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/panelId.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents PanelIds for the available Expansional panels.
+ */
+export type PanelId = null | "PerformanceData" | "ReceiveLevel" | "TransmissionPower" | "AdaptiveModulation" | "Temperature" | "SINR" | "CPD"; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
new file mode 100644
index 000000000..30f97fb54
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Moment } from "moment";
+
+//export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents performance data fields of the performance history table as used in the database
+ */
+export type PerformanceDatabaseDataType = {
+ _id: string;
+ es: number;
+ ses: number;
+ unavailability: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type PerformanceDataType = {
+
+ performanceData: PerformanceDatabaseDataType;
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ es: number;
+ ses: number;
+ unavailability: number;
+} & { _id: string };
+
+
+/**
+ * Represents performance data time interval.
+ */
+export const enum PmDataInterval {
+ pmInterval15Min,
+ pmInterval24Hours
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts
new file mode 100644
index 000000000..2748a3d5d
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type ReceiveLevelDatabaseDataType = {
+ _id: string;
+ rxLevelMin: number;
+ rxLevelAvg: number;
+ rxLevelMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type ReceiveLevelDataType = {
+ performanceData: ReceiveLevelDatabaseDataType;
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ rxLevelMin: number;
+ rxLevelAvg: number;
+ rxLevelMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts
new file mode 100644
index 000000000..5c675feb8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type SignalToInterferenceDatabaseDataType = {
+ _id: string;
+ snirMin: number;
+ snirAvg: number;
+ snirMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type SignalToInterferenceDataType = {
+ performanceData: SignalToInterferenceDatabaseDataType;
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ snirMin: number;
+ snirAvg: number;
+ snirMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
new file mode 100644
index 000000000..3b0cb7683
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type TemperatureDatabaseDataType = {
+ _id: string;
+ rfTempMin: number;
+ rfTempAvg: number;
+ rfTempMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type TemperatureDataType = {
+ performanceData: TemperatureDatabaseDataType
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ rfTempMin: number;
+ rfTempAvg: number;
+ rfTempMax: number;
+} & { _id: string };
+
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
new file mode 100644
index 000000000..99123f55e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/topologyNetconf.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export interface TopologyNode {
+ "node-id": string;
+}
+
+export interface Topology {
+ "topology-id": string;
+ node: TopologyNode[];
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts
new file mode 100644
index 000000000..62c00bfe4
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts
@@ -0,0 +1,44 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { HitEntry, Result } from '../../../../framework/src/models';
+
+
+/**
+ * Represents Receive level data fields of the performance history table.
+ */
+export type TransmissionPowerDatabaseDataType = {
+ _id: string;
+ txLevelMin: number;
+ txLevelAvg: number;
+ txLevelMax: number;
+};
+
+/**
+ * Internally used type to provide table and chart data
+ */
+export type TransmissionPowerDataType = {
+ performanceData: TransmissionPowerDatabaseDataType;
+ radioSignalId: string;
+ scannerId: string;
+ timeStamp: string;
+ suspectIntervalFlag: boolean;
+ txLevelMin: number;
+ txLevelAvg: number;
+ txLevelMax: number;
+} & { _id: string };
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
new file mode 100644
index 000000000..df3ffd90a
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/pluginPerformance.tsx
@@ -0,0 +1,111 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react";
+import { faBook } from '@fortawesome/free-solid-svg-icons';
+
+import applicationManager from '../../../framework/src/services/applicationManager';
+
+import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-router-dom';
+import performanceHistoryRootHandler from './handlers/performanceHistoryRootHandler';
+import { PmDataInterval } from './models/performanceDataType';
+import PerformanceHistoryApplication from './views/performanceHistoryApplication';
+import { ApplicationStore } from '../../../framework/src/store/applicationStore';
+
+import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import { updateMountIdActionCreator } from "./actions/deviceListActions";
+
+let api: {
+ readonly applicationStore: ApplicationStore | null;
+ readonly applicationStoreInitialized: Promise<ApplicationStore>;
+}
+
+const mapProps = (state: IApplicationStoreState) => ({
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ updateMountId: (mountId: string) => dispatcher.dispatch(updateMountIdActionCreator(mountId))
+});
+
+let currentMountId: string | null = null;
+let lastUrl: string = "/performanceHistory";
+const PerformanceHistoryApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string}> & Connect<typeof mapProps, typeof mapDisp>) => {
+ let mountId: string = "";
+ if (props.location.pathname !== lastUrl) {
+ // ensure the asynchronus update will only be called once per path
+ lastUrl = props.location.pathname;
+ let index = lastUrl.lastIndexOf("performanceHistory/");
+ if(index >= 0) {
+ mountId = lastUrl.substr(index+19);
+ } else {
+ mountId = "";
+ }
+
+ window.setTimeout(async () => {
+ // check if the mountId has changed
+ if (currentMountId !== mountId) {
+ currentMountId = mountId;
+ await props.updateMountId(currentMountId);
+ }
+ });
+ }
+ return (
+ <PerformanceHistoryApplication />
+ );
+});
+
+const PerformanceHistoryRouterApp = withRouter((props: RouteComponentProps) => {
+ props.history.action = "POP";
+ return (
+ <Switch>
+ <Route path={`${props.match.path}/:mountId`} component={PerformanceHistoryApplicationRouteAdapter} />
+ <Route path={`${props.match.path}`} component={PerformanceHistoryApplicationRouteAdapter} />
+ <Redirect to={`${props.match.path}`} />
+ </Switch>
+ )
+});
+
+export function register() {
+ api = applicationManager.registerApplication({
+ name: "performanceHistory",
+ icon: faBook,
+ rootComponent: PerformanceHistoryRouterApp,
+ rootActionHandler: performanceHistoryRootHandler,
+ menuEntry: "Performance"
+ });
+}
+
+export function setPmDataInterval(pmDataInterval: PmDataInterval): boolean {
+ let reload: boolean = true;
+ if (api && api.applicationStore) {
+ if (api.applicationStore.state.performanceHistory.pmDataIntervalType !== pmDataInterval) {
+ reload = true;
+ }
+ api.applicationStore.state.performanceHistory.pmDataIntervalType = pmDataInterval;
+ }
+ return reload;
+}
+
+
+export function getPmDataInterval(): PmDataInterval {
+ let result = api && api.applicationStore
+ ? api.applicationStore.state.performanceHistory.pmDataIntervalType
+ : PmDataInterval.pmInterval15Min;
+ return result ? result : PmDataInterval.pmInterval15Min;
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
new file mode 100644
index 000000000..2b03d1c2e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
@@ -0,0 +1,108 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from '../../../../framework/src/services/restService';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { convertPropertyNames, replaceUpperCase } from '../../../../framework/src/utilities/yangHelper';
+import { LtpIds } from '../models/availableLtps';
+import { DeviceListType } from '../models/deviceListType';
+import { Topology, TopologyNode } from '../models/topologyNetconf';
+
+/**
+ * Represents a web api accessor service for Network elements actions.
+ */
+class PerformanceService {
+
+ /**
+ * Get distinct ltps based on the selected network element and time period from the historicalperformance15min database table.
+ */
+ public async getDistinctLtpsFromDatabase(networkElement: string, selectedTimePeriod: string): Promise<LtpIds[] | null> {
+ let path;
+ const query = {
+ "filter": [{
+ "property": "node-name",
+ "filtervalue": networkElement
+ }],
+ "sortorder": [],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+
+
+ if (selectedTimePeriod === "15min") {
+ path = '/restconf/operations/data-provider:read-pmdata-15m-ltp-list';
+ } else {
+ path = '/restconf/operations/data-provider:read-pmdata-24h-ltp-list';
+ }
+
+ const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
+ return result && result.output && result.output.data.map(ne => ({ key: ne })) || null;
+ }
+
+
+
+ /**
+ * Gets all devices from the performanceHistory 15min backend.
+ */
+ public async getDeviceListfromPerf15minHistory(): Promise<(DeviceListType)[] | null> {
+ const path = '/restconf/operations/data-provider:read-pmdata-15m-device-list';
+ const query = {
+ "input": {
+ "filter": [],
+ "sortorder": [],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ };
+
+ const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result.output && result.output.data && result.output.data.map(ne => ({
+ nodeId: ne
+ })) || null;
+ }
+
+ /**
+ * Gets all devices from the performanceHistory 24h backend.
+ */
+ public async getDeviceListfromPerf24hHistory(): Promise<(DeviceListType)[] | null> {
+ const path = '/restconf/operations/data-provider:read-pmdata-24h-device-list';
+ const query = {
+ "input": {
+ "filter": [],
+ "sortorder": [],
+ "pagination": {
+ "size": 20,
+ "page": 1
+ }
+ }
+ };
+
+ const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(query) });
+ return result && result.output && result.output.data && result.output.data.map(ne => ({
+ nodeId: ne
+ })) || null;
+ }
+}
+
+
+export const PerformanceHistoryService = new PerformanceService();
+export default PerformanceHistoryService;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
new file mode 100644
index 000000000..3240f73f1
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
@@ -0,0 +1,75 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { IDataSetsObject } from '../models/chartTypes';
+import { Line } from 'react-chartjs-2';
+import * as moment from 'moment';
+import { ITimeStamp } from 'models/chartTypes';
+
+const style: React.CSSProperties = {
+ height: "350px"
+}
+export const lineChart = (chartPagedData: IDataSetsObject) => {
+ return (
+ <div style={style}>
+ <Line ref="chart" data={chartPagedData} options={{
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ displayFormats: {
+ 'second': 'DD MMM YYYY HH:mm:ss',
+ 'minute': 'DD MMM YYYY HH:mm:ss',
+ 'hour': 'DD MMM YYYY HH:mm:ss',
+ 'year': 'DD MMM YYYY HH:mm:ss',
+ },
+ parser: function (date: string) {
+ let offsetValue = new Date().getTimezoneOffset();
+ var utcDate = moment(date, 'YYYY-MM-DDTHH:mm:ss').utcOffset(offsetValue).utc(false);
+ return utcDate;
+ }
+ },
+ display: true,
+ scaleLabel: {
+ display: true,
+ labelString: 'Timestamp'
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ beginAtZero: true
+ },
+ scaleLabel: {
+ display: true,
+ labelString: 'Value'
+ }
+ }]
+ }
+ }} />
+ </div>
+ );
+}
+
+export const sortDataByTimeStamp = <T extends ITimeStamp>(_rows: T[]): T[] => {
+ return (_rows.sort((a, b) => {
+ const result = Date.parse(a["timeStamp"]) - Date.parse(b["timeStamp"]);
+ return isNaN(result) ? 0 : result;
+ }));
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
new file mode 100644
index 000000000..b5a3a3f36
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ColumnType, ColumnModel } from '../../../../framework/src/components/material-table';
+
+import { PmDataInterval } from '../models/performanceDataType';
+import { getPmDataInterval } from '../pluginPerformance';
+
+export const addColumnLabels = <T>(name: string, title: string, disableFilter = true, disableSorting = true): ColumnModel<T> => {
+ return { property: name as keyof T, title: title, type: ColumnType.text, disableFilter: disableFilter, disableSorting: disableSorting };
+}
+
+export function getFilter(): string {
+ switch (getPmDataInterval()) {
+ case PmDataInterval.pmInterval15Min:
+ return "pmdata-15m";
+ case PmDataInterval.pmInterval24Hours:
+ return "pmdata-24h";
+ default:
+ throw new Error("Unknown time intervall");
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
new file mode 100644
index 000000000..ae22f8041
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
@@ -0,0 +1,371 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles';
+import FormControl from '@material-ui/core/FormControl';
+import MenuItem from '@material-ui/core/MenuItem';
+import Select from '@material-ui/core/Select';
+
+import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { Panel } from '../../../../framework/src/components/material-ui';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { Dispatch } from '../../../../framework/src/flux/store';
+
+import { PanelId } from '../models/panelId';
+import { PmDataInterval } from '../models/performanceDataType';
+import PerformanceData from '../components/performanceData';
+import ReceiveLevel from '../components/receiveLevel';
+import TransmissionPower from '../components/transmissionPower';
+import AdaptiveModulation from '../components/adaptiveModulation';
+import Temperature from '../components/temperature';
+import SignalToInterference from '../components/signalToInterference';
+import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
+import { loadAllDeviceListAsync } from '../actions/deviceListActions';
+import { TimeChangeAction } from '../actions/timeChangeAction';
+import { loadDistinctLtpsbyNetworkElementAsync } from '../actions/ltpAction';
+import { SetPanelAction } from '../actions/panelChangeActions';
+import { createPerformanceDataPreActions, performanceDataReloadAction, createPerformanceDataActions } from '../handlers/performanceDataHandler';
+import { createReceiveLevelPreActions, receiveLevelReloadAction, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
+import { createTransmissionPowerPreActions, transmissionPowerReloadAction, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler';
+import { createAdaptiveModulationPreActions, adaptiveModulationReloadAction, createAdaptiveModulationActions } from '../handlers/adaptiveModulationHandler';
+import { createTemperaturePreActions, temperatureReloadAction, createTemperatureActions } from '../handlers/temperatureHandler';
+import { createSignalToInterferencePreActions, signalToInterferenceReloadAction, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler';
+import { createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
+
+import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+
+const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
+ root: {
+ display: "flex",
+ flexWrap: "wrap",
+ },
+ margin: {
+ margin: theme.spacing(1),
+ },
+ display: {
+ display: "inline-block"
+ },
+ selectDropdown: {
+ borderRadius: 1,
+ position: "relative",
+ backgroundColor: theme.palette.background.paper,
+ border: "1px solid #ced4da",
+ fontSize: 16,
+ width: "auto",
+ padding: "5px 26px 5px 12px",
+ transition: theme.transitions.create(["border-color", "box-shadow"]),
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ ...state.performanceHistory,
+ activePanel: state.performanceHistory.currentOpenPanel,
+ availableLtps: state.performanceHistory.ltps.distinctLtps,
+ networkElements: state.performanceHistory.networkElements.deviceList,
+});
+
+const mapDispatcher = (dispatcher: IDispatcher) => ({
+ enableFilterPerformanceData: createPerformanceDataActions(dispatcher.dispatch),
+ enableFilterReceiveLevel: createReceiveLevelActions(dispatcher.dispatch),
+ enableFilterTransmissionPower: createTransmissionPowerActions(dispatcher.dispatch),
+ enableFilterAdaptiveModulation: createAdaptiveModulationActions(dispatcher.dispatch),
+ enableFilterTemperature: createTemperatureActions(dispatcher.dispatch),
+ enableFilterSinr: createSignalToInterferenceActions(dispatcher.dispatch),
+ enableFilterCpd: createCrossPolarDiscriminationActions(dispatcher.dispatch),
+ reloadPerformanceData: () => dispatcher.dispatch(performanceDataReloadAction),
+ reloadReceiveLevel: () => dispatcher.dispatch(receiveLevelReloadAction),
+ reloadTransmissionPower: () => dispatcher.dispatch(transmissionPowerReloadAction),
+ reloadAdaptiveModulation: () => dispatcher.dispatch(adaptiveModulationReloadAction),
+ reloadTemperature: () => dispatcher.dispatch(temperatureReloadAction),
+ reloadSignalToInterference: () => dispatcher.dispatch(signalToInterferenceReloadAction),
+ reloadCrossPolarDiscrimination: () => dispatcher.dispatch(crossPolarDiscriminationReloadAction),
+ performanceDataPreActions: createPerformanceDataPreActions(dispatcher.dispatch),
+ receiveLevelPreActions: createReceiveLevelPreActions(dispatcher.dispatch),
+ transmissionPowerPreActions: createTransmissionPowerPreActions(dispatcher.dispatch),
+ adaptiveModulationPreActions: createAdaptiveModulationPreActions(dispatcher.dispatch),
+ temperaturePreActions: createTemperaturePreActions(dispatcher.dispatch),
+ signalToInterferencePreActions: createSignalToInterferencePreActions(dispatcher.dispatch),
+ crossPolarDiscriminationPreActions: createCrossPolarDiscriminationPreActions(dispatcher.dispatch),
+ getAllDevicesPMdata: async () => {
+ await dispatcher.dispatch(loadAllDeviceListAsync);
+ },
+ getDistinctLtpsIds: (selectedNetworkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLTP?: Function) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
+ setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
+ timeIntervalChange: (time: PmDataInterval) => dispatcher.dispatch(new TimeChangeAction(time)),
+ changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
+ dispatch(new NavigateToApplication("performanceHistory", nodeId));
+ })
+});
+
+export type NetworkElementType = {
+ nodeId: string,
+}
+const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementType>;
+
+type PerformanceHistoryComponentProps = Connect<typeof mapProps, typeof mapDispatcher> & WithStyles<typeof PerformanceHistoryComponentStyles>;
+
+type PerformanceHistoryComponentState = {
+ selectedNetworkElement: string,
+ selectedTimePeriod: string,
+ selectedLtp: string,
+ showNetworkElementsTable: boolean,
+ showLtps: boolean,
+ showPanels: boolean
+};
+
+/**
+* Represents the component for Performance history application.
+*/
+class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComponentProps, PerformanceHistoryComponentState>{
+ /**
+ * Initialises this instance
+ */
+ constructor(props: PerformanceHistoryComponentProps) {
+ super(props);
+ this.state = {
+ selectedNetworkElement: "-1",
+ selectedTimePeriod: "15min",
+ selectedLtp: "-1",
+ showNetworkElementsTable: true,
+ showLtps: false,
+ showPanels: false
+ };
+ }
+
+ onTogglePanel = (panelId: PanelId) => {
+ const nextActivePanel = panelId === this.props.activePanel ? null : panelId;
+ this.props.setCurrentPanel(nextActivePanel);
+ switch (nextActivePanel) {
+ case "PerformanceData":
+ this.props.reloadPerformanceData();
+ break;
+ case "ReceiveLevel":
+ this.props.reloadReceiveLevel();
+ break;
+ case "TransmissionPower":
+ this.props.reloadTransmissionPower();
+ break;
+ case "AdaptiveModulation":
+ this.props.reloadAdaptiveModulation();
+ break;
+ case "Temperature":
+ this.props.reloadTemperature();
+ break;
+ case "SINR":
+ this.props.reloadSignalToInterference();
+ break;
+ case "CPD":
+ this.props.reloadCrossPolarDiscrimination();
+ break;
+ default:
+ // do nothing if all panels are closed
+ break;
+ }
+ }
+
+ render(): JSX.Element {
+ const { classes } = this.props;
+ const { activePanel, nodeId } = this.props;
+ if (nodeId === "") {
+ return (
+ <>
+ <NetworkElementTable title={"Please select the network element!"} idProperty={"nodeId"} rows={this.props.networkElements} asynchronus
+ onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId) }} columns={
+ [{ property: "nodeId", title: "Node Name" }]
+ } />
+ </>
+ )
+ }
+ else {
+ 3
+ this.handleURLChange(nodeId);
+ return (
+ <>
+ <h3>Selected Network Element: {this.state.selectedNetworkElement} </h3>
+ {this.state.showLtps && (
+ <div>
+ <FormControl className={classes.display}>
+ <span>
+ Select LTP
+ </span>
+ <Select className={classes.selectDropdown} value={this.state.selectedLtp} onChange={this.handleLtpChange} >
+ <MenuItem value={"-1"}><em>--Select--</em></MenuItem>
+ {this.props.availableLtps.map(ltp =>
+ (<MenuItem value={ltp.key} key={ltp.key}>{ltp.key}</MenuItem>))}
+ </Select>
+ <span> Time-Period </span>
+ <Select className={classes.selectDropdown} value={this.state.selectedTimePeriod} onChange={this.handleTimePeriodChange} >
+ <MenuItem value={"15min"}>15min</MenuItem>
+ <MenuItem value={"24hours"}>24hours</MenuItem>
+ </Select>
+ </FormControl>
+ {this.state.showPanels && (
+ <div>
+ <Panel activePanel={activePanel} panelId={"PerformanceData"} onToggle={this.onTogglePanel} title={"Performance Data"}>
+ <PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"ReceiveLevel"} onToggle={this.onTogglePanel} title={"Receive Level"}>
+ <ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"TransmissionPower"} onToggle={this.onTogglePanel} title={"Transmission Power"}>
+ <TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"AdaptiveModulation"} onToggle={this.onTogglePanel} title={"Adaptive Modulation"}>
+ <AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"Temperature"} onToggle={this.onTogglePanel} title={"Temperature"}>
+ <Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"SINR"} onToggle={this.onTogglePanel} title={"Signal-to-interference-plus-noise ratio (SINR)"}>
+ <SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ <Panel activePanel={activePanel} panelId={"CPD"} onToggle={this.onTogglePanel} title={"Cross Polar Discrimination"}>
+ <CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
+ </Panel>
+ </div>
+ )}
+ </div>
+ )}
+ </>
+ );
+ }
+ };
+
+ public componentDidMount() {
+ this.props.getAllDevicesPMdata();
+ this.props.enableFilterPerformanceData.onToggleFilter();
+ this.props.enableFilterReceiveLevel.onToggleFilter();
+ this.props.enableFilterTransmissionPower.onToggleFilter();
+ this.props.enableFilterTemperature.onToggleFilter();
+ this.props.enableFilterAdaptiveModulation.onToggleFilter();
+ this.props.enableFilterSinr.onToggleFilter();
+ this.props.enableFilterCpd.onToggleFilter();
+ }
+
+ /**
+ * Function which selects the first ltp returned from the database on selection of network element.
+ */
+ private selectFirstLtp = (firstLtp: string) => {
+ this.setState({
+ showPanels: true,
+ selectedLtp: firstLtp
+ });
+ this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, firstLtp);
+ }
+
+ /**
+ * A function which loads the tables based on prefilters defined by network element and ltp on selected time period.
+ */
+ private preFilterChangeAndReload = (networkElement: string, timePeriod: string, ltp: string) => {
+ const preFilter = {
+ "node-name": networkElement,
+ "uuid-interface": ltp
+ };
+ this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
+ this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
+ this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
+ this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
+ this.props.temperaturePreActions.onPreFilterChanged(preFilter);
+ this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
+ this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(preFilter);
+
+ }
+
+ /**
+ * Function which handles network element changes.
+ */
+ private handleNetworkElementSelect = (selectedNetworkElement: string) => {
+
+ this.setState({
+ showLtps: true,
+ selectedNetworkElement: selectedNetworkElement,
+ showNetworkElementsTable: false,
+ showPanels: false,
+ selectedLtp: "-1"
+ });
+ this.props.changeNode(selectedNetworkElement);
+ this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
+ }
+
+ private handleURLChange = (selectedNetworkElement: string) => {
+ if (selectedNetworkElement !== this.state.selectedNetworkElement) {
+ this.setState({
+ showLtps: true,
+ selectedNetworkElement: selectedNetworkElement,
+ showPanels: false,
+ selectedLtp: "-1"
+ });
+ this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
+ }
+ }
+
+ /**
+ * Function which resets the ltps to "--select--" in the state if the passed parameter @ltpNotSelected is true.
+ * @param ltpNotSelected: true, if existing selected is not available in the given time period, else false
+ */
+ private resetLtpDropdown = (ltpNotSelected: boolean) => {
+ if (ltpNotSelected) {
+ this.setState({
+ selectedLtp: "-1",
+ });
+ }
+ }
+
+ /**
+ * Function which handles the time period changes.
+ */
+ private handleTimePeriodChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
+ const selectedTimeInterval = event.target.value === "15min"
+ ? PmDataInterval.pmInterval15Min
+ : PmDataInterval.pmInterval24Hours
+
+ this.setState({
+ selectedTimePeriod: event.target.value,
+ });
+ this.props.timeIntervalChange(selectedTimeInterval);
+ this.props.reloadPerformanceData();
+ this.props.reloadReceiveLevel();
+ this.props.reloadTransmissionPower();
+ this.props.reloadAdaptiveModulation();
+ this.props.reloadTemperature();
+ this.props.reloadSignalToInterference();
+ this.props.reloadCrossPolarDiscrimination();
+ this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
+ this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp);
+ }
+
+ /**
+ * Function which handles the ltp changes.
+ */
+ private handleLtpChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
+ var showPanels: boolean = true;
+ if (event.target.value === "-1") {
+ showPanels = false;
+ }
+ this.setState({
+ showPanels: showPanels,
+ selectedLtp: event.target.value
+ });
+ this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value);
+ }
+}
+
+const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
+export default PerformanceHistoryApplication;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
new file mode 100644
index 000000000..1e882fc69
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/MyOdluxBundle.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class MyOdluxBundle extends OdluxBundle {
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ }
+
+ @Override
+ public void clean() {
+ super.clean();
+ }
+
+ @Override
+ public String getResourceFileContent(String filename) {
+ return super.getResourceFileContent(filename);
+ }
+
+ @Override
+ public boolean hasResource(String filename) {
+ return super.hasResource(filename);
+ }
+
+ @Override
+ public void setBundleName(String bundleName) {
+ super.setBundleName(bundleName);
+ }
+
+ @Override
+ public void setLoader(OdluxBundleLoader loader) {
+ super.setLoader(loader);
+ }
+
+ @Override
+ public String getBundleName() {
+ return super.getBundleName();
+ }
+
+ @Override
+ public OdluxBundleLoader getLoader() {
+ return super.getLoader();
+ }
+
+ public MyOdluxBundle() {
+ super();
+ }
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..1bcbf0127
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,9 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="loadersvc" availability="mandatory" activation="eager" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader"/>
+
+ <bean id="bundle" init-method="initialize" destroy-method="clean" class="org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle">
+ <property name="loader" ref="loadersvc"/>
+ <property name="bundleName" value="performanceHistoryApp"/>
+ <property name="index" value="55"/>
+ </bean>
+</blueprint>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
new file mode 100644
index 000000000..edf68e096
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/java/org/onap/ccsdk/features/sdnr/wt/odlux/bundles/test/TestBundleRes.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.bundles.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.bundles.MyOdluxBundle;
+
+public class TestBundleRes {
+
+ @Test
+ public void test() {
+ OdluxBundleLoaderImpl loader = OdluxBundleLoaderImpl.getInstance();
+ MyOdluxBundle b = new MyOdluxBundle();
+ b.setLoader(loader);
+ b.setIndex(0);
+ b.setBundleName("abc");
+ b.initialize();
+ assertTrue(loader.getNumberOfBundles()==1);
+ assertNotNull(b.getLoader());
+ assertEquals("abc",b.getBundleName());
+ assertTrue(b.hasResource("test.js"));
+ assertNotNull(b.getResourceFileContent("test.js"));
+ b.clean();
+ assertTrue(loader.getNumberOfBundles()==0);
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/resources/test.js b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/resources/test.js
new file mode 100644
index 000000000..b47fdc39f
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src2/test/resources/test.js
@@ -0,0 +1,5 @@
+asdac sad
+as
+d
+sad
+ sadfa \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json b/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json
new file mode 100644
index 000000000..a66b5d828
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "prop-types",
+ "react",
+ "react-dom"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
new file mode 100644
index 000000000..9c2414864
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
@@ -0,0 +1,143 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "../..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "../../framework" : "../..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ performanceHistoryApp: ["./pluginPerformance.tsx"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "../../framework/src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new CopyWebpackPlugin([{
+ from: 'index.html',
+ to: distPath
+ }]),
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: frameworkPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/restconf": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ },
+ "/database": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ }
+ }
+ }
+ }];
+}
diff --git a/sdnr/wt/odlux/core/features/pom.xml b/sdnr/wt/odlux/core/features/pom.xml
new file mode 100644
index 000000000..a643ec2fe
--- /dev/null
+++ b/sdnr/wt/odlux/core/features/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- * ============LICENSE_START=======================================================
+ * ONAP : CCSDK.feature.sdnr.wt * ================================================================================
+ * Copyright (C) 2018 highstreet technologies GmbH Intellectual Property.
+ * All rights reserved. * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); * you may
+ not use this file except in compliance with the License. * You may obtain
+ a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *
+ * Unless required by applicable law or agreed to in writing, software * distributed
+ under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES
+ OR CONDITIONS OF ANY KIND, either express or implied. * See the License for
+ the specific language governing permissions and * limitations under the License.
+ * ============LICENSE_END========================================================= -->
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-feature</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>feature</packaging>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId} :: feature</name>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>${odl.controller.mdsal.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/sdnr/wt/odlux/core/installer/pom.xml b/sdnr/wt/odlux/core/installer/pom.xml
new file mode 100755
index 000000000..98a4fd50f
--- /dev/null
+++ b/sdnr/wt/odlux/core/installer/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-installer</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <properties>
+ <application.name>sdnr-wt-odlux-core</application.name>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>${application.name}-feature</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>${application.name}-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-nested-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>true</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <!--<includeArtifactIds>sdnr-wt-apigateway-provider,${application.name}</includeArtifactIds> -->
+ <!--<scope>provided</scope> -->
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/core/installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt/odlux/core/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..c4eb9aa25
--- /dev/null
+++ b/sdnr/wt/odlux/core/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/sdnr/wt/odlux/core/model/pom.xml b/sdnr/wt/odlux/core/model/pom.xml
new file mode 100644
index 000000000..1618e7aa1
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name>
+ <packaging>bundle</packaging>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>*</Import-Package>
+ <Export-Package>org.onap.ccsdk.features.sdnr.wt.odlux.*,com.opensymphony.*</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java b/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java
new file mode 100644
index 000000000..133b08494
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2002-2003,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.*;
+
+
+/**
+ * This class is extremely useful for loading resources and classes in a fault tolerant manner
+ * that works across different applications servers.
+ *
+ * It has come out of many months of frustrating use of multiple application servers at Atlassian,
+ * please don't change things unless you're sure they're not going to break in one server or another!
+ *
+ * It was brought in from oscore trunk revision 147.
+ *
+ * @author $Author$
+ * @version $Revision$
+ */
+public class ClassLoaderUtil {
+ //~ Methods ////////////////////////////////////////////////////////////////
+
+ /**
+ * Load all resources with a given name, potentially aggregating all results
+ * from the searched classloaders. If no results are found, the resource name
+ * is prepended by '/' and tried again.
+ *
+ * This method will try to load the resources using the following methods (in order):
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param resourceName The name of the resources to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static Iterator<URL> getResources(String resourceName, Class<?> callingClass, boolean aggregate) throws IOException {
+
+ AggregateIterator<URL> iterator = new AggregateIterator<>();
+
+ iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
+
+ if (!iterator.hasNext() || aggregate) {
+ iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
+ }
+
+ if (!iterator.hasNext() || aggregate) {
+ ClassLoader cl = callingClass.getClassLoader();
+
+ if (cl != null) {
+ iterator.addEnumeration(cl.getResources(resourceName));
+ }
+ }
+
+ if (!iterator.hasNext() && resourceName != null && (resourceName.length() == 0 || resourceName.charAt(0) != '/')) {
+ return getResources('/' + resourceName, callingClass, aggregate);
+ }
+
+ return iterator;
+ }
+
+ /**
+ * Load a given resource.
+ *
+ * This method will try to load the resource using the following methods (in order):
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static URL getResource(String resourceName, Class<?> callingClass) {
+ URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
+
+ if (url == null) {
+ url = ClassLoaderUtil.class.getClassLoader().getResource(resourceName);
+ }
+
+ if (url == null) {
+ ClassLoader cl = callingClass.getClassLoader();
+
+ if (cl != null) {
+ url = cl.getResource(resourceName);
+ }
+ }
+
+ if (url == null && resourceName != null && (resourceName.length() == 0 || resourceName.charAt(0) != '/')) {
+ return getResource('/' + resourceName, callingClass);
+ }
+
+ return url;
+ }
+
+ /**
+ * This is a convenience method to load a resource as a stream.
+ *
+ * The algorithm used to find the resource is given in getResource()
+ *
+ * @param resourceName The name of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
+ public static InputStream getResourceAsStream(String resourceName, Class<?> callingClass) {
+ URL url = getResource(resourceName, callingClass);
+
+ try {
+ return url != null ? url.openStream() : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Load a class with a given name.
+ *
+ * It will try to load the class in the following order:
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>Using the basic Class.forName()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>From the callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param className The name of the class to load
+ * @param callingClass The Class object of the calling object
+ * @throws ClassNotFoundException If the class cannot be found anywhere.
+ */
+ public static Class<?> loadClass(String className, Class<?> callingClass) throws ClassNotFoundException {
+ try {
+ return Thread.currentThread().getContextClassLoader().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException ex) {
+ try {
+ return ClassLoaderUtil.class.getClassLoader().loadClass(className);
+ } catch (ClassNotFoundException exc) {
+ return callingClass.getClassLoader().loadClass(className);
+ }
+ }
+ }
+ }
+
+ /**
+ * Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one
+ * ahead of the enumerator to protect against returning duplicates.
+ */
+ static class AggregateIterator<E> implements Iterator<E> {
+
+ LinkedList<Enumeration<E>> enums = new LinkedList<>();
+ Enumeration<E> cur = null;
+ E next = null;
+ Set<E> loaded = new HashSet<>();
+
+ public AggregateIterator<E> addEnumeration(Enumeration<E> e) {
+ if (e.hasMoreElements()) {
+ if (cur == null) {
+ cur = e;
+ next = e.nextElement();
+ loaded.add(next);
+ } else {
+ enums.add(e);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public E next() {
+ if (next != null) {
+ E prev = next;
+ next = loadNext();
+ return prev;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ private Enumeration<E> determineCurrentEnumeration() {
+ if (cur != null && !cur.hasMoreElements()) {
+ if (enums.size() > 0) {
+ cur = enums.removeLast();
+ } else {
+ cur = null;
+ }
+ }
+ return cur;
+ }
+
+ private E loadNext() {
+ if (determineCurrentEnumeration() != null) {
+ E tmp = cur.nextElement();
+ int loadedSize = loaded.size();
+ while (loaded.contains(tmp)) {
+ tmp = loadNext();
+ if (tmp == null || loaded.size() > loadedSize) {
+ break;
+ }
+ }
+ if (tmp != null) {
+ loaded.add(tmp);
+ }
+ return tmp;
+ }
+ return null;
+
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java
new file mode 100644
index 000000000..4b58aac44
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Iterator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+
+public class ClassLoaderUtilExt {
+
+ final static Logger LOG = LoggerFactory.getLogger(ClassLoaderUtilExt.class);
+
+ public static URL getResource(String resourceName, Class<?> callingClass) {
+
+ Iterator<URL> urls = null;
+ URL url = null;
+ try {
+ urls = getResources(resourceName, callingClass, true);
+ } catch (IOException e) {
+ LOG.debug("No resource {}",resourceName);
+ }
+ if (urls != null) {
+ while (urls.hasNext()) {
+ URL u = urls.next();
+ LOG.debug("found " + u.toString());
+ url = u;
+ break;
+ }
+ }
+ if (url == null) {
+ LOG.debug("res currently not found. try to find with bundle");
+ Bundle b = FrameworkUtil.getBundle(callingClass);
+ if(b!=null)
+ {
+ url = b.getEntry(resourceName);
+ }
+ else {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ url = loader.getResource(resourceName);
+ }
+
+ }
+ return url;
+ }
+
+ public static Iterator<URL> getResources(String resourceName, Class<?> callingClass, boolean aggregate)
+ throws IOException {
+ return ClassLoaderUtil.getResources(resourceName, callingClass, aggregate);
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/IndexOdlBundle.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/IndexOdlBundle.java
new file mode 100644
index 000000000..d193edb04
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/IndexOdlBundle.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles;
+
+public interface IndexOdlBundle {
+
+}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java
new file mode 100644
index 000000000..4e2332b4e
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+/**
+ * At startup of each karaf bundle, each UI module creates an instance of this class via blueprint.
+ * Initialize method gets called at loading of bundle.
+ */
+
+public class OdluxBundle {
+
+ final static Logger LOG = LoggerFactory.getLogger(OdluxBundle.class);
+ private static final String LR = "\n";
+
+ private String bundleName;
+ private OdluxBundleLoader loader;
+ private int index;
+
+ /**
+ * @return the index
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * @param index the index to set
+ */
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public OdluxBundleLoader getLoader() {
+ return loader;
+ }
+
+ public void setLoader(OdluxBundleLoader loader) {
+ this.loader = loader;
+ }
+
+ public void setBundleName(String bundleName) {
+ this.bundleName = bundleName;
+ }
+
+ public String getBundleName() {
+ return this.bundleName;
+ }
+
+ public OdluxBundle() {}
+
+ protected OdluxBundle(final OdluxBundleLoader loader, final String bundleName) {
+ this.loader = loader;
+ this.bundleName = bundleName;
+ }
+
+ public void initialize() {
+
+ LOG.info("Registering resources");
+ if (this.loader != null) {
+ if (this.bundleName == null)
+ LOG.error("bundle name is missing. Bundle can not be registered with odlux");
+ else {
+ LOG.info("Registering bunlde {}", this.bundleName);
+ this.loader.addBundle(this);
+ }
+ }
+ }
+
+ public void clean() {
+ LOG.info("Unregistering resources");
+
+ if (this.loader != null) {
+ this.loader.removeBundle(this);
+ }
+ }
+
+ public boolean hasResource(String filename) {
+ return this.getResource(filename) != null;
+ }
+
+ public String getResourceFileContent(String filename) {
+ return this.loadFileContent(this.getResource(filename));
+ }
+
+ protected URL getResource(String filename) {
+ return ClassLoaderUtilExt.getResource(filename, this.getClass());
+ }
+
+ protected String loadFileContent(final URL url ) {
+ if (url == null)
+ return null;
+ LOG.debug("try to load res " + url.toString());
+ StringBuilder sb = new StringBuilder();
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new InputStreamReader(url.openStream()));
+
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ sb.append(inputLine + LR);
+ }
+ } catch (IOException e) {
+ LOG.warn("could not load resfile " + url.toString() + ": " + e.getMessage());
+ return null;
+ }
+ finally {
+ if(in!=null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+
+ }
+ }
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java
new file mode 100644
index 000000000..ce003c664
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles;
+
+public interface OdluxBundleLoader {
+
+ public void addBundle(OdluxBundle bundle);
+
+ public void removeBundle(OdluxBundle bundle);
+
+ public int getNumberOfBundles();
+
+ public String getResourceContent(String fn, OdluxBundleResourceAccess indexBundle);
+
+}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java
new file mode 100644
index 000000000..d7ac3e9c4
--- /dev/null
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles;
+
+import java.util.List;
+
+public interface OdluxBundleResourceAccess {
+
+ boolean hasResource(String fn);
+ String getResourceFileContent(String fn, List<String> bundleNames);
+ String getBundleName();
+
+}
diff --git a/sdnr/wt/odlux/core/pom.xml b/sdnr/wt/odlux/core/pom.xml
new file mode 100644
index 000000000..c41075a10
--- /dev/null
+++ b/sdnr/wt/odlux/core/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-top</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>odlux-core</name>
+
+ <properties>
+ <feature-name>sdnr-wt-odlux-core</feature-name>
+ </properties>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <modules>
+ <module>model</module>
+ <module>provider</module>
+ <module>features</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/sdnr/wt/odlux/core/provider/pom.xml b/sdnr/wt/odlux/core/provider/pom.xml
new file mode 100644
index 000000000..84838a05f
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-provider</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name>
+ <packaging>bundle</packaging>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-core-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sdnr-wt-odlux-framework</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>org.onap.ccsdk.features.sdnr.wt.odlux.*;resolution:=optional,*;
+ </Import-Package>
+ <Embed-Dependency>sdnr-wt-odlux-framework;inline=true</Embed-Dependency>
+ <Embed-Transitive>true</Embed-Transitive>
+ <Export-Package>${project.groupId}.*</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java
new file mode 100644
index 000000000..73d61a7b3
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleResourceAccess;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IndexOdluxBundle extends OdluxBundle implements OdluxBundleResourceAccess {
+
+ private static Logger LOG = LoggerFactory.getLogger(IndexOdluxBundle.class);
+
+ private static final String LR = "\n";
+ private static final String BUNDLENAME_APP = "run";
+ private static final String regexRequire = "require\\(\\[(\"" + BUNDLENAME_APP + "\")\\]";
+ private static final String regexFunction = "function[\\ ]*\\((" + BUNDLENAME_APP + ")\\)[\\ ]*\\{";
+ private static final String regexFunctionBody = "(" + BUNDLENAME_APP + "\\.runApplication\\(\\);)";
+ private static final Pattern patternRequire = Pattern.compile(regexRequire);
+ private static final Pattern patternFunction = Pattern.compile(regexFunction);
+ private static final Pattern patternFunctionBody = Pattern.compile(regexFunctionBody);
+
+ public IndexOdluxBundle() {
+ super(null, BUNDLENAME_APP);
+
+ }
+ @Override
+ protected String loadFileContent(URL url)
+ {
+ return loadFileContent(url, OdluxBundleLoaderImpl.getInstance().getLoadedBundles(this.getBundleName()));
+ }
+
+ @Override
+ public String getResourceFileContent(String fn, List<String> bundleNames) {
+ return loadFileContent(this.getResource(fn),bundleNames);
+ }
+
+ private static String loadFileContent(URL url, List<String> bundlesNamesList) {
+ if (url == null) {
+ return null;
+ }
+ LOG.debug("try to load res " + url.toString());
+ StringBuilder sb = new StringBuilder();
+ Matcher matcher;
+ BufferedReader in=null;
+ try {
+ in = new BufferedReader(new InputStreamReader(url.openStream()));
+
+ String inputLine;
+ while ((inputLine = in.readLine()) != null) {
+ if (url.getFile().endsWith("index.html")) {
+ matcher = patternRequire.matcher(inputLine);
+ if (matcher.find()) {
+ inputLine = inputLine.substring(0, matcher.start(1)) + "\"" + String.join("\",\"", bundlesNamesList)
+ + "\"" + inputLine.substring(matcher.end(1));
+ }
+ matcher = patternFunction.matcher(inputLine);
+ if (matcher.find()) {
+ inputLine = inputLine.substring(0, matcher.start(1)) + String.join(",", bundlesNamesList)
+ + inputLine.substring(matcher.end(1));
+ }
+ matcher = patternFunctionBody.matcher(inputLine);
+ if (matcher.find()) {
+ String hlp = "";
+ for (String bundle : bundlesNamesList) {
+ if (!bundle.equals(BUNDLENAME_APP)) {
+ hlp += bundle + ".register();" + LR;
+ }
+ }
+ inputLine = inputLine.substring(0, matcher.start(1)) + hlp
+ + inputLine.substring(matcher.start(1));
+ }
+ }
+ sb.append(inputLine + LR);
+ }
+
+ } catch (IOException e) {
+ LOG.warn("could not load resfile {} : {}", url, e.getMessage());
+ return null;
+ }
+ finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e) {
+
+ }
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java
new file mode 100644
index 000000000..d6d466ab9
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.nio.file.Files;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IndexServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 3039669437157215355L;
+ private static Logger LOG = LoggerFactory.getLogger(IndexServlet.class);
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ if (req.getRequestURI() != null && req.getRequestURI().contains("favicon.ico")) {
+ this.sendFile(resp, "etc/favicon.ico","image/x-icon");
+ } else {
+
+ LOG.debug("redirect to odlux/index.html");
+ resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ resp.setHeader("Location", "odlux/index.html");
+ }
+ }
+
+ private void sendFile(HttpServletResponse response, String filename, String mimeType) {
+ File f = new File(filename);
+ if (f.exists()) {
+ try {
+ byte[] bytes = Files.readAllBytes(f.toPath());
+ response.setContentType(mimeType);
+ response.setContentLength(bytes.length);
+ response.setStatus(HttpURLConnection.HTTP_OK);
+ OutputStream os = response.getOutputStream();
+ os.write(bytes);
+ os.flush();
+ os.close();
+ } catch (IOException e) {
+ LOG.debug("problem sending {}: {}", filename, e);
+ }
+ } else {
+ LOG.debug("file not found: {}",filename);
+ response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/OdluxBundleLoaderImpl.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/OdluxBundleLoaderImpl.java
new file mode 100644
index 000000000..205c96129
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/OdluxBundleLoaderImpl.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentSkipListSet;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleResourceAccess;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OdluxBundleLoaderImpl implements OdluxBundleLoader {
+
+ private final static Logger LOG = LoggerFactory.getLogger(OdluxBundleLoaderImpl.class);
+
+ private static OdluxBundleLoaderImpl singleton = null;
+
+ private Object lock;
+ // private List<OdluxBundle> bundles;
+ private ConcurrentSkipListSet<OdluxBundle> bundles2;
+ private Comparator<OdluxBundle> sortorderbundlecomparator;
+
+ public OdluxBundleLoaderImpl() {
+ if (singleton != null) {
+ LOG.error("Multiple intializations of singleton");
+ } else {
+ lock = new Object();
+ sortorderbundlecomparator = (arg0, arg1) -> {
+ int diff = arg0.getIndex() - arg1.getIndex();
+ return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+ };
+ bundles2 = new ConcurrentSkipListSet<>(sortorderbundlecomparator);
+
+ singleton = this;
+ }
+ }
+
+ public static OdluxBundleLoaderImpl getInstance() {
+ if (singleton == null) {
+ LOG.warn("Test initialization order");
+ new OdluxBundleLoaderImpl();
+ }
+ return singleton;
+ }
+
+ @Override
+ public int getNumberOfBundles() {
+ synchronized (lock) {
+ return this.bundles2.size();
+ }
+ }
+
+ @Override
+ public void addBundle(OdluxBundle bundle) {
+ LOG.debug("odlux bundle " + bundle.getBundleName() + " added");
+ this.bundles2.add(bundle);
+
+
+ }
+
+ @Override
+ public void removeBundle(OdluxBundle bundle) {
+ this.bundles2.remove(bundle);
+ LOG.debug("odlux bundle " + bundle.getBundleName() + " removed");
+
+ }
+
+ public List<String> getLoadedBundles(String myBundleName) {
+ List<String> list = new ArrayList<>();
+ for (OdluxBundle b : bundles2) {
+ list.add(b.getBundleName());
+ }
+ list.add(myBundleName);
+ return list;
+ }
+
+ private List<String> getBundleNames(String myBundleName) {
+ final List<String> names = new ArrayList<>();
+ for (OdluxBundle b : bundles2) {
+ names.add(b.getBundleName());
+ }
+ names.add(myBundleName);
+ return names;
+ }
+
+ public String getResourceContent(String fn, OdluxBundleResourceAccess indexBundle) {
+ String fileContent = null;
+
+ if (indexBundle.hasResource(fn)) {
+ fileContent = indexBundle.getResourceFileContent(fn, getBundleNames(indexBundle.getBundleName()));
+ } else {
+ LOG.debug("not found in framework res. try to find in applications");
+ final Iterator<OdluxBundle> it = bundles2.iterator();
+ while (it.hasNext()) {
+ OdluxBundle b = it.next();
+ if (b.hasResource(fn)) {
+ LOG.debug("found res in " + b.getBundleName());
+ fileContent = b.getResourceFileContent(fn);
+ break;
+ }
+ }
+ }
+ return fileContent;
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
new file mode 100644
index 000000000..fe00662aa
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.wt.odlux;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResFilesServlet extends HttpServlet {
+
+ private static final long serialVersionUID = -6807215213921798293L;
+ private static Logger LOG = LoggerFactory.getLogger(ResFilesServlet.class);
+
+
+ private final IndexOdluxBundle indexBundle;
+
+ public ResFilesServlet() {
+ super();
+ indexBundle = new IndexOdluxBundle();
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ final String fn = req.getRequestURI();
+ LOG.debug("Get request with for URI: {}", fn);
+
+ OdluxBundleLoader odluxBundleLoader = OdluxBundleLoaderImpl.getInstance();
+ if (odluxBundleLoader != null) {
+ String fileContent = odluxBundleLoader.getResourceContent(fn, indexBundle);
+ if (fileContent != null) {
+ //Store header info
+ String mimeType = getMimeType(fn);
+ byte[] byteContent = fileContent.getBytes(java.nio.charset.StandardCharsets.UTF_8);
+ int length = byteContent.length;
+
+ LOG.debug("Found file in resources. Name {} mimetype {} length {} and write to output stream", fn, mimeType, length);
+ resp.setContentType(mimeType);
+ resp.setContentLength(length);
+ resp.setStatus(HttpURLConnection.HTTP_OK);
+ OutputStream os = resp.getOutputStream();
+ os.write(byteContent);
+ os.flush();
+ os.close();
+ } else {
+ LOG.debug("File {} not found in res.", fn);
+ resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
+ } else {
+ LOG.debug("BundleLoaderInstance to found.", fn);
+ resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
+ }
+
+ public String loadFileContent(String filename) {
+ return this.indexBundle.getResourceFileContent(filename);
+ }
+
+ //Provide own function that can be overloaded for test
+ public String getMimeType(String fileName) {
+ return getServletContext().getMimeType(fileName);
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/sdnr/wt/odlux/core/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..5dab578de
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs">
+
+ <bean id="indexServlet"
+ class="org.onap.ccsdk.features.sdnr.wt.odlux.IndexServlet">
+ </bean>
+
+ <service interface="javax.servlet.http.HttpServlet" ref="indexServlet">
+ <service-properties>
+ <entry key="alias" value="/index2.html" />
+ </service-properties>
+ </service>
+
+ <bean id="indexServlet2"
+ class="org.onap.ccsdk.features.sdnr.wt.odlux.IndexServlet">
+ </bean>
+
+ <service interface="javax.servlet.http.HttpServlet" ref="indexServlet2">
+ <service-properties>
+ <entry key="alias" value="/favicon.ico" />
+ </service-properties>
+ </service>
+
+ <bean id="resFilesServlet"
+ class="org.onap.ccsdk.features.sdnr.wt.odlux.ResFilesServlet">
+ </bean>
+
+ <service interface="javax.servlet.http.HttpServlet" ref="resFilesServlet">
+ <service-properties>
+ <entry key="alias" value="/odlux" />
+ </service-properties>
+ </service>
+ <bean id="loadersvc" class="org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl"/>
+ <service id="serviceRegistration" interface="org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader" ref="loadersvc"/>
+
+</blueprint>
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java
new file mode 100644
index 000000000..bebbffdcf
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.odlux.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class TestBundleLoaderImpl {
+
+ @Test
+ public void test() {
+ OdluxBundleLoader loader = OdluxBundleLoaderImpl.getInstance();
+ int loaded = loader.getNumberOfBundles();
+
+ OdluxBundle bundle1 = new OdluxBundle();
+ bundle1.setBundleName("b1");
+ bundle1.setIndex(0);
+ bundle1.setLoader(loader);
+ OdluxBundle bundle2 = new OdluxBundle();
+ bundle2.setBundleName("b2");
+ bundle2.setIndex(55);
+ bundle2.setLoader(loader);
+ bundle1.initialize();
+ bundle2.initialize();
+ assertNotNull(bundle1.getResourceFileContent("index.html"));
+ assertNotNull(bundle2.getResourceFileContent("index2.html"));
+ assertEquals(loaded+2, loader.getNumberOfBundles());
+ loader.addBundle(bundle1);
+ loader.addBundle(bundle2);
+ assertEquals(loaded+2, loader.getNumberOfBundles());
+ loader.removeBundle(bundle1);
+ loader.removeBundle(bundle2);
+ assertEquals(loaded, loader.getNumberOfBundles());
+
+ assertTrue(bundle1.hasResource("index.html"));
+ assertTrue(bundle2.hasResource("index2.html"));
+ assertNotNull(bundle1.getLoader());
+ assertEquals(0,bundle1.getIndex());
+ bundle1.clean();
+ bundle2.clean();
+ assertEquals(loaded,loader.getNumberOfBundles());
+
+
+ }
+}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java
new file mode 100644
index 000000000..3c9ad4308
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.odlux.test;
+import static org.junit.Assert.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.ResFilesServlet;
+
+public class TestLoadResources {
+
+ @Test
+ public void test() {
+ ResFilesServlet servlet = new ResFilesServlet();
+ String indexhtml=null;
+ indexhtml=servlet.loadFileContent("odlux/index.html");
+ assertNotNull(indexhtml);
+ final String regex = "require\\(\\[.*\"run\".*\\]";
+ final Pattern pattern = Pattern.compile(regex,Pattern.MULTILINE);
+ System.out.println(indexhtml);
+ final Matcher matcher = pattern.matcher(indexhtml);
+ assertTrue("Can not find patter '"+regex+"'",matcher.find());
+ }
+ @Test
+ public void test2() {
+
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java
new file mode 100644
index 000000000..78d5eb8fe
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.odlux.test;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.IndexServlet;
+
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class TestRedirect {
+
+ private static final int RESPONSECODE_REDIRECT = 301;
+
+ @Test
+ public void test() {
+ PublicIndexServlet servlet =new PublicIndexServlet();
+ HttpServletRequest req = mock(HttpServletRequest.class);
+ HttpServletResponse resp = mock(HttpServletResponse.class);
+ try {
+ servlet.doGet(req,resp);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ verify(resp).setStatus(RESPONSECODE_REDIRECT);
+ }
+
+ private static class PublicIndexServlet extends IndexServlet{
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ super.doGet(req, resp);
+ }
+ }
+
+}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java
new file mode 100644
index 000000000..217735c40
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ ******************************************************************************/
+package org.onap.ccsdk.features.sdnr.odlux.test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.WriteListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import static org.mockito.Mockito.*;
+import org.junit.Test;
+import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
+import org.onap.ccsdk.features.sdnr.wt.odlux.ResFilesServlet;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
+import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
+
+public class TestResFileServlet {
+
+ PublicResFilesServlet servlet;
+
+ @Test
+ public void test() throws ServletException {
+ servlet = new PublicResFilesServlet();
+ servlet.init();
+
+ OdluxBundleLoader loader = OdluxBundleLoaderImpl.getInstance();
+ OdluxBundle b = new OdluxBundle();
+ b.setBundleName("b1");
+ b.setIndex(9);
+ b.setLoader(loader);
+ b.initialize();
+ System.out.println("Subtest1");
+ testResReq("odlux/index.html", HttpURLConnection.HTTP_OK);
+ System.out.println("Subtest2");
+ testResReq("odlux/fragmich.txt", HttpURLConnection.HTTP_NOT_FOUND);
+ System.out.println("Done");
+ }
+
+ private void testResReq(String res, int responseCode) {
+ HttpServletRequest req = mock(HttpServletRequest.class);
+ HttpServletResponse resp = mock(HttpServletResponse.class);
+ when(req.getRequestURI()).thenReturn(res);
+ StringWriter out = new StringWriter();
+ ServletOutputStream printOut = new ServletOutputStream() {
+
+ @Override
+ public void write(int arg0) throws IOException {
+ out.write(arg0);
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setWriteListener(WriteListener writeListener) {
+
+ }
+ };
+ try {
+ when(resp.getOutputStream()).thenReturn(printOut);
+ servlet.doGet(req, resp);
+ } catch (ServletException | IOException e) {
+ fail(e.getMessage());
+ }
+ verify(resp).setStatus(responseCode);
+ }
+
+
+ @SuppressWarnings("serial")
+ private class PublicResFilesServlet extends ResFilesServlet {
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ super.doGet(req, resp);
+ }
+ @Override
+ public String getMimeType(String fileName) {
+ return "mimetype";
+ }
+ }
+}
diff --git a/sdnr/wt/odlux/core/provider/src/test/resources/index.html b/sdnr/wt/odlux/core/provider/src/test/resources/index.html
new file mode 100644
index 000000000..4f4584dd9
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/resources/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["run"], function (run) {
+ run.runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/core/provider/src/test/resources/index2.html b/sdnr/wt/odlux/core/provider/src/test/resources/index2.html
new file mode 100644
index 000000000..4f4584dd9
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/resources/index2.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["run"], function (run) {
+ run.runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index.html b/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index.html
new file mode 100644
index 000000000..4f4584dd9
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["run"], function (run) {
+ run.runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index2.html b/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index2.html
new file mode 100644
index 000000000..4f4584dd9
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/resources/odlux/index2.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["run"], function (run) {
+ run.runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/core/provider/src/test/resources/simplelogger.properties b/sdnr/wt/odlux/core/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..426f84834
--- /dev/null
+++ b/sdnr/wt/odlux/core/provider/src/test/resources/simplelogger.properties
@@ -0,0 +1,38 @@
+# SLF4J's SimpleLogger configuration file
+# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
+
+# Default logging detail level for all instances of SimpleLogger.
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, defaults to "info".
+org.slf4j.simpleLogger.defaultLogLevel=debug
+
+# Logging detail level for a SimpleLogger instance named "xxx.yyy.zzz".
+# Must be one of ("trace", "debug", "info", "warn", or "error").
+# If not specified, the default logging detail level is used.
+# org.slf4j.simpleLogger.log.xxx.yyy=debug
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager=info
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.archiveservice=debug
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.internalTypes.Resources=info
+org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.netconf.container=info
+
+# Set to true if you want the current date and time to be included in output messages.
+# Default is false, and will output the number of milliseconds elapsed since startup.
+#org.slf4j.simpleLogger.showDateTime=false
+
+# The date and time format to be used in the output messages.
+# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
+# If the format is not specified or is invalid, the default format is used.
+# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
+#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
+
+# Set to true if you want to output the current thread name.
+# Defaults to true.
+#org.slf4j.simpleLogger.showThreadName=true
+
+# Set to true if you want the Logger instance name to be included in output messages.
+# Defaults to true.
+#org.slf4j.simpleLogger.showLogName=true
+
+# Set to true if you want the last component of the name to be included in output messages.
+# Defaults to false.
+#org.slf4j.simpleLogger.showShortLogName=false
diff --git a/sdnr/wt/odlux/framework/.babelrc b/sdnr/wt/odlux/framework/.babelrc
new file mode 100644
index 000000000..3d8cd1260
--- /dev/null
+++ b/sdnr/wt/odlux/framework/.babelrc
@@ -0,0 +1,17 @@
+{
+ "presets": [
+ ["@babel/preset-react"],
+ ["@babel/preset-env", {
+ "targets": {
+ "chrome": "66"
+ },
+ "spec": true,
+ "loose": false,
+ "modules": false,
+ "debug": false,
+ "useBuiltIns": "usage",
+ "forceAllTransforms": true
+ }]
+ ],
+ "plugins": []
+}
diff --git a/sdnr/wt/odlux/framework/LICENSE b/sdnr/wt/odlux/framework/LICENSE
new file mode 100644
index 000000000..3556ffa71
--- /dev/null
+++ b/sdnr/wt/odlux/framework/LICENSE
@@ -0,0 +1,13 @@
+/*
+ * ============LICENSE_START=============================================================================================================
+ * Copyright (c) 2018 highstreet-technolgies.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+ * ============LICENSE_END===============================================================================================================
+ *
+ */ \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/package.json b/sdnr/wt/odlux/framework/package.json
new file mode 100644
index 000000000..d0fe49b57
--- /dev/null
+++ b/sdnr/wt/odlux/framework/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "@odlux/framework",
+ "version": "0.1.4",
+ "description": "A react based modular UI framework",
+ "main": "index.js",
+ "scripts": {
+ "start": "webpack-dev-server --env debug",
+ "prebuild": "rimraf dist",
+ "build": "webpack --env release --config webpack.vendor.js && webpack --env release --config webpack.config.js && webpack --env release --config webpack.runner.js",
+ "build:run": "webpack --env release --config webpack.runner.js",
+ "build:dev": "webpack --env debug --config webpack.config.js",
+ "vendor:dev": "webpack --env debug --config webpack.vendor.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://git.mfico.de/highstreet-technologies/odlux.git"
+ },
+ "keywords": [
+ "reactjs",
+ "redux",
+ "ui",
+ "framework"
+ ],
+ "author": "Matthias Fischer",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "@types/node": "11.9.5",
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "jquery": "3.3.1",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1",
+ "@fortawesome/react-fontawesome": "0.1.3",
+ "@fortawesome/fontawesome-svg-core": "1.2.12",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "jsonwebtoken": "8.3.0",
+ "@types/jsonwebtoken": "7.2.8"
+ },
+ "dependencies": {
+ "http-server": "^0.11.1"
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
new file mode 100644
index 000000000..467101759
--- /dev/null
+++ b/sdnr/wt/odlux/framework/pom.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>sdnr-wt-odlux-framework</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>sdnr-wt-odlux-framework</name>
+ <properties>
+ <buildtime>${maven.build.timestamp}</buildtime>
+ <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
+ <buildno>36.1a30021(19/12/12)</buildno>
+ <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
+ </properties>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>dist</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>../node_modules</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <!-- eclipse bug build bin folder in basedir -->
+ <fileset>
+ <directory>bin</directory>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>de.jacks-it-lab</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.7.1</version>
+ <executions>
+ <execution>
+ <id>install node and yarn</id>
+ <goals>
+ <goal>install-node-and-yarn</goal>
+ </goals>
+ <!-- optional: default phase is "generate-resources" -->
+ <phase>initialize</phase>
+ <configuration>
+ <nodeVersion>v10.16.3</nodeVersion>
+ <yarnVersion>v1.19.0</yarnVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>clear cache</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <arguments>cache clean</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>install lerna</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <arguments>add lerna@3.13.1 -W --exact</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>exec lerna bootstrap</id>
+ <goals>
+ <goal>lerna</goal>
+ </goals>
+ <phase>initialize</phase>
+ <configuration>
+ <lernaInheritsProxyConfigFromMaven>false</lernaInheritsProxyConfigFromMaven>
+ <arguments>bootstrap</arguments>
+ <installDirectory>${project.basedir}</installDirectory>
+ <workingDirectory>${project.basedir}/../</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yarn build</id>
+ <goals>
+ <goal>yarn</goal>
+ </goals>
+ <configuration>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>com.google.code.maven-replacer-plugin</groupId>
+ <artifactId>replacer</artifactId>
+ <version>1.5.2</version>
+ <executions>
+ <execution>
+ <id>replace version</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>replace</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <basedir>${project.build.directory}/classes/odlux</basedir>
+ <includes>
+ <include>app.js</include>
+ </includes>
+ <replacements>
+ <replacement>
+ <token>##odlux.version##</token>
+ <value>${odlux.version}</value>
+ </replacement>
+ </replacements>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>dist</directory>
+ <targetPath>odlux</targetPath>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/sdnr/wt/odlux/framework/src/actions/authentication.ts b/sdnr/wt/odlux/framework/src/actions/authentication.ts
new file mode 100644
index 000000000..b28100035
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/authentication.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+import { AuthToken } from '../models/authentication';
+
+export class UpdateAuthentication extends Action {
+
+ constructor (public bearerToken: AuthToken | null) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/errorActions.ts b/sdnr/wt/odlux/framework/src/actions/errorActions.ts
new file mode 100644
index 000000000..ddb0d5728
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/errorActions.ts
@@ -0,0 +1,42 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+
+import { ErrorInfo } from '../models/errorInfo';
+export { ErrorInfo } from '../models/errorInfo';
+
+export class AddErrorInfoAction extends Action {
+
+ constructor(public errorInfo: ErrorInfo) {
+ super();
+ }
+}
+
+export class RemoveErrorInfoAction extends Action {
+
+ constructor(public errorInfo: ErrorInfo) {
+ super();
+ }
+}
+
+export class ClearErrorInfoAction extends Action {
+
+ constructor() {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/menuAction.ts b/sdnr/wt/odlux/framework/src/actions/menuAction.ts
new file mode 100644
index 000000000..ec0796587
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/menuAction.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../flux/action';
+
+export class MenuAction extends Action {
+ constructor(public isOpen: boolean) {
+ super();
+ }
+}
+
+export class MenuClosedByUser extends Action {
+ constructor(public isClosed: boolean) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/navigationActions.ts b/sdnr/wt/odlux/framework/src/actions/navigationActions.ts
new file mode 100644
index 000000000..6951b979f
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/navigationActions.ts
@@ -0,0 +1,64 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from "../flux/action";
+
+export abstract class NavigationAction extends Action { }
+
+export class NavigateToApplication<TState = { }> extends NavigationAction {
+
+ constructor(public applicationName: string, public href?: string, public state?: TState, public replace: boolean = false ) {
+ super();
+
+ }
+}
+
+export class PushAction<TState = { }> extends NavigationAction {
+ constructor(public href: string, public state?: TState) {
+ super();
+
+ }
+}
+
+export class ReplaceAction<TState = { }> extends NavigationAction {
+ constructor(public href: string, public state?: TState) {
+ super();
+
+ }
+}
+
+export class GoAction extends NavigationAction {
+ constructor(public index: number) {
+ super();
+
+ }
+}
+
+export class GoBackAction extends NavigationAction {
+
+}
+
+export class GoForwardeAction extends NavigationAction {
+
+}
+
+export class LocationChanged extends NavigationAction {
+ constructor(public pathname: string, public search: string, public hash: string ) {
+ super();
+
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts b/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts
new file mode 100644
index 000000000..32e2b2626
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+import { SnackbarItem } from '../models/snackbarItem';
+import { Omit } from '@material-ui/core';
+
+export class AddSnackbarNotification extends Action {
+
+ constructor(notification: Omit<SnackbarItem, 'key' >) {
+ super();
+
+ this.notification = { ...notification, key: (new Date().getTime() + Math.random()) }
+ }
+
+ public notification: SnackbarItem
+}
+
+export class RemoveSnackbarNotification extends Action {
+ constructor(public key: number) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/titleActions.ts b/sdnr/wt/odlux/framework/src/actions/titleActions.ts
new file mode 100644
index 000000000..4bcfe292e
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/titleActions.ts
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action } from '../flux/action';
+
+import { IconType } from '../models/iconDefinition';
+
+export class SetTitleAction extends Action {
+
+ constructor(public title: string, public icon?: IconType, public appId?: string) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/actions/websocketAction.ts b/sdnr/wt/odlux/framework/src/actions/websocketAction.ts
new file mode 100644
index 000000000..8512d59d5
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/actions/websocketAction.ts
@@ -0,0 +1,8 @@
+import { Action } from "../flux/action";
+
+
+export class SetWebsocketAction extends Action {
+ constructor(public isConnected: boolean) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/app.css b/sdnr/wt/odlux/framework/src/app.css
new file mode 100644
index 000000000..356f36dd0
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/app.css
@@ -0,0 +1,6 @@
+html, body, #app {
+ height: 100%;
+ padding: 0px;
+ margin: 0px;
+ font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/app.tsx b/sdnr/wt/odlux/framework/src/app.tsx
new file mode 100644
index 000000000..85b0dfb34
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/app.tsx
@@ -0,0 +1,108 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+/******************************************************************************
+ * Copyright 2018 highstreet technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+import * as React from 'react';
+import * as ReactDOM from 'react-dom';
+
+import { MuiThemeProvider } from '@material-ui/core/styles';
+
+import { Frame } from './views/frame';
+
+import { AddErrorInfoAction } from './actions/errorActions';
+
+import { applicationStoreCreator } from './store/applicationStore';
+import { ApplicationStoreProvider } from './flux/connect';
+
+import { startHistoryListener } from './middleware/navigation';
+import { startRestService } from './services/restService';
+
+
+import theme from './design/default';
+import '!style-loader!css-loader!./app.css';
+import { ReplaceAction } from './actions/navigationActions';
+import { startForceLogoutService } from './services/forceLogoutService';
+import { startNotificationService } from './services/notificationService';
+
+declare module '@material-ui/core/styles/createMuiTheme' {
+
+ interface IDesign {
+ id: string,
+ name: string,
+ url: string, // image url of a company logo, which will be presented in the ui header
+ height: number, // image height [px] as delivered by the url
+ width: number, // image width [px] as delivered by the url
+ logoHeight: number // height in [px] of the logo (see url) within the ui header
+ }
+
+ interface Theme {
+ design?: IDesign
+ }
+ interface ThemeOptions {
+ design?: IDesign
+ }
+}
+
+export const runApplication = () => {
+ const applicationStore = applicationStoreCreator();
+
+ window.onerror = function (msg: string, url: string, line: number, col: number, error: Error) {
+ // Note that col & error are new to the HTML 5 spec and may not be
+ // supported in every browser. It worked for me in Chrome.
+ var extra = !col ? '' : '\ncolumn: ' + col;
+ extra += !error ? '' : '\nerror: ' + error;
+
+ // You can view the information in an alert to see things working like this:
+ applicationStore.dispatch(new AddErrorInfoAction({ error, message: msg, url, line, col, info: { extra } }));
+
+ var suppressErrorAlert = true;
+ // If you return true, then error alerts (like in older versions of
+ // Internet Explorer) will be suppressed.
+ return suppressErrorAlert;
+ };
+
+ startRestService(applicationStore);
+ startHistoryListener(applicationStore);
+ startForceLogoutService(applicationStore);
+ startNotificationService(applicationStore);
+
+ const App = (): JSX.Element => (
+ <ApplicationStoreProvider applicationStore={applicationStore} >
+ <MuiThemeProvider theme={theme}>
+ <Frame />
+ </MuiThemeProvider>
+ </ApplicationStoreProvider>
+ );
+
+ ReactDOM.render(<App />, document.getElementById('app'));
+
+};
diff --git a/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg b/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg
new file mode 100644
index 000000000..bd9ddf583
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ viewBox="0 0 350.6536 109.43979"
+ height="109.43979"
+ width="350.65359"
+ xml:space="preserve"
+ version="1.1"
+ id="svg2"
+ class="style-svg replaced-svg"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="htlogo_white.svg"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1440"
+ inkscape:window-height="796"
+ id="namedview50"
+ showgrid="false"
+ inkscape:zoom="3.0651398"
+ inkscape:cx="123.67512"
+ inkscape:cy="44.346735"
+ inkscape:window-x="-8"
+ inkscape:window-y="1072"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g12" /><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><linearGradient
+ id="linearGradient58"
+ spreadMethod="pad"
+ gradientTransform="matrix(700.116,-254.822,-254.822,-700.116,227.808,857.597)"
+ gradientUnits="userSpaceOnUse"
+ y2="0"
+ x2="1"
+ y1="0"
+ x1="0"><stop
+ id="stop60"
+ offset="0"
+ style="stop-opacity:1;stop-color:#45a0de" /><stop
+ id="stop62"
+ offset="0.509804"
+ style="stop-opacity:1;stop-color:#2da247" /><stop
+ id="stop64"
+ offset="1"
+ style="stop-opacity:1;stop-color:#f4f01f" /></linearGradient></defs><g
+ transform="matrix(1.25,0,0,-1.25,-25.640145,137.40654)"
+ id="g10"><g
+ transform="scale(0.1,0.1)"
+ id="g12"><path
+ id="path14"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1089.71,559.016 c 0,-19.914 9.13,-38.637 47.77,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.8,0 0,-9.121 c 0,-25.679 -4.32,-31.437 -31.68,-31.437 l -6.48,0 c -22.57,0 -30.49,6.961 -30.49,29.758 l 0,60.96 81.85,0 0,16.801 -81.85,0 0,29.039 -20.64,0 0,-29.039 -26.88,0 0,-16.801 26.88,0 0,-68.882" /><path
+ id="path16"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1215.44,570.543 c 0,-45.125 30.72,-50.164 57.6,-50.164 l 37.44,0 c 38.39,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.2,-18.719 -11.76,-22.082 -37.68,-22.082 l -28.32,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.6,53.043 l -33.12,0 c -29.28,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.92,27.84 9.6,33.121 42.24,33.121 l 30.24,0 c 33.6,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+ id="path18"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1399.01,569.82 c 0,-44.402 32.88,-49.441 51.36,-49.441 l 46.56,0 c 38.4,0 53.76,12.004 53.76,42.965 l 0,3.594 -19.2,0 0,-4.079 c 0,-19.921 -16.08,-25.679 -35.28,-25.679 l -34.8,0 c -24.96,0 -41.76,6.242 -41.76,33.601 l 0,25.68 c 0,30.477 18.24,33.359 37.68,33.359 l 37.92,0 c 20.64,0 34.08,-4.8 34.08,-25.203 l 0,-2.879 19.2,0 0,3.364 c 0,25.918 -15.12,41.519 -53.52,41.519 l -34.56,0 c -30.24,0 -61.44,-5.047 -61.44,-49.441 l 0,-27.36" /><path
+ id="path20"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1582.36,522.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.27,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.47,0 0,72.481 -20.65,0 0,-173.758" /><path
+ id="path22"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1772.14,522.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.25,41.519 -50.88,41.519 l -30.97,0 c -25.67,0 -41.76,-4.078 -49.43,-23.043 l -0.49,0 0,21.121 -19.2,0 0,-122.398" /><path
+ id="path24"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2102.09,571.258 c 0,-28.559 -16.79,-34.078 -40.8,-34.078 l -42,0 c -23.99,0 -40.8,5.519 -40.8,34.078 l 0,24.484 c 0,28.559 16.81,34.078 40.8,34.078 l 42,0 c 24.01,0 40.8,-5.519 40.8,-34.078 l 0,-24.484 z m -144.25,-1.195 c 0,-40.321 28.57,-49.684 67.69,-49.684 l 29.52,0 c 39.12,0 67.69,9.363 67.69,49.684 l 0,26.875 c 0,40.32 -28.57,49.683 -67.69,49.683 l -29.52,0 c -39.12,0 -67.69,-9.363 -67.69,-49.683 l 0,-26.875" /><path
+ id="path26"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2160.42,522.301 20.6484,0 0,173.758 -20.6484,0 0,-173.758 z" /><path
+ id="path28"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2362.98,571.258 c 0,-28.559 -16.8,-34.078 -40.8,-34.078 l -41.99,0 c -24.01,0 -40.8,5.519 -40.8,34.078 l 0,24.484 c 0,28.559 16.79,34.078 40.8,34.078 l 41.99,0 c 24,0 40.8,-5.519 40.8,-34.078 l 0,-24.484 z m -144.24,-1.195 c 0,-40.321 28.56,-49.684 67.68,-49.684 l 29.52,0 c 39.12,0 67.69,9.363 67.69,49.684 l 0,26.875 c 0,40.32 -28.57,49.683 -67.69,49.683 l -29.52,0 c -39.12,0 -67.68,-9.363 -67.68,-49.683 l 0,-26.875" /><path
+ id="path30"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2569.4,644.699 -19.21,0 0,-21.84 -0.48,0 c -6.47,19.918 -22.08,23.762 -37.68,23.762 l -43.92,0 c -23.04,0 -55.2,-5.047 -55.2,-49.441 l 0,-20.399 c 0,-31.445 17.04,-48.965 51.36,-48.965 l 42.48,0 c 28.8,0 37.2,7.442 41.52,18.965 l 0.47,0 0,-18.242 c 0,-33.121 -16.31,-33.598 -57.12,-33.598 l -20.14,0 c -19.21,0 -35.53,4.559 -35.53,20.395 l 0,3.363 -19.2,0 0,-4.082 c 0,-15.601 10.08,-36.476 48,-36.476 l 46.56,0 c 25.68,0 58.09,7.441 58.09,44.402 l 0,122.156 z M 2548.74,577.5 c 0,-21.117 -10.79,-32.883 -40.31,-32.883 l -39.84,0 c -25.2,0 -35.28,8.645 -35.04,36.723 l 0,22.558 c 0.24,20.157 15.36,25.922 36.48,25.922 l 42,0 c 29.04,0 37.2,-14.64 36.71,-37.437 l 0,-14.883" /><path
+ id="path32"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2611.1,673.5 20.64,0 0,22.559 -20.64,0 0,-22.559 z m 0,-151.199 20.64,0 0,122.398 -20.64,0 0,-122.398" /><path
+ id="path34"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2667.98,570.543 c 0,-45.125 30.71,-50.164 57.6,-50.164 l 37.44,0 c 38.39,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.21,-18.719 -11.76,-22.082 -37.69,-22.082 l -28.31,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.6,53.043 l -33.12,0 c -29.29,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.91,27.84 9.6,33.121 42.24,33.121 l 30.24,0 c 33.6,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+ id="path36"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2852.5,557.098 c 0,-36.719 28.57,-36.719 59.05,-36.719 l 37.92,0 c 25.2,0 56.88,1.195 56.88,35.519 l 0,0.485 c 0,33.117 -21.11,36.238 -52.08,36.238 l -54.48,0 c -21.59,0 -24.96,5.762 -24.96,15.84 l 0,4.559 c 0,13.918 6.48,16.8 35.99,16.8 l 36.01,0 c 22.56,0 35.04,-0.48 35.04,-19.203 l 0,-1.195 19.2,0 0,6.476 c 0,17.286 -6.48,30.723 -53.04,30.723 l -31.68,0 c -50.88,0 -62.16,-11.039 -62.16,-30.957 l 0,-7.203 c 0,-23.281 10.8,-32.641 39.85,-32.641 l 63.59,0 c 24.72,0 28.08,-6.48 28.08,-18.238 l 0,-0.961 c 0,-18.238 -9.84,-19.441 -40.8,-19.441 l -44.17,0 c -21.11,0 -29.03,6.242 -29.03,21.359 l 0,6 -19.21,0 0,-7.441" /><path
+ id="path38"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1078.67,762.301 20.65,0 0,69.597 c 0,28.805 11.03,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.12,-11.761 45.12,-29.757 l 0,-77.762 20.64,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.48,0 0,72.481 -20.65,0 0,-173.758" /><path
+ id="path40"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1271.34,913.5 20.64,0 0,22.559 -20.64,0 0,-22.559 z m 0,-151.199 20.64,0 0,122.398 -20.64,0 0,-122.398" /><path
+ id="path42"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1484.7,884.699 -19.19,0 0,-21.84 -0.49,0 c -6.48,19.918 -22.08,23.762 -37.68,23.762 l -43.92,0 c -23.04,0 -55.2,-5.047 -55.2,-49.441 l 0,-20.399 c 0,-31.445 17.04,-48.965 51.36,-48.965 l 42.48,0 c 28.8,0 37.2,7.442 41.52,18.965 l 0.48,0 0,-18.242 c 0,-33.121 -16.32,-33.598 -57.12,-33.598 l -20.16,0 c -19.2,0 -35.52,4.559 -35.52,20.395 l 0,3.363 -19.2,0 0,-4.082 c 0,-15.601 10.08,-36.476 48,-36.476 l 46.56,0 c 25.68,0 58.08,7.441 58.08,44.402 l 0,122.156 z M 1464.06,817.5 c 0,-21.117 -10.8,-32.883 -40.32,-32.883 l -39.84,0 c -25.2,0 -35.27,8.645 -35.04,36.723 l 0,22.558 c 0.24,20.157 15.36,25.922 36.48,25.922 l 42,0 c 29.04,0 37.2,-14.64 36.72,-37.437 l 0,-14.883" /><path
+ id="path44"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1523.52,762.301 20.65,0 0,69.597 c 0,28.805 11.04,37.922 59.28,37.922 l 5.28,0 c 40.08,0 45.11,-11.761 45.11,-29.757 l 0,-77.762 20.65,0 0,82.801 c 0,22.078 -12.24,41.519 -50.88,41.519 l -29.52,0 c -25.68,0 -41.76,-4.078 -49.44,-23.043 l -0.48,0 0,72.481 -20.65,0 0,-173.758" /><path
+ id="path46"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1708.75,797.098 c 0,-36.719 28.57,-36.719 59.04,-36.719 l 37.93,0 c 25.19,0 56.87,1.195 56.87,35.519 l 0,0.485 c 0,33.117 -21.11,36.238 -52.08,36.238 l -54.47,0 c -21.61,0 -24.96,5.762 -24.96,15.84 l 0,4.559 c 0,13.918 6.47,16.8 35.99,16.8 l 36.01,0 c 22.56,0 35.04,-0.48 35.04,-19.203 l 0,-1.195 19.2,0 0,6.476 c 0,17.286 -6.49,30.723 -53.04,30.723 l -31.69,0 c -50.88,0 -62.16,-11.039 -62.16,-30.957 l 0,-7.203 c 0,-23.281 10.8,-32.641 39.84,-32.641 l 63.6,0 c 24.72,0 28.09,-6.48 28.09,-18.238 l 0,-0.961 c 0,-18.238 -9.85,-19.441 -40.8,-19.441 l -44.17,0 c -21.12,0 -29.04,6.242 -29.04,21.359 l 0,6 -19.2,0 0,-7.441" /><path
+ id="path48"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 1907.92,799.016 c 0,-19.914 9.12,-38.637 47.77,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.81,0 0,-9.121 c 0,-25.679 -4.32,-31.437 -31.67,-31.437 l -6.48,0 c -22.56,0 -30.48,6.961 -30.48,29.758 l 0,60.96 81.84,0 0,16.801 -81.84,0 0,29.039 -20.65,0 0,-29.039 -26.87,0 0,-16.801 26.87,0 0,-68.882" /><path
+ id="path50"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2040.85,762.301 20.64,0 0,77.762 c 0,15.835 10.55,29.757 32.4,29.757 l 12.71,0 c 36.72,0 42.97,-4.8 42.97,-35.043 l 0,-5.277 19.19,0 0,14.641 c 0,30 -12.71,42.48 -51.35,42.48 l -19.45,0 c -14.16,0 -29.75,-3.844 -37.43,-19.683 l -0.49,0 0,17.761 -19.19,0 0,-122.398" /><path
+ id="path52"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2187.69,810.543 c 0,-45.125 30.72,-50.164 57.6,-50.164 l 37.44,0 c 38.4,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.65,0 C 2322.57,780.543 2312,777.18 2286.09,777.18 l -28.32,0 c -36,0 -49.45,7.199 -49.45,35.039 l 0,7.683 136.09,0 0,13.676 c 0,43.68 -26.64,53.043 -63.61,53.043 l -33.11,0 c -29.28,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.07,26.156 -115.44,0 c 1.93,27.84 9.6,33.121 42.25,33.121 l 30.23,0 c 33.61,0 42.96,-12.48 42.96,-24.965 l 0,-8.156" /><path
+ id="path54"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2371.26,810.543 c 0,-45.125 30.73,-50.164 57.6,-50.164 l 37.44,0 c 38.4,0 61.68,8.398 61.68,36.48 l 0,2.403 -20.64,0 c -1.19,-18.719 -11.76,-22.082 -37.68,-22.082 l -28.32,0 c -36.01,0 -49.44,7.199 -49.44,35.039 l 0,7.683 136.08,0 0,13.676 c 0,43.68 -26.64,53.043 -63.59,53.043 l -33.13,0 c -29.27,0 -60,-5.047 -60,-49.441 l 0,-26.637 z m 136.08,26.156 -115.44,0 c 1.92,27.84 9.6,33.121 42.24,33.121 l 30.25,0 c 33.59,0 42.95,-12.48 42.95,-24.965 l 0,-8.156" /><path
+ id="path56"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 2571.4,799.016 c 0,-19.914 9.11,-38.637 47.75,-38.637 l 11.28,0 c 44.64,0 47.04,19.441 47.04,43.922 l 0,13.437 -16.8,0 0,-9.121 c 0,-25.679 -4.31,-31.437 -31.67,-31.437 l -6.49,0 c -22.56,0 -30.48,6.961 -30.48,29.758 l 0,60.96 81.84,0 0,16.801 -81.84,0 0,29.039 -20.63,0 0,-29.039 -26.89,0 0,-16.801 26.89,0 0,-68.882" /><path
+ id="path66"
+ style="fill:url(#linearGradient58);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 414.316,403.621 c -16.695,10.117 -53.621,35.262 -67.011,51.457 -12.836,8.742 -24.672,17.988 -35.45,27.621 -9.265,7.731 -17.839,16.301 -25.644,25.723 -1.172,1.41 -2.32,2.836 -3.441,4.273 -9.063,10.887 -16.875,22.106 -23.372,33.524 -7.628,13.414 -12.269,22.301 -17.019,40.851 -3.981,19.496 -5.234,32.43 -5.082,47.832 -28.332,58.625 -36.563,123.481 -18.883,186.891 13.09,46.949 38.906,86.59 73.777,118.02 7.528,17.125 16.887,33.05 28.067,47.488 10.691,16.629 20.637,30.769 49.383,49.629 27.644,18.15 77.902,31.47 117.879,30.93 18.476,13.53 40.089,20.71 64.839,24.74 47.262,5.39 79.168,2.22 116.493,-6.39 18.808,-4.33 45.027,-17.46 45.027,-17.46 -54.891,19.82 -87.711,22.51 -144.391,17.57 25.133,-8.53 54.653,-29.87 77.192,-58.13 44.23,28.77 86.351,35.13 116.25,19.84 l -4.11,-0.96 c -25.644,13.11 -58.992,5.79 -97.121,-20.08 91.344,7.4 169.336,-18.14 219.184,-78.318 l 0.125,-2.223 c -45.715,55.191 -120.848,79.461 -205.059,73.911 84.348,-25.176 153.828,-74.512 200.754,-135.11 63.703,-70.281 91.414,-159.559 66.129,-250.23 -15.387,-55.18 -48.344,-101.879 -92.93,-137.551 -2.129,-4.223 -14.382,-26.391 -21.718,-33.938 -13.5,-16.859 -30.008,-31.453 -49.657,-43.25 -26.961,-16.179 -56.652,-25.742 -87.773,-29.222 -3.781,-0.762 -7.613,-1.473 -11.484,-2.129 -11.52,-8.075 -25.625,-14.414 -41.614,-18.914 -6.265,-1.801 -12.777,-3.301 -19.418,-4.543 -36.254,-6.082 -81.039,-4.164 -124.425,7.011 -28.528,7.356 -55.516,18.207 -79.497,31.137 z m 337.618,279.375 -0.184,6.477 c 33.586,2.617 63.285,10.574 94.199,21.816 0,0 -50.402,-10.492 -94.547,-12.828 -0.718,16.012 -1.964,32.266 -3.761,48.687 l -0.34,3.075 c 13.105,37.785 22.176,70.148 22.176,70.148 -6.387,-20.391 -14.071,-41.488 -23.02,-63.016 -5.875,47.676 -16.012,92.579 -29.309,133.036 30.336,-10.758 58.536,-22.903 84.047,-36.328 53.414,-88.161 79.442,-183.672 73.118,-265.227 -4.391,-29.281 -13.012,-56.602 -25.758,-80.918 l -0.825,-0.684 c 0.918,9.688 0.629,19.559 -0.792,29.524 -0.165,-9.938 -1.122,-20.363 -2.911,-31.317 l -0.238,-1.398 c -36.898,-29.387 -82.035,-51.129 -131.93,-63.566 0.157,1.562 9.618,28.707 13.27,43.371 3.305,9.632 6.336,19.73 9.074,30.238 5.145,3.516 10.246,7.141 15.305,10.863 0,0 -5.188,-3.039 -14.551,-7.949 12.02,47.359 18.184,102.902 17.055,162.344 53.453,-42.227 87.926,-93.524 94.926,-142.586 1.113,67.512 -34.336,112.504 -95.004,146.238 z M 333.047,859.52 c -10.301,17.363 -17.945,33.175 -20.547,50.64 10.129,5.113 20.969,9.75 32.434,13.887 22.472,6.043 47.168,10.066 73.519,12.086 l -5.664,-4.117 C 382.016,909.348 355.977,886.105 333.047,859.52 Z m -20.945,53.605 c -1.668,13.578 -0.848,27.012 2.687,40.047 13.629,11.637 28.422,22.25 44.195,31.73 28.508,14.231 57.403,23.548 90.801,30.188 -8.578,-16.223 -19.293,-41.961 -28.226,-74.18 -29.555,-3.914 -52.071,-8.015 -76.625,-16.863 -11.555,-3.106 -22.52,-6.746 -32.832,-10.922 z m 348.73,95.825 c 18.594,-27.942 37.102,-64.559 50.938,-103.044 30.394,-11.972 58.132,-26.027 82.953,-41.59 l -3.489,5.422 c -35.339,54.348 -75.664,98.797 -120.496,132.012 50.84,-32.992 96.559,-79.105 134.168,-136.93 2.684,-4.117 5.285,-8.254 7.809,-12.402 10.969,-7.645 21.273,-15.586 30.898,-23.777 52.621,-35.407 88.274,-77.661 99.668,-125.266 -0.133,63.387 -24.105,127.047 -66.343,181.59 -51.118,56.394 -127.426,101.137 -216.106,123.985 z m 50.363,-345.43 c -23.25,-42.028 -48.918,-80.93 -75.531,-115.211 24.883,-14.922 45.047,-32.543 58.422,-51.286 15.269,6.786 27.965,13.024 37.336,17.86 6.832,43.519 8.812,100.844 4.648,173.199 -4.679,-0.559 -8.5,-0.398 -13.082,-0.754 -3.621,-7.969 -8.105,-17.148 -11.793,-23.808 z m -307.539,95.351 c -24.816,-2.672 -43.742,-6.769 -64.582,-13.402 17.864,8.511 37.91,15.195 59.688,19.832 -28.746,19.629 -51.621,41.957 -67.949,65.793 -18.45,-22.781 -34.235,-46.406 -47.02,-70.227 2.09,-12.176 4.801,-24.461 8.125,-36.797 13.629,8.61 29.48,15.77 47.156,21.399 -17.113,-8.156 -32.226,-17.985 -44.941,-29.293 4.719,-16.25 14.672,-42.125 23.359,-61.703 14.754,-12.203 39.66,-30.582 57.074,-41.969 9.215,33.777 17.274,58.293 33.485,94.824 -2.485,21.758 -4.395,51.543 -4.395,51.543 z M 613.887,373.906 c 13.918,2.422 26.574,6.153 37.629,11.035 l 0.75,0.332 c 2.812,1.266 5.519,2.602 8.113,4.016 -43.27,0.524 -88.383,11.902 -132.074,32.734 14.156,-16.507 28.933,-29.168 43.867,-37.355 26.258,-2.254 51.816,-2.172 76.109,-0.031 -21.16,-3.254 -43.258,-5.032 -65.879,-4.867 10.524,-4.297 21.075,-6.325 31.485,-5.864 z m 79.144,26.282 c 28.856,3.609 56.262,12.652 81.074,27.55 25.086,15.063 45.735,35.051 61.825,58.731 -36.25,-25.774 -79.078,-44.801 -125.723,-55.922 l -0.363,-1.356 c -3.047,-10.918 -8.809,-20.609 -16.813,-29.003 z m -147.797,24.066 c 43.317,-18.582 87.555,-27.516 129.371,-25.621 10.231,8.133 17.657,17.84 21.668,28.851 -47.679,-9.605 -98.953,-11.078 -151.039,-3.23 z m -46.187,634.796 c -9.406,-8.19 -17.121,-16.69 -23.402,-30.59 44.066,9.86 84.668,12.07 132.925,5.93 -37.882,15.93 -72.554,24.28 -109.523,24.66 z m 131.582,-28.07 c -28.652,33.59 -65.481,54.73 -95.899,47.25 -10.156,-3.17 -16.96,-7.05 -25.121,-11.99 38.176,-2.87 73.696,-15.34 121.02,-35.26 z M 571.035,708.031 c 13.711,-3.531 26.285,-7.843 38.695,-10.492 -24.523,1.531 -66.074,7.684 -86.843,12.742 -38.117,9.282 -54.282,16.27 -84.098,31.43 -5.652,-11.711 -10.98,-23.336 -15.98,-34.844 4.886,-40.812 12.664,-79.394 22.64,-114.832 33.672,2.77 70.922,-0.226 107.047,-9.531 27.527,-7.094 53.047,-17.301 75.242,-29.617 26.407,33.894 52.102,72.609 75.555,115.004 3.164,5.714 7.234,12.988 10.238,18.691 -33.445,1.5 -56.398,3.75 -103.801,10.957 36.25,-2.266 109.875,1.176 109.875,1.176 -37.574,16.551 -82.113,30.308 -131.773,43.094 -48.844,12.582 -96.305,18.644 -139.715,18.726 l -1.582,-3.601 c 36.336,-20.719 77.582,-36.817 124.5,-48.903 z m -254.148,-73.84 c -19.922,17.575 -32.805,29.309 -49.817,49.231 -7.968,-12.262 -11.718,-21.731 -14.937,-36.039 -1.153,-5.129 -2.219,-10.285 -3.129,-15.457 18.773,-36.582 45.68,-70.598 79.277,-99.985 5.547,13.598 16.114,25.075 30.332,34.286 -5.121,7.039 -10.097,14.265 -14.906,21.664 -13.184,20.269 -17.164,25.371 -26.82,46.3 z m 108.781,-52.16 10.262,-5.273 -2.106,6.859 c -1.621,-0.234 -6.562,-1.316 -8.156,-1.586 z M 274.469,695.734 c 6.469,-6.199 20.172,-21.121 27.304,-27.211 -3.793,9.981 -11.925,30.747 -14.937,40.735 -3.656,-3.699 -9.203,-9.547 -12.367,-13.524 z m -48.09,118.813 c -4.387,-18.231 -4.055,-36.277 0.418,-54.02 -2.961,5.801 -5.379,11.559 -7.195,17.254 -4.196,-42.461 3.519,-87.199 20.277,-127.246 0.488,2.547 1.344,10.11 2.047,14.195 2.453,15.508 4.5,26.016 8.16,42.129 -11.617,16.539 -18.949,36.438 -23.289,53.668 6.652,-13.035 16.047,-26.269 27.484,-39.457 5.008,15.985 11.407,32 19.157,47.875 -6.043,41.114 -5.258,81.02 2.285,117.629 -25.407,-20 -42.684,-44.324 -49.344,-72.027 z m 709.922,-170 c 7.422,59.746 -26.321,127.641 -92.688,184.094 -8.418,5.664 -17.269,11.152 -26.527,16.461 50.605,-86.379 68.984,-178.438 57.273,-256.524 -1.992,-25.672 -7.187,-49.973 -15.75,-72.219 36.059,32.825 62.625,73.719 75.758,120.797 0.684,2.457 1.328,4.922 1.934,7.391 z M 288.707,901.691 c 4.258,2.336 8.668,4.547 13.223,6.653 -0.895,10.953 -0.469,21.957 1.328,32.918 -5.895,-12.508 -10.746,-25.746 -14.551,-39.571 z m -40.098,-30.046 c 8.368,8.699 18.09,16.539 29.02,23.503 2.473,10.395 5.512,20.497 9.109,30.262 -14.898,-16.504 -27.73,-34.504 -38.129,-53.765 z m -2.246,-260.403 c 1.266,-16.219 5.2,-31.91 10.817,-46.492 12.215,-27.102 33.175,-50.285 59.043,-73.496 4.597,-3.379 9.289,-6.559 14.054,-9.535 -5.996,13.586 -7.953,27.398 -4.929,40.883 -32.395,27.742 -58.981,59.703 -78.493,94.207 -0.195,-1.852 -0.359,-3.711 -0.492,-5.567 z m 30.75,136.61 c -5.777,-11.817 -11.312,-25.586 -15.55,-37.36 2.093,-2.242 3.324,-4.086 5.527,-6.324 4.711,4.633 11.34,10.539 16.988,14.609 -2.691,9.723 -5.012,19.418 -6.965,29.075 z m 137.813,166.109 c -30.09,-22.957 -50.508,-39.84 -73.742,-66.703 17.101,-24.082 32.175,-42.192 61.769,-63.039 0.129,59.617 5.953,98.562 11.973,129.742 z m 63.347,42.805 c -5.769,-3.34 -11.503,-6.809 -17.207,-10.414 8.411,0.515 16.961,0.828 25.625,0.937 -3.015,3.121 -5.82,6.285 -8.418,9.477 z m 5.891,16.363 c 41.988,22.187 80.035,37.611 122.715,46.381 -48.469,6.85 -88.973,8.11 -133.481,0.79 -2.347,-15.62 1.137,-32.628 10.766,-47.171 z m -47.473,-25.246 c 11.52,7.613 21.438,13.832 33.282,20.383 -7.852,12.394 -11.328,23.336 -12.668,35.564 -7.832,-17.58 -14.629,-33.74 -20.614,-55.947 z m -77.476,36.734 c 29.711,17.853 59.988,30.823 95.445,39.893 0,0 14.356,22.66 25.043,34.4 -40.375,-4.82 -65.492,-11.69 -98.254,-28.31 -22.383,-11.36 -37.285,-24.19 -50.422,-43.116 -6.414,-9.73 -10.398,-19.398 -13.824,-28.066 13.11,9.375 27.156,17.781 42.012,25.199 z m -78.559,-201.64 c 11.453,21.168 25.301,41.996 41.426,62.089 -10.82,19.153 -17.516,39.094 -19.762,59.239 -5.382,-3.043 -10.527,-6.235 -15.429,-9.567 -8.5,-34.457 -10.645,-72.351 -6.235,-111.761 z M 688.488,485.801 c -48.293,-26.285 -98.433,-43.637 -147,-51.828 54.532,-8.883 108.055,-7.297 157.36,3.226 2.632,15.403 -1.121,32.106 -10.36,48.602 z m 45.766,228.554 c -2.285,-5.847 -4.633,-11.621 -7.024,-17.242 l 1.067,-0.707 7.168,0.512 c -0.367,5.715 -0.766,11.523 -1.211,17.437 z M 725.172,483.59 c 2.152,8.66 4.066,17.965 5.711,27.953 -10.805,-7.273 -21.766,-14.078 -32.84,-20.406 8.266,-13.121 13.172,-26.696 14.043,-40.196 4.742,10.161 9.109,21.075 13.086,32.649 z M 512.363,445.281 c 37.364,25.75 77.864,62.559 111.164,102.242 -20.925,12.305 -45.597,22.641 -73.281,29.778 -36.816,9.48 -72.16,11.66 -102.891,8.097 0.922,-3.14 4.317,-13.179 5.274,-16.273 39.855,-18.266 82.976,-33.98 82.976,-33.98 -27.621,6.031 -53.914,12.203 -79.226,21.687 15.574,-47.457 55.98,-111.648 55.984,-111.551 z m -67.359,-31.867 c 13.047,3.754 26.023,8.07 39.937,15.262 -40.523,-0.938 -67.214,2.875 -101.777,14.558 22.129,-12.675 35.953,-20.589 61.84,-29.82 z m -30.75,0.816 c 4.848,-2.921 11.637,-2.921 15.141,-2.453 -12.45,4.793 -18.77,7.582 -32.567,14.325 7.016,-5.438 9.473,-7.309 17.426,-11.872 z m -45.274,75.879 c 0.313,-10.523 2.223,-20.601 4.047,-29.406 29.856,-11.246 60.684,-16.226 92.512,-17.066 -35.039,11.902 -67.43,27.664 -96.559,46.472 z m 4.266,56.989 c -2.637,-16.524 -4.094,-32 -4.328,-46.207 33.539,-22.34 71.766,-40.559 113.723,-53.27 -39.629,25.649 -76.993,59.184 -109.395,99.477 z m 2.574,14.547 -0.496,-2.629 c 32.727,-41.637 74.149,-80.024 118.262,-107.895 -19.68,31.887 -38.766,66.445 -53.27,112.07 -8.562,3.965 -22.011,9.454 -30.23,13.563 -17.523,-4.359 -22,-6.926 -34.266,-15.109 z m 6.129,29.183 c -1.758,-9.969 -1.23,-6.445 -2.926,-13.933 9.282,3.906 7.297,3.8 18.157,6.308 -8.414,4.363 -7.239,3.117 -15.231,7.625 z m 29.731,89.004 c -12.203,-29.008 -17.723,-48.094 -25.524,-74.707 15.016,-8.785 18.176,-11.496 30.379,-18.172 4.27,0.656 10.77,2.508 15.188,2.969 -8.993,33.039 -14.309,54.793 -20.043,89.91 z m 147.05,250.07 c -4.3,-5.285 -7.832,-9.629 -12.117,-15.191 37.313,-22.055 80.684,-32.52 80.684,-32.52 -8.387,1.184 -12.859,1.758 -27.449,4.938 -21.16,5.004 -43.539,10.957 -59.344,19.957 -25.684,-33.961 -51.887,-72.035 -75.234,-114.242 -3.782,-6.824 -7.454,-13.641 -11.028,-20.449 41.949,2.105 88,-2.434 135.844,-14.754 49.012,-12.629 93.297,-32.336 130.805,-56.379 4.316,8.605 8.441,17.176 12.382,25.699 -0.507,6.207 -1.062,12.519 -1.644,18.941 -5.008,54.649 -15.656,105.219 -30.172,149.618 -23.234,7.691 -47.613,14.589 -72.91,20.656 -24.172,5.789 -46.348,10.308 -69.817,13.726 z m 84.836,82.848 c -21.144,-15.355 -51.222,-43.402 -75.105,-70.973 21.824,-2.793 42.984,-6.07 65.398,-11.441 21.641,-5.188 42.313,-11.375 61.961,-18.434 -15.25,39.45 -34.152,75 -52.254,100.848 z m -90.449,-68.551 c 24.438,27.528 49.297,50.981 73.449,69.341 -46.043,-9 -90.203,-24.47 -136.121,-49.919 4.145,-4.953 8.61,-11.98 13.539,-16.676 17.067,-0.222 31.352,-0.894 49.133,-2.746 z m -18.551,-22.453 c 3.032,3.727 4.895,6.617 7.946,10.219 -9.293,1.176 -15.43,1.633 -24.543,2.426 5.972,-4.868 10.304,-8.231 16.597,-12.645 z M 436.363,773.141 c 4.457,8.707 9.321,17.078 14.285,25.707 22.571,39.211 49.93,80.941 77.497,115.609 -10.946,6.875 -20.879,14.125 -29.618,21.676 -17.609,1.097 -34.793,1.469 -51.425,1.097 -5.895,-3.98 -10.344,-7.226 -16.145,-11.488 -9.559,-44.469 -14.918,-94.359 -12.781,-151.203 l 3.16,-2.148 c 5.012,0.707 9.871,0.246 15.027,0.75 z M 419.77,736.914 c 1.832,3.973 3.699,7.957 5.601,11.945 -2.273,1.278 -4.519,2.563 -6.738,3.864 0.324,-5.235 0.703,-10.504 1.137,-15.809 z M 365.832,571.656 c 1.977,11.266 2.617,13.098 5.559,25.016 -17.149,10.098 -22.774,13.883 -37.493,24.617 7.684,-15.121 7.758,-13.68 17.375,-28.473 4.707,-7.234 9.563,-14.293 14.559,-21.16 z m -5.91,-64.59 c -0.125,13.739 0.82,28.489 2.793,44.063 -8.481,-8.254 -14.43,-17.691 -17.313,-28.047 -0.41,-1.473 -0.757,-2.949 -1.035,-4.445 5.051,-3.961 10.242,-7.817 15.555,-11.571 z m 4.719,-43.027 c -2.293,9.727 -3.739,20.383 -4.368,31.852 -5.75,3.929 -11.371,7.968 -16.851,12.129 0.098,-13.27 4.816,-27.082 13.492,-40.618 2.559,-1.168 5.137,-2.293 7.727,-3.363 z m 89.195,-61.324 c -4.52,-0.969 -8.941,-1.621 -13.266,-1.957 16.895,-7.879 35.582,-14.621 55.731,-19.813 29.906,-7.703 58.527,-10.898 84.375,-10.238 -6.406,2.5 -12.75,5.773 -19.008,9.762 -22.934,1.386 -46.266,4.855 -69.586,10.863 -13.176,3.395 -25.93,7.203 -38.246,11.383 z m 55.227,24.047 c -15.844,-10.192 -27.801,-15.782 -42.344,-20.543 9.496,-3.114 19.203,-5.957 29.117,-8.508 19.066,-4.914 38.074,-8.527 56.816,-10.949 -13.984,10.609 -31.91,25.652 -43.589,40 z M 631.309,542.75 c -29.774,-37.652 -60.614,-69.477 -90.477,-93.41 54.66,9.137 105.574,27.234 143.426,43.41 -11.699,17.816 -29.731,35.137 -52.949,50" /><path
+ id="path68"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1095.13,368.133 21.29,0 62.34,-124.289 0.38,0 0,124.289 13.43,0 0,-138.867 -21.29,0 -62.34,124.289 -0.38,0 0,-124.289 -13.43,0 0,138.867" /><path
+ id="path70"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1270.6,287.574 c 0,20.715 -0.38,29.918 -22.25,29.918 -21.86,0 -22.25,-9.203 -22.25,-29.918 l 44.5,0 z m -44.5,-12.277 0,-9.016 c 0,-21.289 3.64,-27.426 20.52,-27.426 19.76,0 23.98,0.387 23.98,19.567 l 12.27,0 0,-3.649 c 0,-19.558 -4.79,-27.039 -34.14,-27.039 -32.22,0 -36.06,10.739 -36.06,50.446 0,40.468 6.53,50.441 36.06,50.441 29.35,0 34.14,-11.894 34.14,-38.555 l 0,-14.769 -56.77,0" /><path
+ id="path72"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1306.45,315.961 -10.17,0 0,11.125 10.17,0 0,22.637 12.27,0 0,-22.637 31.65,0 0,-11.125 -31.65,0 0,-65.406 c 0,-8.055 2.49,-11.7 10.55,-11.7 9.21,0 13.24,1.731 13.24,23.399 l 11.12,0 c 0,-31.258 -9.97,-34.52 -24.17,-34.52 -18.03,0 -23.01,5.563 -23.01,20.137 l 0,68.09" /><path
+ id="path74"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1358.22,327.086 12.09,0 19.37,-85.352 0.38,0 18.41,85.352 17.65,0 18.41,-85.543 0.39,0 19.37,85.543 12.08,0 -23.21,-97.82 -17.83,0 -17.84,85.543 -0.39,0 -17.83,-85.543 -17.84,0 -23.21,97.82" /><path
+ id="path76"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1522.18,238.855 c 19.57,0 22.63,2.879 22.63,39.325 0,36.437 -3.06,39.312 -22.63,39.312 -19.56,0 -22.63,-2.875 -22.63,-39.312 0,-36.446 3.07,-39.325 22.63,-39.325 z m 0,89.766 c 32.23,0 36.06,-11.508 36.06,-50.441 0,-40.477 -4.22,-50.446 -36.06,-50.446 -31.84,0 -36.06,9.969 -36.06,50.446 0,38.933 3.84,50.441 36.06,50.441" /><path
+ id="path78"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1576.82,327.086 12.28,0 0,-11.891 0.38,0 c 4.6,9.399 10.36,13.426 22.64,13.426 15.53,0 22.63,-6.715 22.63,-26.277 l 0,-7.864 -11.12,0 c 0.19,18.028 -1.92,23.012 -15.93,23.012 -12.27,0.199 -18.6,-6.707 -18.6,-20.133 l 0,-68.093 -12.28,0 0,97.82" /><path
+ id="path80"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1665.42,275.297 -5.37,0 0,-46.031 -12.27,0 0,138.867 12.27,0 0,-80.559 5.75,0 28.97,39.512 15.15,0 -34.33,-45.266 39.51,-52.554 -16.31,0 -33.37,46.031" /><path
+ id="path82"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1787.76,259.57 c -0.38,-16.875 2.68,-20.715 20.91,-20.715 19.75,0 23.39,2.879 23.39,19.372 0,12.851 -1.33,13.812 -24.55,15.156 -24.55,1.344 -31.26,4.984 -31.26,26.66 0,20.523 3.84,28.578 32.99,28.578 28.59,0 34.14,-6.523 34.14,-27.047 l -12.27,0 c 0,14.965 -4.03,15.918 -22.44,15.918 -17.08,0 -20.14,-1.722 -20.14,-16.875 0,-13.812 1.73,-14.961 22.44,-16.109 28.96,-1.731 33.37,-4.031 33.37,-25.508 0,-23.02 -4.41,-31.266 -36.06,-31.266 -22.44,0 -32.8,2.684 -32.8,31.836 l 12.28,0" /><path
+ id="path84"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1898.8,238.855 c 19.56,0 22.63,2.879 22.63,39.325 0,36.437 -3.07,39.312 -22.63,39.312 -19.57,0 -22.63,-2.875 -22.63,-39.312 0,-36.446 3.06,-39.325 22.63,-39.325 z m 0,89.766 c 32.22,0 36.06,-11.508 36.06,-50.441 0,-40.477 -4.22,-50.446 -36.06,-50.446 -31.84,0 -36.06,9.969 -36.06,50.446 0,38.933 3.84,50.441 36.06,50.441" /><path
+ id="path86"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 1956.7,229.266 12.2813,0 0,138.867 -12.2813,0 0,-138.867 z" /><path
+ id="path88"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2061.04,229.266 -12.28,0 0,12.664 -0.39,0 c -6.13,-10.555 -12.85,-14.196 -27.04,-14.196 -22.64,0 -28.77,11.313 -28.77,30.301 l 0,69.051 12.28,0 0,-66.172 c 0,-11.316 2.49,-22.059 18.6,-22.059 14.96,0 25.32,5.758 25.32,26.469 l 0,61.762 12.28,0 0,-97.82" /><path
+ id="path90"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2084.61,315.961 -10.16,0 0,11.125 10.16,0 0,22.637 12.28,0 0,-22.637 31.65,0 0,-11.125 -31.65,0 0,-65.406 c 0,-8.055 2.49,-11.7 10.54,-11.7 9.21,0 13.24,1.731 13.24,23.399 l 11.12,0 c 0,-31.258 -9.97,-34.52 -24.16,-34.52 -18.03,0 -23.02,5.563 -23.02,20.137 l 0,68.09" /><path
+ id="path92"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2148.47,327.086 12.28,0 0,-97.82 -12.28,0 0,97.82 z m 0,41.047 12.28,0 0,-16.301 -12.28,0 0,16.301" /><path
+ id="path94"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2218.67,238.855 c 19.56,0 22.62,2.879 22.62,39.325 0,36.437 -3.06,39.312 -22.62,39.312 -19.58,0 -22.64,-2.875 -22.64,-39.312 0,-36.446 3.06,-39.325 22.64,-39.325 z m 0,89.766 c 32.21,0 36.05,-11.508 36.05,-50.441 0,-40.477 -4.22,-50.446 -36.05,-50.446 -31.85,0 -36.07,9.969 -36.07,50.446 0,38.933 3.84,50.441 36.07,50.441" /><path
+ id="path96"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2273.3,327.086 12.28,0 0,-12.656 0.38,0 c 6.14,10.547 12.85,14.191 27.05,14.191 22.63,0 28.77,-11.316 28.77,-30.305 l 0,-69.05 -12.28,0 0,66.172 c 0,11.32 -2.5,22.054 -18.6,22.054 -14.96,0 -25.32,-5.75 -25.32,-26.461 l 0,-61.765 -12.28,0 0,97.82" /><path
+ id="path98"
+ style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 2374.17,259.57 c -0.38,-16.875 2.69,-20.715 20.91,-20.715 19.76,0 23.4,2.879 23.4,19.372 0,12.851 -1.34,13.812 -24.55,15.156 -24.55,1.344 -31.26,4.984 -31.26,26.66 0,20.523 3.84,28.578 32.99,28.578 28.58,0 34.14,-6.523 34.14,-27.047 l -12.28,0 c 0,14.965 -4.02,15.918 -22.44,15.918 -17.07,0 -20.14,-1.722 -20.14,-16.875 0,-13.812 1.73,-14.961 22.45,-16.109 28.96,-1.731 33.36,-4.031 33.36,-25.508 0,-23.02 -4.4,-31.266 -36.05,-31.266 -22.44,0 -32.8,2.684 -32.8,31.836 l 12.27,0" /></g></g></svg> \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg.d.ts b/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg.d.ts
new file mode 100644
index 000000000..60e4856dd
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/assets/images/defaultLogo.svg.d.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+declare const path: string;
+export default path; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/common/event.ts b/sdnr/wt/odlux/framework/src/common/event.ts
new file mode 100644
index 000000000..913487911
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/common/event.ts
@@ -0,0 +1,81 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+/**
+ * Represents an event.
+ * Events enable a class or object to notify other classes or objects when something of interest occurs.
+ * The class that sends (or invokes) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.
+ *
+ * Objects can create an instances of an Events and offer that Events for other objects to attach to.
+ * Objects who want to be informed about an Event can attach a function (an event handler) to the event which is then called when the event is fired.
+ *
+ * @template TEventArg Type of the event argument. Use void if the event does not has an argument.
+ */
+export class Event<TEventArg> {
+
+ /**
+ * Creates a new instance of the Event class.
+ */
+ constructor() {
+ this.eventHandlers = new Array<(arg: TEventArg) => void>();
+ }
+
+ /**
+ * Adds an event handler to this event, so that when the event is fired the given event handler function is called.
+ *
+ * @param eventHandler The event handler function to add to this event.
+ * @throws {Error} Thrown if the given event handler function has already been added to this event.
+ */
+ public addHandler = (eventHandler: (arg: TEventArg) => void): void => {
+ if (this.eventHandlers.indexOf(eventHandler) > -1) {
+ throw new Error("The given event handler is already added to this event.");
+ }
+
+ this.eventHandlers.push(eventHandler);
+ }
+
+ /**
+ * Removes an event handler from this event, so that the given event handler function will not be called anymore when the event is fired.
+ *
+ * @param eventHandler: The event handler function to remove.
+ * @throws {Error} Thrown if the given event handler function has not been added to this event before.
+ */
+ public removeHandler = (eventHandler: (arg: TEventArg) => void): void => {
+ const index = this.eventHandlers.indexOf(eventHandler);
+ if (!(index > -1)) {
+ throw new Error("The given event handler has not been added to this event yet.");
+ }
+
+ this.eventHandlers.splice(index, 1);
+ }
+
+ /**
+ * Invokes the event and calls all event handler functions currently registered on the event.
+ *
+ * @param argument The argument for the event. The argument will be passed to all registered event handler functions.
+ */
+ public invoke = (argument?: TEventArg): void => {
+ this.eventHandlers.forEach((eventHandler: (arg?: TEventArg) => void, index: number, array: Array<(arg: TEventArg) => void>): void => {
+ eventHandler(argument);
+ });
+ }
+
+ private eventHandlers: Array<(arg?: TEventArg) => void>;
+
+}
diff --git a/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx b/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx
new file mode 100644
index 000000000..4cf63e927
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx
@@ -0,0 +1,126 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import Modal from '@material-ui/core/Modal';
+import Button from '@material-ui/core/Button';
+import Card from '@material-ui/core/Card';
+import CardActions from '@material-ui/core/CardActions';
+import CardContent from '@material-ui/core/CardContent';
+import Typography from '@material-ui/core/Typography';
+
+import { ClearErrorInfoAction, RemoveErrorInfoAction } from '../actions/errorActions';
+
+import connect, { Connect } from '../flux/connect';
+
+const styles = (theme: Theme) => createStyles({
+ modal: {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ paper: {
+ width: theme.spacing(50),
+ backgroundColor: theme.palette.background.paper,
+ boxShadow: theme.shadows[5],
+ padding: theme.spacing(4),
+ },
+ card: {
+ minWidth: 275,
+ },
+ bullet: {
+ display: 'inline-block',
+ margin: '0 2px',
+ transform: 'scale(0.8)',
+ },
+ title: {
+ marginBottom: 16,
+ fontSize: 14,
+ },
+ pos: {
+ marginBottom: 12,
+ },
+});
+
+type ErrorDisplayProps = WithStyles<typeof styles> & Connect;
+
+// function getModalStyle() {
+// const top = 50 + rand();
+// const left = 50 + rand();
+
+// return {
+// top: `${ top }%`,
+// left: `${ left }%`,
+// transform: `translate(-${ top }%, -${ left }%)`,
+// };
+// }
+
+/**
+ * Represents a compnent for formaing and displaying errors.
+ */
+class ErrorDisplayComponent extends React.Component<ErrorDisplayProps> {
+ constructor(props: ErrorDisplayProps) {
+ super(props);
+ }
+
+ render(): JSX.Element {
+ const { classes, state } = this.props;
+ const errorInfo = state.framework.applicationState.errors.length && state.framework.applicationState.errors[state.framework.applicationState.errors.length - 1];
+ return (
+ <Modal className={classes.modal}
+ aria-labelledby="simple-modal-title"
+ aria-describedby="simple-modal-description"
+ open={state.framework.applicationState.errors && state.framework.applicationState.errors.length > 0}
+ onClose={() => this.props.dispatch(new ClearErrorInfoAction())}
+ >
+ {errorInfo &&
+ <div className={classes.paper}>
+ <Card className={classes.card}>
+ <CardContent>
+ <Typography className={classes.title} color="textSecondary">
+ {errorInfo.title != null ? errorInfo.title : "Something went wrong."}
+ </Typography>
+ <Typography variant="h5" component="h2">
+ {errorInfo.error && errorInfo.error.toString()}
+ </Typography>
+ <Typography className={classes.pos} color="textSecondary">
+ {errorInfo.message && errorInfo.message.toString()}
+ </Typography>
+ <Typography component="p">
+ {errorInfo.info && errorInfo.info.componentStack && errorInfo.info.componentStack.split('\n').map(line => {
+ return [line, <br />];
+ })}
+ {errorInfo.info && errorInfo.info.extra && errorInfo.info.extra.split('\n').map(line => {
+ return [line, <br />];
+ })}
+ </Typography>
+ </CardContent>
+ <CardActions>
+ <Button size="small" onClick={() => this.props.dispatch(new RemoveErrorInfoAction(errorInfo))} >Close</Button>
+ </CardActions>
+ </Card>
+ </div> || <div></div>
+ }
+ </Modal>
+ );
+ }
+}
+
+export const ErrorDisplay = withStyles(styles)(connect()(ErrorDisplayComponent));
+export default ErrorDisplay; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/logo.tsx b/sdnr/wt/odlux/framework/src/components/logo.tsx
new file mode 100644
index 000000000..470eb9620
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/logo.tsx
@@ -0,0 +1,98 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+/******************************************************************************
+ * Copyright 2018 highstreet technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; // infra for styling
+
+
+import defaultLogo from '../assets/images/defaultLogo.svg';
+
+const styles = (theme: Theme) => createStyles({
+ headerLogo: {
+ backgroundImage: "url(" + (theme.design && theme.design.url || defaultLogo) + ")",
+ backgroundColor: theme.palette.primary.main,
+ backgroundRepeat: "no-repeat",
+ backgroundSize: "auto " + (theme.design && theme.design.logoHeight || 70) + "px",
+ height: theme.design && theme.design.logoHeight || 70,
+ width: theme.design ? theme.design.width / theme.design.height * theme.design.logoHeight : 220
+ }
+});
+
+type LogoProps = RouteComponentProps<{ id: string }> & WithStyles<typeof styles>;
+interface ILogoState {
+ windowWidth: number
+}
+
+class LogoComponent extends React.Component<LogoProps, ILogoState> {
+
+ private hideLogoWhenWindowWidthIsLower: number = 800;
+
+ constructor(props: LogoProps) {
+ super(props);
+ this.state = {
+ windowWidth: 0
+ };
+ this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
+ }
+
+ componentDidMount(): void {
+ this.updateWindowDimensions();
+ window.addEventListener('resize', this.updateWindowDimensions);
+ };
+ componentWillUnmount(): void {
+ window.removeEventListener('resize', this.updateWindowDimensions);
+ };
+ updateWindowDimensions(): void {
+ this.setState({ windowWidth: window.innerWidth });
+ }
+
+ render(): JSX.Element {
+ let div: JSX.Element = <div />;
+ if (this.state.windowWidth >= this.hideLogoWhenWindowWidthIsLower) {
+ div = <div className={this.props.classes.headerLogo} />;
+ } else {
+ console.info([
+ "Logo hidden, because browser window width (",
+ this.state.windowWidth,
+ "px) is lower thershold (",
+ this.hideLogoWhenWindowWidthIsLower,
+ "px)."].join(''));
+ }
+ return div;
+ }
+}
+
+export const Logo = withStyles(styles)(withRouter(LogoComponent));
+export default Logo;
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts b/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
new file mode 100644
index 000000000..c05142084
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+
+export enum ColumnType {
+ text,
+ numeric,
+ boolean,
+ custom
+}
+
+type CustomControl<TData> = {
+ className?: string;
+ style?: React.CSSProperties;
+ rowData: TData;
+}
+
+export type ColumnModel<TData> = {
+ title?: string;
+ disablePadding?: boolean;
+ width?: string | number;
+ className?: string;
+ style?: React.CSSProperties;
+ align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
+ disableSorting?: boolean;
+ disableFilter?: boolean;
+} & ({
+ property: string;
+ type: ColumnType.custom;
+ customControl: React.ComponentType<CustomControl<TData>>;
+} | {
+ property: keyof TData;
+ type: ColumnType.boolean;
+ labels?: { "true": string, "false": string };
+} | {
+ property: keyof TData;
+ type?: ColumnType.numeric | ColumnType.text;
+}); \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
new file mode 100644
index 000000000..3e31c5e03
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
@@ -0,0 +1,552 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import Table from '@material-ui/core/Table';
+import TableBody from '@material-ui/core/TableBody';
+import TableCell from '@material-ui/core/TableCell';
+import TablePagination from '@material-ui/core/TablePagination';
+import TableRow from '@material-ui/core/TableRow';
+import Paper from '@material-ui/core/Paper';
+import Checkbox from '@material-ui/core/Checkbox';
+
+import { TableToolbar } from './tableToolbar';
+import { EnhancedTableHead } from './tableHead';
+import { EnhancedTableFilter } from './tableFilter';
+
+import { ColumnModel, ColumnType } from './columnModel';
+import { Omit } from '@material-ui/core';
+import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
+import { replaceHyphen } from '../../utilities/yangHelper';
+import { string } from 'prop-types';
+export { ColumnModel, ColumnType } from './columnModel';
+
+type propType = string | number | null | undefined | (string | number)[];
+type dataType = { [prop: string]: propType };
+type resultType<TData = dataType> = { page: number, total: number, rows: TData[] };
+
+export type DataCallback<TData = dataType> = (page?: number, rowsPerPage?: number, orderBy?: string | null, order?: 'asc' | 'desc' | null, filter?: { [property: string]: string }) => resultType<TData> | Promise<resultType<TData>>;
+
+function desc(a: dataType, b: dataType, orderBy: string) {
+ if ((b[orderBy] || "") < (a[orderBy] || "")) {
+ return -1;
+ }
+ if ((b[orderBy] || "") > (a[orderBy] || "")) {
+ return 1;
+ }
+ return 0;
+}
+
+function stableSort(array: dataType[], cmp: (a: dataType, b: dataType) => number) {
+ const stabilizedThis = array.map((el, index) => [el, index]) as [dataType, number][];
+ stabilizedThis.sort((a, b) => {
+ const order = cmp(a[0], b[0]);
+ if (order !== 0) return order;
+ return a[1] - b[1];
+ });
+ return stabilizedThis.map(el => el[0]);
+}
+
+function getSorting(order: 'asc' | 'desc' | null, orderBy: string) {
+ return order === 'desc' ? (a: dataType, b: dataType) => desc(a, b, orderBy) : (a: dataType, b: dataType) => -desc(a, b, orderBy);
+}
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ width: '100%',
+ marginTop: theme.spacing(3),
+ },
+ table: {
+ minWidth: 1020,
+ },
+ tableWrapper: {
+ overflowX: 'auto',
+ },
+});
+
+export type MaterialTableComponentState<TData = {}> = {
+ order: 'asc' | 'desc';
+ orderBy: string | null;
+ selected: any[] | null;
+ rows: TData[];
+ total: number;
+ page: number;
+ rowsPerPage: number;
+ loading: boolean;
+ showFilter: boolean;
+ filter: { [property: string]: string };
+};
+
+export type TableApi = { forceRefresh?: () => Promise<void> };
+
+type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
+ columns: ColumnModel<TData>[];
+ idProperty: keyof TData | ((data: TData) => React.Key);
+ tableId?: string;
+ title?: string;
+ enableSelection?: boolean;
+ disableSorting?: boolean;
+ disableFilter?: boolean;
+ customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, onClick: () => void }[];
+ onHandleClick?(event: React.MouseEvent<HTMLTableRowElement>, rowData: TData): void;
+};
+
+type MaterialTableComponentPropsWithRows<TData = {}> = MaterialTableComponentBaseProps<TData> & { rows: TData[]; asynchronus?: boolean; };
+type MaterialTableComponentPropsWithRequestData<TData = {}> = MaterialTableComponentBaseProps<TData> & { onRequestData: DataCallback; tableApi?: TableApi; };
+type MaterialTableComponentPropsWithExternalState<TData = {}> = MaterialTableComponentBaseProps<TData> & MaterialTableComponentState & {
+ onToggleFilter: () => void;
+ onFilterChanged: (property: string, filterTerm: string) => void;
+ onHandleChangePage: (page: number) => void;
+ onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
+ onHandleRequestSort: (property: string) => void;
+};
+
+type MaterialTableComponentProps<TData = {}> =
+ MaterialTableComponentPropsWithRows<TData> |
+ MaterialTableComponentPropsWithRequestData<TData> |
+ MaterialTableComponentPropsWithExternalState<TData>;
+
+function isMaterialTableComponentPropsWithRows(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithRows {
+ return (props as MaterialTableComponentPropsWithRows).rows !== undefined && (props as MaterialTableComponentPropsWithRows).rows instanceof Array;
+}
+
+function isMaterialTableComponentPropsWithRequestData(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithRequestData {
+ return (props as MaterialTableComponentPropsWithRequestData).onRequestData !== undefined && (props as MaterialTableComponentPropsWithRequestData).onRequestData instanceof Function;
+}
+
+function isMaterialTableComponentPropsWithRowsAndRequestData(props: MaterialTableComponentProps): props is MaterialTableComponentPropsWithExternalState {
+ const propsWithExternalState = (props as MaterialTableComponentPropsWithExternalState)
+ return propsWithExternalState.onFilterChanged instanceof Function ||
+ propsWithExternalState.onHandleChangePage instanceof Function ||
+ propsWithExternalState.onHandleChangeRowsPerPage instanceof Function ||
+ propsWithExternalState.onToggleFilter instanceof Function ||
+ propsWithExternalState.onHandleRequestSort instanceof Function
+}
+
+class MaterialTableComponent<TData extends {} = {}> extends React.Component<MaterialTableComponentProps, MaterialTableComponentState> {
+
+ constructor(props: MaterialTableComponentProps) {
+ super(props);
+
+ const page = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.page : 0;
+ const rowsPerPage = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.rowsPerPage || 10 : 10;
+
+ this.state = {
+ filter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.filter || {} : {},
+ showFilter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.showFilter : false,
+ loading: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.loading : false,
+ order: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.order : 'asc',
+ orderBy: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.orderBy : null,
+ selected: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.selected : null,
+ rows: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) || [],
+ total: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.length || 0,
+ page,
+ rowsPerPage,
+ };
+
+ if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+ this.update();
+
+ if (this.props.tableApi) {
+ this.props.tableApi.forceRefresh = () => this.update();
+ }
+ }
+ }
+ render(): JSX.Element {
+ const { classes, columns } = this.props;
+ const { rows, total: rowCount, order, orderBy, selected, rowsPerPage, page, showFilter, filter } = this.state;
+ const emptyRows = rowsPerPage - Math.min(rowsPerPage, rowCount - page * rowsPerPage);
+ const getId = typeof this.props.idProperty !== "function" ? (data: TData) => ((data as { [key: string]: any })[this.props.idProperty as any as string] as string | number) : this.props.idProperty;
+ const toggleFilter = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onToggleFilter : () => { !this.props.disableFilter && this.setState({ showFilter: !showFilter }, this.update) }
+ return (
+ <Paper className={classes.root}>
+ <TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv}
+ onToggleFilter={toggleFilter} />
+ <div className={classes.tableWrapper}>
+ <Table className={classes.table} aria-labelledby="tableTitle">
+ <EnhancedTableHead
+ columns={columns}
+ numSelected={selected && selected.length}
+ order={order}
+ orderBy={orderBy}
+ onSelectAllClick={this.handleSelectAllClick}
+ onRequestSort={this.onHandleRequestSort}
+ rowCount={rows.length}
+ enableSelection={this.props.enableSelection}
+ />
+ <TableBody>
+ {showFilter && <EnhancedTableFilter columns={columns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
+ {rows // may need ordering here
+ .map((entry: TData & { [key: string]: any }) => {
+ const entryId = getId(entry);
+ const isSelected = this.isSelected(entryId);
+ return (
+ <TableRow
+ hover
+ onClick={event => this.handleClick(event, entry, entryId)}
+ role="checkbox"
+ aria-checked={isSelected}
+ tabIndex={-1}
+ key={entryId}
+ selected={isSelected}
+ >
+ {this.props.enableSelection
+ ? <TableCell padding="checkbox" style={{ width: "50px" }}>
+ <Checkbox checked={isSelected} />
+ </TableCell>
+ : null
+ }
+ {
+ this.props.columns.map(
+ col => {
+ const style = col.width ? { width: col.width } : {};
+ return (
+ <TableCell key={col.property} align={col.type === ColumnType.numeric && !col.align ? "right" : col.align} style={style}>
+ {col.type === ColumnType.custom && col.customControl
+ ? <col.customControl className={col.className} style={col.style} rowData={entry} />
+ : col.type === ColumnType.boolean
+ ? <span className={col.className} style={col.style}>{col.labels ? col.labels[entry[col.property] ? "true" : "false"] : String(entry[col.property])}</span>
+ : <span className={col.className} style={col.style}>{String(entry[col.property])}</span>
+ }
+ </TableCell>
+ );
+ }
+ )
+ }
+ </TableRow>
+ );
+ })}
+ {emptyRows > 0 && (
+ <TableRow style={{ height: 49 * emptyRows }}>
+ <TableCell colSpan={this.props.columns.length} />
+ </TableRow>
+ )}
+ </TableBody>
+ </Table>
+ </div>
+ <TablePagination
+ rowsPerPageOptions={[5, 10, 20, 50]}
+ component="div"
+ count={rowCount}
+ rowsPerPage={rowsPerPage}
+ page={page}
+ backIconButtonProps={{
+ 'aria-label': 'Previous Page',
+ }}
+ nextIconButtonProps={{
+ 'aria-label': 'Next Page',
+ }}
+ onChangePage={this.onHandleChangePage}
+ onChangeRowsPerPage={this.onHandleChangeRowsPerPage}
+ />
+ </Paper>
+ );
+ }
+
+ static getDerivedStateFromProps(props: MaterialTableComponentProps, state: MaterialTableComponentState & { _rawRows: {}[] }): MaterialTableComponentState & { _rawRows: {}[] } {
+ if (isMaterialTableComponentPropsWithRowsAndRequestData(props)) {
+ return {
+ ...state,
+ rows: props.rows,
+ total: props.total,
+ orderBy: props.orderBy,
+ order: props.order,
+ filter: props.filter,
+ loading: props.loading,
+ showFilter: props.showFilter,
+ page: props.page,
+ rowsPerPage: props.rowsPerPage
+ }
+ } else if (isMaterialTableComponentPropsWithRows(props) && props.asynchronus && state._rawRows !== props.rows) {
+ const newState = MaterialTableComponent.updateRows(props, state);
+ return {
+ ...state,
+ ...newState,
+ _rawRows: props.rows || []
+ };
+ }
+ return state;
+ }
+
+ private static updateRows(props: MaterialTableComponentPropsWithRows, state: MaterialTableComponentState): { rows: {}[], total: number, page: number } {
+
+ const { page, rowsPerPage, order, orderBy, filter } = state;
+
+ try {
+ let data: dataType[] = props.rows || [];
+ let filtered = false;
+ if (state.showFilter) {
+ Object.keys(filter).forEach(prop => {
+ const exp = filter[prop];
+ filtered = filtered || exp !== undefined;
+ data = exp !== undefined ? data.filter((val) => {
+ const value = val[prop];
+
+ if (value) {
+
+ if (typeof exp === 'boolean') {
+ return value == exp;
+
+ } else if (typeof exp === 'string') {
+
+ const valueAsString = value.toString();
+ if (exp.length === 0) return value;
+
+ const regex = new RegExp("\\*", "g");
+ const regex2 = new RegExp("\\?", "g");
+
+ const countStar = (exp.match(regex) || []).length;
+ const countQuestionmarks = (exp.match(regex2) || []).length;
+
+ if (countStar > 0 || countQuestionmarks > 0) {
+ let editableExpression = exp;
+
+ if (!exp.startsWith('*')) {
+ editableExpression = '^' + exp;
+ }
+
+ if (!exp.endsWith('*')) {
+ editableExpression = editableExpression + '$';
+ }
+
+ const expressionAsRegex = editableExpression.replace(/\*/g, ".*").replace(/\?/g, ".");
+
+ return valueAsString.match(new RegExp(expressionAsRegex, "g"));
+ }
+ else if (exp.includes('>=')) {
+ return Number(valueAsString) >= Number(exp.replace('>=', ''));
+ } else if (exp.includes('<=')) {
+ return Number(valueAsString) <= Number(exp.replace('<=', ''));
+ } else
+ if (exp.includes('>')) {
+ return Number(valueAsString) > Number(exp.replace('>', ''));
+ } else if (exp.includes('<')) {
+ return Number(valueAsString) < Number(exp.replace('<', ''));
+ }
+ }
+ }
+
+ return (value == exp)
+ }) : data;
+ });
+ }
+
+ const rowCount = data.length;
+
+ if (page > 0 && rowsPerPage * page > rowCount) { //if result is smaller than the currently shown page, new search and repaginate
+ let newPage = Math.floor(rowCount / rowsPerPage);
+ return {
+ rows: data,
+ total: rowCount,
+ page: newPage
+ };
+ } else {
+ data = (orderBy && order
+ ? stableSort(data, getSorting(order, orderBy))
+ : data).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
+
+ return {
+ rows: data,
+ total: rowCount,
+ page: page
+ };
+ }
+
+
+ } catch (e) {
+ console.error(e);
+ return {
+ rows: [],
+ total: 0,
+ page: page
+ }
+ }
+ }
+
+ private async update() {
+ if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+ const response = await Promise.resolve(
+ this.props.onRequestData(
+ this.state.page, this.state.rowsPerPage, this.state.orderBy, this.state.order, this.state.showFilter && this.state.filter || {})
+ );
+ this.setState(response);
+ } else {
+ let updateResult = MaterialTableComponent.updateRows(this.props, this.state);
+ this.setState(updateResult);
+ }
+ }
+
+ private onFilterChanged = (property: string, filterTerm: string) => {
+ if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+ this.props.onFilterChanged(property, filterTerm);
+ return;
+ }
+ if (this.props.disableFilter) return;
+ const colDefinition = this.props.columns && this.props.columns.find(col => col.property === property);
+ if (colDefinition && colDefinition.disableFilter) return;
+
+ const filter = { ...this.state.filter, [property]: filterTerm };
+ this.setState({
+ filter
+ }, this.update);
+ };
+
+ private onHandleRequestSort = (event: React.SyntheticEvent, property: string) => {
+ if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+ this.props.onHandleRequestSort(property);
+ return;
+ }
+ if (this.props.disableSorting) return;
+ const colDefinition = this.props.columns && this.props.columns.find(col => col.property === property);
+ if (colDefinition && colDefinition.disableSorting) return;
+
+ const orderBy = this.state.orderBy === property && this.state.order === 'desc' ? null : property;
+ const order = this.state.orderBy === property && this.state.order === 'asc' ? 'desc' : 'asc';
+ this.setState({
+ order,
+ orderBy
+ }, this.update);
+ };
+
+ handleSelectAllClick: () => {};
+
+ private onHandleChangePage = (event: any | null, page: number) => {
+ if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+ this.props.onHandleChangePage(page);
+ return;
+ }
+ this.setState({
+ page
+ }, this.update);
+ };
+
+ private onHandleChangeRowsPerPage = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
+ if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+ this.props.onHandleChangeRowsPerPage(+(event && event.target.value));
+ return;
+ }
+ const rowsPerPage = +(event && event.target.value);
+ if (rowsPerPage && rowsPerPage > 0) {
+ this.setState({
+ rowsPerPage
+ }, this.update);
+ }
+ };
+
+ private isSelected(id: string | number): boolean {
+ let selected = this.state.selected || [];
+ const selectedIndex = selected.indexOf(id);
+ return (selectedIndex > -1);
+ }
+
+ private handleClick(event: any, rowData: TData, id: string | number): void {
+ if (this.props.onHandleClick instanceof Function) {
+ this.props.onHandleClick(event, rowData);
+ return;
+ }
+ if (!this.props.enableSelection) {
+ return;
+ }
+ let selected = this.state.selected || [];
+ const selectedIndex = selected.indexOf(id);
+ if (selectedIndex > -1) {
+ selected = [
+ ...selected.slice(0, selectedIndex),
+ ...selected.slice(selectedIndex + 1)
+ ];
+ } else {
+ selected = [
+ ...selected,
+ id
+ ];
+ }
+ this.setState({
+ selected
+ });
+ }
+
+
+ private exportToCsv = async () => {
+ let file;
+ let data: dataType[] | null = null;
+ let csv: string[] = [];
+
+ if (isMaterialTableComponentPropsWithRequestData(this.props)) {
+ // table with extra request handler
+ this.setState({ loading: true });
+ const result = await Promise.resolve(
+ this.props.onRequestData(0, 1000, this.state.orderBy, this.state.order, this.state.showFilter && this.state.filter || {})
+ );
+ data = result.rows;
+ this.setState({ loading: true });
+ } else if (isMaterialTableComponentPropsWithRowsAndRequestData(this.props)) {
+ // table with generated handlers note: exports data shown on current page
+ data = this.props.rows;
+ }
+ else {
+ // table with local data
+ data = MaterialTableComponent.updateRows(this.props, this.state).rows;
+ }
+
+ if (data && data.length > 0) {
+ csv.push(this.props.columns.map(col => col.title || col.property).join(',') + "\r\n");
+ this.state.rows && this.state.rows.forEach((row: any) => {
+ csv.push(this.props.columns.map(col => row[col.property]).join(',') + "\r\n");
+ });
+ const properties = { type: "text/csv;charset=utf-8" }; // Specify the file's mime-type.
+ try {
+ // Specify the filename using the File constructor, but ...
+ file = new File(csv, "export.csv", properties);
+ } catch (e) {
+ // ... fall back to the Blob constructor if that isn't supported.
+ file = new Blob(csv, properties);
+ }
+ }
+ if (!file) return;
+ var reader = new FileReader();
+ reader.onload = function (e) {
+ const dataUri = reader.result as any;
+ const link = document.createElement("a");
+ if (typeof link.download === 'string') {
+ link.href = dataUri;
+ link.download = "export.csv";
+
+ //Firefox requires the link to be in the body
+ document.body.appendChild(link);
+
+ //simulate click
+ link.click();
+
+ //remove the link when done
+ document.body.removeChild(link);
+ } else {
+ window.open(dataUri);
+ }
+ }
+ reader.readAsDataURL(file);
+
+ // const url = URL.createObjectURL(file);
+ // window.location.replace(url);
+ }
+}
+
+export type MaterialTableCtorType<TData extends {} = {}> = new () => React.Component<Omit<MaterialTableComponentProps<TData>, 'classes'>>;
+
+export const MaterialTable = withStyles(styles)(MaterialTableComponent);
+export default MaterialTable; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
new file mode 100644
index 000000000..737ea85f9
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -0,0 +1,88 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { ColumnModel, ColumnType } from './columnModel';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+
+import TableCell from '@material-ui/core/TableCell';
+import TableRow from '@material-ui/core/TableRow';
+import Input from '@material-ui/core/Input';
+import { Select, FormControl, InputLabel, MenuItem } from '@material-ui/core';
+
+
+const styles = (theme: Theme) => createStyles({
+ container: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ },
+ input: {
+ margin: theme.spacing(1),
+ },
+});
+
+interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
+ onFilterChanged: (property: string, filterTerm: string) => void;
+ filter: { [property: string]: string };
+ columns: ColumnModel<{}>[];
+ enableSelection?: boolean;
+}
+
+class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterComponentProps> {
+ createFilterHandler = (property: string) => (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
+ this.props.onFilterChanged && this.props.onFilterChanged(property, event.target.value);
+ };
+
+ render() {
+ const { columns, filter, classes } = this.props;
+ return (
+ <TableRow>
+ {this.props.enableSelection
+ ? <TableCell padding="checkbox" style={{ width: "50px" }}>
+ </TableCell>
+ : null
+ }
+ {columns.map(col => {
+ const style = col.width ? { width: col.width } : {};
+ return (
+ <TableCell
+ key={col.property}
+ padding={col.disablePadding ? 'none' : 'default'}
+ style={style}
+ >
+ {col.disableFilter || (col.type === ColumnType.custom)
+ ? null
+ : (col.type === ColumnType.boolean)
+ ? <Select className={classes.input} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} >
+ <MenuItem value={undefined}>
+ <em>None</em>
+ </MenuItem>
+ <MenuItem value={true as any as string}>{col.labels ? col.labels["true"] : "true"}</MenuItem>
+ <MenuItem value={false as any as string}>{col.labels ? col.labels["false"] : "false"}</MenuItem>
+ </Select>
+ : <Input className={classes.input} inputProps={{ 'aria-label': 'Filter' }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />}
+ </TableCell>
+ );
+ }, this)}
+ </TableRow>
+ );
+ }
+}
+
+export const EnhancedTableFilter = withStyles(styles)(EnhancedTableFilterComponent); \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx
new file mode 100644
index 000000000..428f4cf3f
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import { ColumnModel, ColumnType } from './columnModel';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import TableSortLabel from '@material-ui/core/TableSortLabel';
+import TableCell from '@material-ui/core/TableCell';
+import TableHead from '@material-ui/core/TableHead';
+import TableRow from '@material-ui/core/TableRow';
+import Checkbox from '@material-ui/core/Checkbox';
+import Tooltip from '@material-ui/core/Tooltip';
+
+interface IEnhancedTableHeadComponentProps {
+ numSelected: number | null;
+ onRequestSort: (event: React.SyntheticEvent, property: string) => void;
+ onSelectAllClick: () => void;
+ order: 'asc' | 'desc';
+ orderBy: string | null;
+ rowCount: number;
+ columns: ColumnModel<{}>[];
+ enableSelection?: boolean;
+}
+
+class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadComponentProps> {
+ createSortHandler = (property: string) => (event: React.SyntheticEvent) => {
+ this.props.onRequestSort(event, property);
+ };
+
+ render() {
+ const { onSelectAllClick, order, orderBy, numSelected, rowCount, columns } = this.props;
+
+ return (
+ <TableHead>
+ <TableRow>
+ { this.props.enableSelection
+ ? <TableCell padding="checkbox" style={ { width: "50px" } }>
+ <Checkbox
+ indeterminate={ numSelected && numSelected > 0 && numSelected < rowCount || undefined }
+ checked={ numSelected === rowCount }
+ onChange={ onSelectAllClick }
+ />
+ </TableCell>
+ : null
+ }
+ { columns.map(col => {
+ const style = col.width ? { width: col.width } : {};
+ return (
+ <TableCell
+ key={ col.property }
+ align={ col.type === ColumnType.numeric ? 'right' : 'left' }
+ padding={ col.disablePadding ? 'none' : 'default' }
+ sortDirection={ orderBy === (col.property) ? order : false }
+ style={ style }
+ >
+ { col.disableSorting || (col.type === ColumnType.custom)
+ ? <TableSortLabel
+ active={ false }
+ direction={ undefined }
+ >
+ { col.title || col.property }
+ </TableSortLabel>
+ : <Tooltip
+ title="Sort"
+ placement={ col.type === ColumnType.numeric ? 'bottom-end' : 'bottom-start' }
+ enterDelay={ 300 }
+ >
+ <TableSortLabel
+ active={ orderBy === col.property }
+ direction={ order || undefined }
+ onClick={ this.createSortHandler(col.property) }
+ >
+ { col.title || col.property }
+ </TableSortLabel>
+ </Tooltip> }
+ </TableCell>
+ );
+ }, this) }
+ </TableRow>
+ </TableHead>
+ );
+ }
+}
+
+export const EnhancedTableHead = EnhancedTableHeadComponent; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx
new file mode 100644
index 000000000..a4080b51b
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx
@@ -0,0 +1,149 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import IconButton from '@material-ui/core/IconButton';
+import Tooltip from '@material-ui/core/Tooltip';
+import Toolbar from '@material-ui/core/Toolbar';
+import Typography from '@material-ui/core/Typography';
+import DeleteIcon from '@material-ui/icons/Delete';
+import MoreIcon from '@material-ui/icons/MoreVert';
+import FilterListIcon from '@material-ui/icons/FilterList';
+import MenuItem from '@material-ui/core/MenuItem';
+import Menu from '@material-ui/core/Menu';
+import { lighten } from '@material-ui/core/styles/colorManipulator';
+import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon';
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ paddingRight: theme.spacing(1),
+ },
+ highlight:
+ theme.palette.type === 'light'
+ ? {
+ color: theme.palette.secondary.main,
+ backgroundColor: lighten(theme.palette.secondary.light, 0.85),
+ }
+ : {
+ color: theme.palette.text.primary,
+ backgroundColor: theme.palette.secondary.dark,
+ },
+ spacer: {
+ flex: '1 1 100%',
+ },
+ actions: {
+ color: theme.palette.text.secondary,
+ display: "flex",
+ flex: "auto",
+ flexDirection: "row"
+ },
+ title: {
+ flex: '0 0 auto',
+ },
+ menuButton: {
+ marginLeft: -12,
+ marginRight: 20,
+ },
+});
+
+interface ITableToolbarComponentProps extends WithStyles<typeof styles> {
+ numSelected: number | null;
+ title?: string;
+ tableId?: string;
+ customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, onClick: () => void }[];
+ onToggleFilter: () => void;
+ onExportToCsv: () => void;
+}
+
+class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null }> {
+ constructor(props: ITableToolbarComponentProps) {
+ super(props);
+
+ this.state = {
+ anchorEl: null
+ };
+ }
+
+ private handleMenu = (event: React.MouseEvent<HTMLElement>) => {
+ this.setState({ anchorEl: event.currentTarget });
+ };
+
+ private handleClose = () => {
+ this.setState({ anchorEl: null });
+ };
+ render() {
+ const { numSelected, classes } = this.props;
+ const open = !!this.state.anchorEl;
+ const buttonPrefix = this.props.tableId !== undefined ? this.props.tableId + '-' : '';
+ return (
+ <Toolbar className={`${classes.root} ${numSelected && numSelected > 0 ? classes.highlight : ''} `} >
+ <div className={classes.title}>
+ {numSelected && numSelected > 0 ? (
+ <Typography color="inherit" variant="subtitle1">
+ {numSelected} selected
+ </Typography>
+ ) : (
+ <Typography variant="h5" id="tableTitle">
+ {this.props.title || null}
+ </Typography>
+ )}
+ </div>
+ <div className={classes.spacer} />
+ <div className={classes.actions}>
+ {this.props.customActionButtons
+ ? this.props.customActionButtons.map((action, ind) => (
+ <Tooltip key={`custom-action-${ind}`} title={action.tooltip}>
+ <IconButton aria-label={buttonPrefix + `custom-action-${ind}`} onClick={() => action.onClick()}>
+ <action.icon />
+ </IconButton>
+ </Tooltip>
+ ))
+ : null}
+ {numSelected && numSelected > 0 ? (
+ <Tooltip title="Delete">
+ <IconButton aria-label={buttonPrefix + "delete"}>
+ <DeleteIcon />
+ </IconButton>
+ </Tooltip>
+ ) : (
+ <Tooltip title="Filter list">
+ <IconButton aria-label={buttonPrefix + "filter-list"} onClick={() => { this.props.onToggleFilter && this.props.onToggleFilter() }}>
+ <FilterListIcon />
+ </IconButton>
+ </Tooltip>
+ )}
+ <Tooltip title="Actions">
+ <IconButton color="inherit"
+ aria-owns={open ? 'menu-appbar' : undefined}
+ aria-haspopup="true"
+ onClick={this.handleMenu} >
+ <MoreIcon />
+ </IconButton>
+ </Tooltip>
+ <Menu id="menu-appbar" anchorEl={this.state.anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
+ transformOrigin={{ vertical: 'top', horizontal: 'right' }} open={open} onClose={this.handleClose} >
+ <MenuItem onClick={this.props.onExportToCsv}>Export as CSV</MenuItem>
+ </Menu>
+ </div>
+ </Toolbar>
+ );
+ }
+};
+
+export const TableToolbar = withStyles(styles)(TableToolbarComponent); \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
new file mode 100644
index 000000000..6e8902c07
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
@@ -0,0 +1,263 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from '../../flux/action';
+import { Dispatch } from '../../flux/store';
+
+import { AddErrorInfoAction } from '../../actions/errorActions';
+import { IApplicationStoreState } from '../../store/applicationStore';
+
+import { DataCallback } from ".";
+export interface IExternalTableState<TData> {
+ order: 'asc' | 'desc';
+ orderBy: string | null;
+ selected: any[] | null;
+ rows: TData[];
+ total: number;
+ page: number;
+ rowsPerPage: number;
+ loading: boolean;
+ showFilter: boolean;
+ filter: { [property: string]: string };
+ preFilter: { [property: string]: string };
+}
+
+/** Create an actionHandler and actions for external table states. */
+export function createExternal<TData>(callback: DataCallback<TData>, selectState: (appState: IApplicationStoreState) => IExternalTableState<TData>) {
+
+ //#region Actions
+ abstract class TableAction extends Action { }
+
+
+ class RequestSortAction extends TableAction {
+ constructor(public orderBy: string) {
+ super();
+ }
+ }
+
+ class SetSelectedAction extends TableAction {
+ constructor(public selected: TData[] | null) {
+ super();
+ }
+ }
+
+ class SetPageAction extends TableAction {
+ constructor(public page: number) {
+ super();
+ }
+ }
+
+ class SetRowsPerPageAction extends TableAction {
+ constructor(public rowsPerPage: number) {
+ super();
+ }
+ }
+
+ class SetPreFilterChangedAction extends TableAction {
+ constructor(public preFilter: { [key: string]: string }) {
+ super();
+ }
+ }
+
+ class SetFilterChangedAction extends TableAction {
+ constructor(public filter: { [key: string]: string }) {
+ super();
+ }
+ }
+
+ class SetShowFilterAction extends TableAction {
+ constructor(public show: boolean) {
+ super();
+ }
+ }
+
+ class RefreshAction extends TableAction {
+ constructor() {
+ super();
+ }
+ }
+
+ class SetResultAction extends TableAction {
+ constructor(public result: { page: number, total: number, rows: TData[] }) {
+ super();
+ }
+ }
+
+ // #endregion
+
+ //#region Action Handler
+ const externalTableStateInit: IExternalTableState<TData> = {
+ order: 'asc',
+ orderBy: null,
+ selected: null,
+ rows: [],
+ total: 0,
+ page: 0,
+ rowsPerPage: 10,
+ loading: false,
+ showFilter: false,
+ filter: {},
+ preFilter: {}
+ };
+
+ const externalTableStateActionHandler: IActionHandler<IExternalTableState<TData>> = (state = externalTableStateInit, action) => {
+ if (!(action instanceof TableAction)) return state;
+ if (action instanceof RefreshAction) {
+ state = {
+ ...state,
+ loading: true
+ }
+ } else if (action instanceof SetResultAction) {
+ state = {
+ ...state,
+ loading: false,
+ rows: action.result.rows,
+ total: action.result.total,
+ page: action.result.page,
+ }
+ } else if (action instanceof RequestSortAction) {
+ state = {
+ ...state,
+ loading: true,
+ orderBy: state.orderBy === action.orderBy && state.order === 'desc' ? null : action.orderBy,
+ order: state.orderBy === action.orderBy && state.order === 'asc' ? 'desc' : 'asc',
+ }
+ } else if (action instanceof SetShowFilterAction) {
+ state = {
+ ...state,
+ loading: true,
+ showFilter: action.show
+ }
+ } else if (action instanceof SetPreFilterChangedAction) {
+ state = {
+ ...state,
+ loading: true,
+ preFilter: action.preFilter
+ }
+ } else if (action instanceof SetFilterChangedAction) {
+ state = {
+ ...state,
+ loading: true,
+ filter: action.filter
+ }
+ } else if (action instanceof SetPageAction) {
+ state = {
+ ...state,
+ loading: true,
+ page: action.page
+ }
+ } else if (action instanceof SetRowsPerPageAction) {
+ state = {
+ ...state,
+ loading: true,
+ rowsPerPage: action.rowsPerPage
+ }
+ }
+ return state;
+ }
+
+ //const createTableAction(tableAction)
+
+ //#endregion
+ const reloadAction = (dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+ dispatch(new RefreshAction());
+ const ownState = selectState(getAppState());
+ const filter = { ...ownState.preFilter, ...(ownState.showFilter && ownState.filter || {}) };
+ Promise.resolve(callback(ownState.page, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result => {
+
+ if (ownState.page > 0 && ownState.rowsPerPage * ownState.page > result.total) { //if result is smaller than the currently shown page, new search and repaginate
+
+ let newPage = Math.floor(result.total / ownState.rowsPerPage);
+
+ Promise.resolve(callback(newPage, ownState.rowsPerPage, ownState.orderBy, ownState.order, filter)).then(result1 => {
+ dispatch(new SetResultAction(result1));
+ });
+
+
+ } else {
+ dispatch(new SetResultAction(result));
+ }
+
+
+ }).catch(error => new AddErrorInfoAction(error));
+ };
+
+ const createPreActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
+ return {
+ onPreFilterChanged: (preFilter: { [key: string]: string }) => {
+ dispatch(new SetPreFilterChangedAction(preFilter));
+ (!skipRefresh) && dispatch(reloadAction);
+ }
+ };
+ }
+
+ const createActions = (dispatch: Dispatch, skipRefresh: boolean = false) => {
+ return {
+ onRefresh: () => {
+ dispatch(reloadAction);
+ },
+ onHandleRequestSort: (orderBy: string) => {
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new RequestSortAction(orderBy));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ },
+ onToggleFilter: () => {
+ dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+ const { showFilter } = selectState(getAppState());
+ dispatch(new SetShowFilterAction(!showFilter));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ },
+ onFilterChanged: (property: string, filterTerm: string) => {
+ dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
+ let { filter } = selectState(getAppState());
+ filter = { ...filter, [property]: filterTerm };
+ dispatch(new SetFilterChangedAction(filter));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ },
+ onHandleChangePage: (page: number) => {
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new SetPageAction(page));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ },
+ onHandleChangeRowsPerPage: (rowsPerPage: number | null) => {
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new SetRowsPerPageAction(rowsPerPage || 10));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ }
+ // selected:
+ };
+ };
+
+ const createProperties = (state: IApplicationStoreState) => {
+ return {
+ ...selectState(state)
+ }
+ }
+
+ return {
+ reloadAction: reloadAction,
+ createActions: createActions,
+ createProperties: createProperties,
+ createPreActions: createPreActions,
+ actionHandler: externalTableStateActionHandler
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/index.ts b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts
new file mode 100644
index 000000000..e0e3fc943
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { ListItemLink } from './listItemLink';
+export { Panel } from './panel';
+export { ToggleButton, ToggleButtonClassKey } from './toggleButton';
+export { TreeView, ITreeItem, TreeViewCtorType} from './treeView';
+export { Loader } from './loader';
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx
new file mode 100644
index 000000000..1a7e58f77
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx
@@ -0,0 +1,67 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { NavLink, Link, Route } from 'react-router-dom';
+
+import ListItem from '@material-ui/core/ListItem';
+import ListItemIcon from '@material-ui/core/ListItemIcon';
+import ListItemText from '@material-ui/core/ListItemText';
+
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+const styles = (theme: Theme) => createStyles({
+ active: {
+ backgroundColor: theme.palette.action.selected
+ }
+});
+
+export interface IListItemLinkProps extends WithStyles<typeof styles> {
+ icon: JSX.Element | null;
+ primary: string | React.ComponentType;
+ secondary?: React.ComponentType;
+ to: string;
+ exact?: boolean;
+}
+
+export const ListItemLink = withStyles(styles)((props: IListItemLinkProps) => {
+ const { icon, primary: Primary, secondary: Secondary, classes, to, exact = false } = props;
+ const renderLink = (itemProps: any): JSX.Element => (<NavLink exact={ exact } to={ to } activeClassName={ classes.active } { ...itemProps } />);
+
+ return (
+ <>
+ <ListItem button component={ renderLink }>
+ { icon
+ ? <ListItemIcon>{ icon }</ListItemIcon>
+ : null
+ }
+ { typeof Primary === 'string'
+ ? <ListItemText primary={ Primary } style={{ padding: 0 }} />
+ : <Primary />
+ }
+ </ListItem>
+ { Secondary
+ ? <Route exact={ exact } path={ to } component={ Secondary } />
+ : null
+ }
+ </>
+ );
+ }
+);
+
+export default ListItemLink;
+
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx
new file mode 100644
index 000000000..5ab2fd415
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+import * as React from "react";
+
+import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+const styles = (theme: Theme) => createStyles({
+ "@keyframes spin": {
+ "0%": { transform: "rotate(0deg)" },
+ "100%": { transform: "rotate(360deg)" },
+ },
+ loader: {
+ border: `16px solid ${theme.palette.grey.A200}`,
+ borderTop: `16px solid ${theme.palette.secondary.main}`,
+ borderRadius: "50%",
+ width: "120px",
+ height: "120px",
+ animation: "$spin 2s linear infinite",
+ }
+});
+
+const LoaderComponent: React.FC<WithStyles<typeof styles>> = (props) => {
+ return (
+ <div className={props.classes.loader} />
+ );
+};
+
+export const Loader = withStyles(styles)(LoaderComponent);
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx
new file mode 100644
index 000000000..378d48592
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withStyles, Theme, WithStyles, createStyles } from '@material-ui/core/styles';
+
+import { ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Typography, ExpansionPanelActions } from '@material-ui/core';
+
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import { SvgIconProps } from '@material-ui/core/SvgIcon';
+
+const styles = (theme: Theme) => createStyles({
+ accordion: {
+ // background: theme.palette.secondary.dark,
+ // color: theme.palette.primary.contrastText
+ },
+ detail: {
+ // background: theme.palette.background.paper,
+ // color: theme.palette.text.primary,
+ position: "relative",
+ display: 'flex',
+ flexDirection: 'column'
+ },
+ text: {
+ // color: theme.palette.common.white,
+ // fontSize: "1rem"
+ },
+});
+
+type PanalProps = WithStyles<typeof styles> & {
+ activePanel: string | null,
+ panelId: string,
+ title: string,
+ customActionButtons?: JSX.Element[];
+ onToggle: (panelId: string | null) => void;
+}
+
+const PanelComponent: React.SFC<PanalProps> = (props) => {
+ const { classes, activePanel, onToggle } = props;
+ return (
+ <ExpansionPanel className={classes.accordion} expanded={activePanel === props.panelId} onChange={() => onToggle(props.panelId)} >
+ <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography className={classes.text} >{props.title}</Typography>
+ </ExpansionPanelSummary>
+ <ExpansionPanelDetails className={classes.detail}>
+ {props.children}
+ </ExpansionPanelDetails>
+ {props.customActionButtons
+ ? <ExpansionPanelActions>
+ {props.customActionButtons}
+ </ExpansionPanelActions>
+ : null}
+ </ExpansionPanel>
+ );
+};
+
+export const Panel = withStyles(styles)(PanelComponent);
+export default Panel; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/snackDisplay.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/snackDisplay.tsx
new file mode 100644
index 000000000..437784ce5
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/snackDisplay.tsx
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { Connect, connect, IDispatcher } from '../../flux/connect';
+import { RemoveSnackbarNotification } from '../../actions/snackbarActions';
+
+import { WithSnackbarProps, withSnackbar } from 'notistack';
+
+const mapProps = (state: IApplicationStoreState) => ({
+ notifications: state.framework.applicationState.snackBars
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ removeSnackbar: (key: number) => {
+ dispatcher.dispatch(new RemoveSnackbarNotification(key));
+ }
+});
+
+type DisplaySnackbarsComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithSnackbarProps;
+
+class DisplaySnackbarsComponent extends React.Component<DisplaySnackbarsComponentProps> {
+ private displayed: number[] = [];
+
+ private storeDisplayed = (id: number) => {
+ this.displayed = [...this.displayed, id];
+ };
+
+ public shouldComponentUpdate({ notifications: newSnacks = [] }: DisplaySnackbarsComponentProps) {
+
+ const { notifications: currentSnacks } = this.props;
+ let notExists = false;
+ for (let i = 0; i < newSnacks.length; i++) {
+ if (notExists) continue;
+ notExists = notExists || !currentSnacks.filter(({ key }) => newSnacks[i].key === key).length;
+ }
+ return notExists;
+ }
+
+ componentDidUpdate() {
+ const { notifications = [] } = this.props;
+
+ notifications.forEach(notification => {
+ if (this.displayed.includes(notification.key)) return;
+ const options = notification.options || {};
+ this.props.enqueueSnackbar(notification.message, options);
+ this.storeDisplayed(notification.key);
+ this.props.removeSnackbar(notification.key);
+ });
+ }
+
+ render() {
+ return null;
+ }
+}
+
+const DisplayStackbars = withSnackbar(connect(mapProps, mapDispatch)(DisplaySnackbarsComponent));
+export default DisplayStackbars; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx
new file mode 100644
index 000000000..1a29d6970
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx
@@ -0,0 +1,179 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react';
+import classNames from 'classnames';
+import { withStyles, WithStyles, Theme, createStyles } from '@material-ui/core/styles';
+import { fade } from '@material-ui/core/styles/colorManipulator';
+import ButtonBase from '@material-ui/core/ButtonBase';
+
+
+export const styles = (theme: Theme) => createStyles({
+ /* Styles applied to the root element. */
+ root: {
+ ...theme.typography.button,
+ height: 32,
+ minWidth: 48,
+ margin: 0,
+ padding: `${theme.spacing(1 - 4)}px ${theme.spacing(1.5)}px`,
+ borderRadius: 2,
+ willChange: 'opacity',
+ color: fade(theme.palette.action.active, 0.38),
+ '&:hover': {
+ textDecoration: 'none',
+ // Reset on mouse devices
+ backgroundColor: fade(theme.palette.text.primary, 0.12),
+ '@media (hover: none)': {
+ backgroundColor: 'transparent',
+ },
+ '&$disabled': {
+ backgroundColor: 'transparent',
+ },
+ },
+ '&:not(:first-child)': {
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ },
+ '&:not(:last-child)': {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ },
+ },
+ /* Styles applied to the root element if `disabled={true}`. */
+ disabled: {
+ color: fade(theme.palette.action.disabled, 0.12),
+ },
+ /* Styles applied to the root element if `selected={true}`. */
+ selected: {
+ color: theme.palette.action.active,
+ '&:after': {
+ content: '""',
+ display: 'block',
+ position: 'absolute',
+ overflow: 'hidden',
+ borderRadius: 'inherit',
+ width: '100%',
+ height: '100%',
+ left: 0,
+ top: 0,
+ pointerEvents: 'none',
+ zIndex: 0,
+ backgroundColor: 'currentColor',
+ opacity: 0.38,
+ },
+ '& + &:before': {
+ content: '""',
+ display: 'block',
+ position: 'absolute',
+ overflow: 'hidden',
+ width: 1,
+ height: '100%',
+ left: 0,
+ top: 0,
+ pointerEvents: 'none',
+ zIndex: 0,
+ backgroundColor: 'currentColor',
+ opacity: 0.12,
+ },
+ },
+ /* Styles applied to the `label` wrapper element. */
+ label: {
+ width: '100%',
+ display: 'inherit',
+ alignItems: 'inherit',
+ justifyContent: 'inherit',
+ },
+});
+
+export type ToggleButtonClassKey = 'disabled' | 'root' | 'label' | 'selected';
+
+interface IToggleButtonProps extends WithStyles<typeof styles> {
+ className?: string;
+ component?: React.ReactType<IToggleButtonProps>;
+ disabled?: boolean;
+ disableFocusRipple?: boolean;
+ disableRipple?: boolean;
+ selected?: boolean;
+ type?: string;
+ value?: any;
+ onClick?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
+ onChange?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
+}
+
+class ToggleButtonComponent extends React.Component<IToggleButtonProps> {
+ handleChange = (event: React.FormEvent<HTMLElement>) => {
+ const { onChange, onClick, value } = this.props;
+
+ event.stopPropagation();
+ if (onClick) {
+ onClick(event, value);
+ if (event.isDefaultPrevented()) {
+ return;
+ }
+ }
+
+ if (onChange) {
+ onChange(event, value);
+ }
+ event.preventDefault();
+ };
+
+ render() {
+ const {
+ children,
+ className: classNameProp,
+ classes,
+ disableFocusRipple,
+ disabled,
+ selected,
+ ...other
+ } = this.props;
+
+ const className = classNames(
+ classes.root,
+ {
+ [classes.disabled]: disabled,
+ [classes.selected]: selected,
+ },
+ classNameProp,
+ );
+
+ return (
+ <ButtonBase
+ className={className}
+ disabled={disabled}
+ focusRipple={!disableFocusRipple}
+ onClick={this.handleChange}
+ href="#"
+ {...other}
+ >
+ <span className={classes.label}>{children}</span>
+ </ButtonBase>
+ );
+ }
+ public static defaultProps = {
+ disabled: false,
+ disableFocusRipple: false,
+ disableRipple: false,
+ };
+
+ public static muiName = 'ToggleButton';
+}
+
+export const ToggleButton = withStyles(styles, { name: 'MuiToggleButton' })(ToggleButtonComponent);
+export default ToggleButton; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx
new file mode 100644
index 000000000..6460e8a3f
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import classNames from 'classnames';
+import { withStyles, WithStyles, Theme, createStyles } from '@material-ui/core/styles';
+
+export const styles = (theme: Theme) => createStyles({
+ /* Styles applied to the root element. */
+ root: {
+ transition: theme.transitions.create('background,box-shadow'),
+ background: 'transparent',
+ borderRadius: 2,
+ overflow: 'hidden',
+ },
+ /* Styles applied to the root element if `selected={true}` or `selected="auto" and `value` set. */
+ selected: {
+ background: theme.palette.background.paper,
+ boxShadow: theme.shadows[2],
+ },
+});
+
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
new file mode 100644
index 000000000..e4eb3a794
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
@@ -0,0 +1,268 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { SvgIconProps } from '@material-ui/core/SvgIcon';
+import { List, ListItem, TextField, ListItemText, ListItemIcon, WithTheme, withTheme, Omit } from '@material-ui/core';
+
+import FileIcon from '@material-ui/icons/InsertDriveFile';
+import CloseIcon from '@material-ui/icons/ExpandLess';
+import OpenIcon from '@material-ui/icons/ExpandMore';
+import FolderIcon from '@material-ui/icons/Folder';
+
+export interface ITreeItem {
+ disabled?: boolean;
+ icon?: React.ComponentType<SvgIconProps>;
+}
+
+type TreeViewComponentState<TData extends ITreeItem = ITreeItem> = {
+ /** All indices of all expanded Items */
+ expandedItems: TData[];
+ /** The index of the active iten or undefined if no item is active. */
+ activeItem: undefined | TData;
+ /** The search term or undefined if search is corrently not active. */
+ searchTerm: undefined | string;
+}
+
+type TreeViewComponentBaseProps<TData extends ITreeItem = ITreeItem> = WithTheme & {
+ items: TData[];
+ contentProperty: keyof Omit<TData, keyof ITreeItem>;
+ childrenProperty: keyof Omit<TData, keyof ITreeItem>;
+ useFolderIcons?: boolean;
+ enableSearchBar?: boolean;
+ autoExpandFolder?: boolean;
+ style?: React.CSSProperties;
+ itemHeight?: number;
+ depthOffset?: number;
+}
+
+type TreeViewComponentWithInternalStateProps<TData extends ITreeItem = ITreeItem> = TreeViewComponentBaseProps<TData> & {
+ onItemClick?: (item: TData) => void;
+ onFolderClick?: (item: TData) => void;
+}
+
+type TreeViewComponentWithExternalStateProps<TData extends ITreeItem = ITreeItem> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+ onSearch: (searchTerm: string) => void;
+ onItemClick: (item: TData) => void;
+ onFolderClick: (item: TData) => void;
+}
+
+type TreeViewComponentProps<TData extends ITreeItem = ITreeItem> =
+ TreeViewComponentWithInternalStateProps<TData> |
+ TreeViewComponentWithExternalStateProps<TData>;
+
+function isTreeViewComponentWithExternalStateProps<TData extends ITreeItem = ITreeItem>(props: TreeViewComponentProps<TData>): props is TreeViewComponentWithExternalStateProps<TData> {
+ const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps<TData>)
+ return (
+ propsWithExternalState.onSearch instanceof Function ||
+ propsWithExternalState.expandedItems !== undefined ||
+ propsWithExternalState.activeItem !== undefined ||
+ propsWithExternalState.searchTerm !== undefined
+ );
+}
+
+class TreeViewComponent<TData extends ITreeItem> extends React.Component<TreeViewComponentProps<TData>, TreeViewComponentState> {
+
+ /**
+ * Initializes a new instance.
+ */
+ constructor(props: TreeViewComponentProps<TData>) {
+ super(props);
+
+ this.state = {
+ expandedItems: [],
+ activeItem: undefined,
+ searchTerm: undefined
+ };
+ }
+
+ render(): JSX.Element {
+ this.itemIndex = 0;
+ const { searchTerm } = this.state;
+ const { children, items, enableSearchBar } = this.props;
+ const styles = {
+ root: {
+ padding: 0,
+ paddingBottom: 8,
+ paddingTop: children ? 0 : 8,
+ ...this.props.style
+ },
+ search: {
+ padding: `0px ${this.props.theme.spacing(1)}px`
+ }
+ };
+ return (
+ <div style={styles.root}>
+ {children}
+ {enableSearchBar && <TextField label={"Search"} fullWidth={true} style={styles.search} value={searchTerm} onChange={this.onChangeSearchText} /> || null}
+ <List>
+ {this.renderItems(items, searchTerm && searchTerm.toLowerCase())}
+ </List>
+ </div>
+ );
+ }
+
+ private itemIndex: number = 0;
+ private renderItems = (items: TData[], searchTerm: string | undefined, depth: number = 1) => {
+ return items.reduce((acc, item) => {
+
+ const children = this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]);
+ const childrenJsx = children && this.renderItems(children, searchTerm, depth + 1);
+
+ const expanded = searchTerm
+ ? children && childrenJsx.length > 0
+ : !children
+ ? false
+ : this.state.expandedItems.indexOf(item) > -1;
+ const isFolder = children !== undefined;
+
+ const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded);
+ itemJsx && acc.push(itemJsx);
+
+ if (isFolder && expanded) {
+ acc.push(...childrenJsx);
+ }
+ return acc;
+
+ }, [] as JSX.Element[]);
+ }
+ private renderItem = (item: TData, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => {
+ const styles = {
+ item: {
+ paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)),
+ backgroundColor: this.state.activeItem === item ? this.props.theme.palette.action.selected : undefined,
+ height: this.props.itemHeight || undefined,
+ cursor: item.disabled ? 'not-allowed' : 'pointer',
+ color: item.disabled ? this.props.theme.palette.text.disabled : this.props.theme.palette.text.primary,
+ overflow: 'hidden',
+ transform: 'translateZ(0)',
+ }
+ };
+
+ const text = (item as any)[this.props.contentProperty] as string || ''; // need to keep track of search
+ const matchIndex = searchTerm ? text.toLowerCase().indexOf(searchTerm) : -1;
+ const searchTermLength = searchTerm && searchTerm.length || 0;
+
+ const handleClickCreator = (isIcon: boolean) => (event: React.SyntheticEvent) => {
+ if (item.disabled) return;
+ event.preventDefault();
+ event.stopPropagation();
+ if (isFolder && (this.props.autoExpandFolder || isIcon)) {
+ this.props.onFolderClick ? this.props.onFolderClick(item) : this.onFolderClick(item);
+ } else {
+ this.props.onItemClick ? this.props.onItemClick(item) : this.onItemClick(item);
+ }
+ };
+
+ return ((searchTerm && (matchIndex > -1 || expanded) || !searchTerm)
+ ? (
+ <ListItem key={`tree-list-${this.itemIndex++}`} style={styles.item} onClick={handleClickCreator(false)} button >
+
+ { // display the left icon
+ (this.props.useFolderIcons && <ListItemIcon>{isFolder ? <FolderIcon /> : <FileIcon />}</ListItemIcon>) ||
+ (item.icon && (<ListItemIcon><item.icon /></ListItemIcon>))}
+
+
+ { // highlight search result
+ matchIndex > -1
+ ? (<span>
+ {text.substring(0, matchIndex)}
+ <span
+ style={{
+ display: 'inline-block',
+ backgroundColor: 'rgba(255,235,59,0.5)',
+ padding: '3px',
+ }}
+ >
+ {text.substring(matchIndex, matchIndex + searchTermLength)}
+ </span>
+ {text.substring(matchIndex + searchTermLength)}
+ </span>)
+ : (<ListItemText primary={text} />)
+ }
+
+ { // display the right icon, depending on the state
+ !isFolder ? null : expanded ? (<OpenIcon onClick={handleClickCreator(true)} />) : (<CloseIcon onClick={handleClickCreator(true)} />)}
+ </ListItem>
+ )
+ : null
+ );
+ }
+
+ private onFolderClick = (item: TData) => {
+ // toggle items with children
+ if (this.state.searchTerm) return;
+ const indexOfItemToToggle = this.state.expandedItems.indexOf(item);
+ if (indexOfItemToToggle === -1) {
+ this.setState({
+ expandedItems: [...this.state.expandedItems, item],
+ });
+ } else {
+ this.setState({
+ expandedItems: [
+ ...this.state.expandedItems.slice(0, indexOfItemToToggle),
+ ...this.state.expandedItems.slice(indexOfItemToToggle + 1),
+ ]
+ });
+ }
+ };
+
+ private onItemClick = (item: TData) => {
+ // activate items without children
+ this.setState({
+ activeItem: item,
+ });
+ };
+
+ private onChangeSearchText = (event: React.ChangeEvent<HTMLInputElement>) => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (isTreeViewComponentWithExternalStateProps(this.props)) {
+ this.props.onSearch(event.target.value)
+ } else {
+ this.setState({
+ searchTerm: event.target.value
+ });
+ }
+ };
+
+ static getDerivedStateFromProps(props: TreeViewComponentProps, state: TreeViewComponentState): TreeViewComponentState {
+ if (isTreeViewComponentWithExternalStateProps(props)) {
+ return {
+ ...state,
+ expandedItems: props.expandedItems || [],
+ activeItem: props.activeItem,
+ searchTerm: props.searchTerm
+ };
+ }
+ return state;
+ }
+
+ public static defaultProps = {
+ useFolderIcons: false,
+ enableSearchBar: false,
+ autoExpandFolder: false,
+ depthOffset: 0
+ }
+}
+
+export type TreeViewCtorType<TData extends ITreeItem = ITreeItem> = new () => React.Component<Omit<TreeViewComponentProps<TData>, 'theme'>>;
+
+export const TreeView = withTheme(TreeViewComponent);
+export default TreeView; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
new file mode 100644
index 000000000..00d43d99c
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
@@ -0,0 +1,142 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import { faHome, faAddressBook } from '@fortawesome/free-solid-svg-icons';
+
+import Drawer from '@material-ui/core/Drawer';
+import List from '@material-ui/core/List';
+
+import Divider from '@material-ui/core/Divider';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import ListItemLink from '../components/material-ui/listItemLink';
+
+import connect, { Connect, IDispatcher } from '../flux/connect';
+import { MenuAction } from '../actions/menuAction';
+import * as classNames from 'classnames';
+
+const drawerWidth = 240;
+
+const styles = (theme: Theme) => createStyles({
+ drawerPaper: {
+ position: 'relative',
+ width: drawerWidth,
+ },
+ toolbar: theme.mixins.toolbar,
+ drawerOpen: {
+ width: drawerWidth,
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ drawerClose: {
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ overflowX: 'hidden',
+ width: theme.spacing(7) + 1,
+ [theme.breakpoints.up('sm')]: {
+ width: theme.spacing(9) + 1,
+ },
+ }
+});
+
+const tabletWidthBreakpoint = 768;
+
+export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, dispatch }: WithStyles<typeof styles> & Connect & Connect) => {
+ const { user } = state.framework.authenticationState
+ const isOpen = state.framework.applicationState.isMenuOpen
+ const closedByUser = state.framework.applicationState.isMenuClosedByUser
+
+ const [responsive, setResponsive] = React.useState(false);
+
+ React.useEffect(() => {
+
+ function handleResize() {
+ if (user && user.isValid) {
+ if (window.innerWidth < tabletWidthBreakpoint && !responsive) {
+ setResponsive(true);
+ if (!closedByUser) {
+ console.log("responsive menu collapsed")
+ dispatch(new MenuAction(false));
+ }
+
+ } else if (window.innerWidth > tabletWidthBreakpoint && responsive) {
+ setResponsive(false);
+ if (!closedByUser) {
+ console.log("responsive menu restored")
+ dispatch(new MenuAction(true));
+ }
+
+ }
+ }
+ }
+ window.addEventListener("resize", handleResize);
+
+
+ return () => {
+ window.removeEventListener("resize", handleResize);
+ }
+ })
+
+ return (
+ <Drawer
+ variant="permanent"
+ className={
+ classNames({
+ [classes.drawerOpen]: isOpen,
+ [classes.drawerClose]: !isOpen
+ })
+ }
+ classes={{
+ paper: classes.drawerPaper,
+ }}
+ >
+ {user && user.isValid && <>
+ <div className={classes.toolbar} />
+ { /* https://fiffty.github.io/react-treeview-mui/ */}
+ <List component="nav">
+ <ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} />
+ <Divider />
+ {
+ state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
+ const reg = state.framework.applicationRegistraion[key];
+ return reg && (
+ <ListItemLink
+ key={reg.name}
+ to={reg.path || `/${reg.name}`}
+ primary={reg.menuEntry || reg.name}
+ secondary={reg.subMenuEntry}
+ icon={reg.icon && <FontAwesomeIcon icon={reg.icon} /> || null} />
+ ) || null;
+ }) || null
+ }
+ <Divider />
+ <ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} />
+ </List>
+ </> || null
+ }
+ </Drawer>)
+}));
+
+export default NavigationMenu; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx b/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx
new file mode 100644
index 000000000..e6af2eb5d
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx
@@ -0,0 +1,55 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import connect, { Connect } from '../../flux/connect';
+
+import { SetTitleAction } from '../../actions/titleActions';
+import { AddErrorInfoAction } from '../../actions/errorActions';
+
+import { IconType } from '../../models/iconDefinition';
+
+export interface IAppFrameProps {
+ title: string;
+ icon?: IconType;
+ appId?: string
+}
+
+/**
+ * Represents a component to wich will embed each single app providing the
+ * functionality to update the title and implement an exeprion border.
+ */
+export class AppFrame extends React.Component<IAppFrameProps & Connect> {
+
+ public render(): JSX.Element {
+ return (
+ <div style={{ flex: "1", overflow: "auto", display: "flex", flexDirection: "column" }}>
+ { this.props.children }
+ </div>
+ )
+ }
+
+ public componentDidMount() {
+ this.props.dispatch(new SetTitleAction(this.props.title, this.props.icon, this.props.appId));
+ }
+ public componentDidCatch(error: Error | null, info: object) {
+ this.props.dispatch(new AddErrorInfoAction({ error, info }));
+ }
+}
+
+export default connect()(AppFrame); \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/components/titleBar.tsx b/sdnr/wt/odlux/framework/src/components/titleBar.tsx
new file mode 100644
index 000000000..7168ff496
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/titleBar.tsx
@@ -0,0 +1,208 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+import AppBar from '@material-ui/core/AppBar';
+import Toolbar from '@material-ui/core/Toolbar';
+import Typography from '@material-ui/core/Typography';
+import Button from '@material-ui/core/Button';
+import IconButton from '@material-ui/core/IconButton';
+import Block from '@material-ui/icons/Block';
+import Adjust from '@material-ui/icons/Adjust';
+import MenuIcon from '@material-ui/icons/Menu';
+import AccountCircle from '@material-ui/icons/AccountCircle';
+import MenuItem from '@material-ui/core/MenuItem';
+import Menu from '@material-ui/core/Menu';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+import { faDotCircle } from '@fortawesome/free-solid-svg-icons';
+
+import { UpdateAuthentication } from '../actions/authentication';
+import { ReplaceAction } from '../actions/navigationActions';
+
+import connect, { Connect, IDispatcher } from '../flux/connect';
+import Logo from './logo';
+import { MenuAction, MenuClosedByUser } from '../actions/menuAction';
+
+const styles = (theme: Theme) => createStyles({
+ appBar: {
+ zIndex: theme.zIndex.drawer + 1,
+ },
+ grow: {
+ flexGrow: 1,
+ },
+ menuButton: {
+ marginLeft: -12,
+ marginRight: 20,
+ },
+ icon: {
+ marginLeft: 16,
+ marginRight: 8
+ },
+ connected: {
+ color: "green"
+ },
+ notConnected: {
+ color: "red"
+ },
+ notificationInfo: {
+ marginLeft: 5
+ }
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => {
+ return {
+ logout: () => {
+ dispatcher.dispatch(new UpdateAuthentication(null));
+ dispatcher.dispatch(new ReplaceAction("/login"));
+ },
+ toggleMainMenu: (value: boolean, value2: boolean) => {
+ dispatcher.dispatch(new MenuAction(value));
+ dispatcher.dispatch(new MenuClosedByUser(value2))
+ }
+ }
+};
+
+type TitleBarProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<undefined, typeof mapDispatch>
+
+class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLElement | null }> {
+
+ constructor(props: TitleBarProps) {
+ super(props);
+ this.state = {
+ anchorEl: null
+ }
+
+ }
+ render(): JSX.Element {
+ const { classes, state, history, location } = this.props;
+ const open = !!this.state.anchorEl;
+ let toolbarElements: Array<JSX.Element>;
+ toolbarElements = [];
+
+ // create notificationInfo element
+ const notificationInfo = state.framework.applicationState.isWebsocketAvailable != undefined ?
+ (state.framework.applicationState.isWebsocketAvailable ?
+ <Typography variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.connected} icon={faDotCircle} /> |</Typography> : <Typography variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.notConnected} icon={faBan} /> |</Typography>)
+ : <Typography variant="body1" className={classes.notificationInfo}>Notifications N/A |</Typography>;
+
+
+ // add notificationInfo element before help
+ if (state.framework.applicationRegistraion) {
+ let isNotificationInfoAdded = false;
+ Object.keys(state.framework.applicationRegistraion).map(key => {
+ const reg = state.framework.applicationRegistraion[key];
+ if (reg && reg.statusBarElement) {
+ if (key === "help") {
+ isNotificationInfoAdded = true;
+ toolbarElements.push(notificationInfo);
+ }
+ toolbarElements.push(<reg.statusBarElement key={key} />);
+ }
+ });
+
+ // add notificationInfo in case help wasn't found
+ if (!isNotificationInfoAdded) {
+ toolbarElements.push(notificationInfo);
+ }
+ }
+
+ return (
+ <AppBar position="absolute" className={classes.appBar}>
+ <Toolbar>
+ <IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleMainMenu}>
+ <MenuIcon />
+ </IconButton>
+ <Logo />
+ <Typography variant="h6" color="inherit" >
+ {state.framework.applicationState.icon
+ ? (<FontAwesomeIcon className={classes.icon} icon={state.framework.applicationState.icon} />)
+ : null}
+ {state.framework.applicationState.title}
+ </Typography>
+ <div className={classes.grow}></div>
+ {
+ // render toolbar
+ toolbarElements.map((item) => {
+ return item
+ })
+ }
+
+ {state.framework.authenticationState.user
+ ? (<div>
+ <Button aria-label="current user menu button"
+ aria-owns={open ? 'menu-appbar' : undefined}
+ aria-haspopup="true"
+ onClick={this.openMenu}
+ color="inherit"
+ >
+ <AccountCircle />
+ {state.framework.authenticationState.user.user}
+ </Button>
+ <Menu
+ id="menu-appbar"
+ anchorEl={this.state.anchorEl}
+ anchorOrigin={{
+ vertical: 'top',
+ horizontal: 'right',
+ }}
+ transformOrigin={{
+ vertical: 'top',
+ horizontal: 'right',
+ }}
+ open={open}
+ onClose={this.closeMenu}
+ >
+ {/* <MenuItem onClick={ this.closeMenu }>Profile</MenuItem> */}
+ <MenuItem onClick={() => {
+ this.props.logout();
+ this.closeMenu();
+ }}>Logout</MenuItem>
+ </Menu>
+ </div>)
+ : (<Button onClick={() => { history.push('/login') }} color="inherit" disabled={location.pathname == "/login"}>Login</Button>)}
+ </Toolbar>
+ </AppBar>
+ );
+ };
+
+ private toggleMainMenu = (event: React.MouseEvent<HTMLElement>) => {
+ console.log(this.props);
+ if (this.props.state.framework.authenticationState.user && this.props.state.framework.authenticationState.user.isValid) {
+ const isMainMenuOpen = this.props.state.framework.applicationState.isMenuOpen
+ const isClosedByUser = this.props.state.framework.applicationState.isMenuClosedByUser
+ this.props.toggleMainMenu(!isMainMenuOpen, !isClosedByUser);
+ }
+ }
+
+ private openMenu = (event: React.MouseEvent<HTMLElement>) => {
+ this.setState({ anchorEl: event.currentTarget });
+ };
+
+ private closeMenu = () => {
+ this.setState({ anchorEl: null });
+ };
+}
+
+//todo: ggf. https://github.com/acdlite/recompose verwenden zur Vereinfachung
+
+export const TitleBar = withStyles(styles)(withRouter(connect(undefined, mapDispatch)(TitleBarComponent)));
+export default TitleBar; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/design/default.ts b/sdnr/wt/odlux/framework/src/design/default.ts
new file mode 100644
index 000000000..542c436f6
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/design/default.ts
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+/******************************************************************************
+ * Copyright 2018 highstreet technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *****************************************************************************/
+
+import { createMuiTheme } from '@material-ui/core/styles';
+
+const theme = createMuiTheme({
+ design: {
+ id: "onap",
+ name: "Open Networking Automation Plattform (ONAP)",
+ url: "https://www.onap.org/wp-content/uploads/sites/20/2017/02/logo_onap_2017.png",
+ height: 49,
+ width: 229,
+ logoHeight: 32,
+ },
+ palette: {
+ primary: {
+ light: "#eeeeee",
+ main: "#ffffff",
+ dark: "#e0e0e0",
+ contrastText: "#07819B"
+ },
+ secondary: {
+ light: "rgba(7, 129, 155, 94)",
+ main: "rgba(7, 129, 155, 201)",
+ dark: "#07819B",
+ contrastText: "#ffffff"
+ },
+ },
+ overrides: { //temp fix for labels turning white after material new version (palette primary color)
+ MuiFormLabel: {
+ root: {
+ "&$focused": {
+ color: "rgba(143,143,143,1)"
+ }
+ },
+
+ focused: {}
+ },
+ MuiInput: {
+ underline: {
+
+ "&:after": {
+ borderBottom: "2px solid #444444"
+ }
+ }
+ }
+ },
+});
+
+export default theme; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/favicon.ico b/sdnr/wt/odlux/framework/src/favicon.ico
new file mode 100644
index 000000000..a8a5d31ca
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/favicon.ico
Binary files differ
diff --git a/sdnr/wt/odlux/framework/src/flux/action.ts b/sdnr/wt/odlux/framework/src/flux/action.ts
new file mode 100644
index 000000000..76890257e
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/flux/action.ts
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * Represents an action in the odlux flux architecture.
+ */
+export abstract class Action { }
+
+export interface IActionHandler<TState, TAction extends Action = Action> {
+ (state: TState | undefined, action: TAction): TState;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/flux/connect.ts b/sdnr/wt/odlux/framework/src/flux/connect.ts
new file mode 100644
index 000000000..f54e4e0f0
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/flux/connect.ts
@@ -0,0 +1,161 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import * as PropTypes from 'prop-types';
+
+import { Dispatch } from '../flux/store';
+
+import { ApplicationStore, IApplicationStoreState } from '../store/applicationStore';
+
+interface IApplicationStoreContext {
+ applicationStore: ApplicationStore;
+}
+
+export interface IDispatcher {
+ dispatch: Dispatch;
+}
+
+interface IApplicationStoreProps {
+ state: IApplicationStoreState;
+}
+
+interface IDispatchProps {
+ dispatch: Dispatch;
+}
+
+type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
+
+type ComponentDecoratorInfer<TMergedProps> = {
+ <TProps>(wrappedComponent: React.ComponentType<TProps & TMergedProps>): React.ComponentClass<Omit<TProps & TMergedProps, keyof TMergedProps>>;
+};
+
+export type Connect<TMapProps extends ((...args: any) => any) | undefined = undefined, TMapDispatch extends ((...args: any) => any) | undefined = undefined> =
+ (TMapProps extends ((...args: any) => any) ? ReturnType<TMapProps> : IApplicationStoreProps) &
+ (TMapDispatch extends ((...args: any) => any) ? ReturnType<TMapDispatch> : IDispatchProps);
+
+export function connect(): ComponentDecoratorInfer<IApplicationStoreProps & IDispatchProps>;
+
+export function connect<TStateProps>(
+ mapStateToProps: (state: IApplicationStoreState) => TStateProps
+): ComponentDecoratorInfer<TStateProps & IDispatchProps>;
+
+export function connect<TStateProps, TDispatchProps>(
+ mapStateToProps: (state: IApplicationStoreState) => TStateProps,
+ mapDispatchToProps: (dispatcher: IDispatcher) => TDispatchProps
+): ComponentDecoratorInfer<TStateProps & TDispatchProps>;
+
+
+export function connect<TDispatchProps>(
+ mapStateToProps: undefined,
+ mapDispatchToProps: (dispatcher: IDispatcher) => TDispatchProps
+): ComponentDecoratorInfer<IApplicationStoreProps & TDispatchProps>;
+
+
+export function connect<TProps, TStateProps, TDispatchProps>(
+ mapStateToProps?: ((state: IApplicationStoreState) => TStateProps),
+ mapDispatchToProps?: ((dispatcher: IDispatcher) => TDispatchProps)
+):
+ ((WrappedComponent: React.ComponentType<TProps & (IApplicationStoreProps | TStateProps) & IDispatchProps>) => React.ComponentType<TProps>) {
+
+ const injectApplicationStore = (WrappedComponent: React.ComponentType<TProps & (IApplicationStoreProps | TStateProps) & IDispatchProps>): React.ComponentType<TProps> => {
+
+ class StoreAdapter extends React.Component<TProps, {}> {
+ public static contextTypes = { ...WrappedComponent.contextTypes, applicationStore: PropTypes.object.isRequired };
+ context: IApplicationStoreContext;
+
+ render(): JSX.Element {
+
+ if (isWrappedComponentIsVersion1(WrappedComponent)) {
+ const element = React.createElement(WrappedComponent, { ...(this.props as any), state: this.store.state, dispatch: this.store.dispatch.bind(this.store) });
+ return element;
+ } else if (mapStateToProps && isWrappedComponentIsVersion2(WrappedComponent)) {
+ const element = React.createElement(WrappedComponent, { ...(this.props as any), ...(mapStateToProps(this.store.state) as any), dispatch: this.store.dispatch.bind(this.store) });
+ return element;
+ } else if (mapStateToProps && mapDispatchToProps && isWrappedComponentIsVersion3(WrappedComponent)) {
+ const element = React.createElement(WrappedComponent, { ...(this.props as any), ...(mapStateToProps(this.store.state) as any), ...(mapDispatchToProps({ dispatch: this.store.dispatch.bind(this.store) }) as any) });
+ return element;
+ } else if (!mapStateToProps && mapDispatchToProps && isWrappedComponentIsVersion4(WrappedComponent)) {
+ const element = React.createElement(WrappedComponent, { ...(this.props as any), state: this.store.state, ...(mapDispatchToProps({ dispatch: this.store.dispatch.bind(this.store) }) as any) });
+ return element;
+ }
+ throw new Error("Invalid arguments in connect.");
+ }
+
+ componentDidMount(): void {
+ this.store && this.store.changed.addHandler(this.handleStoreChanged);
+ }
+
+ componentWillUnmount(): void {
+ this.store && this.store.changed.removeHandler(this.handleStoreChanged);
+ }
+
+ private get store(): ApplicationStore {
+ return this.context.applicationStore;
+ }
+
+ private handleStoreChanged = () => {
+ this.forceUpdate();
+ }
+ }
+
+ return StoreAdapter;
+ }
+
+
+ return injectApplicationStore;
+
+ /* inline methods */
+
+ function isWrappedComponentIsVersion1(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & IApplicationStoreProps & IDispatchProps> {
+ return !mapStateToProps && !mapDispatchToProps;
+ }
+
+ function isWrappedComponentIsVersion2(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & IDispatchProps> {
+ return !!mapStateToProps && !mapDispatchToProps;
+ }
+
+ function isWrappedComponentIsVersion3(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & TDispatchProps> {
+ return !!mapStateToProps && !!mapDispatchToProps;
+ }
+
+ function isWrappedComponentIsVersion4(wrappedComponent: any): wrappedComponent is React.ComponentType<TProps & TStateProps & TDispatchProps> {
+ return !mapStateToProps && !!mapDispatchToProps;
+ }
+}
+
+interface ApplicationStoreProviderProps extends React.Props<ApplicationStoreProvider> {
+ applicationStore: ApplicationStore;
+}
+
+export class ApplicationStoreProvider extends React.Component<ApplicationStoreProviderProps>
+ implements /* React.ComponentLifecycle<ApplicationStoreProviderProps, any>, */ React.ChildContextProvider<IApplicationStoreContext> {
+
+ public static childContextTypes = { applicationStore: PropTypes.object.isRequired };
+
+ getChildContext(): IApplicationStoreContext {
+ return {
+ applicationStore: this.props.applicationStore
+ };
+ }
+
+ render(): JSX.Element {
+ return React.Children.only(this.props.children) as any; //type error, fix when possible
+ }
+}
+
+export default connect; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/flux/middleware.ts b/sdnr/wt/odlux/framework/src/flux/middleware.ts
new file mode 100644
index 000000000..de6505c4f
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/flux/middleware.ts
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from './action';
+import { Store, Dispatch, Enhancer } from './store';
+
+export interface MiddlewareArg<T> {
+ dispatch: Dispatch;
+ getState: () => T;
+}
+
+export interface Middleware<T> {
+ (obj: MiddlewareArg<T>): Function;
+}
+
+class InitialisationAction extends Action { };
+const initialisationAction = new InitialisationAction();
+
+export type ActionHandlerMapObject<S extends { [key: string]: any }, A extends Action = Action> = {
+ [K in keyof S]: IActionHandler<S[K], A>
+}
+
+export const combineActionHandler = <TState extends { [key: string]: any }, TAction extends Action = Action>(actionHandlers: ActionHandlerMapObject<TState, TAction>) : IActionHandler<TState, TAction> => {
+ const finalActionHandlers = {} as { [key: string]: any }; // https://github.com/microsoft/TypeScript/issues/31808
+ Object.keys(actionHandlers).forEach(actionHandlerKey => {
+ const handler = actionHandlers[actionHandlerKey];
+ if (typeof handler === 'function') {
+ finalActionHandlers[actionHandlerKey] = handler;
+ }
+ });
+
+ // ensure initialisation
+ Object.keys(finalActionHandlers).forEach(key => {
+ const actionHandler = finalActionHandlers[key];
+ const initialState = actionHandler(undefined, initialisationAction);
+ if (typeof initialState === 'undefined') {
+ const errorMessage = `Action handler ${ key } returned undefiend during initialization.`;
+ throw new Error(errorMessage);
+ }
+ });
+
+ return function combination<TAction extends Action>(state: TState = ({} as TState), action: TAction) {
+ let hasChanged = false;
+ const nextState = {} as { [key: string]: any }; // https://github.com/microsoft/TypeScript/issues/31808
+ Object.keys(finalActionHandlers).forEach(key => {
+ const actionHandler = finalActionHandlers[key];
+ const previousState = state[key];
+ const nextStateKey = actionHandler(previousState, action);
+ if (typeof nextStateKey === 'undefined') {
+ const errorMessage = `Given ${ action.constructor } and action handler ${ key } returned undefiend.`;
+ throw new Error(errorMessage);
+ }
+ nextState[key] = nextStateKey;
+ hasChanged = hasChanged || nextStateKey !== previousState;
+ });
+ return (hasChanged ? nextState : state) as TState;
+ };
+};
+
+export const chainMiddleware = <TStoreState>(...middlewares: Middleware<TStoreState>[]): Enhancer<TStoreState> => {
+ return (store: Store<TStoreState>) => {
+ const middlewareAPI = {
+ getState() { return store.state },
+ dispatch: <TAction extends Action>(action: TAction) => store.dispatch(action) // we want to use the combinded dispatch
+ // we should NOT use the flux dispatcher here, since the action would affect ALL stores
+ };
+ const chain = middlewares.map(middleware => middleware(middlewareAPI));
+ return compose(...chain)(store.dispatch) as Dispatch;
+ }
+};
+
+/**
+ * Composes single-argument functions from right to left. The rightmost
+ * function can take multiple arguments as it provides the signature for
+ * the resulting composite function.
+ *
+ * @param {...Function} funcs The functions to compose.
+ * @returns {Function} A function obtained by composing the argument functions
+ * from right to left. For example, compose(f, g, h) is identical to doing
+ * (...args) => f(g(h(...args))).
+ */
+const compose = (...funcs: Function[]) => {
+ if (funcs.length === 0) {
+ return (arg: any) => arg
+ }
+
+ if (funcs.length === 1) {
+ return funcs[0]
+ }
+
+ return funcs.reduce((a, b) => (...args: any[]) => a(b(...args)));
+};
+
diff --git a/sdnr/wt/odlux/framework/src/flux/store.ts b/sdnr/wt/odlux/framework/src/flux/store.ts
new file mode 100644
index 000000000..dd80ce7ba
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/flux/store.ts
@@ -0,0 +1,98 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Event } from "../common/event"
+
+import { Action } from './action';
+import { IActionHandler } from './action';
+
+export interface Dispatch {
+ <TAction extends Action>(action: TAction): TAction;
+}
+
+export interface Enhancer<TStoreState> {
+ (store: Store<TStoreState>): Dispatch;
+}
+
+class InitialisationAction extends Action { };
+const initialisationAction = new InitialisationAction();
+
+export class Store<TStoreState> {
+
+ constructor(actionHandler: IActionHandler<TStoreState>, enhancer?: Enhancer<TStoreState>)
+ constructor(actionHandler: IActionHandler<TStoreState>, initialState: TStoreState, enhancer?: Enhancer<TStoreState>)
+ constructor(actionHandler: IActionHandler<TStoreState>, initialState?: TStoreState | Enhancer<TStoreState>, enhancer?: Enhancer<TStoreState>) {
+ if (typeof initialState === 'function') {
+ enhancer = initialState as Enhancer<TStoreState>;
+ initialState = undefined;
+ }
+
+ this._isDispatching = false;
+
+ this.changed = new Event<void>(); // sollten wir hier eventuell sogar den state mit übergeben ?
+
+ this._actionHandler = actionHandler;
+
+ this._state = initialState as TStoreState;
+ if (enhancer) this._dispatch = enhancer(this);
+
+ this._dispatch(initialisationAction);
+ }
+
+ public changed: Event<void>;
+
+ private _dispatch: Dispatch = <TAction extends Action>(payload: TAction): TAction => {
+ if (payload == null || !(payload instanceof Action)) {
+ throw new Error(
+ 'Actions must inherit from type Action. ' +
+ 'Use a custom middleware for async actions.'
+ );
+ }
+
+ if (this._isDispatching) {
+ throw new Error('ActionHandler may not dispatch actions.');
+ }
+
+ const oldState = this._state;
+ try {
+ this._isDispatching = true;
+ this._state = this._actionHandler(oldState, payload);
+ } finally {
+ this._isDispatching = false;
+ }
+
+ if (this._state !== oldState) {
+ this.changed.invoke();
+ }
+
+ return payload;
+ }
+
+ public get dispatch(): Dispatch {
+ return this._dispatch;
+ }
+
+ public get state() {
+ return this._state
+ }
+
+ private _state: TStoreState;
+ private _isDispatching: boolean;
+ private _actionHandler: IActionHandler<TStoreState>;
+
+}
+
diff --git a/sdnr/wt/odlux/framework/src/handlers/applicationRegistryHandler.ts b/sdnr/wt/odlux/framework/src/handlers/applicationRegistryHandler.ts
new file mode 100644
index 000000000..ec7b0a04a
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/handlers/applicationRegistryHandler.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+
+import { ApplicationInfo } from '../models/applicationInfo';
+import { applicationManager } from '../services/applicationManager';
+
+export interface IApplicationRegistration {
+ [name: string]: ApplicationInfo;
+}
+
+const applicationRegistrationInit: IApplicationRegistration = applicationManager.applications;
+
+export const applicationRegistryHandler: IActionHandler<IApplicationRegistration> = (state = applicationRegistrationInit, action) => {
+ return state;
+};
diff --git a/sdnr/wt/odlux/framework/src/handlers/applicationStateHandler.ts b/sdnr/wt/odlux/framework/src/handlers/applicationStateHandler.ts
new file mode 100644
index 000000000..a93f96a82
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/handlers/applicationStateHandler.ts
@@ -0,0 +1,108 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+import { SetTitleAction } from '../actions/titleActions';
+
+import { AddSnackbarNotification, RemoveSnackbarNotification } from '../actions/snackbarActions';
+import { AddErrorInfoAction, RemoveErrorInfoAction, ClearErrorInfoAction } from '../actions/errorActions';
+import { MenuAction, MenuClosedByUser } from '../actions/menuAction'
+import { IconType } from '../models/iconDefinition';
+
+import { ErrorInfo } from '../models/errorInfo';
+import { SnackbarItem } from '../models/snackbarItem';
+import { SetWebsocketAction } from '../actions/websocketAction';
+
+export interface IApplicationState {
+ title: string;
+ appId?: string;
+ icon?: IconType;
+ isMenuOpen: boolean;
+ isMenuClosedByUser: boolean;
+ errors: ErrorInfo[];
+ snackBars: SnackbarItem[];
+ isWebsocketAvailable: boolean | undefined;
+}
+
+const applicationStateInit: IApplicationState = { title: "Loading ...", errors: [], snackBars: [], isMenuOpen: true, isMenuClosedByUser: false, isWebsocketAvailable: undefined };
+
+export const applicationStateHandler: IActionHandler<IApplicationState> = (state = applicationStateInit, action) => {
+ if (action instanceof SetTitleAction) {
+ state = {
+ ...state,
+ title: action.title,
+ icon: action.icon,
+ appId: action.appId
+ };
+ } else if (action instanceof AddErrorInfoAction) {
+ state = {
+ ...state,
+ errors: [
+ ...state.errors,
+ action.errorInfo
+ ]
+ };
+ } else if (action instanceof RemoveErrorInfoAction) {
+ const index = state.errors.indexOf(action.errorInfo);
+ if (index > -1) {
+ state = {
+ ...state,
+ errors: [
+ ...state.errors.slice(0, index),
+ ...state.errors.slice(index + 1)
+ ]
+ };
+ }
+ } else if (action instanceof ClearErrorInfoAction) {
+ if (state.errors && state.errors.length) {
+ state = {
+ ...state,
+ errors: []
+ };
+ }
+ } else if (action instanceof AddSnackbarNotification) {
+ state = {
+ ...state,
+ snackBars: [
+ ...state.snackBars,
+ action.notification
+ ]
+ };
+ } else if (action instanceof RemoveSnackbarNotification) {
+ state = {
+ ...state,
+ snackBars: state.snackBars.filter(s => s.key !== action.key)
+ };
+ } else if (action instanceof MenuAction) {
+ state = {
+ ...state,
+ isMenuOpen: action.isOpen
+ }
+ } else if (action instanceof MenuClosedByUser) {
+ state = {
+ ...state,
+ isMenuClosedByUser: action.isClosed
+ }
+ }
+ else if (action instanceof SetWebsocketAction) {
+ state = {
+ ...state,
+ isWebsocketAvailable: action.isConnected
+ }
+ }
+ return state;
+};
diff --git a/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts b/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts
new file mode 100644
index 000000000..82b228dc0
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+import { UpdateAuthentication } from '../actions/authentication';
+
+import { User } from '../models/authentication';
+
+import { onLogin, onLogout } from '../services/applicationApi';
+import { startWebsocketSession, endWebsocketSession } from '../services/notificationService';
+
+export interface IAuthenticationState {
+ user?: User;
+}
+
+const initialToken = localStorage.getItem("userToken");
+
+if (initialToken !== null) {
+ startWebsocketSession();
+}
+
+const authenticationStateInit: IAuthenticationState = {
+ user: initialToken && User.fromString(initialToken) || undefined
+};
+
+export const authenticationStateHandler: IActionHandler<IAuthenticationState> = (state = authenticationStateInit, action) => {
+ if (action instanceof UpdateAuthentication) {
+
+ const user = action.bearerToken && new User(action.bearerToken) || undefined;
+ if (user) {
+ localStorage.setItem("userToken", user.toString());
+ startWebsocketSession();
+ onLogin();
+ } else {
+ localStorage.removeItem("userToken");
+ endWebsocketSession();
+ onLogout();
+ }
+
+ state = {
+ ...state,
+ user
+ };
+ }
+
+ return state;
+};
diff --git a/sdnr/wt/odlux/framework/src/handlers/navigationStateHandler.ts b/sdnr/wt/odlux/framework/src/handlers/navigationStateHandler.ts
new file mode 100644
index 000000000..6ecdf2f79
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/handlers/navigationStateHandler.ts
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { IActionHandler } from '../flux/action';
+import { LocationChanged } from '../actions/navigationActions';
+
+
+export interface INavigationState {
+ pathname: string;
+ search: string;
+ hash: string;
+}
+
+const navigationStateInit: INavigationState = {
+ pathname: '/',
+ search: '',
+ hash: '',
+};
+
+
+export const navigationStateHandler: IActionHandler<INavigationState> = (state = navigationStateInit, action) => {
+ if (action instanceof LocationChanged) {
+ state = {
+ ...state,
+ pathname: action.pathname,
+ search: action.search,
+ hash: action.hash
+ }
+ }
+ return state;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/index.dev.html b/sdnr/wt/odlux/framework/src/index.dev.html
new file mode 100644
index 000000000..71cb7408d
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/index.dev.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["app" /*,"connectApp","inventoryApp","faultApp","helpApp"*/], function (app,connectApp,inventoryApp,faultApp,helpApp) {
+ // connectApp.register();
+ // inventoryApp.register();
+ // faultApp.register();
+ // helpApp.register();
+ app("./app.tsx").runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/index.html b/sdnr/wt/odlux/framework/src/index.html
new file mode 100644
index 000000000..1a373392d
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
+ <!-- <link rel="stylesheet" href="./vendor.css" > -->
+ <title>O D L UX</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <script type="text/javascript" src="./require.js"></script>
+ <script type="text/javascript" src="./config.js"></script>
+ <script>
+ // run the application
+ require(["run"], function (run) {
+ run.runApplication();
+ });
+ </script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/middleware/api.ts b/sdnr/wt/odlux/framework/src/middleware/api.ts
new file mode 100644
index 000000000..8e9bc6459
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/middleware/api.ts
@@ -0,0 +1,72 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Action, IActionHandler } from '../flux/action';
+import { MiddlewareArg } from '../flux/middleware';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { AddErrorInfoAction, ErrorInfo } from '../actions/errorActions';
+
+const baseUrl = `${ window.location.origin }${ window.location.pathname }`;
+
+export class ApiAction<TResult, TSuccessAction extends Action & { result: TResult }> extends Action {
+ constructor(public endpoint: string, public successAction: { new(result: TResult): TSuccessAction }, public authenticate: boolean = false) {
+ super();
+ }
+}
+
+export const apiMiddleware = (store: MiddlewareArg<IApplicationStoreState>) => (next: Dispatch) => <A extends Action>(action: A) => {
+
+ // So the middleware doesn't get applied to every single action
+ if (action instanceof ApiAction) {
+ const user = store && store.getState().framework.authenticationState.user;
+ const token = user && user.token || null;
+ let config = { headers: {} };
+
+ if (action.authenticate) {
+ if (token) {
+ config = {
+ ...config,
+ headers: {
+ ...config.headers,
+ // 'Authorization': `Bearer ${ token }`
+ authorization: "Basic YWRtaW46YWRtaW4="
+ }
+ }
+ } else {
+ return next(new AddErrorInfoAction({ message: 'Please login to continue.' }));
+ }
+ }
+
+ fetch(baseUrl + action.endpoint.replace(/\/{2,}/, '/'), config)
+ .then(response =>
+ response.json().then(data => ({ data, response }))
+ )
+ .then(result => {
+ next(new action.successAction(result.data));
+ })
+ .catch((error: any) => {
+ next(new AddErrorInfoAction((error instanceof Error) ? { error: error } : { message: error.toString() }));
+ });
+ }
+
+ // let all actions pass
+ return next(action);
+}
+
+export default apiMiddleware; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/middleware/logger.ts b/sdnr/wt/odlux/framework/src/middleware/logger.ts
new file mode 100644
index 000000000..47725e696
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/middleware/logger.ts
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Dispatch } from '../flux/store';
+import { MiddlewareApi } from '../store/applicationStore';
+
+
+function createLoggerMiddleware() {
+ return function logger({ getState }: MiddlewareApi) {
+ return (next: Dispatch): Dispatch => action => {
+ console.log('will dispatch', action);
+ const returnValue = next(action);
+ console.log('state after dispatch', getState());
+ return returnValue;
+ };
+ }
+}
+
+export const logger = createLoggerMiddleware();
+export default logger; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/middleware/navigation.ts b/sdnr/wt/odlux/framework/src/middleware/navigation.ts
new file mode 100644
index 000000000..d5cdcd44b
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/middleware/navigation.ts
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Location, History, createHashHistory } from "history";
+
+import { ApplicationStore } from "../store/applicationStore";
+import { Dispatch } from '../flux/store';
+
+import { LocationChanged, NavigateToApplication } from "../actions/navigationActions";
+import { PushAction, ReplaceAction, GoAction, GoBackAction, GoForwardeAction } from '../actions/navigationActions';
+
+import { applicationManager } from "../services/applicationManager";
+
+const routerMiddlewareCreator = (history: History) => () => (next: Dispatch): Dispatch => (action) => {
+
+ if (action instanceof NavigateToApplication) {
+ const application = applicationManager.applications && applicationManager.applications[action.applicationName];
+ if (application) {
+ const href = `/${application.path || application.name}${action.href ? '/' + action.href : ''}`.replace(/\/{2,}/i, '/');
+ if (action.replace) {
+ history.replace(href, action.state);
+ } else {
+ history.push(href, action.state);
+ }
+ }
+ } else if (action instanceof PushAction) {
+ history.push(action.href, action.state);
+ } else if (action instanceof ReplaceAction) {
+ history.replace(action.href, action.state);
+ } else if (action instanceof GoAction) {
+ history.go(action.index);
+ } else if (action instanceof GoBackAction) {
+ history.goBack();
+ } else if (action instanceof GoForwardeAction) {
+ history.goForward();
+ } else if (action instanceof LocationChanged) {
+ // ensure user is logged in and token is valid
+ if (!action.pathname.startsWith("/login") && applicationStore && (!applicationStore.state.framework.authenticationState.user || !applicationStore.state.framework.authenticationState.user.isValid)) {
+ history.replace(`/login?returnTo=${action.pathname}`);
+ } else {
+ return next(action);
+ }
+ } else {
+ return next(action);
+ }
+ return action;
+};
+
+function startListener(history: History, store: ApplicationStore) {
+ store.dispatch(new LocationChanged(history.location.pathname, history.location.search, history.location.hash));
+ history.listen((location: Location) => {
+ store.dispatch(new LocationChanged(location.pathname, location.search, location.hash));
+ });
+}
+
+const history = createHashHistory();
+let applicationStore: ApplicationStore | null = null;
+
+export function startHistoryListener(store: ApplicationStore) {
+ applicationStore = store;
+ startListener(history, store);
+}
+
+export const routerMiddleware = routerMiddlewareCreator(history);
+export default routerMiddleware;
diff --git a/sdnr/wt/odlux/framework/src/middleware/thunk.ts b/sdnr/wt/odlux/framework/src/middleware/thunk.ts
new file mode 100644
index 000000000..18f40c4ca
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/middleware/thunk.ts
@@ -0,0 +1,35 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Dispatch } from '../flux/store';
+import { MiddlewareApi } from '../store/applicationStore';
+
+function createThunkMiddleware() {
+ return ({ dispatch, getState }: MiddlewareApi) =>
+ (next : Dispatch) : Dispatch =>
+ action => {
+ if (typeof action === 'function') {
+ return action(dispatch, getState);
+ }
+
+ return next(action);
+ };
+}
+
+export const thunk = createThunkMiddleware();
+export default thunk; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/models/applicationInfo.ts b/sdnr/wt/odlux/framework/src/models/applicationInfo.ts
new file mode 100644
index 000000000..0b33777dc
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/applicationInfo.ts
@@ -0,0 +1,52 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ComponentType } from 'react';
+import { IconType } from './iconDefinition';
+
+import { IActionHandler } from '../flux/action';
+import { Middleware } from '../flux/middleware';
+
+/** Represents the information needed about an application to integrate. */
+export class ApplicationInfo {
+ /** The name of the application. */
+ name: string;
+ /** Optional: The title of the application, if null ot undefined the name will be used. */
+ title?: string;
+ /** Optional: The icon of the application for the navigation and title bar. */
+ icon?: IconType;
+ /** Optional: The description of the application. */
+ description?: string;
+ /** The root component of the application. */
+ rootComponent: ComponentType;
+ /** Optional: The root action handler of the application. */
+ rootActionHandler?: IActionHandler<{ [key: string]: any }>;
+ /** Optional: Application speciffic middlewares. */
+ middlewares?: Middleware<{ [key: string]: any }>[];
+ /** Optional: A mapping object with the exported components. */
+ exportedComponents?: { [key: string]: ComponentType }
+ /** Optional: The entry to be shown in the menu. If undefiened the name will be used. */
+ menuEntry?: string | React.ComponentType;
+ /** Optional: A component to be shown in the menu when this app is active below the main entry. If undefiened the name will be used. */
+ subMenuEntry?: React.ComponentType;
+ /** Optional: A component to be shown in the applications status bar. If undefiened the name will be used. */
+ statusBarElement?: React.ComponentType;
+ /** Optional: A component to be shown in the dashboardview. If undefiened the name will be used. */
+ dashbaordElement?: React.ComponentType;
+ /** Optional: The pasth for this application. If undefined the name will be use as path. */
+ path?: string;
+}
diff --git a/sdnr/wt/odlux/framework/src/models/authentication.ts b/sdnr/wt/odlux/framework/src/models/authentication.ts
new file mode 100644
index 000000000..a50c5ded4
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/authentication.ts
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type AuthToken = {
+ username: string;
+ access_token: string;
+ token_type: string;
+ expires: number;
+}
+
+
+export class User {
+
+ constructor (private _bearerToken: AuthToken) {
+
+ }
+
+ public get user(): string | null {
+ return this._bearerToken && this._bearerToken.username;
+ };
+
+ public get token(): string | null {
+ return this._bearerToken && this._bearerToken.access_token;
+ }
+
+ public get tokenType(): string | null {
+ return this._bearerToken && this._bearerToken.token_type;
+ }
+
+ public get isValid(): boolean {
+ return (this._bearerToken && (new Date().valueOf()) < this._bearerToken.expires) || false;
+ }
+
+ public toString() {
+ return JSON.stringify(this._bearerToken);
+ }
+
+ public static fromString(data: string) {
+ return new User(JSON.parse(data));
+ }
+
+
+}
diff --git a/sdnr/wt/odlux/framework/src/models/elasticSearch.ts b/sdnr/wt/odlux/framework/src/models/elasticSearch.ts
new file mode 100644
index 000000000..12cfd7d28
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/elasticSearch.ts
@@ -0,0 +1,56 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type Result<TSource extends {}> = {
+ output: {
+ pagination?: {
+ size: number,
+ page: number,
+ total: number
+ },
+ data: TSource[];
+ }
+}
+
+export type HitEntry<TSource extends {}> = {
+ _index: string;
+ _type: string;
+ _id: string;
+ _score: number;
+ _source: TSource;
+}
+
+type ActionResponse ={
+ _index: string;
+ _type: string;
+ _id: string;
+ _shards: {
+ total: number,
+ successful: number,
+ failed: number
+ },
+
+}
+
+export type PostResponse = ActionResponse & {
+ created: boolean
+}
+
+export type DeleteResponse = ActionResponse & {
+ found: boolean
+}
+
diff --git a/sdnr/wt/odlux/framework/src/models/errorInfo.ts b/sdnr/wt/odlux/framework/src/models/errorInfo.ts
new file mode 100644
index 000000000..21217a108
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/errorInfo.ts
@@ -0,0 +1,29 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export type ErrorInfo = {
+ title?: string,
+ error?: Error | null,
+ url?: string,
+ line?: number,
+ col?: number,
+ info?: {
+ extra?: string,
+ componentStack?: string
+ },
+ message?: string
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/models/iconDefinition.ts b/sdnr/wt/odlux/framework/src/models/iconDefinition.ts
new file mode 100644
index 000000000..e93d20ee3
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/iconDefinition.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
+
+export type IconType = IconDefinition; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/models/index.ts b/sdnr/wt/odlux/framework/src/models/index.ts
new file mode 100644
index 000000000..4b8dc20aa
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/index.ts
@@ -0,0 +1,18 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export * from './elasticSearch'; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/models/restService.ts b/sdnr/wt/odlux/framework/src/models/restService.ts
new file mode 100644
index 000000000..03f580b01
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/restService.ts
@@ -0,0 +1,48 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+/**
+ * The PlainObject type is a JavaScript object containing zero or more key-value pairs.
+ */
+export interface PlainObject<T = any> {
+ [key: string]: T;
+}
+
+export interface AjaxParameter {
+ /**
+ * The HTTP method to use for the request (e.g. "POST", "GET", "PUT").
+ */
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH';
+ /**
+ * An object of additional header key/value pairs to send along with requests using the XMLHttpRequest
+ * transport. The header X-Requested-With: XMLHttpRequest is always added, but its default
+ * XMLHttpRequest value can be changed here. Values in the headers setting can also be overwritten from
+ * within the beforeSend function.
+ */
+ headers?: PlainObject<string | null | undefined>;
+ /**
+ * Data to be sent to the server. It is converted to a query string, if not already a string. It's
+ * appended to the url for GET-requests. See processData option to prevent this automatic processing.
+ * Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same
+ * key based on the value of the traditional setting (described below).
+ */
+ data?: PlainObject | string;
+}
+
+
+
diff --git a/sdnr/wt/odlux/framework/src/models/snackbarItem.ts b/sdnr/wt/odlux/framework/src/models/snackbarItem.ts
new file mode 100644
index 000000000..c10d7ef37
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/models/snackbarItem.ts
@@ -0,0 +1,20 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { OptionsObject } from "notistack";
+
+export type SnackbarItem = { key: number, message: string, options?: OptionsObject }; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/run.ts b/sdnr/wt/odlux/framework/src/run.ts
new file mode 100644
index 000000000..10692e8d6
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/run.ts
@@ -0,0 +1,18 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { runApplication } from './app';
diff --git a/sdnr/wt/odlux/framework/src/services/applicationApi.ts b/sdnr/wt/odlux/framework/src/services/applicationApi.ts
new file mode 100644
index 000000000..77287f497
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/applicationApi.ts
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { Event } from '../common/event';
+import { ApplicationStore } from '../store/applicationStore';
+
+let resolveApplicationStoreInitialized: (store: ApplicationStore) => void;
+let applicationStore: ApplicationStore | null = null;
+const applicationStoreInitialized: Promise<ApplicationStore> = new Promise((resolve) => resolveApplicationStoreInitialized = resolve);
+
+const loginEvent = new Event();
+const logoutEvent = new Event();
+
+export const onLogin = () => {
+ loginEvent.invoke();
+}
+
+export const onLogout = () => {
+ logoutEvent.invoke();
+}
+
+export const setApplicationStore = (store: ApplicationStore) => {
+ if (!applicationStore && store) {
+ applicationStore = store;
+ resolveApplicationStoreInitialized(store);
+ }
+}
+
+export const applicationApi = {
+ get applicationStore(): ApplicationStore | null {
+ return applicationStore;
+ },
+
+ get applicationStoreInitialized(): Promise<ApplicationStore> {
+ return applicationStoreInitialized;
+ },
+
+ get loginEvent() {
+ return loginEvent;
+ },
+
+ get logoutEvent() {
+ return logoutEvent;
+ }
+};
+
+export default applicationApi; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/services/applicationManager.ts b/sdnr/wt/odlux/framework/src/services/applicationManager.ts
new file mode 100644
index 000000000..14e3ed0b2
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/applicationManager.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationInfo } from '../models/applicationInfo';
+import { Event } from '../common/event';
+
+import { applicationApi } from './applicationApi';
+
+/** Represents registry to manage all applications. */
+class ApplicationManager {
+
+ /** Stores all registerd applications. */
+ private _applications: { [key: string]: ApplicationInfo };
+
+ /** Initializes a new instance of this class. */
+ constructor() {
+ this._applications = {};
+ this.changed = new Event<void>();
+ }
+
+ /** The chaged event will fire if the registration has changed. */
+ public changed: Event<void>;
+
+ /** Registers a new application. */
+ public registerApplication(applicationInfo: ApplicationInfo) {
+ this._applications[applicationInfo.name] = applicationInfo;
+ this.changed.invoke();
+ return applicationApi;
+ }
+
+ /** Gets all registered applications. */
+ public get applications() {
+ return this._applications;
+ }
+}
+
+/** A singleton instance of the application manager. */
+export const applicationManager = new ApplicationManager();
+export default applicationManager; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/services/authenticationService.ts b/sdnr/wt/odlux/framework/src/services/authenticationService.ts
new file mode 100644
index 000000000..d3d62c566
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/authenticationService.ts
@@ -0,0 +1,53 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest, formEncode } from "./restService";
+import { AuthToken } from "../models/authentication";
+
+type AuthTokenResponse = {
+ access_token: string;
+ token_type: string;
+ expires_in: number;
+}
+
+
+class AuthenticationService {
+ public async authenticateUser(email: string, password: string, scope: string): Promise<AuthToken | null> {
+ const result = await requestRest<string>(`oauth2/token`, {
+ method: "POST",
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ },
+ body: formEncode({
+ grant_type: "password",
+ username: email,
+ password: password,
+ scope: scope
+ })
+ }, false);
+ const resultObj: AuthTokenResponse| null = result && JSON.parse(result);
+ return resultObj && {
+ username: email,
+ access_token: resultObj.access_token,
+ token_type: resultObj.token_type,
+ expires: (new Date().valueOf()) + (resultObj.expires_in * 1000)
+ } || null;
+ }
+}
+
+export const authenticationService = new AuthenticationService();
+export default authenticationService; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/services/forceLogoutService.ts b/sdnr/wt/odlux/framework/src/services/forceLogoutService.ts
new file mode 100644
index 000000000..ce4faab6b
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/forceLogoutService.ts
@@ -0,0 +1,52 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { ApplicationStore } from "../store/applicationStore";
+import { UpdateAuthentication } from "../actions/authentication";
+import { ReplaceAction } from "../actions/navigationActions";
+
+const maxMinutesTillLogout = 15;
+let applicationStore: ApplicationStore | null;
+let tickTimer = 15;
+
+
+export const startForceLogoutService = (store: ApplicationStore) => {
+ applicationStore = store;
+ createForceLogoutInterval();
+};
+
+const createForceLogoutInterval = () => {
+ console.log("logout timer running...")
+
+ return setInterval(function () {
+ if (applicationStore && applicationStore.state.framework.authenticationState.user) {
+ tickTimer--;
+
+ if (tickTimer === 0) {
+ console.log("got logged out by timer")
+ if (applicationStore) {
+ applicationStore.dispatch(new UpdateAuthentication(null));
+ applicationStore.dispatch(new ReplaceAction("/login"));
+ }
+ }
+ }
+
+ }, 1 * 60000)
+}
+
+document.addEventListener("mousemove", function () { tickTimer = maxMinutesTillLogout; }, false) \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/services/index.ts b/sdnr/wt/odlux/framework/src/services/index.ts
new file mode 100644
index 000000000..c6071e7b8
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/index.ts
@@ -0,0 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+export { applicationManager } from './applicationManager';
+export { subscribe, unsubscribe } from './notificationService';
+export { requestRest } from './restService';
+
diff --git a/sdnr/wt/odlux/framework/src/services/notificationService.ts b/sdnr/wt/odlux/framework/src/services/notificationService.ts
new file mode 100644
index 000000000..85d3f716b
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/notificationService.ts
@@ -0,0 +1,190 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as X2JS from 'x2js';
+import { ApplicationStore } from '../store/applicationStore';
+import { SetWebsocketAction } from '../actions/websocketAction';
+
+const socketUrl = [location.protocol === 'https:' ? 'wss://' : 'ws://', 'admin', ':', 'admin', '@', location.hostname, ':', location.port, '/websocket'].join('');
+const subscriptions: { [scope: string]: SubscriptionCallback[] } = {};
+let socketReady: Promise<WebSocket>;
+let userLoggedOut = false;
+let wasWebsocketConnectionEstablished: undefined | boolean;
+let applicationStore: ApplicationStore | null;
+
+
+export interface IFormatedMessage {
+ notifType: string | null;
+ time: string;
+}
+
+export type SubscriptionCallback<TMessage extends IFormatedMessage = IFormatedMessage> = (msg: TMessage) => void;
+
+function formatData(event: MessageEvent): IFormatedMessage | undefined {
+
+ var x2js = new X2JS();
+ var jsonObj: { [key: string]: IFormatedMessage } = x2js.xml2js(event.data);
+ if (jsonObj && typeof (jsonObj) === 'object') {
+
+ const notifType = Object.keys(jsonObj)[0];
+ const formated = jsonObj[notifType];
+ formated.notifType = notifType;
+ formated.time = new Date().toISOString();
+ return formated;
+ }
+ return undefined;
+
+}
+
+export function subscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): boolean {
+ const scopes = scope instanceof Array ? scope : [scope];
+
+ // send all new scopes to subscribe
+ const newScopesToSubscribe: string[] = scopes.reduce((acc: string[], cur: string) => {
+ const currentCallbacks = subscriptions[cur];
+ if (currentCallbacks) {
+ if (!currentCallbacks.some(c => c === callback)) {
+ currentCallbacks.push(callback);
+ }
+ } else {
+ subscriptions[cur] = [callback];
+ acc.push(cur);
+ }
+ return acc;
+ }, []);
+
+ if (newScopesToSubscribe.length === 0) {
+ return true;
+ }
+
+ return true;
+}
+
+
+export function unsubscribe<TMessage extends IFormatedMessage = IFormatedMessage>(scope: string | string[], callback: SubscriptionCallback<TMessage>): Promise<boolean> {
+ return socketReady.then((notificationSocket) => {
+ const scopes = scope instanceof Array ? scope : [scope];
+ scopes.forEach(s => {
+ const callbacks = subscriptions[s];
+ const index = callbacks && callbacks.indexOf(callback);
+ if (index > -1) {
+ callbacks.splice(index, 1);
+ }
+ if (callbacks.length === 0) {
+ subscriptions[s] === undefined;
+ }
+ });
+
+ // send a subscription to all active scopes
+ const scopesToSubscribe = Object.keys(subscriptions);
+ if (notificationSocket.readyState === notificationSocket.OPEN) {
+ const data = {
+ 'data': 'scopes',
+ 'scopes': scopesToSubscribe
+ };
+ notificationSocket.send(JSON.stringify(data));
+ return true;
+ }
+ return false;
+ });
+}
+
+export const startNotificationService = (store: ApplicationStore) => {
+ applicationStore = store;
+}
+
+const connect = (): Promise<WebSocket> => {
+ return new Promise((resolve, reject) => {
+ const notificationSocket = new WebSocket(socketUrl);
+
+ notificationSocket.onmessage = (event) => {
+ // process received event
+ if (typeof event.data === 'string') {
+ const formated = formatData(event);
+ if (formated && formated.notifType) {
+ const callbacks = subscriptions[formated.notifType];
+ if (callbacks) {
+ callbacks.forEach(cb => {
+ // ensure all callbacks will be called
+ try {
+ return cb(formated);
+ } catch (reason) {
+ console.error(reason);
+ }
+ });
+ }
+ }
+ }
+ };
+
+ notificationSocket.onerror = function (error) {
+ console.log("Socket error:");
+ console.log(error);
+ reject("Socket error: " + error);
+ if (applicationStore) {
+ applicationStore.dispatch(new SetWebsocketAction(false));
+ }
+ };
+
+ notificationSocket.onopen = function (event) {
+ if (applicationStore) {
+ applicationStore.dispatch(new SetWebsocketAction(true));
+ }
+ console.log("Socket connection opened.");
+ resolve(notificationSocket);
+
+ // send a subscription to all active scopes
+ const scopesToSubscribe = Object.keys(subscriptions);
+ if (notificationSocket.readyState === notificationSocket.OPEN) {
+ const data = {
+ 'data': 'scopes',
+ 'scopes': scopesToSubscribe
+ };
+ notificationSocket.send(JSON.stringify(data));
+ };
+ };
+
+ notificationSocket.onclose = function (event) {
+ console.log("socket connection closed");
+ if (applicationStore) {
+ applicationStore.dispatch(new SetWebsocketAction(false));
+ }
+ if (!userLoggedOut) {
+ socketReady = connect();
+ }
+ };
+ });
+}
+
+
+
+
+export const startWebsocketSession = () => {
+ socketReady = connect();
+ userLoggedOut = false;
+}
+
+export const endWebsocketSession = () => {
+ socketReady.then(websocket => {
+ websocket.close();
+ userLoggedOut = true;
+ })
+}
+
+
+
+
diff --git a/sdnr/wt/odlux/framework/src/services/restAccessorService.ts b/sdnr/wt/odlux/framework/src/services/restAccessorService.ts
new file mode 100644
index 000000000..ca95ebc1a
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/restAccessorService.ts
@@ -0,0 +1,93 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as $ from 'jquery';
+import { Action, IActionHandler } from '../flux/action';
+import { MiddlewareArg } from '../flux/middleware';
+import { Dispatch } from '../flux/store';
+
+import { IApplicationStoreState } from '../store/applicationStore';
+import { AddErrorInfoAction, ErrorInfo } from '../actions/errorActions';
+import { PlainObject, AjaxParameter } from 'models/restService';
+
+export const absoluteUri = /^(https?:\/\/|blob:)/i;
+export const baseUrl = `${ window.location.origin }${ window.location.pathname }`;
+
+class RestBaseAction extends Action { }
+
+export const createRestApiAccessor = <TResult extends PlainObject>(urlOrPath: string, initialValue: TResult) => {
+ const isLocalRequest = !absoluteUri.test(urlOrPath);
+ const uri = isLocalRequest ? `${ baseUrl }/${ urlOrPath }`.replace(/\/{2,}/, '/') : urlOrPath ;
+
+ class RestRequestAction extends RestBaseAction { constructor(public settings?: AjaxParameter) { super(); } }
+
+ class RestResponseAction extends RestBaseAction { constructor(public result: TResult) { super(); } }
+
+ class RestErrorAction extends RestBaseAction { constructor(public error?: Error | string) { super(); } }
+
+ type RestAction = RestRequestAction | RestResponseAction | RestErrorAction;
+
+ /** Represents our middleware to handle rest backend requests */
+ const restMiddleware = (api: MiddlewareArg<IApplicationStoreState>) =>
+ (next: Dispatch) => (action: RestAction): RestAction => {
+
+ // pass all actions through by default
+ next(action);
+ // handle the RestRequestAction
+ if (action instanceof RestRequestAction) {
+ const state = api.getState();
+ const authHeader = isLocalRequest && state && state.framework.authenticationState.user && state.framework.authenticationState.user.token
+ ? { "Authentication": "Bearer " + state.framework.authenticationState.user.token } : { };
+ $.ajax({
+ url: uri,
+ method: (action.settings && action.settings.method) || "GET",
+ headers: { ...authHeader, ...action.settings && action.settings.headers ? action.settings.headers : { } },
+ }).then((data: TResult) => {
+ next(new RestResponseAction(data));
+ }).catch((err: any) => {
+ next(new RestErrorAction());
+ next(new AddErrorInfoAction((err instanceof Error) ? { error: err } : { message: err.toString() }));
+ });
+ }
+ // allways return action
+ return action;
+ };
+
+ /** Represents our action handler to handle our actions */
+ const restActionHandler: IActionHandler<TResult> = (state = initialValue, action) => {
+ if (action instanceof RestRequestAction) {
+ return {
+ ...(state as any),
+ busy: true
+ };
+ } else if (action instanceof RestResponseAction) {
+ return action.result;
+ } else if (action instanceof RestErrorAction) {
+ return initialValue;
+ }
+ return state;
+ };
+
+ return {
+ requestAction: RestRequestAction,
+ actionHandler: restActionHandler,
+ middleware: restMiddleware,
+ };
+}
+
+
+
diff --git a/sdnr/wt/odlux/framework/src/services/restService.ts b/sdnr/wt/odlux/framework/src/services/restService.ts
new file mode 100644
index 000000000..b02d7d19f
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/restService.ts
@@ -0,0 +1,105 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { ApplicationStore } from "../store/applicationStore";
+import { ReplaceAction } from "../actions/navigationActions";
+
+const baseUri = `${ window.location.origin }`;
+const absUrlPattern = /^https?:\/\//;
+let applicationStore: ApplicationStore | null = null;
+
+export const startRestService = (store: ApplicationStore) => {
+ applicationStore = store;
+};
+
+export const formEncode = (params: { [key: string]: string | number }) => Object.keys(params).map((key) => {
+ return encodeURIComponent(key) + '=' + encodeURIComponent(params[key].toString());
+}).join('&');
+
+/** Sends a rest request to the given path.
+ * @returns The data, or null it there was any error
+ */
+export async function requestRest<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<TData | null> {
+ const res = await requestRestExt<TData>(path, init, authenticate, isResource);
+ if (res && res.status >= 200 && res.status < 300) {
+ return res.data;
+ }
+ return null;
+}
+
+/** Sends a rest request to the given path and reports the server state.
+ * @returns An object with the server state, a message and the data.
+ */
+export async function requestRestExt<TData>(path: string = '', init: RequestInit = {}, authenticate: boolean = true, isResource: boolean = false): Promise<{ status: number, message?: string, data: TData | null }> {
+ const result: { status: number, message?: string, data: TData | null } = {
+ status: -1,
+ data: null,
+ };
+ const isAbsUrl = absUrlPattern.test(path);
+ const uri = isAbsUrl ? path : isResource ? path.replace(/\/{2,}/i, '/') : (baseUri) + ('/' + path).replace(/\/{2,}/i, '/');
+ init = {
+ 'method': 'GET',
+ ...init,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ ...init.headers
+ }
+ };
+ if (!isAbsUrl && authenticate && applicationStore) {
+ const { state: { framework: { authenticationState: { user } } } } = applicationStore;
+ // do not request if the user is not valid
+ if (!user || !user.isValid) {
+ return {
+ ...result,
+ message: "User is not valid or not logged in."
+ };
+ }
+ (init.headers = {
+ ...init.headers,
+ 'Authorization': `${user.tokenType} ${user.token}`
+ //'Authorization': 'Basic YWRtaW46YWRtaW4='
+ });
+ }
+ const fetchResult = await fetch(uri, init);
+ if (fetchResult.status === 401 || fetchResult.status === 403) {
+ applicationStore && applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${applicationStore.state.framework.navigationState.pathname}`));
+ return {
+ ...result,
+ status: 403,
+ message: "Authentication requested by server."
+ };
+ }
+ const contentType = fetchResult.headers.get("Content-Type") || fetchResult.headers.get("content-type");
+ const isJson = contentType && contentType.toLowerCase().startsWith("application/json");
+ try {
+ const data = (isJson ? await fetchResult.json() : await fetchResult.text()) as TData;
+ return {
+ ...result,
+ status: fetchResult.status,
+ message: fetchResult.statusText,
+ data: data
+ };
+ } catch (error) {
+ return {
+ ...result,
+ status: fetchResult.status,
+ message: error && error.message || String(error),
+ data: null
+ };
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/services/snackbarService.ts b/sdnr/wt/odlux/framework/src/services/snackbarService.ts
new file mode 100644
index 000000000..50e279c67
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/services/snackbarService.ts
@@ -0,0 +1,22 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { OptionsObject } from "notistack";
+
+export const snackbarService = {
+ enqueueSnackbar: (message: string, options?: OptionsObject) =>{ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/store/applicationStore.ts b/sdnr/wt/odlux/framework/src/store/applicationStore.ts
new file mode 100644
index 000000000..287eba31c
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/store/applicationStore.ts
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Store } from '../flux/store';
+import { combineActionHandler, MiddlewareArg, Middleware, chainMiddleware } from '../flux/middleware';
+
+import applicationService from '../services/applicationManager';
+
+import { applicationRegistryHandler, IApplicationRegistration } from '../handlers/applicationRegistryHandler';
+import { authenticationStateHandler, IAuthenticationState } from '../handlers/authenticationHandler';
+import { applicationStateHandler, IApplicationState } from '../handlers/applicationStateHandler';
+import { navigationStateHandler, INavigationState } from '../handlers/navigationStateHandler';
+
+import { setApplicationStore } from '../services/applicationApi';
+
+import apiMiddleware from '../middleware/api';
+import thunkMiddleware from '../middleware/thunk';
+import loggerMiddleware from '../middleware/logger';
+import routerMiddleware from '../middleware/navigation';
+
+export type MiddlewareApi = MiddlewareArg<IApplicationStoreState>;
+
+export interface IFrameworkStoreState {
+ applicationRegistraion: IApplicationRegistration;
+ applicationState: IApplicationState;
+ authenticationState: IAuthenticationState;
+ navigationState: INavigationState;
+}
+
+export interface IApplicationStoreState {
+ framework: IFrameworkStoreState;
+}
+
+const frameworkHandlers = combineActionHandler({
+ applicationRegistraion: applicationRegistryHandler,
+ applicationState: applicationStateHandler,
+ authenticationState: authenticationStateHandler,
+ navigationState: navigationStateHandler
+});
+
+export class ApplicationStore extends Store<IApplicationStoreState> { }
+
+/** This function will create the application store considering the currently registered application ans their middlewares. */
+export const applicationStoreCreator = (): ApplicationStore => {
+ const middlewares: Middleware<IApplicationStoreState>[] = [];
+ const actionHandlers = Object.keys(applicationService.applications).reduce((acc, cur) => {
+ const reg = applicationService.applications[cur];
+ reg && typeof reg.rootActionHandler === 'function' && (acc[cur] = reg.rootActionHandler);
+ reg && +(reg.middlewares || 0) && middlewares.push(...(reg.middlewares as Middleware<IApplicationStoreState>[]));
+ return acc;
+ }, { framework: frameworkHandlers } as any);
+
+ const applicationStore = new ApplicationStore(combineActionHandler(actionHandlers), chainMiddleware(loggerMiddleware, thunkMiddleware, routerMiddleware, apiMiddleware, ...middlewares));
+ setApplicationStore(applicationStore);
+ return applicationStore;
+}
+
+export default applicationStoreCreator; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/styles/att.ts b/sdnr/wt/odlux/framework/src/styles/att.ts
new file mode 100644
index 000000000..cfd743d11
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/styles/att.ts
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { createMuiTheme } from '@material-ui/core/styles';
+
+const theme = createMuiTheme({
+ design: {
+ id: "att",
+ name: "AT&T",
+ url: "https://pmcvariety.files.wordpress.com/2016/04/att_logo.jpg?w=1000&h=563&crop=1",
+ height: 70,
+ width: 150,
+ logoHeight: 60,
+ },
+ palette: {
+ primary: {
+ light: "#f2f2f29c",
+ main: "#f2f2f2",
+ dark: "#d5d5d5",
+ contrastText: "#0094d3"
+ },
+ secondary: {
+ light: "#f2f2f2",
+ main: "rgba(51, 171, 226, 1)",
+ dark: "rgba(41, 159, 213, 1)",
+ contrastText: "#0094d3"
+ }
+ },
+});
+
+export default theme;
diff --git a/sdnr/wt/odlux/framework/src/utilities/elasticSearch.ts b/sdnr/wt/odlux/framework/src/utilities/elasticSearch.ts
new file mode 100644
index 000000000..c18a40b0b
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/utilities/elasticSearch.ts
@@ -0,0 +1,78 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Result } from '../models';
+import { DataCallback } from '../components/material-table';
+
+import { requestRest } from '../services/restService';
+
+import { convertPropertyNames, convertPropertyValues, replaceUpperCase, replaceHyphen } from './yangHelper';
+
+type propType = string | number | null | undefined | (string | number)[];
+type dataType = { [prop: string]: propType };
+
+/** Represents a fabric for the searchDataHandler used by the internal data api.
+ * @param typeName The name of the entry type to create a searchDataHandler for.
+ * @param additionalFilters Filterproperties and their values to add permanently.
+ * @returns The searchDataHandler callback to be used with the material table.
+*/
+export function createSearchDataHandler<TResult>(typeName: (() => string) | string, additionalFilters?: {} | null | undefined): DataCallback<(TResult)> {
+ const fetchData: DataCallback<(TResult)> = async (pageIndex, rowsPerPage, orderBy, order, filter) => {
+ const url = `/restconf/operations/data-provider:read-${typeof typeName === "function" ? typeName(): typeName}-list`;
+
+ filter = { ...filter, ...additionalFilters };
+
+ const filterKeys = filter && Object.keys(filter) || [];
+
+ const query = {
+ input: {
+ filter: filterKeys.filter(f => filter![f] != null && filter![f] !== "").map(property => ({ property, filtervalue: filter![property]})),
+ sortorder: orderBy ? [{ property: orderBy, sortorder: order === "desc" ? "descending" : "ascending" }] : [],
+ pagination: { size: rowsPerPage, page: (pageIndex != null && pageIndex > 0 && pageIndex || 0) +1 }
+ }
+ };
+ const result = await requestRest<Result<TResult>>(url, {
+ method: "POST", // *GET, POST, PUT, DELETE, etc.
+ mode: "same-origin", // no-cors, cors, *same-origin
+ cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
+ headers: {
+ "Content-Type": "application/json",
+ // "Content-Type": "application/x-www-form-urlencoded",
+ },
+ body: JSON.stringify(convertPropertyValues(query, replaceUpperCase)), // body data type must match "Content-Type" header
+ });
+
+ if (result) {
+ let rows: TResult[] = [];
+
+ if (result && result.output && result.output.data) {
+ rows = result.output.data.map(obj => convertPropertyNames(obj, replaceHyphen)) || []
+ }
+
+ const data = {
+ page: result.output.pagination && result.output.pagination.page != null && result.output.pagination.page - 1 || 0 , total: result.output.pagination && result.output.pagination.total || 0, rows: rows
+ };
+ return data;
+ }
+
+ return { page: 1, total: 0, rows: [] };
+ };
+
+ return fetchData;
+}
+
diff --git a/sdnr/wt/odlux/framework/src/utilities/withComponents.ts b/sdnr/wt/odlux/framework/src/utilities/withComponents.ts
new file mode 100644
index 000000000..8e460ad4c
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/utilities/withComponents.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import applicationService from '../services/applicationManager';
+export type WithComponents<T extends { [name: string]: string }> = {
+ components: { [prop in keyof T]: React.ComponentType }
+};
+
+export function withComponents<TProps,TMap extends { [name: string]: string }>(mapping: TMap) {
+ return (component: React.ComponentType<TProps & WithComponents<TMap>>): React.ComponentType<TProps> => {
+ const components = {} as any;
+ Object.keys(mapping).forEach(name => {
+ const [appKey, componentKey] = mapping[name].split('.');
+ const reg = applicationService.applications[appKey];
+ components[name] = reg && reg.exportedComponents && reg.exportedComponents[componentKey] || (() => null);
+ });
+ return (props: TProps) => (
+ React.createElement(component, Object.assign({ components }, props))
+ );
+ }
+}
+export default withComponents; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/utilities/yangHelper.ts b/sdnr/wt/odlux/framework/src/utilities/yangHelper.ts
new file mode 100644
index 000000000..127f3e07d
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/utilities/yangHelper.ts
@@ -0,0 +1,39 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+
+export const replaceHyphen = (name: string) => name.replace(/-([a-z])/g, (g) => (g[1].toUpperCase()));
+export const replaceUpperCase = (name: string) => name.replace(/([a-z][A-Z])/g, (g) => g[0] + '-' + g[1].toLowerCase());
+
+export const convertPropertyNames = <T extends { [prop: string]: any }>(obj: T, conv: (name: string) => string): T => {
+ return Object.keys(obj).reduce<{ [prop: string]: any }>((acc, cur) => {
+ acc[conv(cur)] = typeof obj[cur] === "object" ? convertPropertyNames(obj[cur], conv) : obj[cur];
+ return acc;
+ }, obj instanceof Array ? [] : {}) as T;
+}
+
+export const convertPropertyValues = <T extends { [prop: string]: any }>(obj: T, conv: (name: string) => string): T => {
+ return Object.keys(obj).reduce<{ [prop: string]: any }>((acc, cur) => {
+ acc[cur] = typeof obj[cur] === "object"
+ ? convertPropertyValues(obj[cur], conv)
+ : cur === "property"
+ ? conv(obj[cur])
+ : obj[cur];
+ return acc;
+ }, obj instanceof Array ? [] : {}) as T;
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx
new file mode 100644
index 000000000..d47e09c3a
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/views/about.tsx
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+const AboutComponent = () => {
+
+ return (
+ <div>
+ <h2>About</h2>
+ <div style={{ margin: "0 auto" }}>##odlux.version##</div>
+ </div>
+ );
+};
+
+export const About = AboutComponent;
+export default About; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/views/frame.tsx b/sdnr/wt/odlux/framework/src/views/frame.tsx
new file mode 100644
index 000000000..b93b7ee01
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/views/frame.tsx
@@ -0,0 +1,118 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
+
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+import { faHome, faAddressBook, faSignInAlt } from '@fortawesome/free-solid-svg-icons';
+
+import AppFrame from '../components/routing/appFrame';
+import TitleBar from '../components/titleBar';
+import Menu from '../components/navigationMenu';
+import ErrorDisplay from '../components/errorDisplay';
+import SnackDisplay from '../components/material-ui/snackDisplay';
+
+import Home from '../views/home';
+import Login from '../views/login';
+import About from '../views/about';
+import Test from '../views/test';
+
+import applicationService from '../services/applicationManager';
+import { SnackbarProvider } from 'notistack';
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ flexGrow: 1,
+ height: '100%',
+ zIndex: 1,
+ overflow: 'hidden',
+ position: 'relative',
+ display: 'flex',
+ },
+ content: {
+ flexGrow: 1,
+ display: "flex",
+ flexDirection: "column",
+ backgroundColor: theme.palette.background.default,
+ padding: theme.spacing(3),
+ minWidth: 0, // So the Typography noWrap works
+ },
+ toolbar: theme.mixins.toolbar
+});
+
+type FrameProps = WithStyles<typeof styles>;
+
+class FrameComponent extends React.Component<FrameProps>{
+
+ render() {
+ const registrations = applicationService.applications;
+ const { classes } = this.props;
+ return (
+ <SnackbarProvider maxSnack={3}>
+ <Router>
+ <div className={classes.root}>
+ <SnackDisplay />
+ <ErrorDisplay />
+ <TitleBar />
+ <Menu />
+ <main className={classes.content}>
+ {
+ <div className={classes.toolbar} /> //needed for margins, don't remove!
+ }
+ <Switch>
+ <Route exact path="/" component={() => (
+ <AppFrame title={"Home"} icon={faHome} >
+ <Home />
+ </AppFrame>
+ )} />
+ <Route path="/about" component={() => (
+ <AppFrame title={"About"} icon={faAddressBook} >
+ <About />
+ </AppFrame>
+ )} />
+ {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => (
+ <AppFrame title={"Test"} icon={faAddressBook} >
+ <Test />
+ </AppFrame>
+ )} /> : null}
+ <Route path="/login" component={() => (
+ <AppFrame title={"Login"} icon={faSignInAlt} >
+ <Login />
+ </AppFrame>
+ )} />
+ {Object.keys(registrations).map(p => {
+ const application = registrations[p];
+ return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => (
+ <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} >
+ <application.rootComponent />
+ </AppFrame>
+ )} />)
+ })}
+ <Redirect to="/" />
+ </Switch>
+ </main>
+ </div>
+ </Router>
+ </SnackbarProvider>
+ );
+ }
+}
+
+export const Frame = withStyles(styles)(FrameComponent);
+
+export default Frame;
diff --git a/sdnr/wt/odlux/framework/src/views/home.tsx b/sdnr/wt/odlux/framework/src/views/home.tsx
new file mode 100644
index 000000000..4a4084e88
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/views/home.tsx
@@ -0,0 +1,27 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+export const Home = (props: React.Props<any>) => {
+ return (
+ <div>
+ <h1>Welcome to ODLUX.</h1>
+ </div>
+ )
+}
+export default Home; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/views/login.tsx b/sdnr/wt/odlux/framework/src/views/login.tsx
new file mode 100644
index 000000000..3f6ef6134
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/views/login.tsx
@@ -0,0 +1,210 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+import { withRouter, RouteComponentProps } from 'react-router-dom';
+
+import Avatar from '@material-ui/core/Avatar';
+import Button from '@material-ui/core/Button';
+import Dialog from '@material-ui/core/Dialog';
+import DialogActions from '@material-ui/core/DialogActions';
+import DialogContent from '@material-ui/core/DialogContent';
+import DialogContentText from '@material-ui/core/DialogContentText';
+import DialogTitle from '@material-ui/core/DialogTitle';
+import CssBaseline from '@material-ui/core/CssBaseline';
+import FormControl from '@material-ui/core/FormControl';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
+import Checkbox from '@material-ui/core/Checkbox';
+import Input from '@material-ui/core/Input';
+import InputLabel from '@material-ui/core/InputLabel';
+import LockIcon from '@material-ui/icons/LockOutlined';
+import Paper from '@material-ui/core/Paper';
+import Typography from '@material-ui/core/Typography';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import connect, { Connect } from '../flux/connect';
+import authenticationService from '../services/authenticationService';
+
+import { UpdateAuthentication } from '../actions/authentication';
+
+const styles = (theme: Theme) => createStyles({
+ layout: {
+ width: 'auto',
+ display: 'block', // Fix IE11 issue.
+ marginLeft: theme.spacing(3),
+ marginRight: theme.spacing(3),
+ [theme.breakpoints.up(400 + theme.spacing(3) * 2)]: {
+ width: 400,
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ },
+ },
+ paper: {
+ marginTop: theme.spacing(8),
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ padding: `${theme.spacing(2)}px ${theme.spacing(3)}px ${theme.spacing(3)}px`,
+ },
+ avatar: {
+ margin: theme.spacing(1),
+ backgroundColor: theme.palette.secondary.main,
+ },
+ form: {
+ width: '100%', // Fix IE11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ marginTop: theme.spacing(3),
+ },
+});
+
+type LoginProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect;
+
+interface ILoginState {
+ busy: boolean;
+ username: string;
+ password: string;
+ scope: string;
+ message: string;
+}
+
+
+// todo: ggf. redirect to einbauen
+class LoginComponent extends React.Component<LoginProps, ILoginState> {
+
+ constructor(props: LoginProps) {
+ super(props);
+
+ this.state = {
+ busy: false,
+ username: '',
+ password: '',
+ scope: 'sdn',
+ message: ''
+ };
+ }
+
+ render(): JSX.Element {
+ const { classes } = this.props;
+ return (
+ <React.Fragment>
+ <CssBaseline />
+ <main className={classes.layout}>
+ <Paper className={classes.paper}>
+ <Avatar className={classes.avatar}>
+ <LockIcon />
+ </Avatar>
+ <Typography variant="caption">Sign in</Typography>
+ <form className={classes.form}>
+ <FormControl margin="normal" required fullWidth>
+ <InputLabel htmlFor="username">Username</InputLabel>
+ <Input id="username" name="username" autoComplete="username" autoFocus
+ disabled={this.state.busy}
+ value={this.state.username}
+ onChange={event => { this.setState({ username: event.target.value }) }} />
+ </FormControl>
+ <FormControl margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Password</InputLabel>
+ <Input
+ name="password"
+ type="password"
+ id="password"
+ autoComplete="current-password"
+ disabled={this.state.busy}
+ value={this.state.password}
+ onChange={event => { this.setState({ password: event.target.value }) }}
+ />
+ </FormControl>
+ <FormControl margin="normal" required fullWidth>
+ <InputLabel htmlFor="password">Domain</InputLabel>
+ <Input
+ name="scope"
+ type="scope"
+ id="scope"
+ disabled={this.state.busy}
+ value={this.state.scope}
+ onChange={event => { this.setState({ scope: event.target.value }) }}
+ />
+ </FormControl>
+ <FormControlLabel
+ control={<Checkbox value="remember" color="secondary" />}
+ label="Remember me"
+ />
+ <Button
+ type="submit"
+ fullWidth
+ variant="contained"
+ color="primary"
+ disabled={this.state.busy}
+ className={classes.submit}
+ onClick={this.onSignIn}
+ >
+ Sign in
+ </Button>
+ </form>
+ </Paper>
+ </main>
+ <Dialog
+ open={!!this.state.message}
+ onClose={() => { this.setState({ message: '' }) }}
+ aria-labelledby="alert-dialog-title"
+ aria-describedby="alert-dialog-description"
+ >
+ <DialogTitle id="alert-dialog-title">{"Error"}</DialogTitle>
+ <DialogContent>
+ <DialogContentText id="alert-dialog-description">
+ {this.state.message}
+ </DialogContentText>
+ </DialogContent>
+ <DialogActions>
+ <Button onClick={() => { this.setState({ message: '' }) }} color="secondary" autoFocus>
+ OK
+ </Button>
+ </DialogActions>
+ </Dialog>
+ </React.Fragment>
+ );
+ }
+
+ private onSignIn = async (event: React.MouseEvent<HTMLButtonElement>) => {
+ event.preventDefault();
+
+ this.setState({ busy: true });
+ const token = await authenticationService.authenticateUser(this.state.username, this.state.password, this.state.scope);
+ this.props.dispatch(new UpdateAuthentication(token));
+ this.setState({ busy: false });
+
+ if (token) {
+ const query =
+ this.props.state.framework.navigationState.search &&
+ this.props.state.framework.navigationState.search.replace(/^\?/, "")
+ .split('&').map(e => e.split("="));
+ const returnTo = query && query.find(e => e[0] === "returnTo");
+ this.props.history.replace(returnTo && returnTo[1] || "/");
+ }
+ else {
+ this.setState({
+ message: "Could not log in. Please check your credentials or ask your administrator for assistence.",
+ password: ""
+ })
+ }
+ }
+}
+
+export const Login = withStyles(styles)(withRouter(connect()(LoginComponent)));
+export default Login; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/views/test.tsx b/sdnr/wt/odlux/framework/src/views/test.tsx
new file mode 100644
index 000000000..68b189340
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/views/test.tsx
@@ -0,0 +1,878 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from 'react';
+
+import { withComponents, WithComponents } from '../utilities/withComponents';
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import ExpansionPanel from '@material-ui/core/ExpansionPanel';
+import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
+import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
+import Typography from '@material-ui/core/Typography';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+
+import { MaterialTable, MaterialTableCtorType, ColumnType } from '../components/material-table';
+import { TreeView, ITreeItem, TreeViewCtorType } from '../components/material-ui/treeView';
+import { SvgIconProps } from '@material-ui/core/SvgIcon';
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ width: '100%',
+ },
+ heading: {
+ fontSize: theme.typography.pxToRem(15),
+ fontWeight: theme.typography.fontWeightRegular,
+ },
+});
+
+class SampleData {
+ _id: string;
+ index: number;
+ guid: string;
+ isActive: boolean;
+ balance: string;
+ age: number;
+ firstName: string;
+ lastName: string;
+ company: string;
+ email: string;
+ registered: string;
+ latitude: string;
+ longitude: string;
+}
+
+// https://next.json-generator.com/NJ5Bv-v1I
+const tableData: SampleData[] = [
+ {
+ "_id": "5c0e18399919a5c43636fdf2",
+ "index": 0,
+ "guid": "48728d8e-8300-4d0f-b967-e2166d023066",
+ "isActive": false,
+ "balance": "$3,480.16",
+ "age": 33,
+ "firstName": "Brooke",
+ "lastName": "Morris",
+ "company": "ZORROMOP",
+ "email": "brooke.morris@zorromop.de",
+ "registered": "Sunday, February 11, 2018 2:55 PM",
+ "latitude": "-69.109379",
+ "longitude": "113.735639"
+ },
+ {
+ "_id": "5c0e1839b61e3eeaf164259d",
+ "index": 1,
+ "guid": "28723570-1507-422e-b78c-924402371fb1",
+ "isActive": false,
+ "balance": "$1,305.01",
+ "age": 28,
+ "firstName": "Jolene",
+ "lastName": "Everett",
+ "company": "ZENCO",
+ "email": "jolene.everett@zenco.de",
+ "registered": "Saturday, December 8, 2018 5:17 PM",
+ "latitude": "13.683025",
+ "longitude": "85.101421"
+ },
+ {
+ "_id": "5c0e1839e81f57913c5d2147",
+ "index": 2,
+ "guid": "e914dc5d-91a3-405d-ac48-aee6f0cd391a",
+ "isActive": true,
+ "balance": "$1,418.37",
+ "age": 28,
+ "firstName": "Elva",
+ "lastName": "Travis",
+ "company": "ZYTREK",
+ "email": "elva.travis@zytrek.de",
+ "registered": "Thursday, March 10, 2016 5:13 PM",
+ "latitude": "53.75862",
+ "longitude": "-67.784532"
+ },
+ {
+ "_id": "5c0e1839bc9224a2b54c0f69",
+ "index": 3,
+ "guid": "88cbdce0-0bcc-4d16-83c3-3017690503c4",
+ "isActive": true,
+ "balance": "$1,709.60",
+ "age": 21,
+ "firstName": "Ellis",
+ "lastName": "Mcpherson",
+ "company": "DIGIPRINT",
+ "email": "ellis.mcpherson@digiprint.de",
+ "registered": "Sunday, December 21, 2014 5:25 AM",
+ "latitude": "46.486149",
+ "longitude": "-66.657067"
+ },
+ {
+ "_id": "5c0e183951b51475db0f35d1",
+ "index": 4,
+ "guid": "c887ac86-7ba1-4eb6-9b47-e88a1bcb3713",
+ "isActive": true,
+ "balance": "$3,578.54",
+ "age": 25,
+ "firstName": "Marcia",
+ "lastName": "Rocha",
+ "company": "ZAPPIX",
+ "email": "marcia.rocha@zappix.de",
+ "registered": "Tuesday, June 16, 2015 11:21 AM",
+ "latitude": "-39.905461",
+ "longitude": "150.873895"
+ },
+ {
+ "_id": "5c0e18398c5be8d362a578eb",
+ "index": 5,
+ "guid": "0d160697-9b5b-4941-9b5f-4ba3a7f97b49",
+ "isActive": true,
+ "balance": "$414.98",
+ "age": 32,
+ "firstName": "Lavonne",
+ "lastName": "Wilkins",
+ "company": "FARMAGE",
+ "email": "lavonne.wilkins@farmage.de",
+ "registered": "Monday, February 1, 2016 5:27 PM",
+ "latitude": "-16.839256",
+ "longitude": "-105.824746"
+ },
+ {
+ "_id": "5c0e18399804086c836d7d56",
+ "index": 6,
+ "guid": "715a5f63-35b6-4903-a46e-ba584b005e64",
+ "isActive": false,
+ "balance": "$1,755.78",
+ "age": 32,
+ "firstName": "Wise",
+ "lastName": "Berg",
+ "company": "ZIZZLE",
+ "email": "wise.berg@zizzle.de",
+ "registered": "Saturday, March 28, 2015 1:40 AM",
+ "latitude": "51.15269",
+ "longitude": "65.795093"
+ },
+ {
+ "_id": "5c0e18399c4d13538bcaf8c9",
+ "index": 7,
+ "guid": "7ee50269-23e8-499e-9a16-09f393d7600c",
+ "isActive": false,
+ "balance": "$342.52",
+ "age": 27,
+ "firstName": "Isabel",
+ "lastName": "Battle",
+ "company": "EZENTIA",
+ "email": "isabel.battle@ezentia.de",
+ "registered": "Thursday, June 7, 2018 12:16 AM",
+ "latitude": "-53.318152",
+ "longitude": "-153.516824"
+ },
+ {
+ "_id": "5c0e18398d7fb9a4eceeffa2",
+ "index": 8,
+ "guid": "1e30c9ac-2297-4f16-83e6-9559b1ebe92c",
+ "isActive": true,
+ "balance": "$3,184.71",
+ "age": 36,
+ "firstName": "Lenora",
+ "lastName": "Crawford",
+ "company": "KIDGREASE",
+ "email": "lenora.crawford@kidgrease.de",
+ "registered": "Saturday, January 7, 2017 6:17 PM",
+ "latitude": "-72.431496",
+ "longitude": "9.413359"
+ },
+ {
+ "_id": "5c0e18395837069ab6b79d00",
+ "index": 9,
+ "guid": "d04a02ed-5899-4729-a7e5-2d85b5d03973",
+ "isActive": true,
+ "balance": "$1,553.28",
+ "age": 35,
+ "firstName": "Sasha",
+ "lastName": "Bridges",
+ "company": "IDEALIS",
+ "email": "sasha.bridges@idealis.de",
+ "registered": "Sunday, February 4, 2018 7:02 PM",
+ "latitude": "8.095691",
+ "longitude": "-105.758195"
+ },
+ {
+ "_id": "5c0e18390be19bf65acad180",
+ "index": 10,
+ "guid": "3a1a77e6-ef15-4598-8274-c68ac3bb922a",
+ "isActive": false,
+ "balance": "$3,587.96",
+ "age": 20,
+ "firstName": "Wilkins",
+ "lastName": "Beasley",
+ "company": "DIGIFAD",
+ "email": "wilkins.beasley@digifad.de",
+ "registered": "Monday, March 5, 2018 1:27 PM",
+ "latitude": "-88.062704",
+ "longitude": "149.95661"
+ },
+ {
+ "_id": "5c0e1839ffbbad5c9954e49f",
+ "index": 11,
+ "guid": "97a56950-a08c-4e00-8002-ba2d5de4da5d",
+ "isActive": false,
+ "balance": "$1,997.80",
+ "age": 31,
+ "firstName": "Sullivan",
+ "lastName": "Mcclain",
+ "company": "EARTHMARK",
+ "email": "sullivan.mcclain@earthmark.de",
+ "registered": "Saturday, October 27, 2018 2:51 PM",
+ "latitude": "-81.86349",
+ "longitude": "-79.596991"
+ },
+ {
+ "_id": "5c0e183914bd464d55e7325f",
+ "index": 12,
+ "guid": "294f6485-d0f9-4b25-b998-325ae90fa769",
+ "isActive": true,
+ "balance": "$1,405.46",
+ "age": 24,
+ "firstName": "Herminia",
+ "lastName": "Fischer",
+ "company": "ECOLIGHT",
+ "email": "herminia.fischer@ecolight.de",
+ "registered": "Thursday, January 16, 2014 4:48 PM",
+ "latitude": "48.224363",
+ "longitude": "11.08339"
+ },
+ {
+ "_id": "5c0e183968ec2556d8f6566c",
+ "index": 13,
+ "guid": "16edfea4-7b37-4e54-868c-c369b413dd78",
+ "isActive": false,
+ "balance": "$3,440.67",
+ "age": 39,
+ "firstName": "Blanchard",
+ "lastName": "Blackwell",
+ "company": "GEOFORMA",
+ "email": "blanchard.blackwell@geoforma.de",
+ "registered": "Wednesday, July 30, 2014 4:07 AM",
+ "latitude": "-52.169297",
+ "longitude": "10.415879"
+ },
+ {
+ "_id": "5c0e183939a0fc955f2d94da",
+ "index": 14,
+ "guid": "4ed454e2-dde1-4ab5-a434-4a82205ced2d",
+ "isActive": true,
+ "balance": "$1,883.27",
+ "age": 35,
+ "firstName": "Gayle",
+ "lastName": "Little",
+ "company": "AQUAZURE",
+ "email": "gayle.little@aquazure.de",
+ "registered": "Tuesday, December 12, 2017 5:08 PM",
+ "latitude": "-58.473236",
+ "longitude": "38.022269"
+ },
+ {
+ "_id": "5c0e1839099f9221ccd968ac",
+ "index": 15,
+ "guid": "1d052fd4-7c54-45fb-b0db-7de1acc4262a",
+ "isActive": false,
+ "balance": "$2,601.94",
+ "age": 31,
+ "firstName": "Jocelyn",
+ "lastName": "Richards",
+ "company": "GINK",
+ "email": "jocelyn.richards@gink.de",
+ "registered": "Sunday, October 30, 2016 9:12 PM",
+ "latitude": "-43.489676",
+ "longitude": "2.557869"
+ },
+ {
+ "_id": "5c0e183970f320f377321c3f",
+ "index": 16,
+ "guid": "45bca125-8831-48c3-b22b-29ae318e7096",
+ "isActive": false,
+ "balance": "$3,441.74",
+ "age": 34,
+ "firstName": "Berta",
+ "lastName": "Valentine",
+ "company": "ISOSPHERE",
+ "email": "berta.valentine@isosphere.de",
+ "registered": "Sunday, March 19, 2017 8:22 PM",
+ "latitude": "-40.188039",
+ "longitude": "-170.085092"
+ },
+ {
+ "_id": "5c0e1839ab960bb0a9f4f392",
+ "index": 17,
+ "guid": "d7b5122a-94c9-423c-b799-1a8f8314b152",
+ "isActive": false,
+ "balance": "$56.39",
+ "age": 21,
+ "firstName": "Russell",
+ "lastName": "Powers",
+ "company": "TETAK",
+ "email": "russell.powers@tetak.de",
+ "registered": "Thursday, November 3, 2016 9:23 PM",
+ "latitude": "-51.610519",
+ "longitude": "-133.280363"
+ },
+ {
+ "_id": "5c0e183998f0195404b9aaa4",
+ "index": 18,
+ "guid": "a043ba97-ea7e-48ce-bb15-18ee09fb393d",
+ "isActive": true,
+ "balance": "$1,503.57",
+ "age": 37,
+ "firstName": "Rosario",
+ "lastName": "Brennan",
+ "company": "VIAGRAND",
+ "email": "rosario.brennan@viagrand.de",
+ "registered": "Saturday, March 17, 2018 10:32 PM",
+ "latitude": "-43.773365",
+ "longitude": "47.58682"
+ },
+ {
+ "_id": "5c0e1839bcb2a5cc567129ac",
+ "index": 19,
+ "guid": "de6d5d36-201e-4f87-9976-ed31f3160e42",
+ "isActive": false,
+ "balance": "$1,160.18",
+ "age": 29,
+ "firstName": "Anita",
+ "lastName": "Hodges",
+ "company": "TUBALUM",
+ "email": "anita.hodges@tubalum.de",
+ "registered": "Sunday, November 26, 2017 11:54 AM",
+ "latitude": "7.080244",
+ "longitude": "-9.970715"
+ },
+ {
+ "_id": "5c0e18394b37e854a1ef371c",
+ "index": 20,
+ "guid": "9407113b-896a-4699-ac1b-363bc3c6f8ad",
+ "isActive": false,
+ "balance": "$34.81",
+ "age": 31,
+ "firstName": "Barrett",
+ "lastName": "Weaver",
+ "company": "DUOFLEX",
+ "email": "barrett.weaver@duoflex.de",
+ "registered": "Tuesday, November 3, 2015 9:31 AM",
+ "latitude": "40.30558",
+ "longitude": "-69.986664"
+ },
+ {
+ "_id": "5c0e1839b5658f90e16a86e0",
+ "index": 21,
+ "guid": "81f894c4-c931-422d-a30e-593824d95bf9",
+ "isActive": true,
+ "balance": "$2,808.63",
+ "age": 26,
+ "firstName": "Baxter",
+ "lastName": "Chase",
+ "company": "BUNGA",
+ "email": "baxter.chase@bunga.de",
+ "registered": "Friday, October 28, 2016 7:10 AM",
+ "latitude": "-49.05652",
+ "longitude": "63.123535"
+ },
+ {
+ "_id": "5c0e1839cb9462c9ecbb59af",
+ "index": 22,
+ "guid": "92e67862-4fdf-43af-a3ef-ef3edb8d6706",
+ "isActive": true,
+ "balance": "$3,552.71",
+ "age": 29,
+ "firstName": "Olga",
+ "lastName": "Kemp",
+ "company": "OHMNET",
+ "email": "olga.kemp@ohmnet.de",
+ "registered": "Saturday, March 26, 2016 11:51 AM",
+ "latitude": "-17.450481",
+ "longitude": "-13.945794"
+ },
+ {
+ "_id": "5c0e18396f999c2b8ac731a9",
+ "index": 23,
+ "guid": "a682eaae-34f0-4973-b8a0-30972de0732b",
+ "isActive": false,
+ "balance": "$1,999.20",
+ "age": 21,
+ "firstName": "Ebony",
+ "lastName": "Le",
+ "company": "MULTRON",
+ "email": "ebony.le@multron.de",
+ "registered": "Friday, March 27, 2015 9:23 AM",
+ "latitude": "-70.380014",
+ "longitude": "173.20685"
+ },
+ {
+ "_id": "5c0e18391cfb28263eb42db7",
+ "index": 24,
+ "guid": "f1cddb5f-0b89-453e-b0c9-8193a56cc610",
+ "isActive": true,
+ "balance": "$2,950.91",
+ "age": 30,
+ "firstName": "Norman",
+ "lastName": "Price",
+ "company": "COMVEX",
+ "email": "norman.price@comvex.de",
+ "registered": "Tuesday, August 21, 2018 11:17 PM",
+ "latitude": "86.501469",
+ "longitude": "159.545352"
+ },
+ {
+ "_id": "5c0e18394a6be11128c7e5ca",
+ "index": 25,
+ "guid": "dadb738a-40fd-45b6-abac-023a803d95c2",
+ "isActive": true,
+ "balance": "$2,767.09",
+ "age": 25,
+ "firstName": "Sara",
+ "lastName": "Ruiz",
+ "company": "AUSTECH",
+ "email": "sara.ruiz@austech.de",
+ "registered": "Wednesday, June 20, 2018 6:34 AM",
+ "latitude": "86.784904",
+ "longitude": "-120.331325"
+ },
+ {
+ "_id": "5c0e183974631549eda97cea",
+ "index": 26,
+ "guid": "b5c43ee5-14ed-4ab5-b3db-b31a8bb65ceb",
+ "isActive": true,
+ "balance": "$3,235.42",
+ "age": 32,
+ "firstName": "Holly",
+ "lastName": "Santos",
+ "company": "LOVEPAD",
+ "email": "holly.santos@lovepad.de",
+ "registered": "Thursday, November 22, 2018 9:26 PM",
+ "latitude": "-19.640066",
+ "longitude": "50.410992"
+ },
+ {
+ "_id": "5c0e1839ab9b933881429d78",
+ "index": 27,
+ "guid": "94961092-65ca-41b9-bc69-3e40ce2cafc9",
+ "isActive": true,
+ "balance": "$2,106.34",
+ "age": 39,
+ "firstName": "Rachel",
+ "lastName": "Douglas",
+ "company": "DEMINIMUM",
+ "email": "rachel.douglas@deminimum.de",
+ "registered": "Sunday, April 9, 2017 3:55 AM",
+ "latitude": "31.395281",
+ "longitude": "-1.899514"
+ },
+ {
+ "_id": "5c0e183937f743155859c5a9",
+ "index": 28,
+ "guid": "07d7ef18-bcef-483d-999e-0b3da4a7098b",
+ "isActive": true,
+ "balance": "$2,260.65",
+ "age": 40,
+ "firstName": "Reed",
+ "lastName": "Workman",
+ "company": "BUZZMAKER",
+ "email": "reed.workman@buzzmaker.de",
+ "registered": "Wednesday, May 28, 2014 3:44 PM",
+ "latitude": "23.789646",
+ "longitude": "106.938375"
+ },
+ {
+ "_id": "5c0e1839f8f4b60beb28b7ed",
+ "index": 29,
+ "guid": "9b4952e5-aa0e-4919-9e17-7c357a297394",
+ "isActive": false,
+ "balance": "$702.99",
+ "age": 27,
+ "firstName": "Cochran",
+ "lastName": "Ware",
+ "company": "HIVEDOM",
+ "email": "cochran.ware@hivedom.de",
+ "registered": "Monday, October 16, 2017 5:51 AM",
+ "latitude": "85.953108",
+ "longitude": "124.590037"
+ },
+ {
+ "_id": "5c0e1839342fbd54a88269df",
+ "index": 30,
+ "guid": "30937d5b-9514-4ebd-b628-2cfb5017fe41",
+ "isActive": false,
+ "balance": "$385.88",
+ "age": 35,
+ "firstName": "Cote",
+ "lastName": "Hess",
+ "company": "TERAPRENE",
+ "email": "cote.hess@teraprene.de",
+ "registered": "Thursday, March 15, 2018 4:42 PM",
+ "latitude": "81.38211",
+ "longitude": "64.516797"
+ },
+ {
+ "_id": "5c0e18395b6dc85d73ce1fb3",
+ "index": 31,
+ "guid": "f34847da-7f96-4cd8-8d8a-b06c0eb0a8f2",
+ "isActive": true,
+ "balance": "$3,494.56",
+ "age": 27,
+ "firstName": "Daniels",
+ "lastName": "Ayala",
+ "company": "BESTO",
+ "email": "daniels.ayala@besto.de",
+ "registered": "Sunday, December 18, 2016 10:52 AM",
+ "latitude": "47.704227",
+ "longitude": "41.674767"
+ },
+ {
+ "_id": "5c0e183974587cdccf30b13f",
+ "index": 32,
+ "guid": "fdbb6d83-0e47-4453-b8a7-b47f44e4164b",
+ "isActive": false,
+ "balance": "$2,087.38",
+ "age": 26,
+ "firstName": "Powers",
+ "lastName": "Drake",
+ "company": "GENESYNK",
+ "email": "powers.drake@genesynk.de",
+ "registered": "Saturday, September 29, 2018 12:24 AM",
+ "latitude": "40.580432",
+ "longitude": "110.940759"
+ },
+ {
+ "_id": "5c0e18397b51245e971c58b8",
+ "index": 33,
+ "guid": "6adfe544-238b-4001-b2a6-f50ea3094da3",
+ "isActive": true,
+ "balance": "$3,566.22",
+ "age": 34,
+ "firstName": "Pacheco",
+ "lastName": "Ramsey",
+ "company": "ENVIRE",
+ "email": "pacheco.ramsey@envire.de",
+ "registered": "Friday, September 11, 2015 12:14 AM",
+ "latitude": "-30.691235",
+ "longitude": "69.343692"
+ },
+ {
+ "_id": "5c0e18391ede9c0996fd09e7",
+ "index": 34,
+ "guid": "d190b32f-d33b-4c17-a18a-bb2f57e79ba7",
+ "isActive": false,
+ "balance": "$1,671.63",
+ "age": 32,
+ "firstName": "Mcintyre",
+ "lastName": "Chan",
+ "company": "ORBAXTER",
+ "email": "mcintyre.chan@orbaxter.de",
+ "registered": "Wednesday, May 7, 2014 7:11 PM",
+ "latitude": "7.380435",
+ "longitude": "70.955103"
+ },
+ {
+ "_id": "5c0e1839fe48069c9c260fa9",
+ "index": 35,
+ "guid": "a41c064b-6bf4-4ba5-b229-9b657d286936",
+ "isActive": false,
+ "balance": "$24.02",
+ "age": 27,
+ "firstName": "Genevieve",
+ "lastName": "Sparks",
+ "company": "ZBOO",
+ "email": "genevieve.sparks@zboo.de",
+ "registered": "Saturday, December 16, 2017 2:51 PM",
+ "latitude": "-63.406337",
+ "longitude": "118.662621"
+ },
+ {
+ "_id": "5c0e1839a7e8e76accf0803e",
+ "index": 36,
+ "guid": "3e71864d-4be5-418e-ace8-346c3d7a9c5f",
+ "isActive": true,
+ "balance": "$3,261.01",
+ "age": 30,
+ "firstName": "Powell",
+ "lastName": "Patterson",
+ "company": "GAZAK",
+ "email": "powell.patterson@gazak.de",
+ "registered": "Thursday, May 18, 2017 10:10 AM",
+ "latitude": "-10.428548",
+ "longitude": "64.979192"
+ },
+ {
+ "_id": "5c0e183984b0320f1118a8b0",
+ "index": 37,
+ "guid": "ec5b292c-6efb-471b-9bf5-a47286e03515",
+ "isActive": false,
+ "balance": "$918.71",
+ "age": 37,
+ "firstName": "Tara",
+ "lastName": "Mcmillan",
+ "company": "GRAINSPOT",
+ "email": "tara.mcmillan@grainspot.de",
+ "registered": "Sunday, May 17, 2015 1:01 PM",
+ "latitude": "-13.519031",
+ "longitude": "67.931062"
+ },
+ {
+ "_id": "5c0e183965875876835ccd79",
+ "index": 38,
+ "guid": "b7e97ffb-439a-4454-90af-7f5ebd565ebc",
+ "isActive": true,
+ "balance": "$574.99",
+ "age": 28,
+ "firstName": "Pennington",
+ "lastName": "Gallegos",
+ "company": "CEDWARD",
+ "email": "pennington.gallegos@cedward.de",
+ "registered": "Wednesday, September 26, 2018 6:01 AM",
+ "latitude": "-63.693261",
+ "longitude": "-38.352153"
+ },
+ {
+ "_id": "5c0e183922505dd21be49009",
+ "index": 39,
+ "guid": "5187aa39-4357-462b-9508-3c537d26d70d",
+ "isActive": false,
+ "balance": "$2,447.08",
+ "age": 26,
+ "firstName": "Meagan",
+ "lastName": "Irwin",
+ "company": "SENTIA",
+ "email": "meagan.irwin@sentia.de",
+ "registered": "Saturday, April 2, 2016 4:39 PM",
+ "latitude": "1.051313",
+ "longitude": "-86.168315"
+ },
+ {
+ "_id": "5c0e183900a9f7f896e5b3b1",
+ "index": 40,
+ "guid": "31889843-79e7-4636-9ca1-4eb5cbcb0ae3",
+ "isActive": true,
+ "balance": "$1,992.25",
+ "age": 22,
+ "firstName": "Kelly",
+ "lastName": "Cobb",
+ "company": "BOVIS",
+ "email": "kelly.cobb@bovis.de",
+ "registered": "Tuesday, August 9, 2016 5:36 PM",
+ "latitude": "-85.547579",
+ "longitude": "-89.794104"
+ },
+ {
+ "_id": "5c0e18393b25b8552ff950e2",
+ "index": 41,
+ "guid": "0bf02edc-ca1b-4cfe-8356-b65881bdca11",
+ "isActive": true,
+ "balance": "$465.96",
+ "age": 27,
+ "firstName": "Angela",
+ "lastName": "Booker",
+ "company": "EQUICOM",
+ "email": "angela.booker@equicom.de",
+ "registered": "Thursday, July 30, 2015 1:39 AM",
+ "latitude": "-9.345395",
+ "longitude": "107.070665"
+ },
+ {
+ "_id": "5c0e183955d747ebbe25437b",
+ "index": 42,
+ "guid": "6405e559-5849-4d12-ae4e-520f13b4dffe",
+ "isActive": true,
+ "balance": "$15.63",
+ "age": 28,
+ "firstName": "Carrie",
+ "lastName": "Mclean",
+ "company": "BOINK",
+ "email": "carrie.mclean@boink.de",
+ "registered": "Wednesday, February 1, 2017 1:50 PM",
+ "latitude": "72.287519",
+ "longitude": "-135.436286"
+ },
+ {
+ "_id": "5c0e1839e9cfe1b28e31e7e6",
+ "index": 43,
+ "guid": "e49e7ca7-a6cc-4cdb-bebe-5a3b6ba931eb",
+ "isActive": true,
+ "balance": "$3,127.94",
+ "age": 33,
+ "firstName": "Callie",
+ "lastName": "Cooley",
+ "company": "MUSIX",
+ "email": "callie.cooley@musix.de",
+ "registered": "Wednesday, August 30, 2017 4:58 PM",
+ "latitude": "-38.954739",
+ "longitude": "-152.706424"
+ },
+ {
+ "_id": "5c0e18391bafa0750ff4f280",
+ "index": 44,
+ "guid": "c245ffd3-4924-4dce-ae4a-f4cabf057b54",
+ "isActive": false,
+ "balance": "$1,320.36",
+ "age": 35,
+ "firstName": "Terry",
+ "lastName": "Bennett",
+ "company": "EXOTECHNO",
+ "email": "terry.bennett@exotechno.de",
+ "registered": "Friday, June 17, 2016 11:54 PM",
+ "latitude": "-48.946183",
+ "longitude": "32.53167"
+ },
+ {
+ "_id": "5c0e1839e91b27fcce34b70f",
+ "index": 45,
+ "guid": "0860cb66-de4c-410e-8233-aeef5ee9d64e",
+ "isActive": false,
+ "balance": "$1,187.75",
+ "age": 30,
+ "firstName": "Phoebe",
+ "lastName": "Bartlett",
+ "company": "VORATAK",
+ "email": "phoebe.bartlett@voratak.de",
+ "registered": "Tuesday, July 25, 2017 2:57 AM",
+ "latitude": "-63.208957",
+ "longitude": "-91.209743"
+ },
+ {
+ "_id": "5c0e183987e8a4e98415c8dd",
+ "index": 46,
+ "guid": "49219833-172c-4659-9192-d1116a5ca833",
+ "isActive": false,
+ "balance": "$3,225.24",
+ "age": 38,
+ "firstName": "Jordan",
+ "lastName": "Evans",
+ "company": "PHARMACON",
+ "email": "jordan.evans@pharmacon.de",
+ "registered": "Sunday, April 23, 2017 6:27 PM",
+ "latitude": "-59.454678",
+ "longitude": "67.251185"
+ },
+ {
+ "_id": "5c0e183944979692cc1a3e48",
+ "index": 47,
+ "guid": "680c4d15-d539-4db9-8793-a2f6d3f354aa",
+ "isActive": false,
+ "balance": "$2,913.14",
+ "age": 28,
+ "firstName": "Goodman",
+ "lastName": "Cain",
+ "company": "CAXT",
+ "email": "goodman.cain@caxt.de",
+ "registered": "Tuesday, November 1, 2016 6:11 PM",
+ "latitude": "-30.187547",
+ "longitude": "-164.313273"
+ },
+ {
+ "_id": "5c0e1839ef5312ac08e3cbc3",
+ "index": 48,
+ "guid": "85f5fa5d-b6b3-47c6-ad1b-faee10a4e1bd",
+ "isActive": true,
+ "balance": "$544.97",
+ "age": 27,
+ "firstName": "Aisha",
+ "lastName": "Oliver",
+ "company": "MINGA",
+ "email": "aisha.oliver@minga.de",
+ "registered": "Sunday, July 3, 2016 8:18 AM",
+ "latitude": "-21.527536",
+ "longitude": "141.029691"
+ },
+ {
+ "_id": "5c0e1839c2e58f5da04f29fd",
+ "index": 49,
+ "guid": "e2ee9b25-5887-49a9-a1c6-17432154d266",
+ "isActive": true,
+ "balance": "$3,621.65",
+ "age": 31,
+ "firstName": "Erin",
+ "lastName": "Lester",
+ "company": "SLOFAST",
+ "email": "erin.lester@slofast.de",
+ "registered": "Saturday, February 20, 2016 5:13 AM",
+ "latitude": "-30.080798",
+ "longitude": "-1.291093"
+ }
+];
+
+const components = {
+ 'counter': 'demoApp.counter'
+};
+
+class TreeDemoItem implements ITreeItem {
+ title: string;
+ children?: TreeDemoItem[];
+ disabled?: boolean;
+ icon?: React.ComponentType<SvgIconProps>;
+}
+
+const treeData: TreeDemoItem[] = [
+ {
+ title: "Erste Ebene", children: [
+ {
+ title: "Zweite Ebene", children: [
+ { title: "Dritte Ebene" },
+ ]
+ },
+ { title: "Zweite Ebene 2" },
+ ]
+ },
+ { title: "Erste Ebene 3" },
+];
+
+const SampleDataMaterialTable = MaterialTable as MaterialTableCtorType<SampleData>;
+
+const SampleTree = TreeView as any as TreeViewCtorType<TreeDemoItem>;
+
+const TestComponent = (props: WithComponents<typeof components> & WithStyles<typeof styles>) => {
+
+ return (
+ <div>
+ <h2>About</h2>
+ <ExpansionPanel>
+ <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography className={props.classes.heading}>Client Side Table Demo</Typography>
+ </ExpansionPanelSummary>
+ <ExpansionPanelDetails>
+ <SampleDataMaterialTable rows={tableData} columns={
+ [
+ { property: "index", type: ColumnType.text, title: "Index", width: "80px", disableFilter: true, disableSorting: true },
+ { property: "firstName", type: ColumnType.text, title: "First Name" },
+ { property: "lastName", type: ColumnType.text, title: "Last Name" },
+ { property: "age", type: ColumnType.numeric, title: "Age", width: "60px" },
+ { property: "email", type: ColumnType.text, title: "eMail" },
+ { property: "actions", type: ColumnType.custom, title: "Actions", customControl: ({ rowData }) => (<div>Button</div>) },
+ ]
+ } idProperty={"_id"} title={"Customers 2018"} >
+ </SampleDataMaterialTable>
+ </ExpansionPanelDetails>
+ </ExpansionPanel>
+ <ExpansionPanel>
+ <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
+ <Typography className={props.classes.heading}>Tree Demo</Typography>
+ </ExpansionPanelSummary>
+ <ExpansionPanelDetails>
+ <SampleTree items={treeData} contentProperty={"title"} childrenProperty={"children"} useFolderIcons enableSearchBar />
+ </ExpansionPanelDetails>
+ </ExpansionPanel>
+ </div>
+ )
+};
+
+export const Test = withComponents(components)(withStyles(styles)(TestComponent));
+export default Test;
diff --git a/sdnr/wt/odlux/framework/tsconfig.json b/sdnr/wt/odlux/framework/tsconfig.json
new file mode 100644
index 000000000..d801f7c8e
--- /dev/null
+++ b/sdnr/wt/odlux/framework/tsconfig.json
@@ -0,0 +1,39 @@
+{
+ "compilerOptions": {
+ "baseUrl": "./src",
+ "outDir": "./dist",
+ "sourceMap": true,
+ "forceConsistentCasingInFileNames": true,
+ "allowSyntheticDefaultImports": false,
+ "allowUnreachableCode": false,
+ "allowUnusedLabels": false,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "pretty": true,
+ "newLine": "LF",
+ "module": "es2015",
+ "target": "es2016",
+ "moduleResolution": "node",
+ "experimentalDecorators": true,
+ "jsx": "preserve",
+ "lib": [
+ "dom",
+ "es2015",
+ "es2016"
+ ],
+ "types": [
+ "node",
+ "prop-types",
+ "react",
+ "react-dom",
+ "jest"
+ ]
+ },
+ "exclude": [
+ "dist",
+ "node_modules"
+ ]
+}
diff --git a/sdnr/wt/odlux/framework/webpack.config.js b/sdnr/wt/odlux/framework/webpack.config.js
new file mode 100644
index 000000000..578a0ae44
--- /dev/null
+++ b/sdnr/wt/odlux/framework/webpack.config.js
@@ -0,0 +1,203 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const CopyWebpackPlugin = require("copy-webpack-plugin");
+const requirejsPlugin = require('requirejs-webpack-plugin');
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ return [{
+ name: "Client",
+ mode: "none", //disable default behavior
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ app: [
+ "./app.tsx",
+ "./services",
+ "./components/material-table",
+ "./components/material-ui",
+ "./utilities/elasticSearch",
+ "./models"],
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ library: "[name]", // related to webpack.DllPlugin::name
+ libraryTarget: "umd2",
+ filename: "[name].js",
+ chunkFilename: "[name].js"
+ },
+
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }, {
+ test: /\.(png|gif|jpg|svg)$/,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: './images/[hash].[ext]'
+ }
+ }]
+ }]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ mangle: {
+ reserved: ["./app.tsx"]
+ },
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ new CopyWebpackPlugin([{
+ from: '../../node_modules/requirejs/require.js',
+ to: '.'
+ }, {
+ from: './favicon.ico',
+ to: '.'
+ }, {
+ from: env === "release" ? './index.html' : 'index.dev.html',
+ to: './index.html'
+ }]),
+ new requirejsPlugin({
+ path: distPath,
+ filename: 'config.js',
+ baseUrl: '',
+ pathUrl: '',
+ processOutput: function (assets) {
+ return 'require.config(' + JSON.stringify(assets, null, 2) + ')';
+ }
+ }),
+ // new HtmlWebpackPlugin({
+ // filename: "index.html",
+ // template: "./index.html",
+ // inject: "head"
+ // }),
+ // new HtmlWebpackIncludeAssetsPlugin({
+ // assets: ['vendor.js'],
+ // append: false
+ // }),
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "src"),
+ manifest: require(path.resolve(frameworkPath, "vendor-manifest.json")),
+ sourceType: "umd2"
+ }),
+ new webpack.DllPlugin({
+ context: path.resolve(__dirname, "src"),
+ name: "[name]",
+ path: path.resolve(distPath, "[name]-manifest.json")
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ ] : [
+ new webpack.HotModuleReplacementPlugin(),
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new webpack.WatchIgnorePlugin([
+ /css\.d\.ts$/,
+ /less\.d\.ts$/
+ ])
+ ]
+ ],
+
+ devServer: {
+ public: "http://localhost:3100",
+ contentBase: distPath,
+
+ compress: true,
+ headers: {
+ "Access-Control-Allow-Origin": "*"
+ },
+ host: "0.0.0.0",
+ port: 3100,
+ disableHostCheck: true,
+ historyApiFallback: true,
+ inline: true,
+ hot: false,
+ quiet: false,
+ stats: {
+ colors: true
+ },
+ proxy: {
+ "/oauth2/**/*": {
+ target: "http://10.20.6.29:48181",
+ secure: false
+ }
+ }
+ }
+
+ }];
+}
+
+
diff --git a/sdnr/wt/odlux/framework/webpack.runner.js b/sdnr/wt/odlux/framework/webpack.runner.js
new file mode 100644
index 000000000..c07721f5c
--- /dev/null
+++ b/sdnr/wt/odlux/framework/webpack.runner.js
@@ -0,0 +1,85 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+const TerserPlugin = require('terser-webpack-plugin');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ return [{
+ name: "App",
+
+ mode: "none", //disable default behavior
+
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ run: ["./run.ts"]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ filename: "[name].js",
+ library: "[name]",
+ libraryTarget: "umd2",
+ chunkFilename: "[name].js"
+ },
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ }, {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ }]
+ },
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+ plugins: [
+ new webpack.DllReferencePlugin({
+ context: path.resolve(__dirname, "./src"),
+ manifest: require(path.resolve(frameworkPath, "app-manifest.json")),
+ sourceType: "umd2"
+ }),
+
+ ]
+ }
+ ]
+}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/webpack.vendor.js b/sdnr/wt/odlux/framework/webpack.vendor.js
new file mode 100644
index 000000000..649c9b974
--- /dev/null
+++ b/sdnr/wt/odlux/framework/webpack.vendor.js
@@ -0,0 +1,130 @@
+/**
+ * Webpack 4 configuration file
+ * see https://webpack.js.org/configuration/
+ * see https://webpack.js.org/configuration/dev-server/
+ */
+
+"use strict";
+
+const path = require("path");
+const webpack = require("webpack");
+
+const TerserPlugin = require('terser-webpack-plugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const extractCSS = new ExtractTextPlugin('vendor.css');
+
+// const __dirname = (path => path.replace(/^([a-z]\:)/, c => c.toUpperCase()))(process.__dirname());
+
+module.exports = (env) => {
+ const distPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ const frameworkPath = path.resolve(__dirname, env === "release" ? "." : "..", "dist");
+ return [{
+ name: "Vendor",
+ mode: "none", //disable default behavior
+ target: "web",
+
+ context: path.resolve(__dirname, "src"),
+
+ entry: {
+ vendor: [
+ "@babel/polyfill",
+ "@fortawesome/fontawesome-svg-core",
+ "@fortawesome/free-solid-svg-icons",
+ "@fortawesome/react-fontawesome",
+ "jquery",
+ "react",
+ "react-dom",
+ "react-router-dom",
+ "@material-ui/core"
+ ]
+ },
+
+ devtool: env === "release" ? false : "source-map",
+
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"]
+ },
+
+ output: {
+ path: distPath,
+ library: "[name]", // related to webpack.DllPlugin::name
+ libraryTarget: "umd2",
+ filename: "[name].js",
+ chunkFilename: "[name].js"
+ },
+
+ module: {
+ rules: [{
+ test: /\.tsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }, {
+ loader: "ts-loader"
+ }]
+ },
+ {
+ test: /\.jsx?$/,
+ exclude: /node_modules/,
+ use: [{
+ loader: "babel-loader"
+ }]
+ },
+ {
+ test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+ loader: 'url-loader?limit=100000&name=assets/[name].[ext]'
+ }, {
+ test: /\.s?css$/i,
+ loader: extractCSS.extract(['css-loader?minimize', 'sass-loader'])
+ }, {
+ test: /\.json$/,
+ loader: 'json-loader'
+ },
+ ]
+ },
+
+ optimization: {
+ noEmitOnErrors: true,
+ namedModules: env !== "release",
+ minimize: env === "release",
+ minimizer: env !== "release" ? [] : [new TerserPlugin({
+ terserOptions: {
+ warnings: false, // false, true, "verbose"
+ compress: {
+ drop_console: true,
+ drop_debugger: true,
+ }
+ }
+ })],
+ },
+
+ plugins: [
+ extractCSS,
+ new webpack.DllPlugin({
+ context: path.resolve(__dirname, "src"),
+ name: "[name]",
+ path: path.resolve(distPath, "[name]-manifest.json")
+ }),
+ ...(env === "release") ? [
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'production'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ })
+ ] : [
+ new webpack.HotModuleReplacementPlugin(),
+ new webpack.DefinePlugin({
+ "process.env": {
+ NODE_ENV: "'development'",
+ VERSION: JSON.stringify(require("./package.json").version)
+ }
+ }),
+ new webpack.WatchIgnorePlugin([
+ /s?css\.d\.ts$/,
+ /less\.d\.ts$/
+ ])
+ ]
+ ]
+ }];
+}
diff --git a/sdnr/wt/odlux/jest.json b/sdnr/wt/odlux/jest.json
new file mode 100644
index 000000000..5d6e74825
--- /dev/null
+++ b/sdnr/wt/odlux/jest.json
@@ -0,0 +1,18 @@
+{
+ "moduleFileExtensions": [
+ "ts",
+ "tsx",
+ "js",
+ "jsx"
+ ],
+ "moduleNameMapper": {
+ "^@odlux/framework$": "<rootDir>/framework/src",
+ "^@odlux/(.*)$": "<rootDir>/apps/$1/src"
+ },
+ "transform": {
+ "^.+\\.(ts|tsx)$": "ts-jest"
+ },
+ "testMatch": [
+ "**/*-test.(ts|tsx)"
+ ]
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/lerna.json b/sdnr/wt/odlux/lerna.json
new file mode 100644
index 000000000..744f9e374
--- /dev/null
+++ b/sdnr/wt/odlux/lerna.json
@@ -0,0 +1,12 @@
+{
+ "lerna": "2.9.0",
+ "version": "independent",
+ "command": {
+ "init": {
+ "exact": true
+ }
+ },
+ "npmClient": "yarn",
+ "useWorkspaces": true,
+ "packages": ["framework","apps/*"]
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/package.json b/sdnr/wt/odlux/package.json
new file mode 100644
index 000000000..5d4714dac
--- /dev/null
+++ b/sdnr/wt/odlux/package.json
@@ -0,0 +1,82 @@
+{
+ "private": true,
+ "version": "0.1.0",
+ "workspaces": [
+ "framework",
+ "apps/*"
+ ],
+ "scripts": {
+ "init": "lerna bootstrap --hoist",
+ "build": "lerna build",
+ "test": "jest --no-cache --coverage --config jest.json"
+ },
+ "dependencies": {
+ "@fortawesome/fontawesome-svg-core": "1.2.12",
+ "@fortawesome/free-solid-svg-icons": "5.6.3",
+ "@fortawesome/react-fontawesome": "0.1.3",
+ "@material-ui/core": "4.6.1",
+ "@material-ui/icons": "4.5.1",
+ "@types/classnames": "2.2.6",
+ "@types/flux": "3.1.8",
+ "@types/jquery": "3.3.10",
+ "@types/jsonwebtoken": "7.2.8",
+ "@types/node": "11.11.6",
+ "@types/react": "16.9.11",
+ "@types/react-dom": "16.9.4",
+ "@types/react-router-dom": "4.3.1",
+ "@types/react-transition-group": "2.0.15",
+ "@types/x2js": "3.1.0",
+ "classnames": "2.2.6",
+ "jquery": "3.3.1",
+ "jsonwebtoken": "8.3.0",
+ "lerna": "3.13.1",
+ "notistack": "0.9.6",
+ "prop-types": "15.7.2",
+ "react": "16.11.0",
+ "react-dom": "16.11.0",
+ "react-router-dom": "4.3.1",
+ "react-transition-group": "4.3.0",
+ "x2js": "3.2.3"
+ },
+ "devDependencies": {
+ "@babel/core": "7.1.0",
+ "@babel/polyfill": "7.0.0",
+ "@babel/preset-env": "7.1.0",
+ "@babel/preset-react": "7.0.0",
+ "@types/jest": "23.3.12",
+ "autoprefixer": "9.1.5",
+ "babel-loader": "8.0.4",
+ "copy-webpack-plugin": "4.5.2",
+ "css-loader": "1.0.0",
+ "extract-text-webpack-plugin": "next",
+ "file-loader": "2.0.0",
+ "html-webpack-include-assets-plugin": "1.0.5",
+ "html-webpack-plugin": "3.2.0",
+ "jest": "23.6.0",
+ "less": "3.8.1",
+ "less-loader": "4.1.0",
+ "node-sass": "4.9.3",
+ "postcss-loader": "3.0.0",
+ "requirejs": "2.3.6",
+ "requirejs-webpack-plugin": "1.0.5",
+ "rimraf": "2.6.2",
+ "sass-loader": "7.1.0",
+ "style-loader": "0.23.0",
+ "terser-webpack-plugin": "1.2.1",
+ "ts-jest": "23.10.5",
+ "ts-loader": "5.2.1",
+ "tslint": "5.12.1",
+ "tslint-config-airbnb": "5.11.1",
+ "tslint-config-airbnb-base": "0.2.0",
+ "tslint-config-prettier": "1.17.0",
+ "tslint-eslint-rules": "4.1.1",
+ "tslint-react": "3.6.0",
+ "tslint-react-recommended": "1.0.15",
+ "typescript": "3.7.2",
+ "typings-for-css-modules-loader": "1.7.0",
+ "url-loader": "1.1.2",
+ "webpack": "4.28.4",
+ "webpack-cli": "3.2.1",
+ "webpack-dev-server": "3.1.14"
+ }
+}
diff --git a/sdnr/wt/odlux/pom.xml b/sdnr/wt/odlux/pom.xml
new file mode 100644
index 000000000..cade21b30
--- /dev/null
+++ b/sdnr/wt/odlux/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.5.1-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
+ <artifactId>odlux-top</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>odlux</name>
+
+ <modules>
+ <module>framework</module>
+ <module>core</module>
+ <module>apps/apiDemo</module>
+ <module>apps/connectApp</module>
+ <module>apps/demoApp</module>
+ <module>apps/faultApp</module>
+ <module>apps/helpApp</module>
+ <module>apps/inventoryApp</module>
+ <module>apps/mediatorApp</module>
+ <module>apps/maintenanceApp</module>
+ <module>apps/minimumApp</module>
+ <module>apps/performanceHistoryApp</module>
+ <module>apps/eventLogApp</module>
+ <module>apps/configurationApp</module>
+ <module>apps/app-feature</module>
+ <module>apps/app-installer</module>
+ </modules>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>exec-maven-plugin</artifactId>
+ <groupId>org.codehaus.mojo</groupId>
+ <executions>
+ <execution><!-- Run our version calculation script -->
+ <id>Clean node and node_modules</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <executable>rm</executable>
+ <arguments>
+ <argument>-r</argument>
+ <argument>node_modules</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/sdnr/wt/odlux/yarn.lock b/sdnr/wt/odlux/yarn.lock
new file mode 100644
index 000000000..9ce3e4baf
--- /dev/null
+++ b/sdnr/wt/odlux/yarn.lock
@@ -0,0 +1,11055 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35", "@babel/code-frame@^7.5.5":
+ version "7.5.5"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d"
+ integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==
+ dependencies:
+ "@babel/highlight" "^7.0.0"
+
+"@babel/core@7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.0.tgz#08958f1371179f62df6966d8a614003d11faeb04"
+ integrity sha512-9EWmD0cQAbcXSc+31RIoYgEHx3KQ2CCSMDBhnXrShWvo45TMw+3/55KVxlhkG53kw9tl87DqINgHDgFVhZJV/Q==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/generator" "^7.0.0"
+ "@babel/helpers" "^7.1.0"
+ "@babel/parser" "^7.1.0"
+ "@babel/template" "^7.1.0"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ convert-source-map "^1.1.0"
+ debug "^3.1.0"
+ json5 "^0.5.0"
+ lodash "^4.17.10"
+ resolve "^1.3.2"
+ semver "^5.4.1"
+ source-map "^0.5.0"
+
+"@babel/generator@^7.0.0", "@babel/generator@^7.7.2":
+ version "7.7.2"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af"
+ integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==
+ dependencies:
+ "@babel/types" "^7.7.2"
+ jsesc "^2.5.1"
+ lodash "^4.17.13"
+ source-map "^0.5.0"
+
+"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz#efc54032d43891fe267679e63f6860aa7dbf4a5e"
+ integrity sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz#32dd9551d6ed3a5fc2edc50d6912852aa18274d9"
+ integrity sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==
+ dependencies:
+ "@babel/helper-explode-assignable-expression" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-builder-react-jsx@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.7.0.tgz#c6b8254d305bacd62beb648e4dea7d3ed79f352d"
+ integrity sha512-LSln3cexwInTMYYoFeVLKnYPPMfWNJ8PubTBs3hkh7wCu9iBaqq1OOyW+xGmEdLxT1nhsl+9SJ+h2oUDYz0l2A==
+ dependencies:
+ "@babel/types" "^7.7.0"
+ esutils "^2.0.0"
+
+"@babel/helper-call-delegate@^7.4.4":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz#df8942452c2c1a217335ca7e393b9afc67f668dc"
+ integrity sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-create-regexp-features-plugin@^7.7.0":
+ version "7.7.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz#6f20443778c8fce2af2ff4206284afc0ced65db6"
+ integrity sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==
+ dependencies:
+ "@babel/helper-regex" "^7.4.4"
+ regexpu-core "^4.6.0"
+
+"@babel/helper-define-map@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz#60b0e9fd60def9de5054c38afde8c8ee409c7529"
+ integrity sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==
+ dependencies:
+ "@babel/helper-function-name" "^7.7.0"
+ "@babel/types" "^7.7.0"
+ lodash "^4.17.13"
+
+"@babel/helper-explode-assignable-expression@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz#db2a6705555ae1f9f33b4b8212a546bc7f9dc3ef"
+ integrity sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==
+ dependencies:
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-function-name@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3"
+ integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.7.0"
+ "@babel/template" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-get-function-arity@^7.0.0", "@babel/helper-get-function-arity@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d"
+ integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-hoist-variables@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz#b4552e4cfe5577d7de7b183e193e84e4ec538c81"
+ integrity sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-member-expression-to-functions@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz#472b93003a57071f95a541ea6c2b098398bcad8a"
+ integrity sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz#99c095889466e5f7b6d66d98dffc58baaf42654d"
+ integrity sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz#154a69f0c5b8fd4d39e49750ff7ac4faa3f36786"
+ integrity sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.7.0"
+ "@babel/helper-simple-access" "^7.7.0"
+ "@babel/helper-split-export-declaration" "^7.7.0"
+ "@babel/template" "^7.7.0"
+ "@babel/types" "^7.7.0"
+ lodash "^4.17.13"
+
+"@babel/helper-optimise-call-expression@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz#4f66a216116a66164135dc618c5d8b7a959f9365"
+ integrity sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-plugin-utils@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
+ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+
+"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4":
+ version "7.5.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351"
+ integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==
+ dependencies:
+ lodash "^4.17.13"
+
+"@babel/helper-remap-async-to-generator@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz#4d69ec653e8bff5bce62f5d33fc1508f223c75a7"
+ integrity sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.7.0"
+ "@babel/helper-wrap-function" "^7.7.0"
+ "@babel/template" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-replace-supers@^7.5.5", "@babel/helper-replace-supers@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz#d5365c8667fe7cbd13b8ddddceb9bd7f2b387512"
+ integrity sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==
+ dependencies:
+ "@babel/helper-member-expression-to-functions" "^7.7.0"
+ "@babel/helper-optimise-call-expression" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-simple-access@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz#97a8b6c52105d76031b86237dc1852b44837243d"
+ integrity sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==
+ dependencies:
+ "@babel/template" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-split-export-declaration@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300"
+ integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==
+ dependencies:
+ "@babel/types" "^7.7.0"
+
+"@babel/helper-wrap-function@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz#15af3d3e98f8417a60554acbb6c14e75e0b33b74"
+ integrity sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==
+ dependencies:
+ "@babel/helper-function-name" "^7.7.0"
+ "@babel/template" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/helpers@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b"
+ integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==
+ dependencies:
+ "@babel/template" "^7.7.0"
+ "@babel/traverse" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/highlight@^7.0.0":
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
+ integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==
+ dependencies:
+ chalk "^2.0.0"
+ esutils "^2.0.2"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.1.0", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
+ version "7.7.3"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043"
+ integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==
+
+"@babel/plugin-proposal-async-generator-functions@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971"
+ integrity sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-remap-async-to-generator" "^7.7.0"
+ "@babel/plugin-syntax-async-generators" "^7.2.0"
+
+"@babel/plugin-proposal-json-strings@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317"
+ integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-json-strings" "^7.2.0"
+
+"@babel/plugin-proposal-object-rest-spread@^7.0.0":
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096"
+ integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.2.0"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5"
+ integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.2.0"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz#549fe1717a1bd0a2a7e63163841cb37e78179d5d"
+ integrity sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-async-generators@^7.0.0", "@babel/plugin-syntax-async-generators@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f"
+ integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-json-strings@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470"
+ integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-jsx@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7"
+ integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
+ integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.0.0", "@babel/plugin-syntax-optional-catch-binding@^7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c"
+ integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-arrow-functions@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550"
+ integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-async-to-generator@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz#e2b84f11952cf5913fe3438b7d2585042772f492"
+ integrity sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-remap-async-to-generator" "^7.7.0"
+
+"@babel/plugin-transform-block-scoped-functions@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190"
+ integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-block-scoping@^7.0.0":
+ version "7.6.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a"
+ integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ lodash "^4.17.13"
+
+"@babel/plugin-transform-classes@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz#b411ecc1b8822d24b81e5d184f24149136eddd4a"
+ integrity sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.7.0"
+ "@babel/helper-define-map" "^7.7.0"
+ "@babel/helper-function-name" "^7.7.0"
+ "@babel/helper-optimise-call-expression" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.7.0"
+ "@babel/helper-split-export-declaration" "^7.7.0"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da"
+ integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-destructuring@^7.0.0":
+ version "7.6.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6"
+ integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-dotall-regex@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz#c5c9ecacab3a5e0c11db6981610f0c32fd698b3b"
+ integrity sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-duplicate-keys@^7.0.0":
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz#c5dbf5106bf84cdf691222c0974c12b1df931853"
+ integrity sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-exponentiation-operator@^7.1.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008"
+ integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-for-of@^7.0.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556"
+ integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-function-name@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz#0fa786f1eef52e3b7d4fc02e54b2129de8a04c2a"
+ integrity sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==
+ dependencies:
+ "@babel/helper-function-name" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-literals@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1"
+ integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-amd@^7.1.0":
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz#ef00435d46da0a5961aa728a1d2ecff063e4fb91"
+ integrity sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-commonjs@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz#3e5ffb4fd8c947feede69cbe24c9554ab4113fe3"
+ integrity sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-simple-access" "^7.7.0"
+ babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-systemjs@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz#9baf471213af9761c1617bb12fd278e629041417"
+ integrity sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ babel-plugin-dynamic-import-node "^2.3.0"
+
+"@babel/plugin-transform-modules-umd@^7.1.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz#d62c7da16670908e1d8c68ca0b5d4c0097b69966"
+ integrity sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-new-target@^7.0.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5"
+ integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-object-super@^7.1.0":
+ version "7.5.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9"
+ integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.5.5"
+
+"@babel/plugin-transform-parameters@^7.1.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16"
+ integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==
+ dependencies:
+ "@babel/helper-call-delegate" "^7.4.4"
+ "@babel/helper-get-function-arity" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-react-display-name@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz#ebfaed87834ce8dc4279609a4f0c324c156e3eb0"
+ integrity sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-react-jsx-self@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz#461e21ad9478f1031dd5e276108d027f1b5240ba"
+ integrity sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@babel/plugin-transform-react-jsx-source@^7.0.0":
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz#583b10c49cf057e237085bcbd8cc960bd83bd96b"
+ integrity sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@babel/plugin-transform-react-jsx@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.7.0.tgz#834b0723ba78cd4d24d7d629300c2270f516d0b7"
+ integrity sha512-mXhBtyVB1Ujfy+0L6934jeJcSXj/VCg6whZzEcgiiZHNS0PGC7vUCsZDQCxxztkpIdF+dY1fUMcjAgEOC3ZOMQ==
+ dependencies:
+ "@babel/helper-builder-react-jsx" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-jsx" "^7.2.0"
+
+"@babel/plugin-transform-regenerator@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz#f1b20b535e7716b622c99e989259d7dd942dd9cc"
+ integrity sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==
+ dependencies:
+ regenerator-transform "^0.14.0"
+
+"@babel/plugin-transform-shorthand-properties@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0"
+ integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-spread@^7.0.0":
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd"
+ integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-sticky-regex@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1"
+ integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+
+"@babel/plugin-transform-template-literals@^7.0.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0"
+ integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-typeof-symbol@^7.0.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2"
+ integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-unicode-regex@^7.0.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz#743d9bcc44080e3cc7d49259a066efa30f9187a3"
+ integrity sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.7.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/polyfill@7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.0.0.tgz#c8ff65c9ec3be6a1ba10113ebd40e8750fb90bff"
+ integrity sha512-dnrMRkyyr74CRelJwvgnnSUDh2ge2NCTyHVwpOdvRMHtJUyxLtMAfhBN3s64pY41zdw0kgiLPh6S20eb1NcX6Q==
+ dependencies:
+ core-js "^2.5.7"
+ regenerator-runtime "^0.11.1"
+
+"@babel/preset-env@7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11"
+ integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-async-generator-functions" "^7.1.0"
+ "@babel/plugin-proposal-json-strings" "^7.0.0"
+ "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.0.0"
+ "@babel/plugin-syntax-async-generators" "^7.0.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-transform-arrow-functions" "^7.0.0"
+ "@babel/plugin-transform-async-to-generator" "^7.1.0"
+ "@babel/plugin-transform-block-scoped-functions" "^7.0.0"
+ "@babel/plugin-transform-block-scoping" "^7.0.0"
+ "@babel/plugin-transform-classes" "^7.1.0"
+ "@babel/plugin-transform-computed-properties" "^7.0.0"
+ "@babel/plugin-transform-destructuring" "^7.0.0"
+ "@babel/plugin-transform-dotall-regex" "^7.0.0"
+ "@babel/plugin-transform-duplicate-keys" "^7.0.0"
+ "@babel/plugin-transform-exponentiation-operator" "^7.1.0"
+ "@babel/plugin-transform-for-of" "^7.0.0"
+ "@babel/plugin-transform-function-name" "^7.1.0"
+ "@babel/plugin-transform-literals" "^7.0.0"
+ "@babel/plugin-transform-modules-amd" "^7.1.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.1.0"
+ "@babel/plugin-transform-modules-systemjs" "^7.0.0"
+ "@babel/plugin-transform-modules-umd" "^7.1.0"
+ "@babel/plugin-transform-new-target" "^7.0.0"
+ "@babel/plugin-transform-object-super" "^7.1.0"
+ "@babel/plugin-transform-parameters" "^7.1.0"
+ "@babel/plugin-transform-regenerator" "^7.0.0"
+ "@babel/plugin-transform-shorthand-properties" "^7.0.0"
+ "@babel/plugin-transform-spread" "^7.0.0"
+ "@babel/plugin-transform-sticky-regex" "^7.0.0"
+ "@babel/plugin-transform-template-literals" "^7.0.0"
+ "@babel/plugin-transform-typeof-symbol" "^7.0.0"
+ "@babel/plugin-transform-unicode-regex" "^7.0.0"
+ browserslist "^4.1.0"
+ invariant "^2.2.2"
+ js-levenshtein "^1.1.3"
+ semver "^5.3.0"
+
+"@babel/preset-react@7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.0.0.tgz#e86b4b3d99433c7b3e9e91747e2653958bc6b3c0"
+ integrity sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-transform-react-display-name" "^7.0.0"
+ "@babel/plugin-transform-react-jsx" "^7.0.0"
+ "@babel/plugin-transform-react-jsx-self" "^7.0.0"
+ "@babel/plugin-transform-react-jsx-source" "^7.0.0"
+
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3":
+ version "7.7.2"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a"
+ integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
+"@babel/template@^7.1.0", "@babel/template@^7.7.0":
+ version "7.7.0"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0"
+ integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/parser" "^7.7.0"
+ "@babel/types" "^7.7.0"
+
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.7.0":
+ version "7.7.2"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09"
+ integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==
+ dependencies:
+ "@babel/code-frame" "^7.5.5"
+ "@babel/generator" "^7.7.2"
+ "@babel/helper-function-name" "^7.7.0"
+ "@babel/helper-split-export-declaration" "^7.7.0"
+ "@babel/parser" "^7.7.2"
+ "@babel/types" "^7.7.2"
+ debug "^4.1.0"
+ globals "^11.1.0"
+ lodash "^4.17.13"
+
+"@babel/types@^7.0.0", "@babel/types@^7.7.0", "@babel/types@^7.7.2":
+ version "7.7.2"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
+ integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
+ dependencies:
+ esutils "^2.0.2"
+ lodash "^4.17.13"
+ to-fast-properties "^2.0.0"
+
+"@emotion/hash@^0.7.1":
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.3.tgz#a166882c81c0c6040975dd30df24fae8549bd96f"
+ integrity sha512-14ZVlsB9akwvydAdaEnVnvqu6J2P6ySv39hYyl/aoB6w/V+bXX0tay8cF6paqbgZsN2n5Xh15uF4pE+GvE+itw==
+
+"@fimbul/bifrost@^0.21.0":
+ version "0.21.0"
+ resolved "https://registry.yarnpkg.com/@fimbul/bifrost/-/bifrost-0.21.0.tgz#d0fafa25938fda475657a6a1e407a21bbe02c74e"
+ integrity sha512-ou8VU+nTmOW1jeg+FT+sn+an/M0Xb9G16RucrfhjXGWv1Q97kCoM5CG9Qj7GYOSdu7km72k7nY83Eyr53Bkakg==
+ dependencies:
+ "@fimbul/ymir" "^0.21.0"
+ get-caller-file "^2.0.0"
+ tslib "^1.8.1"
+ tsutils "^3.5.0"
+
+"@fimbul/ymir@^0.21.0":
+ version "0.21.0"
+ resolved "https://registry.yarnpkg.com/@fimbul/ymir/-/ymir-0.21.0.tgz#8525726787aceeafd4e199472c0d795160b5d4a1"
+ integrity sha512-T/y7WqPsm4n3zhT08EpB5sfdm2Kvw3gurAxr2Lr5dQeLi8ZsMlNT/Jby+ZmuuAAd1PnXYzKp+2SXgIkQIIMCUg==
+ dependencies:
+ inversify "^5.0.0"
+ reflect-metadata "^0.1.12"
+ tslib "^1.8.1"
+
+"@fortawesome/fontawesome-common-types@^0.2.12":
+ version "0.2.25"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.25.tgz#6df015905081f2762e5cfddeb7a20d2e9b16c786"
+ integrity sha512-3RuZPDuuPELd7RXtUqTCfed14fcny9UiPOkdr2i+cYxBoTOfQgxcDoq77fHiiHcgWuo1LoBUpvGxFF1H/y7s3Q==
+
+"@fortawesome/fontawesome-svg-core@1.2.12":
+ version "1.2.12"
+ resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.12.tgz#9732617b1e484435f6946645d7f9ad248f12c437"
+ integrity sha512-cqTfa3vZ+Z9UYQnmLfCOwyLnf0Xcoxkmm/BSaI29Yikzu9zIeD4es7lBZMDqLOXYSEQC+rCr8caxFlGJcJVA+w==
+ dependencies:
+ "@fortawesome/fontawesome-common-types" "^0.2.12"
+
+"@fortawesome/free-solid-svg-icons@5.6.3":
+ version "5.6.3"
+ resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.6.3.tgz#1d7f6669ccd6a1ea673699e41f7e32c81401a260"
+ integrity sha512-ld8Gfp1KrncOpFRheThUDlD6/Ro9ZJGqfCEMXlO/x1Cg7ltLc5iYDG7yxDowLcmFY2BGSmxIIU3ZMW5FVTrfwQ==
+ dependencies:
+ "@fortawesome/fontawesome-common-types" "^0.2.12"
+
+"@fortawesome/react-fontawesome@0.1.3":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.3.tgz#266b4047892c3d10498af1075d89252f74015b11"
+ integrity sha512-tc689l67rPZ7+ynZVUgOXY80rAt5KxvuH1qjPpJcbyJzJHzk5yhrD993BjsSEdPBLTtPqmvwynsO/XrAQqHbtg==
+ dependencies:
+ humps "^2.0.1"
+ prop-types "^15.5.10"
+
+"@lerna/add@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.13.1.tgz#2cd7838857edb3b43ed73e3c21f69a20beb9b702"
+ integrity sha512-cXk42YbuhzEnADCK8Qte5laC9Qo03eJLVnr0qKY85jQUM/T4URe3IIUemqpg0CpVATrB+Vz+iNdeqw9ng1iALw==
+ dependencies:
+ "@lerna/bootstrap" "3.13.1"
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/npm-conf" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ dedent "^0.7.0"
+ npm-package-arg "^6.1.0"
+ p-map "^1.2.0"
+ pacote "^9.5.0"
+ semver "^5.5.0"
+
+"@lerna/batch-packages@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/batch-packages/-/batch-packages-3.13.0.tgz#697fde5be28822af9d9dca2f750250b90a89a000"
+ integrity sha512-TgLBTZ7ZlqilGnzJ3xh1KdAHcySfHytgNRTdG9YomfriTU6kVfp1HrXxKJYVGs7ClPUNt2CTFEOkw0tMBronjw==
+ dependencies:
+ "@lerna/package-graph" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ npmlog "^4.1.2"
+
+"@lerna/bootstrap@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.13.1.tgz#f2edd7c8093c8b139e78b0ca5f845f23efd01f08"
+ integrity sha512-mKdi5Ds5f82PZwEFyB9/W60I3iELobi1i87sTeVrbJh/um7GvqpSPy7kG/JPxyOdMpB2njX6LiJgw+7b6BEPWw==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/has-npm-version" "3.13.0"
+ "@lerna/npm-install" "3.13.0"
+ "@lerna/package-graph" "3.13.0"
+ "@lerna/pulse-till-done" "3.13.0"
+ "@lerna/rimraf-dir" "3.13.0"
+ "@lerna/run-lifecycle" "3.13.0"
+ "@lerna/run-parallel-batches" "3.13.0"
+ "@lerna/symlink-binary" "3.13.0"
+ "@lerna/symlink-dependencies" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ dedent "^0.7.0"
+ get-port "^3.2.0"
+ multimatch "^2.1.0"
+ npm-package-arg "^6.1.0"
+ npmlog "^4.1.2"
+ p-finally "^1.0.0"
+ p-map "^1.2.0"
+ p-map-series "^1.0.0"
+ p-waterfall "^1.0.0"
+ read-package-tree "^5.1.6"
+ semver "^5.5.0"
+
+"@lerna/changed@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.13.1.tgz#dc92476aad43c932fe741969bbd0bcf6146a4c52"
+ integrity sha512-BRXitEJGOkoudbxEewW7WhjkLxFD+tTk4PrYpHLyCBk63pNTWtQLRE6dc1hqwh4emwyGncoyW6RgXfLgMZgryw==
+ dependencies:
+ "@lerna/collect-updates" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/listable" "3.13.0"
+ "@lerna/output" "3.13.0"
+ "@lerna/version" "3.13.1"
+
+"@lerna/check-working-tree@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.13.0.tgz#1ddcd4d9b1aceb65efaaa4cd1333a66706d67c9c"
+ integrity sha512-dsdO15NXX5To+Q53SYeCrBEpiqv4m5VkaPZxbGQZNwoRen1MloXuqxSymJANQn+ZLEqarv5V56gydebeROPH5A==
+ dependencies:
+ "@lerna/describe-ref" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+
+"@lerna/child-process@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.13.0.tgz#84e35adf3217a6983edd28080657b9596a052674"
+ integrity sha512-0iDS8y2jiEucD4fJHEzKoc8aQJgm7s+hG+0RmDNtfT0MM3n17pZnf5JOMtS1FJp+SEXOjMKQndyyaDIPFsnp6A==
+ dependencies:
+ chalk "^2.3.1"
+ execa "^1.0.0"
+ strong-log-transformer "^2.0.0"
+
+"@lerna/clean@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.13.1.tgz#9a7432efceccd720a51da5c76f849fc59c5a14ce"
+ integrity sha512-myGIaXv7RUO2qCFZXvx8SJeI+eN6y9SUD5zZ4/LvNogbOiEIlujC5lUAqK65rAHayQ9ltSa/yK6Xv510xhZXZQ==
+ dependencies:
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/prompt" "3.13.0"
+ "@lerna/pulse-till-done" "3.13.0"
+ "@lerna/rimraf-dir" "3.13.0"
+ p-map "^1.2.0"
+ p-map-series "^1.0.0"
+ p-waterfall "^1.0.0"
+
+"@lerna/cli@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-3.13.0.tgz#3d7b357fdd7818423e9681a7b7f2abd106c8a266"
+ integrity sha512-HgFGlyCZbYaYrjOr3w/EsY18PdvtsTmDfpUQe8HwDjXlPeCCUgliZjXLOVBxSjiOvPeOSwvopwIHKWQmYbwywg==
+ dependencies:
+ "@lerna/global-options" "3.13.0"
+ dedent "^0.7.0"
+ npmlog "^4.1.2"
+ yargs "^12.0.1"
+
+"@lerna/collect-updates@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.13.0.tgz#f0828d84ff959ff153d006765659ffc4d68cdefc"
+ integrity sha512-uR3u6uTzrS1p46tHQ/mlHog/nRJGBqskTHYYJbgirujxm6FqNh7Do+I1Q/7zSee407G4lzsNxZdm8IL927HemQ==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/describe-ref" "3.13.0"
+ minimatch "^3.0.4"
+ npmlog "^4.1.2"
+ slash "^1.0.0"
+
+"@lerna/command@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.13.1.tgz#b60dda2c0d9ffbb6030d61ddf7cceedc1e8f7e6e"
+ integrity sha512-SYWezxX+iheWvzRoHCrbs8v5zHPaxAx3kWvZhqi70vuGsdOVAWmaG4IvHLn11ztS+Vpd5PM+ztBWSbnykpLFKQ==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/package-graph" "3.13.0"
+ "@lerna/project" "3.13.1"
+ "@lerna/validation-error" "3.13.0"
+ "@lerna/write-log-file" "3.13.0"
+ dedent "^0.7.0"
+ execa "^1.0.0"
+ is-ci "^1.0.10"
+ lodash "^4.17.5"
+ npmlog "^4.1.2"
+
+"@lerna/conventional-commits@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.13.0.tgz#877aa225ca34cca61c31ea02a5a6296af74e1144"
+ integrity sha512-BeAgcNXuocmLhPxnmKU2Vy8YkPd/Uo+vu2i/p3JGsUldzrPC8iF3IDxH7fuXpEFN2Nfogu7KHachd4tchtOppA==
+ dependencies:
+ "@lerna/validation-error" "3.13.0"
+ conventional-changelog-angular "^5.0.3"
+ conventional-changelog-core "^3.1.6"
+ conventional-recommended-bump "^4.0.4"
+ fs-extra "^7.0.0"
+ get-stream "^4.0.0"
+ npm-package-arg "^6.1.0"
+ npmlog "^4.1.2"
+ pify "^3.0.0"
+ semver "^5.5.0"
+
+"@lerna/create-symlink@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.13.0.tgz#e01133082fe040779712c960683cb3a272b67809"
+ integrity sha512-PTvg3jAAJSAtLFoZDsuTMv1wTOC3XYIdtg54k7uxIHsP8Ztpt+vlilY/Cni0THAqEMHvfiToel76Xdta4TU21Q==
+ dependencies:
+ cmd-shim "^2.0.2"
+ fs-extra "^7.0.0"
+ npmlog "^4.1.2"
+
+"@lerna/create@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.13.1.tgz#2c1284cfdc59f0d2b88286d78bc797f4ab330f79"
+ integrity sha512-pLENMXgTkQuvKxAopjKeoLOv9fVUCnpTUD7aLrY5d95/1xqSZlnsOcQfUYcpMf3GpOvHc8ILmI5OXkPqjAf54g==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/npm-conf" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ camelcase "^5.0.0"
+ dedent "^0.7.0"
+ fs-extra "^7.0.0"
+ globby "^8.0.1"
+ init-package-json "^1.10.3"
+ npm-package-arg "^6.1.0"
+ p-reduce "^1.0.0"
+ pacote "^9.5.0"
+ pify "^3.0.0"
+ semver "^5.5.0"
+ slash "^1.0.0"
+ validate-npm-package-license "^3.0.3"
+ validate-npm-package-name "^3.0.0"
+ whatwg-url "^7.0.0"
+
+"@lerna/describe-ref@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.13.0.tgz#fb4c3863fd6bcccad67ce7b183887a5fc1942bb6"
+ integrity sha512-UJefF5mLxLae9I2Sbz5RLYGbqbikRuMqdgTam0MS5OhXnyuuKYBUpwBshCURNb1dPBXTQhSwc7+oUhORx8ojCg==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ npmlog "^4.1.2"
+
+"@lerna/diff@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.13.1.tgz#5c734321b0f6c46a3c87f55c99afef3b01d46520"
+ integrity sha512-cKqmpONO57mdvxtp8e+l5+tjtmF04+7E+O0QEcLcNUAjC6UR2OSM77nwRCXDukou/1h72JtWs0jjcdYLwAmApg==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/validation-error" "3.13.0"
+ npmlog "^4.1.2"
+
+"@lerna/exec@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.13.1.tgz#4439e90fb0877ec38a6ef933c86580d43eeaf81b"
+ integrity sha512-I34wEP9lrAqqM7tTXLDxv/6454WFzrnXDWpNDbiKQiZs6SIrOOjmm6I4FiQsx+rU3o9d+HkC6tcUJRN5mlJUgA==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ "@lerna/child-process" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/run-parallel-batches" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+
+"@lerna/filter-options@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.13.0.tgz#976e3d8b9fcd47001ab981d276565c1e9f767868"
+ integrity sha512-SRp7DCo9zrf+7NkQxZMkeyO1GRN6GICoB9UcBAbXhLbWisT37Cx5/6+jh49gYB63d/0/WYHSEPMlheUrpv1Srw==
+ dependencies:
+ "@lerna/collect-updates" "3.13.0"
+ "@lerna/filter-packages" "3.13.0"
+ dedent "^0.7.0"
+
+"@lerna/filter-packages@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-3.13.0.tgz#f5371249e7e1a15928e5e88c544a242e0162c21c"
+ integrity sha512-RWiZWyGy3Mp7GRVBn//CacSnE3Kw82PxE4+H6bQ3pDUw/9atXn7NRX+gkBVQIYeKamh7HyumJtyOKq3Pp9BADQ==
+ dependencies:
+ "@lerna/validation-error" "3.13.0"
+ multimatch "^2.1.0"
+ npmlog "^4.1.2"
+
+"@lerna/get-npm-exec-opts@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz#d1b552cb0088199fc3e7e126f914e39a08df9ea5"
+ integrity sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/get-packed@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-3.13.0.tgz#335e40d77f3c1855aa248587d3e0b2d8f4b06e16"
+ integrity sha512-EgSim24sjIjqQDC57bgXD9l22/HCS93uQBbGpkzEOzxAVzEgpZVm7Fm1t8BVlRcT2P2zwGnRadIvxTbpQuDPTg==
+ dependencies:
+ fs-extra "^7.0.0"
+ ssri "^6.0.1"
+ tar "^4.4.8"
+
+"@lerna/github-client@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.13.1.tgz#cb9bf9f01685a0cee0fac63f287f6c3673e45aa3"
+ integrity sha512-iPLUp8FFoAKGURksYEYZzfuo9TRA+NepVlseRXFaWlmy36dCQN20AciINpoXiXGoHcEUHXUKHQvY3ARFdMlf3w==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@octokit/plugin-enterprise-rest" "^2.1.1"
+ "@octokit/rest" "^16.16.0"
+ git-url-parse "^11.1.2"
+ npmlog "^4.1.2"
+
+"@lerna/global-options@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.13.0.tgz#217662290db06ad9cf2c49d8e3100ee28eaebae1"
+ integrity sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==
+
+"@lerna/has-npm-version@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.13.0.tgz#6e1f7e9336cce3e029066f0175f06dd9d51ad09f"
+ integrity sha512-Oqu7DGLnrMENPm+bPFGOHnqxK8lCnuYr6bk3g/CoNn8/U0qgFvHcq6Iv8/Z04TsvleX+3/RgauSD2kMfRmbypg==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ semver "^5.5.0"
+
+"@lerna/import@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.13.1.tgz#69d641341a38b79bd379129da1c717d51dd728c7"
+ integrity sha512-A1Vk1siYx1XkRl6w+zkaA0iptV5TIynVlHPR9S7NY0XAfhykjztYVvwtxarlh6+VcNrO9We6if0+FXCrfDEoIg==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/prompt" "3.13.0"
+ "@lerna/pulse-till-done" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ dedent "^0.7.0"
+ fs-extra "^7.0.0"
+ p-map-series "^1.0.0"
+
+"@lerna/init@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.13.1.tgz#0392c822abb3d63a75be4916c5e761cfa7b34dda"
+ integrity sha512-M59WACqim8WkH5FQEGOCEZ89NDxCKBfFTx4ZD5ig3LkGyJ8RdcJq5KEfpW/aESuRE9JrZLzVr0IjKbZSxzwEMA==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/command" "3.13.1"
+ fs-extra "^7.0.0"
+ p-map "^1.2.0"
+ write-json-file "^2.3.0"
+
+"@lerna/link@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.13.1.tgz#7d8ed4774bfa198d1780f790a14abb8722a3aad1"
+ integrity sha512-N3h3Fj1dcea+1RaAoAdy4g2m3fvU7m89HoUn5X/Zcw5n2kPoK8kTO+NfhNAatfRV8VtMXst8vbNrWQQtfm0FFw==
+ dependencies:
+ "@lerna/command" "3.13.1"
+ "@lerna/package-graph" "3.13.0"
+ "@lerna/symlink-dependencies" "3.13.0"
+ p-map "^1.2.0"
+ slash "^1.0.0"
+
+"@lerna/list@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.13.1.tgz#f9513ed143e52156c10ada4070f903c5847dcd10"
+ integrity sha512-635iRbdgd9gNvYLLIbYdQCQLr+HioM5FGJLFS0g3DPGygr6iDR8KS47hzCRGH91LU9NcM1mD1RoT/AChF+QbiA==
+ dependencies:
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/listable" "3.13.0"
+ "@lerna/output" "3.13.0"
+
+"@lerna/listable@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.13.0.tgz#babc18442c590b549cf0966d20d75fea066598d4"
+ integrity sha512-liYJ/WBUYP4N4MnSVZuLUgfa/jy3BZ02/1Om7xUY09xGVSuNVNEeB8uZUMSC+nHqFHIsMPZ8QK9HnmZb1E/eTA==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ chalk "^2.3.1"
+ columnify "^1.5.4"
+
+"@lerna/log-packed@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-3.13.0.tgz#497b5f692a8d0e3f669125da97b0dadfd9e480f3"
+ integrity sha512-Rmjrcz+6aM6AEcEVWmurbo8+AnHOvYtDpoeMMJh9IZ9SmZr2ClXzmD7wSvjTQc8BwOaiWjjC/ukcT0UYA2m7wg==
+ dependencies:
+ byte-size "^4.0.3"
+ columnify "^1.5.4"
+ has-unicode "^2.0.1"
+ npmlog "^4.1.2"
+
+"@lerna/npm-conf@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.13.0.tgz#6b434ed75ff757e8c14381b9bbfe5d5ddec134a7"
+ integrity sha512-Jg2kANsGnhg+fbPEzE0X9nX5oviEAvWj0nYyOkcE+cgWuT7W0zpnPXC4hA4C5IPQGhwhhh0IxhWNNHtjTuw53g==
+ dependencies:
+ config-chain "^1.1.11"
+ pify "^3.0.0"
+
+"@lerna/npm-dist-tag@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.13.0.tgz#49ecbe0e82cbe4ad4a8ea6de112982bf6c4e6cd4"
+ integrity sha512-mcuhw34JhSRFrbPn0vedbvgBTvveG52bR2lVE3M3tfE8gmR/cKS/EJFO4AUhfRKGCTFn9rjaSEzlFGYV87pemQ==
+ dependencies:
+ figgy-pudding "^3.5.1"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^3.9.0"
+ npmlog "^4.1.2"
+
+"@lerna/npm-install@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.13.0.tgz#88f4cc39f4f737c8a8721256b915ea1bcc6a7227"
+ integrity sha512-qNyfts//isYQxore6fsPorNYJmPVKZ6tOThSH97tP0aV91zGMtrYRqlAoUnDwDdAjHPYEM16hNujg2wRmsqqIw==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/get-npm-exec-opts" "3.13.0"
+ fs-extra "^7.0.0"
+ npm-package-arg "^6.1.0"
+ npmlog "^4.1.2"
+ signal-exit "^3.0.2"
+ write-pkg "^3.1.0"
+
+"@lerna/npm-publish@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.13.0.tgz#5c74808376e778865ffdc5885fe83935e15e60c3"
+ integrity sha512-y4WO0XTaf9gNRkI7as6P2ItVDOxmYHwYto357fjybcnfXgMqEA94c3GJ++jU41j0A9vnmYC6/XxpTd9sVmH9tA==
+ dependencies:
+ "@lerna/run-lifecycle" "3.13.0"
+ figgy-pudding "^3.5.1"
+ fs-extra "^7.0.0"
+ libnpmpublish "^1.1.1"
+ npmlog "^4.1.2"
+ pify "^3.0.0"
+ read-package-json "^2.0.13"
+
+"@lerna/npm-run-script@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.13.0.tgz#e5997f045402b9948bdc066033ebb36bf94fc9e4"
+ integrity sha512-hiL3/VeVp+NFatBjkGN8mUdX24EfZx9rQlSie0CMgtjc7iZrtd0jCguLomSCRHYjJuvqgbp+LLYo7nHVykfkaQ==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ "@lerna/get-npm-exec-opts" "3.13.0"
+ npmlog "^4.1.2"
+
+"@lerna/output@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.13.0.tgz#3ded7cc908b27a9872228a630d950aedae7a4989"
+ integrity sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/pack-directory@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.13.1.tgz#5ad4d0945f86a648f565e24d53c1e01bb3a912d1"
+ integrity sha512-kXnyqrkQbCIZOf1054N88+8h0ItC7tUN5v9ca/aWpx298gsURpxUx/1TIKqijL5TOnHMyIkj0YJmnH/PyBVLKA==
+ dependencies:
+ "@lerna/get-packed" "3.13.0"
+ "@lerna/package" "3.13.0"
+ "@lerna/run-lifecycle" "3.13.0"
+ figgy-pudding "^3.5.1"
+ npm-packlist "^1.4.1"
+ npmlog "^4.1.2"
+ tar "^4.4.8"
+ temp-write "^3.4.0"
+
+"@lerna/package-graph@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.13.0.tgz#607062f8d2ce22b15f8d4a0623f384736e67f760"
+ integrity sha512-3mRF1zuqFE1HEFmMMAIggXy+f+9cvHhW/jzaPEVyrPNLKsyfJQtpTNzeI04nfRvbAh+Gd2aNksvaW/w3xGJnnw==
+ dependencies:
+ "@lerna/validation-error" "3.13.0"
+ npm-package-arg "^6.1.0"
+ semver "^5.5.0"
+
+"@lerna/package@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.13.0.tgz#4baeebc49a57fc9b31062cc59f5ee38384429fc8"
+ integrity sha512-kSKO0RJQy093BufCQnkhf1jB4kZnBvL7kK5Ewolhk5gwejN+Jofjd8DGRVUDUJfQ0CkW1o6GbUeZvs8w8VIZDg==
+ dependencies:
+ load-json-file "^4.0.0"
+ npm-package-arg "^6.1.0"
+ write-pkg "^3.1.0"
+
+"@lerna/project@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.13.1.tgz#bce890f60187bd950bcf36c04b5260642e295e79"
+ integrity sha512-/GoCrpsCCTyb9sizk1+pMBrIYchtb+F1uCOn3cjn9yenyG/MfYEnlfrbV5k/UDud0Ei75YBLbmwCbigHkAKazQ==
+ dependencies:
+ "@lerna/package" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ cosmiconfig "^5.1.0"
+ dedent "^0.7.0"
+ dot-prop "^4.2.0"
+ glob-parent "^3.1.0"
+ globby "^8.0.1"
+ load-json-file "^4.0.0"
+ npmlog "^4.1.2"
+ p-map "^1.2.0"
+ resolve-from "^4.0.0"
+ write-json-file "^2.3.0"
+
+"@lerna/prompt@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-3.13.0.tgz#53571462bb3f5399cc1ca6d335a411fe093426a5"
+ integrity sha512-P+lWSFokdyvYpkwC3it9cE0IF2U5yy2mOUbGvvE4iDb9K7TyXGE+7lwtx2thtPvBAfIb7O13POMkv7df03HJeA==
+ dependencies:
+ inquirer "^6.2.0"
+ npmlog "^4.1.2"
+
+"@lerna/publish@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.13.1.tgz#217e401dcb5824cdd6d36555a36303fb7520c514"
+ integrity sha512-KhCJ9UDx76HWCF03i5TD7z5lX+2yklHh5SyO8eDaLptgdLDQ0Z78lfGj3JhewHU2l46FztmqxL/ss0IkWHDL+g==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ "@lerna/check-working-tree" "3.13.0"
+ "@lerna/child-process" "3.13.0"
+ "@lerna/collect-updates" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/describe-ref" "3.13.0"
+ "@lerna/log-packed" "3.13.0"
+ "@lerna/npm-conf" "3.13.0"
+ "@lerna/npm-dist-tag" "3.13.0"
+ "@lerna/npm-publish" "3.13.0"
+ "@lerna/output" "3.13.0"
+ "@lerna/pack-directory" "3.13.1"
+ "@lerna/prompt" "3.13.0"
+ "@lerna/pulse-till-done" "3.13.0"
+ "@lerna/run-lifecycle" "3.13.0"
+ "@lerna/run-parallel-batches" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ "@lerna/version" "3.13.1"
+ figgy-pudding "^3.5.1"
+ fs-extra "^7.0.0"
+ libnpmaccess "^3.0.1"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^3.9.0"
+ npmlog "^4.1.2"
+ p-finally "^1.0.0"
+ p-map "^1.2.0"
+ p-pipe "^1.2.0"
+ p-reduce "^1.0.0"
+ pacote "^9.5.0"
+ semver "^5.5.0"
+
+"@lerna/pulse-till-done@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz#c8e9ce5bafaf10d930a67d7ed0ccb5d958fe0110"
+ integrity sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/resolve-symlink@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.13.0.tgz#3e6809ef53b63fe914814bfa071cd68012e22fbb"
+ integrity sha512-Lc0USSFxwDxUs5JvIisS8JegjA6SHSAWJCMvi2osZx6wVRkEDlWG2B1JAfXUzCMNfHoZX0/XX9iYZ+4JIpjAtg==
+ dependencies:
+ fs-extra "^7.0.0"
+ npmlog "^4.1.2"
+ read-cmd-shim "^1.0.1"
+
+"@lerna/rimraf-dir@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.13.0.tgz#bb1006104b4aabcb6985624273254648f872b278"
+ integrity sha512-kte+pMemulre8cmPqljxIYjCmdLByz8DgHBHXB49kz2EiPf8JJ+hJFt0PzEubEyJZ2YE2EVAx5Tv5+NfGNUQyQ==
+ dependencies:
+ "@lerna/child-process" "3.13.0"
+ npmlog "^4.1.2"
+ path-exists "^3.0.0"
+ rimraf "^2.6.2"
+
+"@lerna/run-lifecycle@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.13.0.tgz#d8835ee83425edee40f687a55f81b502354d3261"
+ integrity sha512-oyiaL1biZdjpmjh6X/5C4w07wNFyiwXSSHH5GQB4Ay4BPwgq9oNhCcxRoi0UVZlZ1YwzSW8sTwLgj8emkIo3Yg==
+ dependencies:
+ "@lerna/npm-conf" "3.13.0"
+ figgy-pudding "^3.5.1"
+ npm-lifecycle "^2.1.0"
+ npmlog "^4.1.2"
+
+"@lerna/run-parallel-batches@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/run-parallel-batches/-/run-parallel-batches-3.13.0.tgz#0276bb4e7cd0995297db82d134ca2bd08d63e311"
+ integrity sha512-bICFBR+cYVF1FFW+Tlm0EhWDioTUTM6dOiVziDEGE1UZha1dFkMYqzqdSf4bQzfLS31UW/KBd/2z8jy2OIjEjg==
+ dependencies:
+ p-map "^1.2.0"
+ p-map-series "^1.0.0"
+
+"@lerna/run@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.13.1.tgz#87e174c1d271894ddd29adc315c068fb7b1b0117"
+ integrity sha512-nv1oj7bsqppWm1M4ifN+/IIbVu9F4RixrbQD2okqDGYne4RQPAXyb5cEZuAzY/wyGTWWiVaZ1zpj5ogPWvH0bw==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/filter-options" "3.13.0"
+ "@lerna/npm-run-script" "3.13.0"
+ "@lerna/output" "3.13.0"
+ "@lerna/run-parallel-batches" "3.13.0"
+ "@lerna/timer" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ p-map "^1.2.0"
+
+"@lerna/symlink-binary@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.13.0.tgz#36a9415d468afcb8105750296902f6f000a9680d"
+ integrity sha512-obc4Y6jxywkdaCe+DB0uTxYqP0IQ8mFWvN+k/YMbwH4G2h7M7lCBWgPy8e7xw/50+1II9tT2sxgx+jMus1sTJg==
+ dependencies:
+ "@lerna/create-symlink" "3.13.0"
+ "@lerna/package" "3.13.0"
+ fs-extra "^7.0.0"
+ p-map "^1.2.0"
+
+"@lerna/symlink-dependencies@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.13.0.tgz#76c23ecabda7824db98a0561364f122b457509cf"
+ integrity sha512-7CyN5WYEPkbPLbqHBIQg/YiimBzb5cIGQB0E9IkLs3+racq2vmUNQZn38LOaazQacAA83seB+zWSxlI6H+eXSg==
+ dependencies:
+ "@lerna/create-symlink" "3.13.0"
+ "@lerna/resolve-symlink" "3.13.0"
+ "@lerna/symlink-binary" "3.13.0"
+ fs-extra "^7.0.0"
+ p-finally "^1.0.0"
+ p-map "^1.2.0"
+ p-map-series "^1.0.0"
+
+"@lerna/timer@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-3.13.0.tgz#bcd0904551db16e08364d6c18e5e2160fc870781"
+ integrity sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==
+
+"@lerna/validation-error@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-3.13.0.tgz#c86b8f07c5ab9539f775bd8a54976e926f3759c3"
+ integrity sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==
+ dependencies:
+ npmlog "^4.1.2"
+
+"@lerna/version@3.13.1":
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.13.1.tgz#5e919d13abb13a663dcc7922bb40931f12fb137b"
+ integrity sha512-WpfKc5jZBBOJ6bFS4atPJEbHSiywQ/Gcd+vrwaEGyQHWHQZnPTvhqLuq3q9fIb9sbuhH5pSY6eehhuBrKqTnjg==
+ dependencies:
+ "@lerna/batch-packages" "3.13.0"
+ "@lerna/check-working-tree" "3.13.0"
+ "@lerna/child-process" "3.13.0"
+ "@lerna/collect-updates" "3.13.0"
+ "@lerna/command" "3.13.1"
+ "@lerna/conventional-commits" "3.13.0"
+ "@lerna/github-client" "3.13.1"
+ "@lerna/output" "3.13.0"
+ "@lerna/prompt" "3.13.0"
+ "@lerna/run-lifecycle" "3.13.0"
+ "@lerna/validation-error" "3.13.0"
+ chalk "^2.3.1"
+ dedent "^0.7.0"
+ minimatch "^3.0.4"
+ npmlog "^4.1.2"
+ p-map "^1.2.0"
+ p-pipe "^1.2.0"
+ p-reduce "^1.0.0"
+ p-waterfall "^1.0.0"
+ semver "^5.5.0"
+ slash "^1.0.0"
+ temp-write "^3.4.0"
+
+"@lerna/write-log-file@3.13.0":
+ version "3.13.0"
+ resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-3.13.0.tgz#b78d9e4cfc1349a8be64d91324c4c8199e822a26"
+ integrity sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==
+ dependencies:
+ npmlog "^4.1.2"
+ write-file-atomic "^2.3.0"
+
+"@material-ui/core@4.6.1":
+ version "4.6.1"
+ resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.6.1.tgz#039f97443547a88c41d290deabfb4a044c6031ec"
+ integrity sha512-TljDMCJmi1zh7JhAFTp8qjIlbkVACiNftrcitzJJ+hAqpuP9PTO4euEkkAuYjISfUFZl3Z4kaOrBwN1HDrhIOQ==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ "@material-ui/styles" "^4.6.0"
+ "@material-ui/system" "^4.5.2"
+ "@material-ui/types" "^4.1.1"
+ "@material-ui/utils" "^4.5.2"
+ "@types/react-transition-group" "^4.2.0"
+ clsx "^1.0.2"
+ convert-css-length "^2.0.1"
+ hoist-non-react-statics "^3.2.1"
+ normalize-scroll-left "^0.2.0"
+ popper.js "^1.14.1"
+ prop-types "^15.7.2"
+ react-transition-group "^4.3.0"
+
+"@material-ui/icons@4.5.1":
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.5.1.tgz#6963bad139e938702ece85ca43067688018f04f8"
+ integrity sha512-YZ/BgJbXX4a0gOuKWb30mBaHaoXRqPanlePam83JQPZ/y4kl+3aW0Wv9tlR70hB5EGAkEJGW5m4ktJwMgxQAeA==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+
+"@material-ui/styles@^4.6.0":
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.6.0.tgz#15679fab6dcbe0cc2416f01a22966f3ea26607c5"
+ integrity sha512-lqqh4UEMdIYcU1Yth4pQyMTah02uAkg3NOT3MirN9FUexdL8pNA6zCHigEgDSfwmvnXyxHhxTkphfy0DRfnt9w==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ "@emotion/hash" "^0.7.1"
+ "@material-ui/types" "^4.1.1"
+ "@material-ui/utils" "^4.5.2"
+ clsx "^1.0.2"
+ csstype "^2.5.2"
+ hoist-non-react-statics "^3.2.1"
+ jss "^10.0.0"
+ jss-plugin-camel-case "^10.0.0"
+ jss-plugin-default-unit "^10.0.0"
+ jss-plugin-global "^10.0.0"
+ jss-plugin-nested "^10.0.0"
+ jss-plugin-props-sort "^10.0.0"
+ jss-plugin-rule-value-function "^10.0.0"
+ jss-plugin-vendor-prefixer "^10.0.0"
+ prop-types "^15.7.2"
+
+"@material-ui/system@^4.5.2":
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.5.2.tgz#7143bd8422a3f33f435c23f378136254004bbd60"
+ integrity sha512-h9RWvdM9XKlHHqwiuhyvWdobptQkHli+m2jJFs7i1AI/hmGsIc4reDmS7fInhETgt/Txx7uiAIznfRNIIVHmQw==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ "@material-ui/utils" "^4.5.2"
+ prop-types "^15.7.2"
+
+"@material-ui/types@^4.1.1":
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-4.1.1.tgz#b65e002d926089970a3271213a3ad7a21b17f02b"
+ integrity sha512-AN+GZNXytX9yxGi0JOfxHrRTbhFybjUJ05rnsBVjcB+16e466Z0Xe5IxawuOayVZgTBNDxmPKo5j4V6OnMtaSQ==
+ dependencies:
+ "@types/react" "*"
+
+"@material-ui/utils@^4.5.2":
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.5.2.tgz#4c2fb531d357cf0da8cece53b588dff9b0bde934"
+ integrity sha512-zhbNfHd1gLa8At6RPDG7uMZubHxbY+LtM6IkSfeWi6Lo4Ax80l62YaN1QmUpO1IvGCkn/j62tQX3yObiQZrJsQ==
+ dependencies:
+ "@babel/runtime" "^7.4.4"
+ prop-types "^15.7.2"
+ react-is "^16.8.6"
+
+"@mrmlnc/readdir-enhanced@^2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
+ integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==
+ dependencies:
+ call-me-maybe "^1.0.1"
+ glob-to-regexp "^0.3.0"
+
+"@nodelib/fs.stat@^1.1.2":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
+ integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
+
+"@octokit/endpoint@^5.5.0":
+ version "5.5.1"
+ resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.5.1.tgz#2eea81e110ca754ff2de11c79154ccab4ae16b3f"
+ integrity sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg==
+ dependencies:
+ "@octokit/types" "^2.0.0"
+ is-plain-object "^3.0.0"
+ universal-user-agent "^4.0.0"
+
+"@octokit/plugin-enterprise-rest@^2.1.1":
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-2.2.2.tgz#c0e22067a043e19f96ff9c7832e2a3019f9be75c"
+ integrity sha512-CTZr64jZYhGWNTDGlSJ2mvIlFsm9OEO3LqWn9I/gmoHI4jRBp4kpHoFYNemG4oA75zUAcmbuWblb7jjP877YZw==
+
+"@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.0.tgz#a64d2a9d7a13555570cd79722de4a4d76371baaa"
+ integrity sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg==
+ dependencies:
+ "@octokit/types" "^2.0.0"
+ deprecation "^2.0.0"
+ once "^1.4.0"
+
+"@octokit/request@^5.2.0":
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.3.1.tgz#3a1ace45e6f88b1be4749c5da963b3a3b4a2f120"
+ integrity sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==
+ dependencies:
+ "@octokit/endpoint" "^5.5.0"
+ "@octokit/request-error" "^1.0.1"
+ "@octokit/types" "^2.0.0"
+ deprecation "^2.0.0"
+ is-plain-object "^3.0.0"
+ node-fetch "^2.3.0"
+ once "^1.4.0"
+ universal-user-agent "^4.0.0"
+
+"@octokit/rest@^16.16.0":
+ version "16.35.0"
+ resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.0.tgz#7ccc1f802f407d5b8eb21768c6deca44e7b4c0d8"
+ integrity sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w==
+ dependencies:
+ "@octokit/request" "^5.2.0"
+ "@octokit/request-error" "^1.0.2"
+ atob-lite "^2.0.0"
+ before-after-hook "^2.0.0"
+ btoa-lite "^1.0.0"
+ deprecation "^2.0.0"
+ lodash.get "^4.4.2"
+ lodash.set "^4.3.2"
+ lodash.uniq "^4.5.0"
+ octokit-pagination-methods "^1.1.0"
+ once "^1.4.0"
+ universal-user-agent "^4.0.0"
+
+"@octokit/types@^2.0.0":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.0.2.tgz#0888497f5a664e28b0449731d5e88e19b2a74f90"
+ integrity sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ==
+ dependencies:
+ "@types/node" ">= 8"
+
+"@types/classnames@2.2.6":
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.6.tgz#dbe8a666156d556ed018e15a4c65f08937c3f628"
+ integrity sha512-XHcYvVdbtAxVstjKxuULYqYaWIzHR15yr1pZj4fnGChuBVJlIAp9StJna0ZJNSgxPh4Nac2FL4JM3M11Tm6fqQ==
+
+"@types/fbemitter@*":
+ version "2.0.32"
+ resolved "https://registry.yarnpkg.com/@types/fbemitter/-/fbemitter-2.0.32.tgz#8ed204da0f54e9c8eaec31b1eec91e25132d082c"
+ integrity sha1-jtIE2g9U6cjq7DGx7skeJRMtCCw=
+
+"@types/flux@3.1.8":
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/@types/flux/-/flux-3.1.8.tgz#987fbf0220d98aa23276c9635a8ef1e505f7c4a4"
+ integrity sha512-U7DS78cK1svrisTa920BM2AEsWnfgnxQmVn+1kju1XgjcDN/iU1Uiyy0pQNaG8s9P1X5Lj3pMaIfVuCjXAlSCA==
+ dependencies:
+ "@types/fbemitter" "*"
+ "@types/react" "*"
+
+"@types/highlight.js@9.12.3":
+ version "9.12.3"
+ resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"
+ integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==
+
+"@types/history@*":
+ version "4.7.3"
+ resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.3.tgz#856c99cdc1551d22c22b18b5402719affec9839a"
+ integrity sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw==
+
+"@types/jest@23.3.12":
+ version "23.3.12"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.12.tgz#7e0ced251fa94c3bc2d1023d4b84b2992fa06376"
+ integrity sha512-/kQvbVzdEpOq4tEWT79yAHSM4nH4xMlhJv2GrLVQt4Qmo8yYsPdioBM1QpN/2GX1wkfMnyXvdoftvLUr0LBj7Q==
+
+"@types/jquery@3.3.10":
+ version "3.3.10"
+ resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.10.tgz#d0afaec7ee55f591992e74c607df5dc7cd9c76ab"
+ integrity sha512-W2bE8pGh9Tsg8mxh+B6BSH8lTG6ZV7K2ZMAlEwSTqKFU1wMI5HShyRKSp3DngnxCmDu35tW3RAC4mxBFYRsTuw==
+
+"@types/jsonwebtoken@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-7.2.8.tgz#8d199dab4ddb5bba3234f8311b804d2027af2b3a"
+ integrity sha512-XENN3YzEB8D6TiUww0O8SRznzy1v+77lH7UmuN54xq/IHIsyWjWOzZuFFTtoiRuaE782uAoRwBe/wwow+vQXZw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/marked@0.6.0":
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.6.0.tgz#e4ac316144a84afda5c2474488d7b9fef3ab9995"
+ integrity sha512-TxwhgR9VsIfRDJ3WwFokG8Xu+ea0nYGDRHdI783WJ983uffatz0ytIeUEIBOwPvRy241KRSNVyywQltuTqDh0w==
+
+"@types/node@*":
+ version "12.12.7"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
+ integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
+
+"@types/node@11.11.6":
+ version "11.11.6"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a"
+ integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
+
+"@types/node@>= 8":
+ version "12.12.17"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.17.tgz#191b71e7f4c325ee0fb23bc4a996477d92b8c39b"
+ integrity sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==
+
+"@types/prop-types@*":
+ version "15.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
+ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
+
+"@types/react-dom@16.9.4":
+ version "16.9.4"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df"
+ integrity sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-router-dom@4.3.1":
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.1.tgz#71fe2918f8f60474a891520def40a63997dafe04"
+ integrity sha512-GbztJAScOmQ/7RsQfO4cd55RuH1W4g6V1gDW3j4riLlt+8yxYLqqsiMzmyuXBLzdFmDtX/uU2Bpcm0cmudv44A==
+ dependencies:
+ "@types/history" "*"
+ "@types/react" "*"
+ "@types/react-router" "*"
+
+"@types/react-router@*":
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.3.tgz#7c7ca717399af64d8733d8cb338dd43641b96f2d"
+ integrity sha512-0gGhmerBqN8CzlnDmSgGNun3tuZFXerUclWkqEhozdLaJtfcJRUTGkKaEKk+/MpHd1KDS1+o2zb/3PkBUiv2qQ==
+ dependencies:
+ "@types/history" "*"
+ "@types/react" "*"
+
+"@types/react-transition-group@2.0.15":
+ version "2.0.15"
+ resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.15.tgz#e5ee3fe558832e141cc6041bdd54caea7b787af8"
+ integrity sha512-S0QnNzbHoWXDbKBl/xk5dxA4FT+BNlBcI3hku991cl8Cz3ytOkUMcCRtzdX11eb86E131bSsQqy5WrPCdJYblw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-transition-group@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.3.tgz#4924133f7268694058e415bf7aea2d4c21131470"
+ integrity sha512-Hk8jiuT7iLOHrcjKP/ZVSyCNXK73wJAUz60xm0mVhiRujrdiI++j4duLiL282VGxwAgxetHQFfqA29LgEeSkFA==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@16.9.11":
+ version "16.9.11"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120"
+ integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^2.2.0"
+
+"@types/x2js@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@types/x2js/-/x2js-3.1.0.tgz#d809ef1ace1a8b55b3e8cb6a1a0b282af66475be"
+ integrity sha1-2AnvGs4ai1Wz6MtqGgsoKvZkdb4=
+ dependencies:
+ x2js "*"
+
+"@webassemblyjs/ast@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"
+ integrity sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==
+ dependencies:
+ "@webassemblyjs/helper-module-context" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/wast-parser" "1.7.11"
+
+"@webassemblyjs/floating-point-hex-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz#a69f0af6502eb9a3c045555b1a6129d3d3f2e313"
+ integrity sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==
+
+"@webassemblyjs/helper-api-error@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz#c7b6bb8105f84039511a2b39ce494f193818a32a"
+ integrity sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==
+
+"@webassemblyjs/helper-buffer@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz#3122d48dcc6c9456ed982debe16c8f37101df39b"
+ integrity sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==
+
+"@webassemblyjs/helper-code-frame@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz#cf8f106e746662a0da29bdef635fcd3d1248364b"
+ integrity sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==
+ dependencies:
+ "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/helper-fsm@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz#df38882a624080d03f7503f93e3f17ac5ac01181"
+ integrity sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==
+
+"@webassemblyjs/helper-module-context@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz#d874d722e51e62ac202476935d649c802fa0e209"
+ integrity sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==
+
+"@webassemblyjs/helper-wasm-bytecode@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz#dd9a1e817f1c2eb105b4cf1013093cb9f3c9cb06"
+ integrity sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==
+
+"@webassemblyjs/helper-wasm-section@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz#9c9ac41ecf9fbcfffc96f6d2675e2de33811e68a"
+ integrity sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+
+"@webassemblyjs/ieee754@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b"
+ integrity sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.11.tgz#d7267a1ee9c4594fd3f7e37298818ec65687db63"
+ integrity sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==
+ dependencies:
+ "@xtuc/long" "4.2.1"
+
+"@webassemblyjs/utf8@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.11.tgz#06d7218ea9fdc94a6793aa92208160db3d26ee82"
+ integrity sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==
+
+"@webassemblyjs/wasm-edit@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz#8c74ca474d4f951d01dbae9bd70814ee22a82005"
+ integrity sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/helper-wasm-section" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+ "@webassemblyjs/wasm-opt" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+ "@webassemblyjs/wast-printer" "1.7.11"
+
+"@webassemblyjs/wasm-gen@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz#9bbba942f22375686a6fb759afcd7ac9c45da1a8"
+ integrity sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/ieee754" "1.7.11"
+ "@webassemblyjs/leb128" "1.7.11"
+ "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wasm-opt@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz#b331e8e7cef8f8e2f007d42c3a36a0580a7d6ca7"
+ integrity sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-buffer" "1.7.11"
+ "@webassemblyjs/wasm-gen" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+
+"@webassemblyjs/wasm-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz#6e3d20fa6a3519f6b084ef9391ad58211efb0a1a"
+ integrity sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-api-error" "1.7.11"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
+ "@webassemblyjs/ieee754" "1.7.11"
+ "@webassemblyjs/leb128" "1.7.11"
+ "@webassemblyjs/utf8" "1.7.11"
+
+"@webassemblyjs/wast-parser@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz#25bd117562ca8c002720ff8116ef9072d9ca869c"
+ integrity sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/floating-point-hex-parser" "1.7.11"
+ "@webassemblyjs/helper-api-error" "1.7.11"
+ "@webassemblyjs/helper-code-frame" "1.7.11"
+ "@webassemblyjs/helper-fsm" "1.7.11"
+ "@xtuc/long" "4.2.1"
+
+"@webassemblyjs/wast-printer@1.7.11":
+ version "1.7.11"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz#c4245b6de242cb50a2cc950174fdbf65c78d7813"
+ integrity sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/wast-parser" "1.7.11"
+ "@xtuc/long" "4.2.1"
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.1":
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8"
+ integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==
+
+JSONStream@^1.0.4, JSONStream@^1.3.4:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
+ integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
+ dependencies:
+ jsonparse "^1.2.0"
+ through ">=2.2.7 <3"
+
+abab@^2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
+ integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
+
+abbrev@1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+ integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
+accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
+ integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
+ dependencies:
+ mime-types "~2.1.24"
+ negotiator "0.6.2"
+
+acorn-dynamic-import@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
+ integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==
+ dependencies:
+ acorn "^5.0.0"
+
+acorn-globals@^4.1.0:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7"
+ integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==
+ dependencies:
+ acorn "^6.0.1"
+ acorn-walk "^6.0.1"
+
+acorn-walk@^6.0.1:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
+ integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
+
+acorn@^5.0.0, acorn@^5.5.3, acorn@^5.6.2:
+ version "5.7.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
+ integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
+
+acorn@^6.0.1:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e"
+ integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==
+
+agent-base@4, agent-base@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+ integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
+agent-base@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+ integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
+agentkeepalive@^3.4.1:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67"
+ integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==
+ dependencies:
+ humanize-ms "^1.2.1"
+
+ajv-errors@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
+ integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
+
+ajv-keywords@^3.1.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
+ integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
+
+ajv@^5.1.0:
+ version "5.5.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
+ integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=
+ dependencies:
+ co "^4.6.0"
+ fast-deep-equal "^1.0.0"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.3.0"
+
+ajv@^6.1.0, ajv@^6.5.5:
+ version "6.10.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
+ integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==
+ dependencies:
+ fast-deep-equal "^2.0.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+amdefine@>=0.0.4:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+ integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
+
+ansi-colors@^3.0.0:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
+ integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
+
+ansi-escapes@^3.0.0, ansi-escapes@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
+ integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
+
+ansi-html@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
+ integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
+
+ansi-regex@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
+
+ansi-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+ integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+
+ansi-regex@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+ integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+
+ansi-styles@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+anymatch@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
+ integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
+ dependencies:
+ micromatch "^3.1.4"
+ normalize-path "^2.1.1"
+
+append-transform@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+ integrity sha1-126/jKlNJ24keja61EpLdKthGZE=
+ dependencies:
+ default-require-extensions "^1.0.0"
+
+aproba@^1.0.3, aproba@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+ integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+
+aproba@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
+ integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
+
+are-we-there-yet@~1.1.2:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
+ integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+arr-diff@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+ integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
+ dependencies:
+ arr-flatten "^1.0.1"
+
+arr-diff@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+ integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
+
+arr-flatten@^1.0.1, arr-flatten@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+ integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
+
+arr-union@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
+ integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
+
+array-differ@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031"
+ integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=
+
+array-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
+ integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
+
+array-find-index@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+ integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+
+array-flatten@^2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
+ integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
+
+array-ify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
+ integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
+
+array-union@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
+ dependencies:
+ array-uniq "^1.0.1"
+
+array-uniq@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+ integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
+
+array-unique@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+ integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
+
+array-unique@^0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+ integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
+
+arrify@^1.0.0, arrify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+ integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+
+asap@^2.0.0, asap@~2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
+
+asn1.js@^4.0.0:
+ version "4.10.1"
+ resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
+ integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==
+ dependencies:
+ bn.js "^4.0.0"
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+
+asn1@~0.2.3:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+ integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+
+assert@^1.1.1:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
+ integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
+ dependencies:
+ object-assign "^4.1.1"
+ util "0.10.3"
+
+assign-symbols@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+ integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
+
+astral-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
+ integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
+
+async-each@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
+ integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
+
+async-foreach@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542"
+ integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=
+
+async-limiter@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
+ integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
+
+async@^2.1.4, async@^2.4.1, async@^2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+ integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
+ dependencies:
+ lodash "^4.17.14"
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+atob-lite@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696"
+ integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=
+
+atob@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
+autoprefixer@9.1.5:
+ version "9.1.5"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.1.5.tgz#8675fd8d1c0d43069f3b19a2c316f3524e4f6671"
+ integrity sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==
+ dependencies:
+ 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@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+
+aws4@^1.6.0, aws4@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
+ integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
+
+babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
+ dependencies:
+ chalk "^1.1.3"
+ esutils "^2.0.2"
+ js-tokens "^3.0.2"
+
+babel-core@^6.0.0, babel-core@^6.26.0:
+ version "6.26.3"
+ resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
+ integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==
+ dependencies:
+ babel-code-frame "^6.26.0"
+ babel-generator "^6.26.0"
+ babel-helpers "^6.24.1"
+ babel-messages "^6.23.0"
+ babel-register "^6.26.0"
+ babel-runtime "^6.26.0"
+ babel-template "^6.26.0"
+ babel-traverse "^6.26.0"
+ babel-types "^6.26.0"
+ babylon "^6.18.0"
+ convert-source-map "^1.5.1"
+ debug "^2.6.9"
+ json5 "^0.5.1"
+ lodash "^4.17.4"
+ minimatch "^3.0.4"
+ path-is-absolute "^1.0.1"
+ private "^0.1.8"
+ slash "^1.0.0"
+ source-map "^0.5.7"
+
+babel-generator@^6.18.0, babel-generator@^6.26.0:
+ version "6.26.1"
+ resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
+ integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==
+ dependencies:
+ 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"
+
+babel-helpers@^6.24.1:
+ version "6.24.1"
+ resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
+ integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=
+ dependencies:
+ babel-runtime "^6.22.0"
+ babel-template "^6.24.1"
+
+babel-jest@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
+ integrity sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==
+ dependencies:
+ babel-plugin-istanbul "^4.1.6"
+ babel-preset-jest "^23.2.0"
+
+babel-loader@8.0.4:
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.4.tgz#7bbf20cbe4560629e2e41534147692d3fecbdce6"
+ integrity sha512-fhBhNkUToJcW9nV46v8w87AJOwAJDz84c1CL57n3Stj73FANM/b9TbCUK4YhdOwEyZ+OxhYpdeZDNzSI29Firw==
+ dependencies:
+ find-cache-dir "^1.0.0"
+ loader-utils "^1.0.2"
+ mkdirp "^0.5.1"
+ util.promisify "^1.0.0"
+
+babel-messages@^6.23.0:
+ version "6.23.0"
+ resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+ integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
+ dependencies:
+ babel-runtime "^6.22.0"
+
+babel-plugin-dynamic-import-node@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f"
+ integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==
+ dependencies:
+ object.assign "^4.1.0"
+
+babel-plugin-istanbul@^4.1.6:
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
+ integrity sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==
+ dependencies:
+ babel-plugin-syntax-object-rest-spread "^6.13.0"
+ find-up "^2.1.0"
+ istanbul-lib-instrument "^1.10.1"
+ test-exclude "^4.2.1"
+
+babel-plugin-jest-hoist@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
+ integrity sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=
+
+babel-plugin-syntax-object-rest-spread@^6.13.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
+ integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
+
+babel-preset-jest@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
+ integrity sha1-jsegOhOPABoaj7HoETZSvxpV2kY=
+ dependencies:
+ babel-plugin-jest-hoist "^23.2.0"
+ babel-plugin-syntax-object-rest-spread "^6.13.0"
+
+babel-register@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
+ integrity sha1-btAhFz4vy0htestFxgCahW9kcHE=
+ dependencies:
+ babel-core "^6.26.0"
+ babel-runtime "^6.26.0"
+ core-js "^2.5.0"
+ home-or-tmp "^2.0.0"
+ lodash "^4.17.4"
+ mkdirp "^0.5.1"
+ source-map-support "^0.4.15"
+
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
+babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+ integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
+ dependencies:
+ 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@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+ integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
+ dependencies:
+ 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@^6.0.0, babel-types@^6.18.0, babel-types@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+ integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
+ dependencies:
+ babel-runtime "^6.26.0"
+ esutils "^2.0.2"
+ lodash "^4.17.4"
+ to-fast-properties "^1.0.3"
+
+babylon@^6.18.0:
+ version "6.18.0"
+ resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+ integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+base64-js@^1.0.2:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
+ integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
+
+base@^0.11.1:
+ version "0.11.2"
+ resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+ integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
+ dependencies:
+ 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"
+
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+ dependencies:
+ tweetnacl "^0.14.3"
+
+before-after-hook@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
+ integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
+
+big.js@^3.1.3:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+ integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
+
+big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+binary-extensions@^1.0.0:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
+ integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
+
+block-stream@*:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+ integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+ dependencies:
+ inherits "~2.0.0"
+
+bluebird@^3.5.1, bluebird@^3.5.5:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de"
+ integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==
+
+bluebird@^3.5.3:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
+ integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
+
+body-parser@1.19.0:
+ version "1.19.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
+ integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
+ dependencies:
+ 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"
+
+bonjour@^3.5.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
+ integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU=
+ dependencies:
+ 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"
+
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^1.8.2:
+ version "1.8.5"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+ integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
+ dependencies:
+ expand-range "^1.8.1"
+ preserve "^0.2.0"
+ repeat-element "^1.1.2"
+
+braces@^2.3.1, braces@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
+ integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
+ dependencies:
+ 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"
+
+brorand@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+ integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+
+browser-process-hrtime@^0.1.2:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4"
+ integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==
+
+browser-resolve@^1.11.3:
+ version "1.11.3"
+ resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
+ integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==
+ dependencies:
+ resolve "1.1.7"
+
+browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48"
+ integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==
+ dependencies:
+ 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@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0"
+ integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==
+ dependencies:
+ browserify-aes "^1.0.4"
+ browserify-des "^1.0.0"
+ evp_bytestokey "^1.0.0"
+
+browserify-des@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c"
+ integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==
+ dependencies:
+ cipher-base "^1.0.1"
+ des.js "^1.0.0"
+ inherits "^2.0.1"
+ safe-buffer "^5.1.2"
+
+browserify-rsa@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+ integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=
+ dependencies:
+ bn.js "^4.1.0"
+ randombytes "^2.0.1"
+
+browserify-sign@^4.0.0:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
+ integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=
+ dependencies:
+ 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@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+ integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
+ dependencies:
+ pako "~1.0.5"
+
+browserslist@^4.1.0:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.2.tgz#1bb984531a476b5d389cedecb195b2cd69fb1348"
+ integrity sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==
+ dependencies:
+ caniuse-lite "^1.0.30001004"
+ electron-to-chromium "^1.3.295"
+ node-releases "^1.1.38"
+
+bs-logger@0.x:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
+ integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
+ dependencies:
+ fast-json-stable-stringify "2.x"
+
+bser@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
+btoa-lite@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
+ integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc=
+
+buffer-equal-constant-time@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
+ integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
+
+buffer-from@1.x, buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+buffer-indexof@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
+ integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
+
+buffer-xor@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+ integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
+
+buffer@^4.3.0:
+ version "4.9.2"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
+ integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
+ dependencies:
+ base64-js "^1.0.2"
+ ieee754 "^1.1.4"
+ isarray "^1.0.0"
+
+builtin-modules@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+ integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
+
+builtin-status-codes@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+ integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
+
+builtins@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
+ integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og=
+
+byline@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
+ integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=
+
+byte-size@^4.0.3:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.4.tgz#29d381709f41aae0d89c631f1c81aec88cd40b23"
+ integrity sha512-82RPeneC6nqCdSwCX2hZUz3JPOvN5at/nTEw/CMf05Smu3Hrpo9Psb7LjN+k+XndNArG1EY8L4+BM3aTM4BCvw==
+
+bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
+
+bytes@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
+ integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
+
+cacache@^10.0.4:
+ version "10.0.4"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
+ integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==
+ dependencies:
+ 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"
+
+cacache@^11.0.2, cacache@^11.3.3:
+ version "11.3.3"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc"
+ integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==
+ dependencies:
+ 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"
+
+cacache@^12.0.0, cacache@^12.0.2:
+ version "12.0.3"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
+ integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==
+ dependencies:
+ bluebird "^3.5.5"
+ chownr "^1.1.1"
+ figgy-pudding "^3.5.1"
+ glob "^7.1.4"
+ graceful-fs "^4.1.15"
+ infer-owner "^1.0.3"
+ 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"
+
+cache-base@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+ integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
+ dependencies:
+ 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"
+
+call-me-maybe@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
+ integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
+
+caller-callsite@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134"
+ integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=
+ dependencies:
+ callsites "^2.0.0"
+
+caller-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4"
+ integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=
+ dependencies:
+ caller-callsite "^2.0.0"
+
+callsites@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50"
+ integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=
+
+camel-case@3.0.x:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
+ integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
+ dependencies:
+ no-case "^2.2.0"
+ upper-case "^1.1.1"
+
+camelcase-keys@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
+ integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
+ dependencies:
+ camelcase "^2.0.0"
+ map-obj "^1.0.0"
+
+camelcase-keys@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77"
+ integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=
+ dependencies:
+ camelcase "^4.1.0"
+ map-obj "^2.0.0"
+ quick-lru "^1.0.0"
+
+camelcase@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+ integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
+
+camelcase@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+ integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
+
+camelcase@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+ integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
+
+camelcase@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+caniuse-lite@^1.0.30000884, caniuse-lite@^1.0.30001004:
+ version "1.0.30001010"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001010.tgz#397a14034d384260453cc81994f494626d34b938"
+ integrity sha512-RA5GH9YjFNea4ZQszdWgh2SC+dpLiRAg4VDQS2b5JRI45OxmbGrYocYHTa9x0bKMQUE7uvHkNPNffUr+pCxSGw==
+
+capture-exit@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f"
+ integrity sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=
+ dependencies:
+ rsvp "^3.3.3"
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+
+chalk@^1.1.1, chalk@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
+ dependencies:
+ 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"
+
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chardet@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
+ integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
+
+chart.js@2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.8.0.tgz#b703b10d0f4ec5079eaefdcd6ca32dc8f826e0e9"
+ integrity sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==
+ dependencies:
+ chartjs-color "^2.1.0"
+ moment "^2.10.2"
+
+chartjs-color-string@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
+ integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
+ dependencies:
+ color-name "^1.0.0"
+
+chartjs-color@^2.1.0:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0"
+ integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
+ dependencies:
+ chartjs-color-string "^0.6.0"
+ color-convert "^1.9.3"
+
+chokidar@^2.0.0, chokidar@^2.0.2:
+ version "2.1.8"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
+ integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==
+ dependencies:
+ anymatch "^2.0.0"
+ async-each "^1.0.1"
+ braces "^2.3.2"
+ glob-parent "^3.1.0"
+ inherits "^2.0.3"
+ is-binary-path "^1.0.0"
+ is-glob "^4.0.0"
+ normalize-path "^3.0.0"
+ path-is-absolute "^1.0.0"
+ readdirp "^2.2.1"
+ upath "^1.1.1"
+ optionalDependencies:
+ fsevents "^1.2.7"
+
+chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
+ integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==
+
+chrome-trace-event@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
+ integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==
+ dependencies:
+ tslib "^1.9.0"
+
+ci-info@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+ integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
+cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+ integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+class-utils@^0.3.5:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+ integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
+ dependencies:
+ arr-union "^3.1.0"
+ define-property "^0.2.5"
+ isobject "^3.0.0"
+ static-extend "^0.1.1"
+
+classnames@2.2.6, classnames@^2.2.6:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+ integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
+
+clean-css@4.2.x:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
+ integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==
+ dependencies:
+ source-map "~0.6.0"
+
+cli-cursor@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+ dependencies:
+ restore-cursor "^2.0.0"
+
+cli-width@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
+ integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
+
+cliui@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+ integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wrap-ansi "^2.0.0"
+
+cliui@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
+ integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==
+ dependencies:
+ string-width "^2.1.1"
+ strip-ansi "^4.0.0"
+ wrap-ansi "^2.0.0"
+
+clone-deep@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713"
+ integrity sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==
+ dependencies:
+ for-own "^1.0.0"
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.0"
+ shallow-clone "^1.0.0"
+
+clone@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+ integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+
+clone@^2.1.1, clone@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
+ integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
+
+clsx@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec"
+ integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg==
+
+cmd-shim@^2.0.2:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.1.0.tgz#e59a08d4248dda3bb502044083a4db4ac890579a"
+ integrity sha512-A5C0Cyf2H8sKsHqX0tvIWRXw5/PK++3Dc0lDbsugr90nOECLLuSPahVQBG8pgmgiXgm/TzBWMqI2rWdZwHduAw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ mkdirp "~0.5.0"
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+ integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
+
+code-point-at@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+ integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
+
+collection-visit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+ integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
+ dependencies:
+ map-visit "^1.0.0"
+ object-visit "^1.0.0"
+
+color-convert@^1.9.0, color-convert@^1.9.3:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+color-name@^1.0.0:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+colors@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
+ integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
+
+colour@0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778"
+ integrity sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=
+
+columnify@^1.5.4:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
+ integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=
+ dependencies:
+ strip-ansi "^3.0.0"
+ wcwidth "^1.0.0"
+
+combined-stream@^1.0.6, combined-stream@~1.0.5, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@2.17.x:
+ version "2.17.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+ integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
+
+commander@^2.12.1, commander@^2.19.0, commander@^2.20.0, commander@~2.20.3:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@~2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+
+compare-func@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648"
+ integrity sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=
+ dependencies:
+ array-ify "^1.0.0"
+ dot-prop "^3.0.0"
+
+component-emitter@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
+ integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+
+compressible@~2.0.16:
+ version "2.0.17"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1"
+ integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==
+ dependencies:
+ mime-db ">= 1.40.0 < 2"
+
+compression@^1.5.2:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+ dependencies:
+ 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@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+concat-stream@^1.5.0:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+concat-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
+ integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^3.0.2"
+ typedarray "^0.0.6"
+
+config-chain@^1.1.11:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
+ integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+connect-history-api-fallback@^1.3.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
+ integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
+
+console-browserify@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
+ integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+ integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
+
+constants-browserify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+ integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
+
+content-disposition@0.5.3:
+ version "0.5.3"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
+ integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
+ dependencies:
+ safe-buffer "5.1.2"
+
+content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+conventional-changelog-angular@^5.0.3:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059"
+ integrity sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==
+ dependencies:
+ compare-func "^1.3.1"
+ q "^1.5.1"
+
+conventional-changelog-core@^3.1.6:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz#b31410856f431c847086a7dcb4d2ca184a7d88fb"
+ integrity sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==
+ dependencies:
+ conventional-changelog-writer "^4.0.6"
+ conventional-commits-parser "^3.0.3"
+ dateformat "^3.0.0"
+ get-pkg-repo "^1.0.0"
+ git-raw-commits "2.0.0"
+ git-remote-origin-url "^2.0.0"
+ git-semver-tags "^2.0.3"
+ lodash "^4.2.1"
+ normalize-package-data "^2.3.5"
+ q "^1.5.1"
+ read-pkg "^3.0.0"
+ read-pkg-up "^3.0.0"
+ through2 "^3.0.0"
+
+conventional-changelog-preset-loader@^2.1.1:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz#580fa8ab02cef22c24294d25e52d7ccd247a9a6a"
+ integrity sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==
+
+conventional-changelog-writer@^4.0.6:
+ version "4.0.11"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz#9f56d2122d20c96eb48baae0bf1deffaed1edba4"
+ integrity sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==
+ dependencies:
+ compare-func "^1.3.1"
+ conventional-commits-filter "^2.0.2"
+ dateformat "^3.0.0"
+ handlebars "^4.4.0"
+ json-stringify-safe "^5.0.1"
+ lodash "^4.17.15"
+ meow "^5.0.0"
+ semver "^6.0.0"
+ split "^1.0.0"
+ through2 "^3.0.0"
+
+conventional-commits-filter@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1"
+ integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==
+ dependencies:
+ lodash.ismatch "^4.4.0"
+ modify-values "^1.0.0"
+
+conventional-commits-parser@^3.0.2, conventional-commits-parser@^3.0.3:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz#23310a9bda6c93c874224375e72b09fb275fe710"
+ integrity sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==
+ dependencies:
+ JSONStream "^1.0.4"
+ is-text-path "^1.0.1"
+ lodash "^4.17.15"
+ meow "^5.0.0"
+ split2 "^2.0.0"
+ through2 "^3.0.0"
+ trim-off-newlines "^1.0.0"
+
+conventional-recommended-bump@^4.0.4:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-4.1.1.tgz#37014fadeda267d0607e2fc81124da840a585127"
+ integrity sha512-JT2vKfSP9kR18RXXf55BRY1O3AHG8FPg5btP3l7LYfcWJsiXI6MCf30DepQ98E8Qhowvgv7a8iev0J1bEDkTFA==
+ dependencies:
+ concat-stream "^2.0.0"
+ conventional-changelog-preset-loader "^2.1.1"
+ conventional-commits-filter "^2.0.2"
+ conventional-commits-parser "^3.0.2"
+ git-raw-commits "2.0.0"
+ git-semver-tags "^2.0.2"
+ meow "^4.0.0"
+ q "^1.5.1"
+
+convert-css-length@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/convert-css-length/-/convert-css-length-2.0.1.tgz#90a76bde5bfd24d72881a5b45d02249b2c1d257c"
+ integrity sha512-iGpbcvhLPRKUbBc0Quxx7w/bV14AC3ItuBEGMahA5WTYqB8lq9jH0kTXFheCBASsYnqeMFZhiTruNxr1N59Axg==
+
+convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
+ integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
+ dependencies:
+ safe-buffer "~5.1.1"
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+
+cookie@0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
+ integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
+
+copy-concurrently@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+ integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
+ dependencies:
+ 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@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+ integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
+
+copy-webpack-plugin@4.5.2:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-4.5.2.tgz#d53444a8fea2912d806e78937390ddd7e632ee5c"
+ integrity sha512-zmC33E8FFSq3AbflTvqvPvBo621H36Afsxlui91d+QyZxPIuXghfnTsa1CuqiAaCPgJoSUWfTFbKJnadZpKEbQ==
+ dependencies:
+ 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@^2.4.0, core-js@^2.5.0, core-js@^2.5.7:
+ version "2.6.10"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
+ integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
+
+core-util-is@1.0.2, core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+corser@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/corser/-/corser-2.0.1.tgz#8eda252ecaab5840dcd975ceb90d9370c819ff87"
+ integrity sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=
+
+cosmiconfig@^5.0.0, cosmiconfig@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
+ integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
+ dependencies:
+ import-fresh "^2.0.0"
+ is-directory "^0.3.1"
+ js-yaml "^3.13.1"
+ parse-json "^4.0.0"
+
+create-ecdh@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
+ integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==
+ dependencies:
+ bn.js "^4.1.0"
+ elliptic "^6.0.0"
+
+create-hash@^1.1.0, create-hash@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
+ integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
+ dependencies:
+ 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@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
+ integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
+ dependencies:
+ 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@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
+ integrity sha1-ElYDfsufDF9549bvE14wdwGEuYI=
+ dependencies:
+ lru-cache "^4.0.1"
+ which "^1.2.9"
+
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+crypto-browserify@^3.11.0:
+ version "3.12.0"
+ resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+ integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
+ dependencies:
+ 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-loader@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56"
+ integrity sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==
+ dependencies:
+ babel-code-frame "^6.26.0"
+ css-selector-tokenizer "^0.7.0"
+ icss-utils "^2.1.0"
+ loader-utils "^1.0.2"
+ lodash.camelcase "^4.3.0"
+ postcss "^6.0.23"
+ postcss-modules-extract-imports "^1.2.0"
+ postcss-modules-local-by-default "^1.2.0"
+ postcss-modules-scope "^1.1.0"
+ postcss-modules-values "^1.3.0"
+ postcss-value-parser "^3.3.0"
+ source-list-map "^2.0.0"
+
+css-select@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-selector-tokenizer@^0.7.0:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
+ integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==
+ dependencies:
+ cssesc "^0.1.0"
+ fastparse "^1.1.1"
+ regexpu-core "^1.0.0"
+
+css-vendor@^2.0.6:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.7.tgz#4e6d53d953c187981576d6a542acc9fb57174bda"
+ integrity sha512-VS9Rjt79+p7M0WkPqcAza4Yq1ZHrsHrwf7hPL/bjQB+c1lwmAI+1FXxYTYt818D/50fFVflw0XKleiBN5RITkg==
+ dependencies:
+ "@babel/runtime" "^7.6.2"
+ is-in-browser "^1.0.2"
+
+css-what@2.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
+ integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
+
+cssesc@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
+ integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
+
+cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1"
+ integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==
+ dependencies:
+ cssom "0.3.x"
+
+csstype@^2.2.0, csstype@^2.5.2, csstype@^2.6.5, csstype@^2.6.7:
+ version "2.6.7"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5"
+ integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==
+
+currently-unhandled@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
+ integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
+ dependencies:
+ array-find-index "^1.0.1"
+
+cyclist@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
+ integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
+
+dargs@^4.0.1:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17"
+ integrity sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=
+ dependencies:
+ number-is-nan "^1.0.0"
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+ dependencies:
+ assert-plus "^1.0.0"
+
+data-urls@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
+ integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==
+ dependencies:
+ abab "^2.0.0"
+ whatwg-mimetype "^2.2.0"
+ whatwg-url "^7.0.0"
+
+dateformat@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
+ integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
+
+debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
+debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
+debuglog@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
+ integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
+
+decamelize-keys@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
+ integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
+ dependencies:
+ decamelize "^1.1.0"
+ map-obj "^1.0.0"
+
+decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+decamelize@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7"
+ integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==
+ dependencies:
+ xregexp "4.0.0"
+
+decode-uri-component@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
+
+dedent@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+ integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
+
+deep-equal@^1.0.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
+ integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==
+ dependencies:
+ is-arguments "^1.0.4"
+ is-date-object "^1.0.1"
+ is-regex "^1.0.4"
+ object-is "^1.0.1"
+ object-keys "^1.1.1"
+ regexp.prototype.flags "^1.2.0"
+
+deep-extend@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+deep-is@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+ integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+
+default-gateway@^2.6.0:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
+ integrity sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==
+ dependencies:
+ execa "^0.10.0"
+ ip-regex "^2.1.0"
+
+default-require-extensions@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+ integrity sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=
+ dependencies:
+ strip-bom "^2.0.0"
+
+defaults@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+ integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+ dependencies:
+ clone "^1.0.2"
+
+define-properties@^1.1.2, define-properties@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+ dependencies:
+ object-keys "^1.0.12"
+
+define-property@^0.2.5:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+ integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
+ dependencies:
+ is-descriptor "^0.1.0"
+
+define-property@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+ integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
+ dependencies:
+ is-descriptor "^1.0.0"
+
+define-property@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
+ integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
+ dependencies:
+ is-descriptor "^1.0.2"
+ isobject "^3.0.1"
+
+del@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+ integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=
+ dependencies:
+ 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"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+ integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
+
+depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+
+deprecation@^2.0.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
+ integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
+
+des.js@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
+ integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==
+ dependencies:
+ inherits "^2.0.1"
+ minimalistic-assert "^1.0.0"
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+
+detect-file@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
+ integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
+
+detect-indent@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
+ integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg=
+ dependencies:
+ repeating "^2.0.0"
+
+detect-indent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
+ integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
+
+detect-libc@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
+
+detect-newline@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+ integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
+
+detect-node@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c"
+ integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==
+
+dezalgo@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
+ integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=
+ dependencies:
+ asap "^2.0.0"
+ wrappy "1"
+
+diff@^3.2.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+ integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+
+diffie-hellman@^5.0.0:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
+ integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==
+ dependencies:
+ bn.js "^4.1.0"
+ miller-rabin "^4.0.0"
+ randombytes "^2.0.0"
+
+dir-glob@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034"
+ integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==
+ dependencies:
+ arrify "^1.0.1"
+ path-type "^3.0.0"
+
+dir-glob@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
+ integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==
+ dependencies:
+ path-type "^3.0.0"
+
+dns-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+ integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0=
+
+dns-packet@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a"
+ integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==
+ dependencies:
+ ip "^1.1.0"
+ safe-buffer "^5.0.1"
+
+dns-txt@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6"
+ integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=
+ dependencies:
+ buffer-indexof "^1.0.0"
+
+doctrine@0.7.2, doctrine@^0.7.2:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523"
+ integrity sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=
+ dependencies:
+ esutils "^1.1.6"
+ isarray "0.0.1"
+
+dom-converter@^0.2:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
+ integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==
+ dependencies:
+ utila "~0.4"
+
+dom-helpers@^5.0.1:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.1.3.tgz#7233248eb3a2d1f74aafca31e52c5299cc8ce821"
+ integrity sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw==
+ dependencies:
+ "@babel/runtime" "^7.6.3"
+ csstype "^2.6.7"
+
+dom-serializer@0:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
+ integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
+ dependencies:
+ domelementtype "^2.0.1"
+ entities "^2.0.0"
+
+domain-browser@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
+ integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
+
+domelementtype@1, domelementtype@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
+ integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
+
+domelementtype@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d"
+ integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==
+
+domexception@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90"
+ integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==
+ dependencies:
+ webidl-conversions "^4.0.2"
+
+domhandler@^2.3.0:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
+ integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==
+ dependencies:
+ domelementtype "1"
+
+domutils@1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+domutils@^1.5.1:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+ integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+dot-prop@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
+ integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc=
+ dependencies:
+ is-obj "^1.0.0"
+
+dot-prop@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
+ integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
+ dependencies:
+ is-obj "^1.0.0"
+
+duplexer@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
+ integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
+
+duplexify@^3.4.2, duplexify@^3.6.0:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
+ integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
+ dependencies:
+ end-of-stream "^1.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+ stream-shift "^1.0.0"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+ integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+ dependencies:
+ jsbn "~0.1.0"
+ safer-buffer "^2.1.0"
+
+ecdsa-sig-formatter@1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
+ integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+ecstatic@^3.0.0:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.3.2.tgz#6d1dd49814d00594682c652adb66076a69d46c48"
+ integrity sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==
+ dependencies:
+ he "^1.1.1"
+ mime "^1.6.0"
+ minimist "^1.1.0"
+ url-join "^2.0.5"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+
+electron-to-chromium@^1.3.295:
+ version "1.3.306"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.306.tgz#e8265301d053d5f74e36cb876486830261fbe946"
+ integrity sha512-frDqXvrIROoYvikSKTIKbHbzO6M3/qC6kCIt/1FOa9kALe++c4VAJnwjSFvf1tYLEUsP2n9XZ4XSCyqc3l7A/A==
+
+elliptic@^6.0.0:
+ version "6.5.1"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b"
+ integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==
+ dependencies:
+ 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@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+ integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+
+encoding@^0.1.11:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
+ dependencies:
+ iconv-lite "~0.4.13"
+
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+ dependencies:
+ once "^1.4.0"
+
+enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66"
+ integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==
+ dependencies:
+ graceful-fs "^4.1.2"
+ memory-fs "^0.5.0"
+ tapable "^1.0.0"
+
+entities@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
+ integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
+
+entities@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
+ integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
+
+err-code@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960"
+ integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=
+
+errno@^0.1.1, errno@^0.1.3, errno@~0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+ integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
+ dependencies:
+ prr "~1.0.1"
+
+error-ex@^1.2.0, error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-abstract@^1.5.1:
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d"
+ integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==
+ dependencies:
+ es-to-primitive "^1.2.0"
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.0"
+ is-callable "^1.1.4"
+ is-regex "^1.0.4"
+ object-inspect "^1.6.0"
+ object-keys "^1.1.1"
+ string.prototype.trimleft "^2.1.0"
+ string.prototype.trimright "^2.1.0"
+
+es-to-primitive@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+
+escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+escodegen@^1.9.1:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541"
+ integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==
+ dependencies:
+ esprima "^3.1.3"
+ estraverse "^4.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.6.1"
+
+eslint-scope@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
+ integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+esprima@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+ integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
+
+esprima@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esrecurse@^4.1.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
+ integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==
+ dependencies:
+ estraverse "^4.1.0"
+
+estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+esutils@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375"
+ integrity sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=
+
+esutils@^2.0.0, esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+
+eventemitter3@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb"
+ integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==
+
+events@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
+ integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==
+
+eventsource@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
+ integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
+ dependencies:
+ original "^1.0.0"
+
+evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+ integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
+ dependencies:
+ md5.js "^1.3.4"
+ safe-buffer "^5.1.1"
+
+exec-sh@^0.2.0:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.2.tgz#2a5e7ffcbd7d0ba2755bdecb16e5a427dfbdec36"
+ integrity sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==
+ dependencies:
+ merge "^1.2.0"
+
+execa@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+ integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
+ dependencies:
+ 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"
+
+execa@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+ integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+ dependencies:
+ 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"
+
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
+
+expand-brackets@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+ integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
+ dependencies:
+ is-posix-bracket "^0.1.0"
+
+expand-brackets@^2.1.4:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
+ integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
+ dependencies:
+ 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"
+
+expand-range@^1.8.1:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+ integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
+ dependencies:
+ fill-range "^2.1.0"
+
+expand-tilde@^2.0.0, expand-tilde@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
+ integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
+ dependencies:
+ homedir-polyfill "^1.0.1"
+
+expect@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
+ integrity sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==
+ dependencies:
+ ansi-styles "^3.2.0"
+ jest-diff "^23.6.0"
+ jest-get-type "^22.1.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
+
+express@^4.16.2:
+ version "4.17.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
+ integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
+ dependencies:
+ 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"
+
+extend-shallow@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+ integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
+ dependencies:
+ is-extendable "^0.1.0"
+
+extend-shallow@^3.0.0, extend-shallow@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
+ integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
+ dependencies:
+ assign-symbols "^1.0.0"
+ is-extendable "^1.0.1"
+
+extend@~3.0.1, extend@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+external-editor@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
+ integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
+ dependencies:
+ chardet "^0.7.0"
+ iconv-lite "^0.4.24"
+ tmp "^0.0.33"
+
+extglob@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+ integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
+ dependencies:
+ is-extglob "^1.0.0"
+
+extglob@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
+ integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
+ dependencies:
+ 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"
+
+extract-text-webpack-plugin@next:
+ version "4.0.0-beta.0"
+ resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz#f7361d7ff430b42961f8d1321ba8c1757b5d4c42"
+ integrity sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==
+ dependencies:
+ async "^2.4.1"
+ loader-utils "^1.1.0"
+ schema-utils "^0.4.5"
+ webpack-sources "^1.1.0"
+
+extsprintf@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+ integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+
+extsprintf@^1.2.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
+ integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
+
+fast-deep-equal@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
+ integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=
+
+fast-deep-equal@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+ integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+
+fast-glob@^2.0.2:
+ version "2.2.7"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
+ integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==
+ dependencies:
+ "@mrmlnc/readdir-enhanced" "^2.2.1"
+ "@nodelib/fs.stat" "^1.1.2"
+ glob-parent "^3.1.0"
+ is-glob "^4.0.0"
+ merge2 "^1.2.3"
+ micromatch "^3.1.10"
+
+fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+ integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
+
+fast-levenshtein@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+
+fastparse@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
+ integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
+
+faye-websocket@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
+ integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=
+ dependencies:
+ websocket-driver ">=0.5.1"
+
+faye-websocket@~0.11.1:
+ version "0.11.3"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
+ integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
+fb-watchman@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
+ integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=
+ dependencies:
+ bser "^2.0.0"
+
+figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
+ integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
+
+figures@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+ integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+file-loader@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde"
+ integrity sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==
+ dependencies:
+ loader-utils "^1.0.2"
+ schema-utils "^1.0.0"
+
+filename-regex@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
+ integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
+
+fileset@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+ integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
+ dependencies:
+ glob "^7.0.3"
+ minimatch "^3.0.3"
+
+fill-range@^2.1.0:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565"
+ integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==
+ dependencies:
+ is-number "^2.1.0"
+ isobject "^2.0.0"
+ randomatic "^3.0.0"
+ repeat-element "^1.1.2"
+ repeat-string "^1.5.2"
+
+fill-range@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
+ integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
+ dependencies:
+ extend-shallow "^2.0.1"
+ is-number "^3.0.0"
+ repeat-string "^1.6.1"
+ to-regex-range "^2.1.0"
+
+finalhandler@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+ dependencies:
+ 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@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
+ integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^1.0.0"
+ pkg-dir "^2.0.0"
+
+find-cache-dir@^2.0.0, find-cache-dir@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
+ integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^2.0.0"
+ pkg-dir "^3.0.0"
+
+find-up@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+ dependencies:
+ path-exists "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+find-up@^2.0.0, find-up@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
+ dependencies:
+ locate-path "^2.0.0"
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+findup-sync@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
+ integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=
+ dependencies:
+ detect-file "^1.0.0"
+ is-glob "^3.1.0"
+ micromatch "^3.0.4"
+ resolve-dir "^1.0.1"
+
+flush-write-stream@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
+ integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.3.6"
+
+follow-redirects@^1.0.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f"
+ integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==
+ dependencies:
+ debug "^3.0.0"
+
+for-in@^0.1.3:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1"
+ integrity sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=
+
+for-in@^1.0.1, for-in@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
+ integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
+
+for-own@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
+ integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
+ dependencies:
+ for-in "^1.0.1"
+
+for-own@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b"
+ integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=
+ dependencies:
+ for-in "^1.0.1"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+ integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+
+form-data@~2.3.1, form-data@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.6"
+ mime-types "^2.1.12"
+
+forwarded@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+ integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
+
+fragment-cache@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
+ integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
+ dependencies:
+ map-cache "^0.2.2"
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+
+from2@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+
+fs-extra@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-minipass@^1.2.5:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
+ integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
+ dependencies:
+ minipass "^2.6.0"
+
+fs-write-stream-atomic@^1.0.8:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+ integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=
+ dependencies:
+ graceful-fs "^4.1.2"
+ iferr "^0.1.5"
+ imurmurhash "^0.1.4"
+ readable-stream "1 || 2"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+fsevents@^1.2.3, fsevents@^1.2.7:
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f"
+ integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==
+ dependencies:
+ nan "^2.12.1"
+ node-pre-gyp "^0.12.0"
+
+fstream@^1.0.0, fstream@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+ integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
+ dependencies:
+ graceful-fs "^4.1.2"
+ inherits "~2.0.0"
+ mkdirp ">=0.5 0"
+ rimraf "2"
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+ integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
+ dependencies:
+ 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@^1.0.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a"
+ integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==
+ dependencies:
+ globule "^1.0.0"
+
+genfun@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537"
+ integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==
+
+get-caller-file@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
+ integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+
+get-caller-file@^2.0.0:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-pkg-repo@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d"
+ integrity sha1-xztInAbYDMVTbCyFP54FIyBWly0=
+ dependencies:
+ hosted-git-info "^2.1.4"
+ meow "^3.3.0"
+ normalize-package-data "^2.3.0"
+ parse-github-repo-url "^1.3.0"
+ through2 "^2.0.0"
+
+get-port@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
+ integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=
+
+get-stdin@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+ integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
+
+get-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+ integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+
+get-stream@^4.0.0, get-stream@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+ integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+ dependencies:
+ pump "^3.0.0"
+
+get-value@^2.0.3, get-value@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
+ integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
+ dependencies:
+ assert-plus "^1.0.0"
+
+git-raw-commits@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5"
+ integrity sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==
+ dependencies:
+ dargs "^4.0.1"
+ lodash.template "^4.0.2"
+ meow "^4.0.0"
+ split2 "^2.0.0"
+ through2 "^2.0.0"
+
+git-remote-origin-url@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f"
+ integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=
+ dependencies:
+ gitconfiglocal "^1.0.0"
+ pify "^2.3.0"
+
+git-semver-tags@^2.0.2, git-semver-tags@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-2.0.3.tgz#48988a718acf593800f99622a952a77c405bfa34"
+ integrity sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==
+ dependencies:
+ meow "^4.0.0"
+ semver "^6.0.0"
+
+git-up@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0"
+ integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw==
+ dependencies:
+ is-ssh "^1.3.0"
+ parse-url "^5.0.0"
+
+git-url-parse@^11.1.2:
+ version "11.1.2"
+ resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.1.2.tgz#aff1a897c36cc93699270587bea3dbcbbb95de67"
+ integrity sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==
+ dependencies:
+ git-up "^4.0.0"
+
+gitconfiglocal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b"
+ integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=
+ dependencies:
+ ini "^1.3.2"
+
+github-markdown-css@2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-2.10.0.tgz#0612fed22816b33b282f37ef8def7a4ecabfe993"
+ integrity sha512-RX5VUC54uX6Lvrm226M9kMzsNeOa81MnKyxb3J0G5KLjyoOySOZgwyKFkUpv6iUhooiUZdogk+OTwQPJ4WttYg==
+
+glob-base@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+ integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
+ dependencies:
+ glob-parent "^2.0.0"
+ is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+ integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
+ dependencies:
+ is-glob "^2.0.0"
+
+glob-parent@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
+ integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
+ dependencies:
+ is-glob "^3.1.0"
+ path-dirname "^1.0.0"
+
+glob-to-regexp@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
+ integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=
+
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ dependencies:
+ 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"
+
+global-modules-path@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.1.tgz#e541f4c800a1a8514a990477b267ac67525b9931"
+ integrity sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg==
+
+global-modules@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
+ integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==
+ dependencies:
+ global-prefix "^1.0.1"
+ is-windows "^1.0.1"
+ resolve-dir "^1.0.0"
+
+global-prefix@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
+ integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
+ dependencies:
+ expand-tilde "^2.0.2"
+ homedir-polyfill "^1.0.1"
+ ini "^1.3.4"
+ is-windows "^1.0.1"
+ which "^1.2.14"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^9.18.0:
+ version "9.18.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+ integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
+
+globby@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+ integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
+ dependencies:
+ array-union "^1.0.1"
+ glob "^7.0.3"
+ object-assign "^4.0.1"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+globby@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680"
+ integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA=
+ dependencies:
+ 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"
+
+globby@^8.0.1:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d"
+ integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==
+ dependencies:
+ array-union "^1.0.1"
+ dir-glob "2.0.0"
+ fast-glob "^2.0.2"
+ glob "^7.1.2"
+ ignore "^3.3.5"
+ pify "^3.0.0"
+ slash "^1.0.0"
+
+globule@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d"
+ integrity sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==
+ dependencies:
+ glob "~7.1.1"
+ lodash "~4.17.10"
+ minimatch "~3.0.2"
+
+graceful-fs@4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.4.tgz#ef089d2880f033b011823ce5c8fae798da775dbd"
+ integrity sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
+ integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
+
+growly@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
+ integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
+
+handle-thing@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
+ integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==
+
+handlebars@^4.0.3:
+ version "4.5.2"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.2.tgz#5a4eb92ab5962ca3415ac188c86dc7f784f76a0f"
+ integrity sha512-29Zxv/cynYB7mkT1rVWQnV7mGX6v7H/miQ6dbEpYTKq5eJBN7PsRB+ViYJlcT6JINTSu4dVB9kOqEun78h6Exg==
+ dependencies:
+ neo-async "^2.6.0"
+ optimist "^0.6.1"
+ source-map "^0.6.1"
+ optionalDependencies:
+ uglify-js "^3.1.4"
+
+handlebars@^4.4.0:
+ version "4.5.3"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
+ integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
+ dependencies:
+ neo-async "^2.6.0"
+ optimist "^0.6.1"
+ source-map "^0.6.1"
+ optionalDependencies:
+ uglify-js "^3.1.4"
+
+har-schema@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+ integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
+
+har-validator@~5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
+ integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=
+ dependencies:
+ ajv "^5.1.0"
+ har-schema "^2.0.0"
+
+har-validator@~5.1.0:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
+ integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
+ dependencies:
+ ajv "^6.5.5"
+ har-schema "^2.0.0"
+
+has-ansi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
+ dependencies:
+ ansi-regex "^2.0.0"
+
+has-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+ integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-symbols@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
+ integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
+
+has-unicode@^2.0.0, has-unicode@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+ integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
+
+has-value@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
+ integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
+ dependencies:
+ get-value "^2.0.3"
+ has-values "^0.1.4"
+ isobject "^2.0.0"
+
+has-value@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
+ integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
+ dependencies:
+ get-value "^2.0.6"
+ has-values "^1.0.0"
+ isobject "^3.0.0"
+
+has-values@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
+ integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
+
+has-values@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
+ integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
+ dependencies:
+ is-number "^3.0.0"
+ kind-of "^4.0.0"
+
+has@^1.0.1, has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+hash-base@^3.0.0:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
+ integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+hash.js@^1.0.0, hash.js@^1.0.3:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42"
+ integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==
+ dependencies:
+ inherits "^2.0.3"
+ minimalistic-assert "^1.0.1"
+
+he@1.2.x, he@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
+highlight.js@9.13.1:
+ version "9.13.1"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
+ integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
+
+history@^4.7.2:
+ version "4.10.1"
+ resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
+ integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ loose-envify "^1.2.0"
+ resolve-pathname "^3.0.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+ value-equal "^1.0.1"
+
+hmac-drbg@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+ integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
+ dependencies:
+ hash.js "^1.0.3"
+ minimalistic-assert "^1.0.0"
+ minimalistic-crypto-utils "^1.0.1"
+
+hoist-non-react-statics@^2.5.0:
+ version "2.5.5"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
+ integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
+
+hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
+ integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
+ dependencies:
+ react-is "^16.7.0"
+
+home-or-tmp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
+ integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg=
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.1"
+
+homedir-polyfill@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
+ integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==
+ dependencies:
+ parse-passwd "^1.0.0"
+
+hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
+ version "2.8.5"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
+ integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
+
+hpack.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+ integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=
+ dependencies:
+ inherits "^2.0.1"
+ obuf "^1.0.0"
+ readable-stream "^2.0.1"
+ wbuf "^1.1.0"
+
+html-encoding-sniffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
+ integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==
+ dependencies:
+ whatwg-encoding "^1.0.1"
+
+html-entities@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
+ integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=
+
+html-minifier@^3.2.3:
+ version "3.5.21"
+ resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c"
+ integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==
+ dependencies:
+ camel-case "3.0.x"
+ clean-css "4.2.x"
+ commander "2.17.x"
+ he "1.2.x"
+ param-case "2.1.x"
+ relateurl "0.2.x"
+ uglify-js "3.4.x"
+
+html-webpack-include-assets-plugin@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/html-webpack-include-assets-plugin/-/html-webpack-include-assets-plugin-1.0.5.tgz#12770c227290451633351b5ed72dda8ce8c0642e"
+ integrity sha512-YkkzE+QfYAuEq8/yEnfTcpCeSLyJ8XmB2LlQzY1GV7/ovDxavcCIKSMF4kIMRrWmFMPU8qog/zvBaQ1RJFFw/g==
+ dependencies:
+ glob "^7.1.3"
+ minimatch "^3.0.4"
+ slash "^2.0.0"
+
+html-webpack-plugin@3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz#b01abbd723acaaa7b37b6af4492ebda03d9dd37b"
+ integrity sha1-sBq71yOsqqeze2r0SS69oD2d03s=
+ dependencies:
+ html-minifier "^3.2.3"
+ loader-utils "^0.2.16"
+ lodash "^4.17.3"
+ pretty-error "^2.0.2"
+ tapable "^1.0.0"
+ toposort "^1.0.0"
+ util.promisify "1.0.0"
+
+htmlparser2@^3.3.0:
+ version "3.10.1"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
+ integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
+ dependencies:
+ domelementtype "^1.3.1"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^3.1.1"
+
+http-cache-semantics@^3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
+ integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
+
+http-deceiver@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+ integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
+
+http-errors@1.7.2:
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
+ integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.1"
+ statuses ">= 1.5.0 < 2"
+ toidentifier "1.0.0"
+
+http-errors@~1.6.2:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+ integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.0"
+ statuses ">= 1.4.0 < 2"
+
+http-errors@~1.7.2:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
+ integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.4"
+ setprototypeof "1.1.1"
+ statuses ">= 1.5.0 < 2"
+ toidentifier "1.0.0"
+
+"http-parser-js@>=0.4.0 <0.4.11":
+ version "0.4.10"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
+ integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=
+
+http-proxy-agent@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
+ integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+ dependencies:
+ agent-base "4"
+ debug "3.1.0"
+
+http-proxy-middleware@~0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab"
+ integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==
+ dependencies:
+ http-proxy "^1.16.2"
+ is-glob "^4.0.0"
+ lodash "^4.17.5"
+ micromatch "^3.1.9"
+
+http-proxy@^1.16.2, http-proxy@^1.8.1:
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a"
+ integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==
+ dependencies:
+ eventemitter3 "^4.0.0"
+ follow-redirects "^1.0.0"
+ requires-port "^1.0.0"
+
+http-server@^0.11.1:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/http-server/-/http-server-0.11.1.tgz#2302a56a6ffef7f9abea0147d838a5e9b6b6a79b"
+ integrity sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==
+ dependencies:
+ colors "1.0.3"
+ corser "~2.0.0"
+ ecstatic "^3.0.0"
+ http-proxy "^1.8.1"
+ opener "~1.4.0"
+ optimist "0.6.x"
+ portfinder "^1.0.13"
+ union "~0.4.3"
+
+http-signature@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+ integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+https-browserify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+ integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
+
+https-proxy-agent@^2.2.1, https-proxy-agent@^2.2.3:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
+ integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
+ dependencies:
+ agent-base "^4.3.0"
+ debug "^3.1.0"
+
+humanize-ms@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+ integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=
+ dependencies:
+ ms "^2.0.0"
+
+humps@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa"
+ integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=
+
+hyphenate-style-name@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
+ integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
+
+iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+icss-replace-symbols@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
+ integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
+
+icss-utils@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
+ integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=
+ dependencies:
+ postcss "^6.0.1"
+
+ieee754@^1.1.4:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84"
+ integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==
+
+iferr@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+ integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
+
+ignore-walk@^3.0.1:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
+ integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
+ dependencies:
+ minimatch "^3.0.4"
+
+ignore@^3.3.5:
+ version "3.3.10"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
+ integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==
+
+image-size@~0.5.0:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
+ integrity sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=
+
+import-cwd@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
+ integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=
+ dependencies:
+ import-from "^2.1.0"
+
+import-fresh@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
+ integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY=
+ dependencies:
+ caller-path "^2.0.0"
+ resolve-from "^3.0.0"
+
+import-from@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
+ integrity sha1-M1238qev/VOqpHHUuAId7ja387E=
+ dependencies:
+ resolve-from "^3.0.0"
+
+import-local@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+ integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
+ dependencies:
+ pkg-dir "^2.0.0"
+ resolve-cwd "^2.0.0"
+
+import-local@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
+ integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
+ dependencies:
+ pkg-dir "^3.0.0"
+ resolve-cwd "^2.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+
+in-publish@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51"
+ integrity sha1-4g/146KvwmkDILbcVSaCqcf631E=
+
+indent-string@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
+ integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
+ dependencies:
+ repeating "^2.0.0"
+
+indent-string@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
+ integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
+
+infer-owner@^1.0.3, infer-owner@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
+ integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inherits@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+ integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
+
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
+ini@^1.3.2, ini@^1.3.4, ini@~1.3.0:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+ integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+
+init-package-json@^1.10.3:
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe"
+ integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==
+ dependencies:
+ glob "^7.1.1"
+ npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0"
+ promzard "^0.3.0"
+ read "~1.0.1"
+ read-package-json "1 || 2"
+ semver "2.x || 3.x || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+ validate-npm-package-name "^3.0.0"
+
+inquirer@^6.2.0:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
+ integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==
+ dependencies:
+ ansi-escapes "^3.2.0"
+ chalk "^2.4.2"
+ cli-cursor "^2.1.0"
+ cli-width "^2.0.0"
+ external-editor "^3.0.3"
+ figures "^2.0.0"
+ lodash "^4.17.12"
+ mute-stream "0.0.7"
+ run-async "^2.2.0"
+ rxjs "^6.4.0"
+ string-width "^2.1.0"
+ strip-ansi "^5.1.0"
+ through "^2.3.6"
+
+internal-ip@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"
+ integrity sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==
+ dependencies:
+ default-gateway "^2.6.0"
+ ipaddr.js "^1.5.2"
+
+interpret@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
+ integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
+
+invariant@^2.2.2, invariant@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
+ dependencies:
+ loose-envify "^1.0.0"
+
+inversify@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.0.1.tgz#500d709b1434896ce5a0d58915c4a4210e34fb6e"
+ integrity sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==
+
+invert-kv@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+ integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
+
+invert-kv@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+ integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+
+ip-regex@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+ integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
+
+ip@1.1.5, ip@^1.1.0, ip@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+
+ipaddr.js@1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
+ integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
+
+ipaddr.js@^1.5.2:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+is-accessor-descriptor@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
+ integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
+ dependencies:
+ kind-of "^3.0.2"
+
+is-accessor-descriptor@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
+ integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
+ dependencies:
+ kind-of "^6.0.0"
+
+is-arguments@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
+ integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+
+is-binary-path@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+ integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
+ dependencies:
+ binary-extensions "^1.0.0"
+
+is-buffer@^1.1.5:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+
+is-callable@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
+ integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
+
+is-ci@^1.0.10:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+ integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+ dependencies:
+ ci-info "^1.5.0"
+
+is-data-descriptor@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
+ integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
+ dependencies:
+ kind-of "^3.0.2"
+
+is-data-descriptor@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
+ integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
+ dependencies:
+ kind-of "^6.0.0"
+
+is-date-object@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+ integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
+
+is-descriptor@^0.1.0:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
+ integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
+ dependencies:
+ is-accessor-descriptor "^0.1.6"
+ is-data-descriptor "^0.1.4"
+ kind-of "^5.0.0"
+
+is-descriptor@^1.0.0, is-descriptor@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
+ integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
+ dependencies:
+ is-accessor-descriptor "^1.0.0"
+ is-data-descriptor "^1.0.0"
+ kind-of "^6.0.2"
+
+is-directory@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
+ integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=
+
+is-dotfile@^1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
+ integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
+
+is-equal-shallow@^0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+ integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
+ dependencies:
+ is-primitive "^2.0.0"
+
+is-extendable@^0.1.0, is-extendable@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+ integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
+
+is-extendable@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
+ integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
+ dependencies:
+ is-plain-object "^2.0.4"
+
+is-extglob@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+ integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
+
+is-extglob@^2.1.0, is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
+is-finite@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
+ integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
+ dependencies:
+ number-is-nan "^1.0.0"
+
+is-fullwidth-code-point@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+ integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+
+is-generator-fn@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a"
+ integrity sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+ integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
+ dependencies:
+ is-extglob "^1.0.0"
+
+is-glob@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+ integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
+ dependencies:
+ is-extglob "^2.1.0"
+
+is-glob@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+ integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-in-browser@^1.0.2, is-in-browser@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
+ integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=
+
+is-number@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+ integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
+ dependencies:
+ kind-of "^3.0.2"
+
+is-number@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+ integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
+ dependencies:
+ kind-of "^3.0.2"
+
+is-number@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
+ integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
+
+is-obj@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+ integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
+
+is-path-cwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+ integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
+
+is-path-in-cwd@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+ integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
+ dependencies:
+ is-path-inside "^1.0.0"
+
+is-path-inside@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+ integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+ integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
+
+is-plain-object@^2.0.3, is-plain-object@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
+ dependencies:
+ isobject "^3.0.1"
+
+is-plain-object@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928"
+ integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==
+ dependencies:
+ isobject "^4.0.0"
+
+is-posix-bracket@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+ integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
+
+is-primitive@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+ integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
+
+is-promise@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+ integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
+
+is-regex@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+ integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
+ dependencies:
+ has "^1.0.1"
+
+is-ssh@^1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3"
+ integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==
+ dependencies:
+ protocols "^1.1.0"
+
+is-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+ integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+
+is-symbol@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
+ integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
+ dependencies:
+ has-symbols "^1.0.0"
+
+is-text-path@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e"
+ integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=
+ dependencies:
+ text-extensions "^1.0.0"
+
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
+is-utf8@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+ integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+
+is-windows@^1.0.1, is-windows@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
+ integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
+
+is-wsl@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+ integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+ integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
+
+isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+
+isobject@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+ integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
+ dependencies:
+ isarray "1.0.0"
+
+isobject@^3.0.0, isobject@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
+
+isobject@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
+ integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+ integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+
+istanbul-api@^1.3.1:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.3.7.tgz#a86c770d2b03e11e3f778cd7aedd82d2722092aa"
+ integrity sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==
+ dependencies:
+ async "^2.1.4"
+ fileset "^2.0.2"
+ istanbul-lib-coverage "^1.2.1"
+ istanbul-lib-hook "^1.2.2"
+ istanbul-lib-instrument "^1.10.2"
+ istanbul-lib-report "^1.1.5"
+ istanbul-lib-source-maps "^1.2.6"
+ istanbul-reports "^1.5.1"
+ js-yaml "^3.7.0"
+ mkdirp "^0.5.1"
+ once "^1.4.0"
+
+istanbul-lib-coverage@^1.2.0, istanbul-lib-coverage@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0"
+ integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==
+
+istanbul-lib-hook@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86"
+ integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==
+ dependencies:
+ append-transform "^0.4.0"
+
+istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.10.2:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca"
+ integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==
+ dependencies:
+ 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@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c"
+ integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==
+ dependencies:
+ istanbul-lib-coverage "^1.2.1"
+ mkdirp "^0.5.1"
+ path-parse "^1.0.5"
+ supports-color "^3.1.2"
+
+istanbul-lib-source-maps@^1.2.4, istanbul-lib-source-maps@^1.2.6:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f"
+ integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==
+ dependencies:
+ debug "^3.1.0"
+ istanbul-lib-coverage "^1.2.1"
+ mkdirp "^0.5.1"
+ rimraf "^2.6.1"
+ source-map "^0.5.3"
+
+istanbul-reports@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a"
+ integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==
+ dependencies:
+ handlebars "^4.0.3"
+
+jest-changed-files@^23.4.2:
+ version "23.4.2"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
+ integrity sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==
+ dependencies:
+ throat "^4.0.0"
+
+jest-cli@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
+ integrity sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==
+ dependencies:
+ ansi-escapes "^3.0.0"
+ chalk "^2.0.1"
+ exit "^0.1.2"
+ glob "^7.1.2"
+ graceful-fs "^4.1.11"
+ import-local "^1.0.0"
+ is-ci "^1.0.10"
+ istanbul-api "^1.3.1"
+ istanbul-lib-coverage "^1.2.0"
+ istanbul-lib-instrument "^1.10.1"
+ istanbul-lib-source-maps "^1.2.4"
+ jest-changed-files "^23.4.2"
+ jest-config "^23.6.0"
+ jest-environment-jsdom "^23.4.0"
+ jest-get-type "^22.1.0"
+ jest-haste-map "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve-dependencies "^23.6.0"
+ jest-runner "^23.6.0"
+ jest-runtime "^23.6.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
+ jest-watcher "^23.4.0"
+ jest-worker "^23.2.0"
+ micromatch "^2.3.11"
+ node-notifier "^5.2.1"
+ prompts "^0.1.9"
+ realpath-native "^1.0.0"
+ rimraf "^2.5.4"
+ slash "^1.0.0"
+ string-length "^2.0.0"
+ strip-ansi "^4.0.0"
+ which "^1.2.12"
+ yargs "^11.0.0"
+
+jest-config@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
+ integrity sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==
+ dependencies:
+ babel-core "^6.0.0"
+ babel-jest "^23.6.0"
+ chalk "^2.0.1"
+ glob "^7.1.1"
+ jest-environment-jsdom "^23.4.0"
+ jest-environment-node "^23.4.0"
+ jest-get-type "^22.1.0"
+ jest-jasmine2 "^23.6.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
+ micromatch "^2.3.11"
+ pretty-format "^23.6.0"
+
+jest-diff@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
+ integrity sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==
+ dependencies:
+ chalk "^2.0.1"
+ diff "^3.2.0"
+ jest-get-type "^22.1.0"
+ pretty-format "^23.6.0"
+
+jest-docblock@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
+ integrity sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=
+ dependencies:
+ detect-newline "^2.1.0"
+
+jest-each@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
+ integrity sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==
+ dependencies:
+ chalk "^2.0.1"
+ pretty-format "^23.6.0"
+
+jest-environment-jsdom@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
+ integrity sha1-BWp5UrP+pROsYqFAosNox52eYCM=
+ dependencies:
+ jest-mock "^23.2.0"
+ jest-util "^23.4.0"
+ jsdom "^11.5.1"
+
+jest-environment-node@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
+ integrity sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=
+ dependencies:
+ jest-mock "^23.2.0"
+ jest-util "^23.4.0"
+
+jest-get-type@^22.1.0:
+ version "22.4.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
+ integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==
+
+jest-haste-map@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
+ integrity sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==
+ dependencies:
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.1.11"
+ invariant "^2.2.4"
+ jest-docblock "^23.2.0"
+ jest-serializer "^23.0.1"
+ jest-worker "^23.2.0"
+ micromatch "^2.3.11"
+ sane "^2.0.0"
+
+jest-jasmine2@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
+ integrity sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==
+ dependencies:
+ babel-traverse "^6.0.0"
+ chalk "^2.0.1"
+ co "^4.6.0"
+ expect "^23.6.0"
+ is-generator-fn "^1.0.0"
+ jest-diff "^23.6.0"
+ jest-each "^23.6.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ pretty-format "^23.6.0"
+
+jest-leak-detector@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
+ integrity sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==
+ dependencies:
+ pretty-format "^23.6.0"
+
+jest-matcher-utils@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
+ integrity sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==
+ dependencies:
+ chalk "^2.0.1"
+ jest-get-type "^22.1.0"
+ pretty-format "^23.6.0"
+
+jest-message-util@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
+ integrity sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=
+ dependencies:
+ "@babel/code-frame" "^7.0.0-beta.35"
+ chalk "^2.0.1"
+ micromatch "^2.3.11"
+ slash "^1.0.0"
+ stack-utils "^1.0.1"
+
+jest-mock@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
+ integrity sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=
+
+jest-regex-util@^23.3.0:
+ version "23.3.0"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
+ integrity sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=
+
+jest-resolve-dependencies@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
+ integrity sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==
+ dependencies:
+ jest-regex-util "^23.3.0"
+ jest-snapshot "^23.6.0"
+
+jest-resolve@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
+ integrity sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==
+ dependencies:
+ browser-resolve "^1.11.3"
+ chalk "^2.0.1"
+ realpath-native "^1.0.0"
+
+jest-runner@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
+ integrity sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==
+ dependencies:
+ exit "^0.1.2"
+ graceful-fs "^4.1.11"
+ jest-config "^23.6.0"
+ jest-docblock "^23.2.0"
+ jest-haste-map "^23.6.0"
+ jest-jasmine2 "^23.6.0"
+ jest-leak-detector "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-runtime "^23.6.0"
+ jest-util "^23.4.0"
+ jest-worker "^23.2.0"
+ source-map-support "^0.5.6"
+ throat "^4.0.0"
+
+jest-runtime@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
+ integrity sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==
+ dependencies:
+ babel-core "^6.0.0"
+ babel-plugin-istanbul "^4.1.6"
+ chalk "^2.0.1"
+ convert-source-map "^1.4.0"
+ exit "^0.1.2"
+ fast-json-stable-stringify "^2.0.0"
+ graceful-fs "^4.1.11"
+ jest-config "^23.6.0"
+ jest-haste-map "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve "^23.6.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
+ micromatch "^2.3.11"
+ realpath-native "^1.0.0"
+ slash "^1.0.0"
+ strip-bom "3.0.0"
+ write-file-atomic "^2.1.0"
+ yargs "^11.0.0"
+
+jest-serializer@^23.0.1:
+ version "23.0.1"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
+ integrity sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=
+
+jest-snapshot@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
+ integrity sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==
+ dependencies:
+ babel-types "^6.0.0"
+ chalk "^2.0.1"
+ jest-diff "^23.6.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-resolve "^23.6.0"
+ mkdirp "^0.5.1"
+ natural-compare "^1.4.0"
+ pretty-format "^23.6.0"
+ semver "^5.5.0"
+
+jest-util@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
+ integrity sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=
+ dependencies:
+ callsites "^2.0.0"
+ chalk "^2.0.1"
+ graceful-fs "^4.1.11"
+ is-ci "^1.0.10"
+ jest-message-util "^23.4.0"
+ mkdirp "^0.5.1"
+ slash "^1.0.0"
+ source-map "^0.6.0"
+
+jest-validate@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
+ integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==
+ dependencies:
+ chalk "^2.0.1"
+ jest-get-type "^22.1.0"
+ leven "^2.1.0"
+ pretty-format "^23.6.0"
+
+jest-watcher@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
+ integrity sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=
+ dependencies:
+ ansi-escapes "^3.0.0"
+ chalk "^2.0.1"
+ string-length "^2.0.0"
+
+jest-worker@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
+ integrity sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=
+ dependencies:
+ merge-stream "^1.0.1"
+
+jest@23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
+ integrity sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==
+ dependencies:
+ import-local "^1.0.0"
+ jest-cli "^23.6.0"
+
+jquery@3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
+ integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
+
+js-base64@^2.1.8:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
+ integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
+
+js-levenshtein@^1.1.3:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
+ integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-tokens@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+ integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
+
+js-yaml@^3.13.1, js-yaml@^3.7.0:
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+ integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+ integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+
+jsdom@^11.5.1:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
+ integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
+ dependencies:
+ abab "^2.0.0"
+ acorn "^5.5.3"
+ acorn-globals "^4.1.0"
+ array-equal "^1.0.0"
+ cssom ">= 0.3.2 < 0.4.0"
+ cssstyle "^1.0.0"
+ data-urls "^1.0.0"
+ domexception "^1.0.1"
+ escodegen "^1.9.1"
+ html-encoding-sniffer "^1.0.2"
+ left-pad "^1.3.0"
+ nwsapi "^2.0.7"
+ parse5 "4.0.0"
+ pn "^1.1.0"
+ request "^2.87.0"
+ request-promise-native "^1.0.5"
+ sax "^1.2.4"
+ symbol-tree "^3.2.2"
+ tough-cookie "^2.3.4"
+ w3c-hr-time "^1.0.1"
+ webidl-conversions "^4.0.2"
+ whatwg-encoding "^1.0.3"
+ whatwg-mimetype "^2.1.0"
+ whatwg-url "^6.4.1"
+ ws "^5.2.0"
+ xml-name-validator "^3.0.0"
+
+jsesc@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
+ integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s=
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
+
+json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-schema-traverse@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+ integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+ integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
+
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+
+json3@^3.3.2:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
+ integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
+
+json5@2.x:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6"
+ integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==
+ dependencies:
+ minimist "^1.2.0"
+
+json5@^0.5.0, json5@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+ integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
+
+json5@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
+ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ dependencies:
+ minimist "^1.2.0"
+
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonparse@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
+ integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
+
+jsonwebtoken@8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz#056c90eee9a65ed6e6c72ddb0a1d325109aaf643"
+ integrity sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==
+ dependencies:
+ jws "^3.1.5"
+ lodash.includes "^4.3.0"
+ lodash.isboolean "^3.0.3"
+ lodash.isinteger "^4.0.4"
+ lodash.isnumber "^3.0.3"
+ lodash.isplainobject "^4.0.6"
+ lodash.isstring "^4.0.1"
+ lodash.once "^4.0.0"
+ ms "^2.1.1"
+
+jsprim@^1.2.2:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+ integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.2.3"
+ verror "1.10.0"
+
+jss-plugin-camel-case@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0.tgz#d601bae2e8e2041cc526add289dcd7062db0a248"
+ integrity sha512-yALDL00+pPR4FJh+k07A8FeDvfoPPuXU48HLy63enAubcVd3DnS+2rgqPXglHDGixIDVkCSXecl/l5GAMjzIbA==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ hyphenate-style-name "^1.0.3"
+ jss "10.0.0"
+
+jss-plugin-default-unit@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0.tgz#601caf5f576fc0c66986fbe8a9aa37307a3a3ea3"
+ integrity sha512-sURozIOdCtGg9ap18erQ+ijndAfEGtTaetxfU3H4qwC18Bi+fdvjlY/ahKbuu0ASs7R/+WKCP7UaRZOjUDMcdQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.0.0"
+
+jss-plugin-global@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.0.0.tgz#0fed1b6461e0d57d6e394f877529009bc1cb3cb6"
+ integrity sha512-80ofWKSQUo62bxLtRoTNe0kFPtHgUbAJeOeR36WEGgWIBEsXLyXOnD5KNnjPqG4heuEkz9eSLccjYST50JnI7Q==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.0.0"
+
+jss-plugin-nested@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.0.0.tgz#d37ecc013c3b0d0e4acc2b48f6b62da6ae53948b"
+ integrity sha512-waxxwl/po1hN3azTyixKnr8ReEqUv5WK7WsO+5AWB0bFndML5Yqnt8ARZ90HEg8/P6WlqE/AB2413TkCRZE8bA==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.0.0"
+ tiny-warning "^1.0.2"
+
+jss-plugin-props-sort@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0.tgz#38a13407384c2a4a7c026659488350669b953b18"
+ integrity sha512-41mf22CImjwNdtOG3r+cdC8+RhwNm616sjHx5YlqTwtSJLyLFinbQC/a4PIFk8xqf1qpFH1kEAIw+yx9HaqZ3g==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.0.0"
+
+jss-plugin-rule-value-function@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0.tgz#3ec1b781b7c86080136dbef6c36e91f20244b72e"
+ integrity sha512-Jw+BZ8JIw1f12V0SERqGlBT1JEPWax3vuZpMym54NAXpPb7R1LYHiCTIlaJUyqvIfEy3kiHMtgI+r2whGgRIxQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.0.0"
+
+jss-plugin-vendor-prefixer@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0.tgz#400280535b0f483a9c78105afe4eee61b70018eb"
+ integrity sha512-qslqvL0MUbWuzXJWdUxpj6mdNUX8jr4FFTo3aZnAT65nmzWL7g8oTr9ZxmTXXgdp7ANhS1QWE7036/Q2isFBpw==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ css-vendor "^2.0.6"
+ jss "10.0.0"
+
+jss@10.0.0, jss@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.0.tgz#998d5026c02accae15708de83bd6ba57bac977d2"
+ integrity sha512-TPpDFsiBjuERiL+dFDq8QCdiF9oDasPcNqCKLGCo/qED3fNYOQ8PX2lZhknyTiAt3tZrfOFbb0lbQ9lTjPZxsQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ csstype "^2.6.5"
+ is-in-browser "^1.1.3"
+ tiny-warning "^1.0.2"
+
+jwa@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
+ integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
+ dependencies:
+ buffer-equal-constant-time "1.0.1"
+ ecdsa-sig-formatter "1.0.11"
+ safe-buffer "^5.0.1"
+
+jws@^3.1.5:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
+ integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
+ dependencies:
+ jwa "^1.4.1"
+ safe-buffer "^5.0.1"
+
+killable@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
+ integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==
+
+kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
+ dependencies:
+ is-buffer "^1.1.5"
+
+kind-of@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+ integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
+ dependencies:
+ is-buffer "^1.1.5"
+
+kind-of@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
+ integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
+
+kind-of@^6.0.0, kind-of@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
+ integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
+
+kleur@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
+ integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
+
+lcid@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+ integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
+ dependencies:
+ invert-kv "^1.0.0"
+
+lcid@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+ integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+ dependencies:
+ invert-kv "^2.0.0"
+
+left-pad@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e"
+ integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==
+
+lerna@3.13.1:
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.13.1.tgz#feaff562176f304bd82329ca29ce46ab6c033463"
+ integrity sha512-7kSz8LLozVsoUNTJzJzy+b8TnV9YdviR2Ee2PwGZSlVw3T1Rn7kOAPZjEi+3IWnOPC96zMPHVmjCmzQ4uubalw==
+ dependencies:
+ "@lerna/add" "3.13.1"
+ "@lerna/bootstrap" "3.13.1"
+ "@lerna/changed" "3.13.1"
+ "@lerna/clean" "3.13.1"
+ "@lerna/cli" "3.13.0"
+ "@lerna/create" "3.13.1"
+ "@lerna/diff" "3.13.1"
+ "@lerna/exec" "3.13.1"
+ "@lerna/import" "3.13.1"
+ "@lerna/init" "3.13.1"
+ "@lerna/link" "3.13.1"
+ "@lerna/list" "3.13.1"
+ "@lerna/publish" "3.13.1"
+ "@lerna/run" "3.13.1"
+ "@lerna/version" "3.13.1"
+ import-local "^1.0.0"
+ npmlog "^4.1.2"
+
+less-loader@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.1.0.tgz#2c1352c5b09a4f84101490274fd51674de41363e"
+ integrity sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==
+ dependencies:
+ clone "^2.1.1"
+ loader-utils "^1.1.0"
+ pify "^3.0.0"
+
+less@3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/less/-/less-3.8.1.tgz#f31758598ef5a1930dd4caefa9e4340641e71e1d"
+ integrity sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==
+ dependencies:
+ clone "^2.1.2"
+ optionalDependencies:
+ 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"
+
+leven@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
+ integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+libnpmaccess@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.2.tgz#8b2d72345ba3bef90d3b4f694edd5c0417f58923"
+ integrity sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ==
+ dependencies:
+ aproba "^2.0.0"
+ get-stream "^4.0.0"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^4.0.0"
+
+libnpmpublish@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.3.tgz#e3782796722d79eef1a0a22944c117e0c4ca4280"
+ integrity sha512-/3LsYqVc52cHXBmu26+J8Ed7sLs/hgGVFMH1mwYpL7Qaynb9RenpKqIKu0sJ130FB9PMkpMlWjlbtU8A4m7CQw==
+ dependencies:
+ aproba "^2.0.0"
+ figgy-pudding "^3.5.1"
+ get-stream "^4.0.0"
+ lodash.clonedeep "^4.5.0"
+ normalize-package-data "^2.4.0"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^4.0.0"
+ semver "^5.5.1"
+ ssri "^6.0.1"
+
+lightercollective@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300"
+ integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==
+
+load-json-file@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+ integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^2.2.0"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+ strip-bom "^2.0.0"
+
+load-json-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+ strip-bom "^3.0.0"
+
+loader-runner@^2.3.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
+ integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
+
+loader-utils@0.2.16:
+ version "0.2.16"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d"
+ integrity sha1-8IYyBm7YKCg13/iN+1JwR2Wt7m0=
+ dependencies:
+ big.js "^3.1.3"
+ emojis-list "^2.0.0"
+ json5 "^0.5.0"
+ object-assign "^4.0.1"
+
+loader-utils@^0.2.16:
+ version "0.2.17"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
+ integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=
+ dependencies:
+ big.js "^3.1.3"
+ emojis-list "^2.0.0"
+ json5 "^0.5.0"
+ object-assign "^4.0.1"
+
+loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
+ integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^2.0.0"
+ json5 "^1.0.1"
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+lodash._reinterpolate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+ integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
+
+lodash.assign@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+ integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=
+
+lodash.camelcase@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+ integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
+
+lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+ integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
+lodash.get@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
+
+lodash.includes@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
+ integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
+
+lodash.isboolean@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+ integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
+
+lodash.isinteger@^4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
+ integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
+
+lodash.ismatch@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
+ integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=
+
+lodash.isnumber@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
+ integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
+
+lodash.isstring@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
+ integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
+
+lodash.mergewith@^4.6.0:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
+ integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
+
+lodash.once@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+ integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
+
+lodash.set@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
+ integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
+
+lodash.sortby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+ integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
+
+lodash.tail@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
+ integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=
+
+lodash.template@^4.0.2:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
+ integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+ lodash.templatesettings "^4.0.0"
+
+lodash.templatesettings@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
+ integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
+ dependencies:
+ lodash._reinterpolate "^3.0.0"
+
+lodash.uniq@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+ integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
+
+lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.10:
+ version "4.17.15"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
+ integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+
+loglevel@^1.4.1:
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312"
+ integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==
+
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+loud-rejection@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
+ dependencies:
+ currently-unhandled "^0.4.1"
+ signal-exit "^3.0.0"
+
+lower-case@^1.1.1:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
+ integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
+
+lru-cache@^4.0.1, lru-cache@^4.1.1:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+ integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
+ dependencies:
+ pseudomap "^1.0.2"
+ yallist "^2.1.2"
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+macos-release@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
+ integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==
+
+make-dir@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
+ integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
+ dependencies:
+ pify "^3.0.0"
+
+make-dir@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+ integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+ dependencies:
+ pify "^4.0.1"
+ semver "^5.6.0"
+
+make-error@1.x:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
+ integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
+
+make-fetch-happen@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.2.tgz#2d156b11696fb32bffbafe1ac1bc085dd6c78a79"
+ integrity sha512-YMJrAjHSb/BordlsDEcVcPyTbiJKkzqMf48N8dAJZT9Zjctrkb6Yg4TY9Sq2AwSIQJFn5qBBKVTYt3vP5FMIHA==
+ dependencies:
+ agentkeepalive "^3.4.1"
+ cacache "^11.3.3"
+ http-cache-semantics "^3.8.1"
+ http-proxy-agent "^2.1.0"
+ https-proxy-agent "^2.2.1"
+ lru-cache "^5.1.1"
+ mississippi "^3.0.0"
+ node-fetch-npm "^2.0.2"
+ promise-retry "^1.1.1"
+ socks-proxy-agent "^4.0.0"
+ ssri "^6.0.0"
+
+make-fetch-happen@^5.0.0:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd"
+ integrity sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==
+ dependencies:
+ agentkeepalive "^3.4.1"
+ cacache "^12.0.0"
+ http-cache-semantics "^3.8.1"
+ http-proxy-agent "^2.1.0"
+ https-proxy-agent "^2.2.3"
+ lru-cache "^5.1.1"
+ mississippi "^3.0.0"
+ node-fetch-npm "^2.0.2"
+ promise-retry "^1.1.1"
+ socks-proxy-agent "^4.0.0"
+ ssri "^6.0.0"
+
+makeerror@1.0.x:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
+ integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=
+ dependencies:
+ tmpl "1.0.x"
+
+map-age-cleaner@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+ integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+ dependencies:
+ p-defer "^1.0.0"
+
+map-cache@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
+ integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
+
+map-obj@^1.0.0, map-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+ integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
+
+map-obj@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
+ integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk=
+
+map-visit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
+ integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
+ dependencies:
+ object-visit "^1.0.0"
+
+marked@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.0.tgz#a18d01cfdcf8d15c3c455b71c8329e5e0f01faa1"
+ integrity sha512-HduzIW2xApSXKXJSpCipSxKyvMbwRRa/TwMbepmlZziKdH8548WSoDP4SxzulEKjlo8BE39l+2fwJZuRKOln6g==
+
+math-random@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
+ integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==
+
+md5.js@^1.3.4:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
+ integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==
+ dependencies:
+ hash-base "^3.0.0"
+ inherits "^2.0.1"
+ safe-buffer "^5.1.2"
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+
+mem@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+ integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+ dependencies:
+ map-age-cleaner "^0.1.1"
+ mimic-fn "^2.0.0"
+ p-is-promise "^2.0.0"
+
+memory-fs@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c"
+ integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==
+ dependencies:
+ errno "^0.1.3"
+ readable-stream "^2.0.1"
+
+memory-fs@~0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+ integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
+ dependencies:
+ errno "^0.1.3"
+ readable-stream "^2.0.1"
+
+meow@^3.3.0, meow@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
+ integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
+ dependencies:
+ 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"
+
+meow@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975"
+ integrity sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==
+ dependencies:
+ camelcase-keys "^4.0.0"
+ decamelize-keys "^1.0.0"
+ loud-rejection "^1.0.0"
+ minimist "^1.1.3"
+ minimist-options "^3.0.1"
+ normalize-package-data "^2.3.4"
+ read-pkg-up "^3.0.0"
+ redent "^2.0.0"
+ trim-newlines "^2.0.0"
+
+meow@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
+ integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==
+ dependencies:
+ camelcase-keys "^4.0.0"
+ decamelize-keys "^1.0.0"
+ loud-rejection "^1.0.0"
+ minimist-options "^3.0.1"
+ normalize-package-data "^2.3.4"
+ read-pkg-up "^3.0.0"
+ redent "^2.0.0"
+ trim-newlines "^2.0.0"
+ yargs-parser "^10.0.0"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
+
+merge-stream@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1"
+ integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=
+ dependencies:
+ readable-stream "^2.0.1"
+
+merge2@^1.2.3:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
+ integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
+
+merge@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
+ integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
+
+micromatch@^2.3.11:
+ version "2.3.11"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+ integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
+ dependencies:
+ 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"
+
+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9:
+ version "3.1.10"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
+ integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
+ dependencies:
+ 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@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+ integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
+ dependencies:
+ bn.js "^4.0.0"
+ brorand "^1.0.1"
+
+mime-db@1.42.0, "mime-db@>= 1.40.0 < 2":
+ version "1.42.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
+ integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
+
+mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
+ version "2.1.25"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437"
+ integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==
+ dependencies:
+ mime-db "1.42.0"
+
+mime@1.6.0, mime@^1.4.1, mime@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mime@^2.0.3, mime@^2.3.1:
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
+ integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
+
+mimic-fn@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
+ integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+
+mimic-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+ integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
+
+minimatch@^3.0.0, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimist-options@^3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954"
+ integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==
+ dependencies:
+ arrify "^1.0.1"
+ is-plain-obj "^1.1.0"
+
+minimist@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
+
+minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+ integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+
+minimist@~0.0.1:
+ version "0.0.10"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+ integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
+
+minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
+ integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
+ dependencies:
+ safe-buffer "^5.1.2"
+ yallist "^3.0.0"
+
+minizlib@^1.2.1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
+ integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
+ dependencies:
+ minipass "^2.9.0"
+
+mississippi@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
+ integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==
+ dependencies:
+ 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"
+
+mississippi@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
+ integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==
+ dependencies:
+ 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"
+
+mixin-deep@^1.2.0:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
+ integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==
+ dependencies:
+ for-in "^1.0.2"
+ is-extendable "^1.0.1"
+
+mixin-object@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/mixin-object/-/mixin-object-2.0.1.tgz#4fb949441dab182540f1fe035ba60e1947a5e57e"
+ integrity sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=
+ dependencies:
+ for-in "^0.1.3"
+ is-extendable "^0.1.1"
+
+mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
+ dependencies:
+ minimist "0.0.8"
+
+modify-values@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
+ integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
+
+moment@^2.10.2:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+ integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
+
+move-concurrently@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+ integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=
+ dependencies:
+ 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@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+ms@^2.0.0, ms@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+multicast-dns-service-types@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
+ integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=
+
+multicast-dns@^6.0.1:
+ version "6.2.3"
+ resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229"
+ integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==
+ dependencies:
+ dns-packet "^1.3.1"
+ thunky "^1.0.2"
+
+multimatch@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
+ integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=
+ dependencies:
+ array-differ "^1.0.0"
+ array-union "^1.0.1"
+ arrify "^1.0.0"
+ minimatch "^3.0.0"
+
+mute-stream@0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+ integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
+
+mute-stream@~0.0.4:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+ integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
+nan@^2.10.0, nan@^2.12.1:
+ version "2.14.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+ integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
+
+nanomatch@^1.2.9:
+ version "1.2.13"
+ resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
+ integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
+ dependencies:
+ 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"
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
+
+needle@^2.2.1:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
+ integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
+ dependencies:
+ debug "^3.2.6"
+ iconv-lite "^0.4.4"
+ sax "^1.2.4"
+
+negotiator@0.6.2:
+ version "0.6.2"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
+ integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
+
+neo-async@^2.5.0, neo-async@^2.6.0:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
+ integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
+
+nice-try@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+no-case@^2.2.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
+ integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
+ dependencies:
+ lower-case "^1.1.1"
+
+node-fetch-npm@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
+ integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==
+ dependencies:
+ encoding "^0.1.11"
+ json-parse-better-errors "^1.0.0"
+ safe-buffer "^5.1.1"
+
+node-fetch@^2.3.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
+ integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
+
+node-forge@0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
+ integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
+
+node-gyp@^3.8.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+ integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
+ dependencies:
+ 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"
+
+node-gyp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45"
+ integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==
+ dependencies:
+ 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 "^4.4.8"
+ which "1"
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=
+
+node-libs-browser@^2.0.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
+ integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
+ dependencies:
+ 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"
+
+node-notifier@^5.2.1:
+ version "5.4.3"
+ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50"
+ integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==
+ dependencies:
+ growly "^1.3.0"
+ is-wsl "^1.1.0"
+ semver "^5.5.0"
+ shellwords "^0.1.1"
+ which "^1.3.0"
+
+node-pre-gyp@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"
+ integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==
+ dependencies:
+ 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"
+
+node-releases@^1.1.38:
+ version "1.1.40"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.40.tgz#a94facfa8e2d612302601ca1361741d529c4515a"
+ integrity sha512-r4LPcC5b/bS8BdtWH1fbeK88ib/wg9aqmg6/s3ngNLn2Ewkn/8J6Iw3P9RTlfIAdSdvYvQl2thCY5Y+qTAQ2iQ==
+ dependencies:
+ semver "^6.3.0"
+
+node-sass@4.9.3:
+ version "4.9.3"
+ resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.3.tgz#f407cf3d66f78308bb1e346b24fa428703196224"
+ integrity sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==
+ dependencies:
+ 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"
+
+"nopt@2 || 3":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+ dependencies:
+ abbrev "1"
+
+nopt@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
+normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.1, normalize-path@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
+ dependencies:
+ remove-trailing-separator "^1.0.1"
+
+normalize-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
+
+normalize-scroll-left@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/normalize-scroll-left/-/normalize-scroll-left-0.2.0.tgz#9445d74275f303cc661e113329aefa492f58114c"
+ integrity sha512-t5oCENZJl8TGusJKoCJm7+asaSsPuNmK6+iEjrZ5TyBj2f02brCRsd4c83hwtu+e5d4LCSBZ0uoDlMjBo+A8yA==
+
+normalize-url@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
+ integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
+
+notistack@0.9.6:
+ version "0.9.6"
+ resolved "https://registry.yarnpkg.com/notistack/-/notistack-0.9.6.tgz#a9b2589e2379096eac292139306f486d4ed5697a"
+ integrity sha512-vo1zOwhQBxwWiMxwVjeSDXNzJuaM/nfkayv4uRo+9ON9CAtaPSNt15QHeELKkbOSLH29fb7zmoZl4AlkCqhGsA==
+ dependencies:
+ classnames "^2.2.6"
+ hoist-non-react-statics "^3.3.0"
+ prop-types "^15.7.2"
+ react-is "^16.8.6"
+
+npm-bundled@^1.0.1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"
+ integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==
+
+npm-lifecycle@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz#0027c09646f0fd346c5c93377bdaba59c6748fdf"
+ integrity sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew==
+ dependencies:
+ byline "^5.0.0"
+ graceful-fs "^4.1.15"
+ node-gyp "^4.0.0"
+ resolve-from "^4.0.0"
+ slide "^1.1.6"
+ uid-number "0.0.6"
+ umask "^1.1.0"
+ which "^1.3.1"
+
+npm-normalize-package-bin@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
+ integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
+
+"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7"
+ integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==
+ dependencies:
+ hosted-git-info "^2.7.1"
+ osenv "^0.1.5"
+ semver "^5.6.0"
+ validate-npm-package-name "^3.0.0"
+
+npm-packlist@^1.1.12, npm-packlist@^1.4.1:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848"
+ integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==
+ dependencies:
+ ignore-walk "^3.0.1"
+ npm-bundled "^1.0.1"
+
+npm-packlist@^1.1.6:
+ version "1.4.6"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4"
+ integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==
+ dependencies:
+ ignore-walk "^3.0.1"
+ npm-bundled "^1.0.1"
+
+npm-pick-manifest@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7"
+ integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==
+ dependencies:
+ figgy-pudding "^3.5.1"
+ npm-package-arg "^6.0.0"
+ semver "^5.4.1"
+
+npm-registry-fetch@^3.9.0:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz#00ff6e4e35d3f75a172b332440b53e93f4cb67de"
+ integrity sha512-VQCEZlydXw4AwLROAXWUR7QDfe2Y8Id/vpAgp6TI1/H78a4SiQ1kQrKZALm5/zxM5n4HIi+aYb+idUAV/RuY0Q==
+ dependencies:
+ JSONStream "^1.3.4"
+ bluebird "^3.5.1"
+ figgy-pudding "^3.4.1"
+ lru-cache "^5.1.1"
+ make-fetch-happen "^4.0.2"
+ npm-package-arg "^6.1.0"
+
+npm-registry-fetch@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz#2b1434f93ccbe6b6385f8e45f45db93e16921d7a"
+ integrity sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==
+ dependencies:
+ JSONStream "^1.3.4"
+ bluebird "^3.5.1"
+ figgy-pudding "^3.4.1"
+ lru-cache "^5.1.1"
+ make-fetch-happen "^5.0.0"
+ npm-package-arg "^6.1.0"
+ safe-buffer "^5.2.0"
+
+npm-run-path@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+ integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
+ dependencies:
+ path-key "^2.0.0"
+
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+ integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
+ dependencies:
+ are-we-there-yet "~1.1.2"
+ console-control-strings "~1.1.0"
+ gauge "~2.7.3"
+ set-blocking "~2.0.0"
+
+nth-check@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
+ integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
+ dependencies:
+ boolbase "~1.0.0"
+
+num2fraction@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
+ integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
+
+number-is-nan@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+ integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
+
+nwsapi@^2.0.7:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
+ integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
+
+oauth-sign@~0.8.2:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+ integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
+
+oauth-sign@~0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+ integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
+
+object-copy@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
+ integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
+ dependencies:
+ copy-descriptor "^0.1.0"
+ define-property "^0.2.5"
+ kind-of "^3.0.3"
+
+object-inspect@^1.6.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
+ integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==
+
+object-is@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
+ integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=
+
+object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object-visit@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
+ integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
+ dependencies:
+ isobject "^3.0.0"
+
+object.assign@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
+ integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+ dependencies:
+ define-properties "^1.1.2"
+ function-bind "^1.1.1"
+ has-symbols "^1.0.0"
+ object-keys "^1.0.11"
+
+object.getownpropertydescriptors@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
+ integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.1"
+
+object.omit@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+ integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
+ dependencies:
+ for-own "^0.1.4"
+ is-extendable "^0.1.1"
+
+object.pick@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+ integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
+ dependencies:
+ isobject "^3.0.1"
+
+obuf@^1.0.0, obuf@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
+octokit-pagination-methods@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
+ integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
+ dependencies:
+ ee-first "1.1.1"
+
+on-headers@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+ dependencies:
+ wrappy "1"
+
+onetime@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
+ dependencies:
+ mimic-fn "^1.0.0"
+
+opener@~1.4.0:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
+ integrity sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=
+
+opn@^5.1.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
+ integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
+ dependencies:
+ is-wsl "^1.1.0"
+
+optimist@0.6.x, optimist@^0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+ integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
+ dependencies:
+ minimist "~0.0.1"
+ wordwrap "~0.0.2"
+
+optionator@^0.8.1:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.6"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ word-wrap "~1.2.3"
+
+original@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
+ integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==
+ dependencies:
+ url-parse "^1.4.3"
+
+os-browserify@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
+ integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+ integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+
+os-locale@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+ integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
+ dependencies:
+ lcid "^1.0.0"
+
+os-locale@^3.0.0, os-locale@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+ integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+ dependencies:
+ execa "^1.0.0"
+ lcid "^2.0.0"
+ mem "^4.0.0"
+
+os-name@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801"
+ integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==
+ dependencies:
+ macos-release "^2.2.0"
+ windows-release "^3.1.0"
+
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+
+osenv@0, osenv@^0.1.4, osenv@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+ integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+p-defer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+ integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+
+p-finally@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+ integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+
+p-is-promise@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+ integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
+p-limit@^1.0.0, p-limit@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
+ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
+ dependencies:
+ p-try "^1.0.0"
+
+p-limit@^2.0.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
+ integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
+ dependencies:
+ p-limit "^1.1.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-map-series@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca"
+ integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=
+ dependencies:
+ p-reduce "^1.0.0"
+
+p-map@^1.1.1, p-map@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
+ integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
+
+p-pipe@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9"
+ integrity sha1-SxoROZoRUgpneQ7loMHViB1r7+k=
+
+p-reduce@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
+ integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
+
+p-try@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+ integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+p-waterfall@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00"
+ integrity sha1-ftlLPOszMngjU69qrhGqn8I1uwA=
+ dependencies:
+ p-reduce "^1.0.0"
+
+pacote@^9.5.0:
+ version "9.5.11"
+ resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.11.tgz#524152077cb392c47b1fbe198aa28f778bef7ee1"
+ integrity sha512-DMDPvFKCjCg6zMS4IfzZyvT57O/bX8XGG00eEoy4K/S4Wj+qiN8KbnmKpsTvfS6OL9r5TAicxMKWbj1yV2Yh4g==
+ dependencies:
+ bluebird "^3.5.3"
+ cacache "^12.0.2"
+ chownr "^1.1.2"
+ figgy-pudding "^3.5.1"
+ get-stream "^4.1.0"
+ glob "^7.1.3"
+ infer-owner "^1.0.4"
+ lru-cache "^5.1.1"
+ make-fetch-happen "^5.0.0"
+ minimatch "^3.0.4"
+ minipass "^2.3.5"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ normalize-package-data "^2.4.0"
+ npm-normalize-package-bin "^1.0.0"
+ npm-package-arg "^6.1.0"
+ npm-packlist "^1.1.12"
+ npm-pick-manifest "^3.0.0"
+ npm-registry-fetch "^4.0.0"
+ osenv "^0.1.5"
+ promise-inflight "^1.0.1"
+ promise-retry "^1.1.1"
+ protoduck "^5.0.1"
+ rimraf "^2.6.2"
+ safe-buffer "^5.1.2"
+ semver "^5.6.0"
+ ssri "^6.0.1"
+ tar "^4.4.10"
+ unique-filename "^1.1.1"
+ which "^1.3.1"
+
+pako@~1.0.5:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
+ integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
+
+parallel-transform@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc"
+ integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==
+ dependencies:
+ cyclist "^1.0.1"
+ inherits "^2.0.3"
+ readable-stream "^2.1.5"
+
+param-case@2.1.x:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247"
+ integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc=
+ dependencies:
+ no-case "^2.2.0"
+
+parse-asn1@^5.0.0:
+ version "5.1.5"
+ resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e"
+ integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==
+ dependencies:
+ 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-github-repo-url@^1.3.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50"
+ integrity sha1-nn2LslKmy2ukJZUGC3v23z28H1A=
+
+parse-glob@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+ integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
+ dependencies:
+ glob-base "^0.3.0"
+ is-dotfile "^1.0.0"
+ is-extglob "^1.0.0"
+ is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
+ dependencies:
+ error-ex "^1.2.0"
+
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
+parse-passwd@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
+ integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
+
+parse-path@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.1.tgz#0ec769704949778cb3b8eda5e994c32073a1adff"
+ integrity sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==
+ dependencies:
+ is-ssh "^1.3.0"
+ protocols "^1.4.0"
+
+parse-url@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f"
+ integrity sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==
+ dependencies:
+ is-ssh "^1.3.0"
+ normalize-url "^3.3.0"
+ parse-path "^4.0.0"
+ protocols "^1.4.0"
+
+parse5@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608"
+ integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==
+
+parseurl@~1.3.2, parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+pascalcase@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+ integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
+
+path-browserify@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
+ integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
+
+path-dirname@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
+ integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
+
+path-exists@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+ dependencies:
+ pinkie-promise "^2.0.0"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+
+path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+path-is-inside@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+ integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+
+path-key@^2.0.0, path-key@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+ integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+
+path-parse@^1.0.5, path-parse@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+ integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+
+path-to-regexp@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
+ integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+ dependencies:
+ isarray "0.0.1"
+
+path-type@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+ integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
+ dependencies:
+ graceful-fs "^4.1.2"
+ pify "^2.0.0"
+ pinkie-promise "^2.0.0"
+
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+ dependencies:
+ pify "^3.0.0"
+
+pbkdf2@^3.0.3:
+ version "3.0.17"
+ resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
+ integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==
+ dependencies:
+ 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@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+
+pify@^2.0.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
+
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+
+pify@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+ integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+
+pkg-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
+ integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
+ dependencies:
+ find-up "^2.1.0"
+
+pkg-dir@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+ integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+ dependencies:
+ find-up "^3.0.0"
+
+pn@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
+ integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==
+
+popper.js@^1.14.1:
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3"
+ integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==
+
+portfinder@^1.0.13, portfinder@^1.0.9:
+ version "1.0.25"
+ resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
+ integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==
+ dependencies:
+ async "^2.6.2"
+ debug "^3.1.1"
+ mkdirp "^0.5.1"
+
+posix-character-classes@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
+ integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
+
+postcss-load-config@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003"
+ integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==
+ dependencies:
+ cosmiconfig "^5.0.0"
+ import-cwd "^2.0.0"
+
+postcss-loader@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d"
+ integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==
+ dependencies:
+ loader-utils "^1.1.0"
+ postcss "^7.0.0"
+ postcss-load-config "^2.0.0"
+ schema-utils "^1.0.0"
+
+postcss-modules-extract-imports@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a"
+ integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==
+ dependencies:
+ postcss "^6.0.1"
+
+postcss-modules-local-by-default@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
+ integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
+ dependencies:
+ css-selector-tokenizer "^0.7.0"
+ postcss "^6.0.1"
+
+postcss-modules-scope@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
+ integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
+ dependencies:
+ css-selector-tokenizer "^0.7.0"
+ postcss "^6.0.1"
+
+postcss-modules-values@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
+ integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
+ dependencies:
+ icss-replace-symbols "^1.1.0"
+ postcss "^6.0.1"
+
+postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281"
+ integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==
+
+postcss@^6.0.1, postcss@^6.0.23:
+ version "6.0.23"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
+ integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
+ dependencies:
+ chalk "^2.4.1"
+ source-map "^0.6.1"
+ supports-color "^5.4.0"
+
+postcss@^7.0.0, postcss@^7.0.2:
+ version "7.0.21"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17"
+ integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==
+ dependencies:
+ chalk "^2.4.2"
+ source-map "^0.6.1"
+ supports-color "^6.1.0"
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+ integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
+
+preserve@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+ integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
+
+pretty-error@^2.0.2:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3"
+ integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=
+ dependencies:
+ renderkid "^2.0.1"
+ utila "~0.4"
+
+pretty-format@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+ integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+ dependencies:
+ ansi-regex "^3.0.0"
+ ansi-styles "^3.2.0"
+
+private@^0.1.6, private@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
+ integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+process@^0.11.10:
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+ integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
+
+promise-inflight@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+ integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
+
+promise-retry@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d"
+ integrity sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=
+ dependencies:
+ err-code "^1.0.0"
+ retry "^0.10.0"
+
+promise@^7.1.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
+ integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
+ dependencies:
+ asap "~2.0.3"
+
+prompts@^0.1.9:
+ version "0.1.14"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
+ integrity sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==
+ dependencies:
+ kleur "^2.0.1"
+ sisteransi "^0.1.1"
+
+promzard@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
+ integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=
+ dependencies:
+ read "1"
+
+prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
+ version "15.7.2"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+ integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.8.1"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
+protocols@^1.1.0, protocols@^1.4.0:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32"
+ integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==
+
+protoduck@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f"
+ integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==
+ dependencies:
+ genfun "^5.0.0"
+
+proxy-addr@~2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
+ integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==
+ dependencies:
+ forwarded "~0.1.2"
+ ipaddr.js "1.9.0"
+
+prr@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+ integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
+
+pseudomap@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+ integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
+
+psl@^1.1.24, psl@^1.1.28:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2"
+ integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==
+
+public-encrypt@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
+ integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==
+ dependencies:
+ 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@^2.0.0, pump@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
+ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pumpify@^1.3.3:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
+ integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
+ dependencies:
+ duplexify "^3.6.0"
+ inherits "^2.0.3"
+ pump "^2.0.0"
+
+punycode@1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+ integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
+
+punycode@^1.2.4, punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+ integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
+
+punycode@^2.1.0, punycode@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+q@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+ integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
+
+qs@6.7.0:
+ version "6.7.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
+ integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
+
+qs@~2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404"
+ integrity sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=
+
+qs@~6.5.1, qs@~6.5.2:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
+ integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+
+querystring-es3@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+ integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
+
+querystring@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+ integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
+
+querystringify@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
+ integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
+
+quick-lru@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
+ integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
+
+randomatic@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
+ integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==
+ dependencies:
+ is-number "^4.0.0"
+ kind-of "^6.0.0"
+ math-random "^1.0.1"
+
+randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+randomfill@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
+ integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==
+ dependencies:
+ randombytes "^2.0.5"
+ safe-buffer "^5.1.0"
+
+range-parser@^1.0.3, range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
+ integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
+ dependencies:
+ bytes "3.1.0"
+ http-errors "1.7.2"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+rc@^1.2.7:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+ integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+ dependencies:
+ deep-extend "^0.6.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+react-chartjs-2@2.7.6:
+ version "2.7.6"
+ resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-2.7.6.tgz#b8cd29bed00bf55b9e8172b06466b4ecf2b86bfb"
+ integrity sha512-xDr0jhgt/o26atftXxTVsepz+QYZI2GNKBYpxtLvYgwffLUm18a9n562reUJAHvuwKsy2v+qMlK5HyjFtSW0mg==
+ dependencies:
+ lodash "^4.17.4"
+ prop-types "^15.5.8"
+
+react-dom@16.11.0:
+ version "16.11.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5"
+ integrity sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+ scheduler "^0.17.0"
+
+react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
+ version "16.11.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.11.0.tgz#b85dfecd48ad1ce469ff558a882ca8e8313928fa"
+ integrity sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==
+
+react-router-dom@4.3.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6"
+ integrity sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==
+ dependencies:
+ history "^4.7.2"
+ invariant "^2.2.4"
+ loose-envify "^1.3.1"
+ prop-types "^15.6.1"
+ react-router "^4.3.1"
+ warning "^4.0.1"
+
+react-router@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e"
+ integrity sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==
+ dependencies:
+ history "^4.7.2"
+ hoist-non-react-statics "^2.5.0"
+ invariant "^2.2.4"
+ loose-envify "^1.3.1"
+ path-to-regexp "^1.7.0"
+ prop-types "^15.6.1"
+ warning "^4.0.1"
+
+react-transition-group@4.3.0, react-transition-group@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683"
+ integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react@16.11.0:
+ version "16.11.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb"
+ integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ prop-types "^15.6.2"
+
+read-cmd-shim@^1.0.1:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16"
+ integrity sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==
+ dependencies:
+ graceful-fs "^4.1.2"
+
+"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1"
+ integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==
+ dependencies:
+ glob "^7.1.1"
+ json-parse-better-errors "^1.0.1"
+ normalize-package-data "^2.0.0"
+ npm-normalize-package-bin "^1.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.2"
+
+read-package-tree@^5.1.6:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636"
+ integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==
+ dependencies:
+ read-package-json "^2.0.0"
+ readdir-scoped-modules "^1.0.0"
+ util-promisify "^2.1.0"
+
+read-pkg-up@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+ integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
+ dependencies:
+ find-up "^1.0.0"
+ read-pkg "^1.0.0"
+
+read-pkg-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
+ integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=
+ dependencies:
+ find-up "^2.0.0"
+ read-pkg "^3.0.0"
+
+read-pkg@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+ integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
+ dependencies:
+ load-json-file "^1.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^1.0.0"
+
+read-pkg@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+ dependencies:
+ load-json-file "^4.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^3.0.0"
+
+read@1, read@~1.0.1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
+ integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=
+ dependencies:
+ mute-stream "~0.0.4"
+
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
+ dependencies:
+ 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"
+
+"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
+ integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readdir-scoped-modules@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
+ integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==
+ dependencies:
+ debuglog "^1.0.1"
+ dezalgo "^1.0.0"
+ graceful-fs "^4.1.2"
+ once "^1.3.0"
+
+readdirp@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525"
+ integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+ micromatch "^3.1.10"
+ readable-stream "^2.0.2"
+
+realpath-native@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
+ integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==
+ dependencies:
+ util.promisify "^1.0.0"
+
+redent@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+ integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
+ dependencies:
+ indent-string "^2.1.0"
+ strip-indent "^1.0.1"
+
+redent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
+ integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=
+ dependencies:
+ indent-string "^3.0.0"
+ strip-indent "^2.0.0"
+
+reflect-metadata@^0.1.12:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
+ integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
+
+regenerate-unicode-properties@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
+ integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==
+ dependencies:
+ regenerate "^1.4.0"
+
+regenerate@^1.2.1, regenerate@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
+ integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
+
+regenerator-runtime@^0.11.0, regenerator-runtime@^0.11.1:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
+regenerator-runtime@^0.13.2:
+ version "0.13.3"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
+ integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
+
+regenerator-transform@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
+ integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==
+ dependencies:
+ private "^0.1.6"
+
+regex-cache@^0.4.2:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
+ integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
+ dependencies:
+ is-equal-shallow "^0.1.3"
+
+regex-not@^1.0.0, regex-not@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
+ integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
+ dependencies:
+ extend-shallow "^3.0.2"
+ safe-regex "^1.1.0"
+
+regexp.prototype.flags@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c"
+ integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==
+ dependencies:
+ define-properties "^1.1.2"
+
+regexpu-core@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
+ integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=
+ dependencies:
+ regenerate "^1.2.1"
+ regjsgen "^0.2.0"
+ regjsparser "^0.1.4"
+
+regexpu-core@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6"
+ integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==
+ dependencies:
+ regenerate "^1.4.0"
+ regenerate-unicode-properties "^8.1.0"
+ regjsgen "^0.5.0"
+ regjsparser "^0.6.0"
+ unicode-match-property-ecmascript "^1.0.4"
+ unicode-match-property-value-ecmascript "^1.1.0"
+
+regjsgen@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+ integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
+
+regjsgen@^0.5.0:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c"
+ integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==
+
+regjsparser@^0.1.4:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+ integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=
+ dependencies:
+ jsesc "~0.5.0"
+
+regjsparser@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c"
+ integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==
+ dependencies:
+ jsesc "~0.5.0"
+
+relateurl@0.2.x:
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+ integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
+
+remove-trailing-separator@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+ integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
+
+renderkid@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149"
+ integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==
+ dependencies:
+ css-select "^1.1.0"
+ dom-converter "^0.2"
+ htmlparser2 "^3.3.0"
+ strip-ansi "^3.0.0"
+ utila "^0.4.0"
+
+repeat-element@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
+ integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
+
+repeat-string@^1.5.2, repeat-string@^1.6.1:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+ integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
+
+repeating@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
+ integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
+ dependencies:
+ is-finite "^1.0.0"
+
+request-promise-core@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9"
+ integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==
+ dependencies:
+ lodash "^4.17.15"
+
+request-promise-native@^1.0.5:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36"
+ integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==
+ dependencies:
+ request-promise-core "1.1.3"
+ stealthy-require "^1.1.1"
+ tough-cookie "^2.3.3"
+
+request@2.87.0:
+ version "2.87.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
+ integrity sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==
+ dependencies:
+ 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"
+
+request@^2.83.0, request@^2.87.0:
+ version "2.88.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
+ integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
+ dependencies:
+ 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@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+
+require-main-filename@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+ integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
+
+requirejs-webpack-plugin@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/requirejs-webpack-plugin/-/requirejs-webpack-plugin-1.0.5.tgz#3bded42b2a9809898579019d6570732670416259"
+ integrity sha1-O97UKyqYCYmFeQGdZXBzJnBBYlk=
+ dependencies:
+ mkdirp "^0.5.1"
+
+requirejs@2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9"
+ integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==
+
+requires-port@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
+
+resolve-cwd@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
+ integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=
+ dependencies:
+ resolve-from "^3.0.0"
+
+resolve-dir@^1.0.0, resolve-dir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43"
+ integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=
+ dependencies:
+ expand-tilde "^2.0.0"
+ global-modules "^1.0.0"
+
+resolve-from@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+ integrity sha1-six699nWiBvItuZTM17rywoYh0g=
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-pathname@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
+ integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
+
+resolve-url@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+ integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
+
+resolve@1.1.7:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+ integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
+
+resolve@1.x, resolve@^1.10.0, resolve@^1.3.2:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6"
+ integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==
+ dependencies:
+ path-parse "^1.0.6"
+
+restore-cursor@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
+ dependencies:
+ onetime "^2.0.0"
+ signal-exit "^3.0.2"
+
+ret@~0.1.10:
+ version "0.1.15"
+ resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
+ integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
+
+retry@^0.10.0:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
+ integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
+
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
+ integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
+ dependencies:
+ glob "^7.1.3"
+
+rimraf@2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+ integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
+ dependencies:
+ glob "^7.0.5"
+
+ripemd160@^2.0.0, ripemd160@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
+ integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==
+ dependencies:
+ hash-base "^3.0.0"
+ inherits "^2.0.1"
+
+rsvp@^3.3.3:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
+ integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+
+run-async@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
+ dependencies:
+ is-promise "^2.1.0"
+
+run-queue@^1.0.0, run-queue@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+ integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=
+ dependencies:
+ aproba "^1.1.1"
+
+rxjs@^6.4.0:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a"
+ integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==
+ dependencies:
+ tslib "^1.9.0"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
+ integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
+
+safe-regex@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
+ integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
+ dependencies:
+ ret "~0.1.10"
+
+"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sane@^2.0.0:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/sane/-/sane-2.5.2.tgz#b4dc1861c21b427e929507a3e751e2a2cb8ab3fa"
+ integrity sha1-tNwYYcIbQn6SlQej51HiosuKs/o=
+ dependencies:
+ anymatch "^2.0.0"
+ capture-exit "^1.2.0"
+ exec-sh "^0.2.0"
+ fb-watchman "^2.0.0"
+ micromatch "^3.1.4"
+ minimist "^1.1.1"
+ walker "~1.0.5"
+ watch "~0.18.0"
+ optionalDependencies:
+ fsevents "^1.2.3"
+
+sass-graph@^2.2.4:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49"
+ integrity sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=
+ dependencies:
+ glob "^7.0.0"
+ lodash "^4.0.0"
+ scss-tokenizer "^0.2.3"
+ yargs "^7.0.0"
+
+sass-loader@7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.1.0.tgz#16fd5138cb8b424bf8a759528a1972d72aad069d"
+ integrity sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==
+ dependencies:
+ 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"
+
+sax@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+scheduler@^0.17.0:
+ version "0.17.0"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe"
+ integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
+schema-utils@^0.4.4, schema-utils@^0.4.5:
+ version "0.4.7"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
+ integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==
+ dependencies:
+ ajv "^6.1.0"
+ ajv-keywords "^3.1.0"
+
+schema-utils@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
+ integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==
+ dependencies:
+ ajv "^6.1.0"
+ ajv-errors "^1.0.0"
+ ajv-keywords "^3.1.0"
+
+scss-tokenizer@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
+ integrity sha1-jrBtualyMzOCTT9VMGQRSYR85dE=
+ dependencies:
+ js-base64 "^2.1.8"
+ source-map "^0.4.2"
+
+select-hose@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+ integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
+
+selfsigned@^1.9.1:
+ version "1.10.7"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b"
+ integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==
+ dependencies:
+ node-forge "0.9.0"
+
+"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+ integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
+semver@^6.0.0, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@~5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+ integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
+
+send@0.17.1:
+ version "0.17.1"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
+ integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
+ dependencies:
+ 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"
+
+serialize-javascript@^1.4.0, serialize-javascript@^1.7.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb"
+ integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==
+
+serve-index@^1.7.2:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+ integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=
+ dependencies:
+ 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"
+
+serve-static@1.14.1:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
+ integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.17.1"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+ integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+
+set-value@^2.0.0, set-value@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
+ integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==
+ dependencies:
+ extend-shallow "^2.0.1"
+ is-extendable "^0.1.1"
+ is-plain-object "^2.0.3"
+ split-string "^3.0.1"
+
+setimmediate@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+ integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
+
+setprototypeof@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+setprototypeof@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
+ integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
+
+sha.js@^2.4.0, sha.js@^2.4.8:
+ version "2.4.11"
+ resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
+ integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
+ dependencies:
+ inherits "^2.0.1"
+ safe-buffer "^5.0.1"
+
+shallow-clone@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571"
+ integrity sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==
+ dependencies:
+ is-extendable "^0.1.1"
+ kind-of "^5.0.0"
+ mixin-object "^2.0.1"
+
+shebang-command@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
+ dependencies:
+ shebang-regex "^1.0.0"
+
+shebang-regex@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+ integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+
+shellwords@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
+ integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
+
+signal-exit@^3.0.0, signal-exit@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+ integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
+
+sisteransi@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
+ integrity sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==
+
+slash@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+ integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
+
+slash@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+ integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
+slide@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+ integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
+
+smart-buffer@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
+ integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
+
+snapdragon-node@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
+ integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
+ dependencies:
+ define-property "^1.0.0"
+ isobject "^3.0.0"
+ snapdragon-util "^3.0.1"
+
+snapdragon-util@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
+ integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
+ dependencies:
+ kind-of "^3.2.0"
+
+snapdragon@^0.8.1:
+ version "0.8.2"
+ resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
+ integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==
+ dependencies:
+ 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"
+
+sockjs-client@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177"
+ integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==
+ dependencies:
+ debug "^3.2.5"
+ eventsource "^1.0.7"
+ faye-websocket "~0.11.1"
+ inherits "^2.0.3"
+ json3 "^3.3.2"
+ url-parse "^1.4.3"
+
+sockjs@0.3.19:
+ version "0.3.19"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
+ integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==
+ dependencies:
+ faye-websocket "^0.10.0"
+ uuid "^3.0.1"
+
+socks-proxy-agent@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
+ integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==
+ dependencies:
+ agent-base "~4.2.1"
+ socks "~2.3.2"
+
+socks@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3"
+ integrity sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==
+ dependencies:
+ ip "1.1.5"
+ smart-buffer "^4.1.0"
+
+sort-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
+ integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=
+ dependencies:
+ is-plain-obj "^1.0.0"
+
+source-list-map@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+
+source-map-resolve@^0.5.0:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
+ integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==
+ dependencies:
+ 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@^0.4.15:
+ version "0.4.18"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
+ integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==
+ dependencies:
+ source-map "^0.5.6"
+
+source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12:
+ version "0.5.16"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
+ integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map-url@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
+ integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
+
+source-map@^0.4.2:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
+ integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
+ dependencies:
+ amdefine ">=0.0.4"
+
+source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+spdx-correct@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
+ integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977"
+ integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
+ integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
+ integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
+
+spdy-transport@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
+ dependencies:
+ debug "^4.1.0"
+ detect-node "^2.0.4"
+ hpack.js "^2.1.6"
+ obuf "^1.1.2"
+ readable-stream "^3.0.6"
+ wbuf "^1.7.3"
+
+spdy@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2"
+ integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==
+ dependencies:
+ debug "^4.1.0"
+ handle-thing "^2.0.0"
+ http-deceiver "^1.2.7"
+ select-hose "^2.0.0"
+ spdy-transport "^3.0.0"
+
+split-string@^3.0.1, split-string@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
+ integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
+ dependencies:
+ extend-shallow "^3.0.0"
+
+split2@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493"
+ integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==
+ dependencies:
+ through2 "^2.0.2"
+
+split@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
+ integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
+ dependencies:
+ through "2"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+
+sshpk@^1.7.0:
+ version "1.16.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
+ integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
+ dependencies:
+ 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@^5.2.4:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06"
+ integrity sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==
+ dependencies:
+ safe-buffer "^5.1.1"
+
+ssri@^6.0.0, ssri@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
+ integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+
+stack-utils@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
+ integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
+
+static-extend@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
+ integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
+ dependencies:
+ define-property "^0.2.5"
+ object-copy "^0.1.0"
+
+"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+
+stdout-stream@^1.4.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de"
+ integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==
+ dependencies:
+ readable-stream "^2.0.1"
+
+stealthy-require@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
+ integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
+
+stream-browserify@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
+ integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
+ dependencies:
+ inherits "~2.0.1"
+ readable-stream "^2.0.2"
+
+stream-each@^1.1.0:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
+ integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==
+ dependencies:
+ end-of-stream "^1.1.0"
+ stream-shift "^1.0.0"
+
+stream-http@^2.7.2:
+ version "2.8.3"
+ resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc"
+ integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==
+ dependencies:
+ 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@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+ integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
+
+string-length@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
+ integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=
+ dependencies:
+ astral-regex "^1.0.0"
+ strip-ansi "^4.0.0"
+
+string-width@^1.0.1, string-width@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
+ dependencies:
+ code-point-at "^1.0.0"
+ is-fullwidth-code-point "^1.0.0"
+ strip-ansi "^3.0.0"
+
+"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+ integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
+ dependencies:
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^4.0.0"
+
+string.prototype.trimleft@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634"
+ integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==
+ dependencies:
+ define-properties "^1.1.3"
+ function-bind "^1.1.1"
+
+string.prototype.trimright@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58"
+ integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==
+ dependencies:
+ define-properties "^1.1.3"
+ function-bind "^1.1.1"
+
+string_decoder@^1.0.0, string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
+ dependencies:
+ ansi-regex "^2.0.0"
+
+strip-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
+ dependencies:
+ ansi-regex "^3.0.0"
+
+strip-ansi@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+ integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+ dependencies:
+ ansi-regex "^4.1.0"
+
+strip-bom@3.0.0, strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
+
+strip-bom@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+ integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
+ dependencies:
+ is-utf8 "^0.2.0"
+
+strip-eof@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+ integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
+
+strip-indent@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
+ integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
+ dependencies:
+ get-stdin "^4.0.1"
+
+strip-indent@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
+ integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
+
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+ integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
+
+strong-log-transformer@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
+ integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==
+ dependencies:
+ duplexer "^0.1.1"
+ minimist "^1.2.0"
+ through "^2.3.4"
+
+style-loader@0.23.0:
+ version "0.23.0"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.0.tgz#8377fefab68416a2e05f1cabd8c3a3acfcce74f1"
+ integrity sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==
+ dependencies:
+ loader-utils "^1.1.0"
+ schema-utils "^0.4.5"
+
+supports-color@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+ integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
+
+supports-color@^3.1.2:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+ dependencies:
+ has-flag "^1.0.0"
+
+supports-color@^5.1.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
+ integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+ dependencies:
+ has-flag "^3.0.0"
+
+symbol-tree@^3.2.2:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
+tapable@^1.0.0, tapable@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+ integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+
+tar@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
+ integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
+ dependencies:
+ block-stream "*"
+ fstream "^1.0.12"
+ inherits "2"
+
+tar@^4, tar@^4.4.10, tar@^4.4.8:
+ version "4.4.13"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
+ integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
+ dependencies:
+ chownr "^1.1.1"
+ fs-minipass "^1.2.5"
+ minipass "^2.8.6"
+ minizlib "^1.2.1"
+ mkdirp "^0.5.0"
+ safe-buffer "^5.1.2"
+ yallist "^3.0.3"
+
+temp-dir@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
+ integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=
+
+temp-write@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492"
+ integrity sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=
+ dependencies:
+ graceful-fs "^4.1.2"
+ is-stream "^1.1.0"
+ make-dir "^1.0.0"
+ pify "^3.0.0"
+ temp-dir "^1.0.0"
+ uuid "^3.0.1"
+
+terser-webpack-plugin@1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#7545da9ae5f4f9ae6a0ac961eb46f5e7c845cc26"
+ integrity sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw==
+ dependencies:
+ 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"
+
+terser-webpack-plugin@^1.1.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4"
+ integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==
+ dependencies:
+ cacache "^12.0.2"
+ find-cache-dir "^2.1.0"
+ is-wsl "^1.1.0"
+ schema-utils "^1.0.0"
+ serialize-javascript "^1.7.0"
+ source-map "^0.6.1"
+ terser "^4.1.2"
+ webpack-sources "^1.4.0"
+ worker-farm "^1.7.0"
+
+terser@^3.8.1:
+ version "3.17.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2"
+ integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==
+ dependencies:
+ commander "^2.19.0"
+ source-map "~0.6.1"
+ source-map-support "~0.5.10"
+
+terser@^4.1.2:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3"
+ integrity sha512-oDG16n2WKm27JO8h4y/w3iqBGAOSCtq7k8dRmrn4Wf9NouL0b2WpMHGChFGZq4nFAQy1FsNJrVQHfurXOSTmOA==
+ dependencies:
+ commander "^2.20.0"
+ source-map "~0.6.1"
+ source-map-support "~0.5.12"
+
+test-exclude@^4.2.1:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20"
+ integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==
+ dependencies:
+ arrify "^1.0.1"
+ micromatch "^2.3.11"
+ object-assign "^4.1.0"
+ read-pkg-up "^1.0.1"
+ require-main-filename "^1.0.1"
+
+text-extensions@^1.0.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26"
+ integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
+
+throat@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
+ integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=
+
+through2@^2.0.0, through2@^2.0.2:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+ dependencies:
+ readable-stream "~2.3.6"
+ xtend "~4.0.1"
+
+through2@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a"
+ integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==
+ dependencies:
+ readable-stream "2 || 3"
+
+through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
+thunky@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
+ integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+
+timers-browserify@^2.0.4:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f"
+ integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==
+ dependencies:
+ setimmediate "^1.0.4"
+
+tiny-invariant@^1.0.2:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.0.6.tgz#b3f9b38835e36a41c843a3b0907a5a7b3755de73"
+ integrity sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==
+
+tiny-warning@^1.0.0, tiny-warning@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
+tmp@^0.0.33:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
+ dependencies:
+ os-tmpdir "~1.0.2"
+
+tmpl@1.0.x:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
+ integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
+
+to-arraybuffer@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+ integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
+
+to-fast-properties@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+ integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
+
+to-object-path@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
+ integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
+ dependencies:
+ kind-of "^3.0.2"
+
+to-regex-range@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
+ integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
+ dependencies:
+ is-number "^3.0.0"
+ repeat-string "^1.6.1"
+
+to-regex@^3.0.1, to-regex@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
+ integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
+ dependencies:
+ define-property "^2.0.2"
+ extend-shallow "^3.0.2"
+ regex-not "^1.0.2"
+ safe-regex "^1.1.0"
+
+toidentifier@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
+ integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+
+toposort@^1.0.0:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
+ integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk=
+
+tough-cookie@^2.3.3, tough-cookie@^2.3.4:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+ integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+ dependencies:
+ psl "^1.1.28"
+ punycode "^2.1.1"
+
+tough-cookie@~2.3.3:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
+ integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==
+ dependencies:
+ punycode "^1.4.1"
+
+tough-cookie@~2.4.3:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
+ integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
+ dependencies:
+ psl "^1.1.24"
+ punycode "^1.4.1"
+
+tr46@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+ integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
+ dependencies:
+ punycode "^2.1.0"
+
+trim-newlines@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
+ integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
+
+trim-newlines@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
+ integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
+
+trim-off-newlines@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
+ integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM=
+
+trim-right@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+ integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
+
+"true-case-path@^1.0.2":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d"
+ integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==
+ dependencies:
+ glob "^7.1.2"
+
+ts-jest@23.10.5:
+ version "23.10.5"
+ resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-23.10.5.tgz#cdb550df4466a30489bf70ba867615799f388dd5"
+ integrity sha512-MRCs9qnGoyKgFc8adDEntAOP64fWK1vZKnOYU1o2HxaqjdJvGqmkLCPCnVq1/If4zkUmEjKPnCiUisTrlX2p2A==
+ dependencies:
+ bs-logger "0.x"
+ buffer-from "1.x"
+ fast-json-stable-stringify "2.x"
+ json5 "2.x"
+ make-error "1.x"
+ mkdirp "0.x"
+ resolve "1.x"
+ semver "^5.5"
+ yargs-parser "10.x"
+
+ts-loader@5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.2.1.tgz#e6815c631dcafc24319ce8be6f8af94908749cf3"
+ integrity sha512-KC0cOvsFVyxBlg5h9jvaMlIL2tNsyQLvT2/OvIlO0AMUBJ4iXTtOfaDEqvmqv2lM/icekQfDsP2PsYBCDHpuOQ==
+ dependencies:
+ chalk "^2.3.0"
+ enhanced-resolve "^4.0.0"
+ loader-utils "^1.0.2"
+ micromatch "^3.1.4"
+ semver "^5.0.1"
+
+tslib@1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
+ integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==
+
+tslib@^1.0.0, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
+ integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
+
+tslint-config-airbnb-base@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/tslint-config-airbnb-base/-/tslint-config-airbnb-base-0.2.0.tgz#d3398daa62df820734f56dee801b79b69def4765"
+ integrity sha512-aYkkvnnaAioFEME6FaMSsKgZvU3hsTbnTuVa3I5y4/SK2CpPOIh1xo9daTBgxhvmpXuFApI1g4zgdUQwf0vyzQ==
+ dependencies:
+ tslint-consistent-codestyle "^1.13.2"
+ tslint-eslint-rules "^5.3.1"
+
+tslint-config-airbnb@5.11.1:
+ version "5.11.1"
+ resolved "https://registry.yarnpkg.com/tslint-config-airbnb/-/tslint-config-airbnb-5.11.1.tgz#51a27fbb8bf24c144d064a274a71da47e7ece617"
+ integrity sha512-hkaittm2607vVMe8eotANGN1CimD5tor7uoY3ypg2VTtEcDB/KGWYbJOz58t8LI4cWSyWtgqYQ5F0HwKxxhlkQ==
+ dependencies:
+ tslint-consistent-codestyle "^1.14.1"
+ tslint-eslint-rules "^5.4.0"
+ tslint-microsoft-contrib "~5.2.1"
+
+tslint-config-prettier@1.17.0:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.17.0.tgz#946ed6117f98f3659a65848279156d87628c33dc"
+ integrity sha512-NKWNkThwqE4Snn4Cm6SZB7lV5RMDDFsBwz6fWUkTxOKGjMx8ycOHnjIbhn7dZd5XmssW3CwqUjlANR6EhP9YQw==
+
+tslint-consistent-codestyle@^1.13.2, tslint-consistent-codestyle@^1.14.1:
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.16.0.tgz#52348ea899a7e025b37cc6545751c6a566a19077"
+ integrity sha512-ebR/xHyMEuU36hGNOgCfjGBNYxBPixf0yU1Yoo6s3BrpBRFccjPOmIVaVvQsWAUAMdmfzHOCihVkcaMfimqvHw==
+ dependencies:
+ "@fimbul/bifrost" "^0.21.0"
+ tslib "^1.7.1"
+ tsutils "^2.29.0"
+
+tslint-eslint-rules@4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-4.1.1.tgz#7c30e7882f26bc276bff91d2384975c69daf88ba"
+ integrity sha1-fDDniC8mvCdr/5HSOEl1xp2viLo=
+ dependencies:
+ doctrine "^0.7.2"
+ tslib "^1.0.0"
+ tsutils "^1.4.0"
+
+tslint-eslint-rules@^5.3.1, tslint-eslint-rules@^5.4.0:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz#e488cc9181bf193fe5cd7bfca213a7695f1737b5"
+ integrity sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==
+ dependencies:
+ doctrine "0.7.2"
+ tslib "1.9.0"
+ tsutils "^3.0.0"
+
+tslint-microsoft-contrib@~5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz#a6286839f800e2591d041ea2800c77487844ad81"
+ integrity sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==
+ dependencies:
+ tsutils "^2.27.2 <2.29.0"
+
+tslint-react-recommended@1.0.15:
+ version "1.0.15"
+ resolved "https://registry.yarnpkg.com/tslint-react-recommended/-/tslint-react-recommended-1.0.15.tgz#4166dc7d87b57280110673c99315a35ac5a76a7e"
+ integrity sha1-QWbcfYe1coARBnPJkxWjWsWnan4=
+
+tslint-react@3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.6.0.tgz#7f462c95c4a0afaae82507f06517ff02942196a1"
+ integrity sha512-AIv1QcsSnj7e9pFir6cJ6vIncTqxfqeFF3Lzh8SuuBljueYzEAtByuB6zMaD27BL0xhMEqsZ9s5eHuCONydjBw==
+ dependencies:
+ tsutils "^2.13.1"
+
+tslint@5.12.1:
+ version "5.12.1"
+ resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.12.1.tgz#8cec9d454cf8a1de9b0a26d7bdbad6de362e52c1"
+ integrity sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==
+ dependencies:
+ 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"
+
+tsutils@^1.4.0:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.9.1.tgz#b9f9ab44e55af9681831d5f28d0aeeaf5c750cb0"
+ integrity sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=
+
+tsutils@^2.13.1, tsutils@^2.27.2, tsutils@^2.29.0:
+ version "2.29.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
+ integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
+ dependencies:
+ tslib "^1.8.1"
+
+"tsutils@^2.27.2 <2.29.0":
+ version "2.28.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.28.0.tgz#6bd71e160828f9d019b6f4e844742228f85169a1"
+ integrity sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==
+ dependencies:
+ tslib "^1.8.1"
+
+tsutils@^3.0.0, tsutils@^3.5.0:
+ version "3.17.1"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
+ integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
+ dependencies:
+ tslib "^1.8.1"
+
+tty-browserify@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+ integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+ integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-is@~1.6.17, type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+
+typescript@3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
+ integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
+
+typings-for-css-modules-loader@1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/typings-for-css-modules-loader/-/typings-for-css-modules-loader-1.7.0.tgz#a9b5c5a0e19b719d616edfc72855ab47dedd00ae"
+ integrity sha512-Mp7zDrcUmbUKl3JTLamTsMX+lntMotEm5I05j2RHB5EHb0WL1dAXlynpdlGR5Ye/QTvtL5w+RGB2jP32YoUpZw==
+ dependencies:
+ colour "0.7.1"
+ graceful-fs "4.1.4"
+ loader-utils "0.2.16"
+
+uglify-js@3.4.x:
+ version "3.4.10"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
+ integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==
+ dependencies:
+ commander "~2.19.0"
+ source-map "~0.6.1"
+
+uglify-js@^3.1.4:
+ version "3.6.9"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.9.tgz#85d353edb6ddfb62a9d798f36e91792249320611"
+ integrity sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==
+ dependencies:
+ commander "~2.20.3"
+ source-map "~0.6.1"
+
+uid-number@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+ integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=
+
+umask@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
+ integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=
+
+unicode-canonical-property-names-ecmascript@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
+ integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
+
+unicode-match-property-ecmascript@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
+ integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^1.0.4"
+ unicode-property-aliases-ecmascript "^1.0.4"
+
+unicode-match-property-value-ecmascript@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277"
+ integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==
+
+unicode-property-aliases-ecmascript@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57"
+ integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==
+
+union-value@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
+ integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==
+ dependencies:
+ arr-union "^3.1.0"
+ get-value "^2.0.6"
+ is-extendable "^0.1.1"
+ set-value "^2.0.1"
+
+union@~0.4.3:
+ version "0.4.6"
+ resolved "https://registry.yarnpkg.com/union/-/union-0.4.6.tgz#198fbdaeba254e788b0efcb630bc11f24a2959e0"
+ integrity sha1-GY+9rrolTniLDvy2MLwR8kopWeA=
+ dependencies:
+ qs "~2.3.3"
+
+unique-filename@^1.1.0, unique-filename@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
+ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
+ dependencies:
+ unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
+ integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
+ dependencies:
+ imurmurhash "^0.1.4"
+
+universal-user-agent@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.0.tgz#27da2ec87e32769619f68a14996465ea1cb9df16"
+ integrity sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA==
+ dependencies:
+ os-name "^3.1.0"
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+unset-value@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
+ integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
+ dependencies:
+ has-value "^0.3.1"
+ isobject "^3.0.0"
+
+upath@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
+ integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+
+upper-case@^1.1.1:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
+ integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
+
+uri-js@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+ integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+ dependencies:
+ punycode "^2.1.0"
+
+urix@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+ integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
+
+url-join@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/url-join/-/url-join-2.0.5.tgz#5af22f18c052a000a48d7b82c5e9c2e2feeda728"
+ integrity sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=
+
+url-loader@1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8"
+ integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==
+ dependencies:
+ loader-utils "^1.1.0"
+ mime "^2.0.3"
+ schema-utils "^1.0.0"
+
+url-parse@^1.4.3:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
+ integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
+ dependencies:
+ querystringify "^2.1.1"
+ requires-port "^1.0.0"
+
+url@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+ integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
+ dependencies:
+ punycode "1.3.2"
+ querystring "0.2.0"
+
+use@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
+ integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
+
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+util-promisify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53"
+ integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=
+ dependencies:
+ object.getownpropertydescriptors "^2.0.3"
+
+util.promisify@1.0.0, util.promisify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+ integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
+ dependencies:
+ define-properties "^1.1.2"
+ object.getownpropertydescriptors "^2.0.3"
+
+util@0.10.3:
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+ integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
+ dependencies:
+ inherits "2.0.1"
+
+util@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"
+ integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==
+ dependencies:
+ inherits "2.0.3"
+
+utila@^0.4.0, utila@~0.4:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+ integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+
+uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
+ integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
+
+v8-compile-cache@^2.0.2:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
+ integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==
+
+validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
+validate-npm-package-name@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
+ integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34=
+ dependencies:
+ builtins "^1.0.3"
+
+value-equal@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
+ integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
+vm-browserify@^1.0.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
+ integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
+
+w3c-hr-time@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045"
+ integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=
+ dependencies:
+ browser-process-hrtime "^0.1.2"
+
+walker@~1.0.5:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
+ integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=
+ dependencies:
+ makeerror "1.0.x"
+
+warning@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+ dependencies:
+ loose-envify "^1.0.0"
+
+watch@~0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986"
+ integrity sha1-KAlUdsbffJDJYxOJkMClQj60uYY=
+ dependencies:
+ exec-sh "^0.2.0"
+ minimist "^1.2.0"
+
+watchpack@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
+ integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==
+ dependencies:
+ chokidar "^2.0.2"
+ graceful-fs "^4.1.2"
+ neo-async "^2.5.0"
+
+wbuf@^1.1.0, wbuf@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
+ dependencies:
+ minimalistic-assert "^1.0.0"
+
+wcwidth@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+ integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
+ dependencies:
+ defaults "^1.0.3"
+
+webidl-conversions@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+ integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
+webpack-cli@3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.1.tgz#779c696c82482491f0803907508db2e276ed3b61"
+ integrity sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA==
+ dependencies:
+ chalk "^2.4.1"
+ cross-spawn "^6.0.5"
+ enhanced-resolve "^4.1.0"
+ findup-sync "^2.0.0"
+ global-modules "^1.0.0"
+ global-modules-path "^2.3.0"
+ import-local "^2.0.0"
+ interpret "^1.1.0"
+ lightercollective "^0.1.0"
+ loader-utils "^1.1.0"
+ supports-color "^5.5.0"
+ v8-compile-cache "^2.0.2"
+ yargs "^12.0.4"
+
+webpack-dev-middleware@3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
+ integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
+ dependencies:
+ memory-fs "~0.4.1"
+ mime "^2.3.1"
+ range-parser "^1.0.3"
+ webpack-log "^2.0.0"
+
+webpack-dev-server@3.1.14:
+ version "3.1.14"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz#60fb229b997fc5a0a1fc6237421030180959d469"
+ integrity sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==
+ dependencies:
+ 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"
+ semver "^5.6.0"
+ serve-index "^1.7.2"
+ sockjs "0.3.19"
+ sockjs-client "1.3.0"
+ spdy "^4.0.0"
+ strip-ansi "^3.0.0"
+ supports-color "^5.1.0"
+ url "^0.11.0"
+ webpack-dev-middleware "3.4.0"
+ webpack-log "^2.0.0"
+ yargs "12.0.2"
+
+webpack-log@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
+ integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
+ dependencies:
+ ansi-colors "^3.0.0"
+ uuid "^3.3.2"
+
+webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
+ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
+ dependencies:
+ source-list-map "^2.0.0"
+ source-map "~0.6.1"
+
+webpack@4.28.4:
+ version "4.28.4"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.28.4.tgz#1ddae6c89887d7efb752adf0c3cd32b9b07eacd0"
+ integrity sha512-NxjD61WsK/a3JIdwWjtIpimmvE6UrRi3yG54/74Hk9rwNj5FPkA4DJCf1z4ByDWLkvZhTZE+P3C/eh6UD5lDcw==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.11"
+ "@webassemblyjs/helper-module-context" "1.7.11"
+ "@webassemblyjs/wasm-edit" "1.7.11"
+ "@webassemblyjs/wasm-parser" "1.7.11"
+ 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"
+ terser-webpack-plugin "^1.1.0"
+ watchpack "^1.5.0"
+ webpack-sources "^1.3.0"
+
+websocket-driver@>=0.5.1:
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9"
+ integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==
+ dependencies:
+ http-parser-js ">=0.4.0 <0.4.11"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
+ integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==
+
+whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+ integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+ dependencies:
+ iconv-lite "0.4.24"
+
+whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+ integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^6.4.1:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
+ integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
+ dependencies:
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.1"
+ webidl-conversions "^4.0.2"
+
+whatwg-url@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+ integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+ dependencies:
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.1"
+ webidl-conversions "^4.0.2"
+
+which-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+ integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
+
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
+which@1, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+wide-align@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
+ integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
+ dependencies:
+ string-width "^1.0.2 || 2"
+
+windows-release@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f"
+ integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==
+ dependencies:
+ execa "^1.0.0"
+
+word-wrap@~1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+wordwrap@~0.0.2:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+ integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
+
+worker-farm@^1.5.2, worker-farm@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
+ integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==
+ dependencies:
+ errno "~0.1.7"
+
+wrap-ansi@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
+ dependencies:
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+write-file-atomic@^2.0.0, write-file-atomic@^2.1.0, write-file-atomic@^2.3.0:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+ integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ signal-exit "^3.0.2"
+
+write-json-file@^2.2.0, write-json-file@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f"
+ integrity sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=
+ dependencies:
+ detect-indent "^5.0.0"
+ graceful-fs "^4.1.2"
+ make-dir "^1.0.0"
+ pify "^3.0.0"
+ sort-keys "^2.0.0"
+ write-file-atomic "^2.0.0"
+
+write-pkg@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.2.0.tgz#0e178fe97820d389a8928bc79535dbe68c2cff21"
+ integrity sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==
+ dependencies:
+ sort-keys "^2.0.0"
+ write-json-file "^2.2.0"
+
+ws@^5.2.0:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f"
+ integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==
+ dependencies:
+ async-limiter "~1.0.0"
+
+x2js@*:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/x2js/-/x2js-3.3.1.tgz#185d0cb19511d150f38db87d02da7e34b07aa49e"
+ integrity sha512-UruP3F9pgFlGbgm/8i28AiNSLN4jlcu8GMBbzuqLqAzV3O49WQDtmJeLefYy8hmBnTEtQEUvPQG8EDFCDDyP6g==
+ dependencies:
+ xmldom "^0.1.19"
+
+x2js@3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/x2js/-/x2js-3.2.3.tgz#b59c0c5f18d36c7391b8a1db068e2bc10132c960"
+ integrity sha512-LJNWWp+WFOdsrp2nfTuC6+erPjZSNfeHsrdWPGpesj5g0gj2WwsedsqbN33wZWf/3loQA0jIR58jrx5Cyj7G/Q==
+ dependencies:
+ xmldom "^0.1.19"
+
+xml-name-validator@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+ integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
+xmldom@^0.1.19:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"
+ integrity sha1-1QH5ezvbQDr4757MIFcxh6rawOk=
+
+xregexp@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
+ integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
+
+xtend@^4.0.0, xtend@~4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+y18n@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+ integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
+
+"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
+ integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
+
+yallist@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+ integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
+
+yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yargs-parser@10.x, yargs-parser@^10.0.0, yargs-parser@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
+ integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
+ dependencies:
+ camelcase "^4.1.0"
+
+yargs-parser@^11.1.1:
+ version "11.1.1"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"
+ integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs-parser@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
+ integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=
+ dependencies:
+ camelcase "^3.0.0"
+
+yargs-parser@^9.0.2:
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+ integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
+ dependencies:
+ camelcase "^4.1.0"
+
+yargs@12.0.2:
+ version "12.0.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
+ integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==
+ dependencies:
+ 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@^11.0.0:
+ version "11.1.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.1.tgz#5052efe3446a4df5ed669c995886cc0f13702766"
+ integrity sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==
+ dependencies:
+ cliui "^4.0.0"
+ decamelize "^1.1.1"
+ find-up "^2.1.0"
+ get-caller-file "^1.0.1"
+ os-locale "^3.1.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 "^9.0.2"
+
+yargs@^12.0.1, yargs@^12.0.4:
+ version "12.0.5"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
+ integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==
+ dependencies:
+ cliui "^4.0.0"
+ decamelize "^1.2.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 "^11.1.1"
+
+yargs@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
+ integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=
+ dependencies:
+ 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"