update odlux sources 00/130800/2
authorMichael Dürre <michael.duerre@highstreet-technologies.com>
Thu, 8 Sep 2022 07:45:06 +0000 (09:45 +0200)
committerMichael Dürre <michael.duerre@highstreet-technologies.com>
Thu, 8 Sep 2022 07:46:47 +0000 (09:46 +0200)
update basic odlux functionality for kohn

Issue-ID: CCSDK-3765
Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
Change-Id: I3723c9c2f35b9012ba537920b294a54bb556cbc6
Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
81 files changed:
sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
sdnr/wt/odlux/apps/configurationApp/src/handlers/connectedNetworkElementsHandler.ts
sdnr/wt/odlux/apps/configurationApp/src/services/yangService.ts
sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
sdnr/wt/odlux/apps/configurationApp/webpack.config.js
sdnr/wt/odlux/apps/connectApp/package.json
sdnr/wt/odlux/apps/connectApp/src/actions/connectionStatusCountActions.ts [deleted file]
sdnr/wt/odlux/apps/connectApp/src/actions/mountedNetworkElementsActions.ts
sdnr/wt/odlux/apps/connectApp/src/actions/networkElementsActions.ts
sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
sdnr/wt/odlux/apps/connectApp/src/components/infoNetworkElementDialog.tsx
sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
sdnr/wt/odlux/apps/connectApp/src/components/refreshNetworkElementsDialog.tsx
sdnr/wt/odlux/apps/connectApp/src/handlers/connectAppRootHandler.ts
sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusCountHandler.ts [deleted file]
sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusCount.ts [deleted file]
sdnr/wt/odlux/apps/connectApp/src/pluginConnect.tsx
sdnr/wt/odlux/apps/connectApp/src/services/connectService.ts
sdnr/wt/odlux/apps/connectApp/src/services/connectionStatusCountService.ts [deleted file]
sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
sdnr/wt/odlux/apps/connectApp/webpack.config.js
sdnr/wt/odlux/apps/faultApp/src/actions/statusActions.ts
sdnr/wt/odlux/apps/faultApp/src/components/dashboardHome.tsx [moved from sdnr/wt/odlux/apps/connectApp/src/components/dashboardHome.tsx with 81% similarity]
sdnr/wt/odlux/apps/faultApp/src/handlers/faultStatusHandler.ts
sdnr/wt/odlux/apps/faultApp/src/models/fault.ts
sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts
sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
sdnr/wt/odlux/apps/helpApp/src/views/helpTocApp.tsx
sdnr/wt/odlux/apps/helpApp/webpack.config.js
sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts
sdnr/wt/odlux/apps/mediatorApp/pom.xml
sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/adaptiveModulationHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/crossPolarDiscriminationHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceDataHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/receiveLevelHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/signalToInterferenceHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperatureHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPowerHandler.ts
sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
sdnr/wt/odlux/framework/pom.xml
sdnr/wt/odlux/framework/src/actions/authentication.ts
sdnr/wt/odlux/framework/src/actions/settingsAction.ts
sdnr/wt/odlux/framework/src/assets/images/home.svg [new file with mode: 0644]
sdnr/wt/odlux/framework/src/assets/images/home.svg.d.ts [moved from sdnr/wt/odlux/apps/faultApp/src/actions/partialUpdatesAction.ts with 80% similarity]
sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
sdnr/wt/odlux/framework/src/components/material-table/index.tsx
sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx [new file with mode: 0644]
sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx
sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx
sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
sdnr/wt/odlux/framework/src/components/titleBar.tsx
sdnr/wt/odlux/framework/src/handlers/applicationStateHandler.ts
sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts
sdnr/wt/odlux/framework/src/index.dev.html
sdnr/wt/odlux/framework/src/index.html
sdnr/wt/odlux/framework/src/models/elasticSearch.ts
sdnr/wt/odlux/framework/src/models/iconDefinition.ts
sdnr/wt/odlux/framework/src/models/settings.ts
sdnr/wt/odlux/framework/src/services/authenticationService.ts
sdnr/wt/odlux/framework/src/services/broadcastService.ts
sdnr/wt/odlux/framework/src/services/forceLogoutService.ts [deleted file]
sdnr/wt/odlux/framework/src/services/restService.ts
sdnr/wt/odlux/framework/src/services/userSessionService.ts
sdnr/wt/odlux/framework/src/utilities/elasticSearch.ts
sdnr/wt/odlux/framework/src/views/about.tsx
sdnr/wt/odlux/framework/src/views/frame.tsx
sdnr/wt/odlux/framework/src/views/login.tsx
sdnr/wt/odlux/framework/src/views/test.tsx
sdnr/wt/odlux/framework/src2/main/resources/version.json
sdnr/wt/odlux/framework/webpack.vendor.js
sdnr/wt/odlux/lerna.json
sdnr/wt/odlux/odlux.properties
sdnr/wt/odlux/yarn.lock

index 0dd42e3..2846dba 100644 (file)
@@ -1,21 +1,3 @@
-/**
- * ============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";
@@ -65,6 +47,22 @@ export class UpdatOutputData extends Action {
   }
 }
 
+type HttpResult = {
+  status: number;
+  message?: string | undefined;
+  data: {
+      [key: string]: any;
+  } | null | undefined;
+};
+
+const checkResponseCode = (restResult: HttpResult) =>{
+  
+  //403 gets handled by the framework from now on
+
+  return restResult.status !== 403 && ( restResult.status < 200 || restResult.status > 299);
+
+}
+
 export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState ) => {
 
   dispatch(new UpdateDeviceDescription("", {}, []));
@@ -81,8 +79,8 @@ export const updateNodeIdAsyncActionCreator = (nodeId: string) => async (dispatc
     }));
     throw new Error(`NetworkElement : [${nodeId}] has no capabilities.`);
   }
-    
-  const parser = new YangParser(unavailableCapabilities || undefined, importOnlyModules || undefined);
+
+  const parser = new YangParser(unavailableCapabilities || undefined, importOnlyModules || undefined, nodeId);
 
   for (let i = 0; i < availableCapabilities.length; ++i){
     const capRaw = availableCapabilities[i];
@@ -146,7 +144,7 @@ const getReferencedDataList = async (refPath: string, dataPath: string, modules:
         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) {
+          if (restResult.data == null || checkResponseCode(restResult)) {
             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 || ''}`);
           }
@@ -178,7 +176,7 @@ const getReferencedDataList = async (refPath: string, dataPath: string, modules:
       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) {
+        if (restResult.data == null || checkResponseCode(restResult)) {
           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 || ''}`);
         }
@@ -426,7 +424,7 @@ export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch:
           return dispatch(new UpdatViewDescription(vPath, [], ds));
         }
         throw new Error(`Did not get response from Server. Status: [${restResult.status}]`);
-      } else if (restResult.status < 200 || restResult.status > 299) {
+      } else if (checkResponseCode(restResult)) {
         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 {
@@ -581,7 +579,7 @@ export const updateDataActionAsyncCreator = (vPath: string, data: any) => async
     // do not extract root member (0)
     if (viewSpecification && viewSpecification.id !== "0") {
       const updateResult = await restService.setConfigData(dataPath, { [`${currentNS}:${dataMember!}`]: data }); // addDataMember using currentNS
-      if (updateResult.status < 200 || updateResult.status > 299) {
+      if (checkResponseCode(updateResult)) {
         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 || ''}`);
       }
@@ -653,7 +651,7 @@ export const removeElementActionAsyncCreator = (vPath: string) => async (dispatc
     }
 
     const updateResult = await restService.removeConfigElement(dataPath);
-    if (updateResult.status < 200 || updateResult.status > 299) {
+    if (checkResponseCode(updateResult)) {
       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 || ''}`);
     }
@@ -747,7 +745,7 @@ export const executeRpcActionAsyncCreator = (vPath: string, data: any) => async
     // do not post root member (0)
     if ((viewSpecification && viewSpecification.id !== "0") || (dataMember! && !data)) {
       const updateResult = await restService.executeRpc(dataPath, { [`${defaultNS}:input`]: data || {} });
-      if (updateResult.status < 200 || updateResult.status > 299) {
+      if (checkResponseCode(updateResult)) {
         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 || ''}`);
       }
index 02f2929..8ca8fdf 100644 (file)
@@ -26,7 +26,7 @@ import { restService } from '../services/restServices';
 export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
 
 // create eleactic search material data fetch handler
-const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', { status: "Connected" });
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: "Connected" });
 
 export const {
   actionHandler: connectedNetworkElementsActionHandler,
index cf4677b..b81a92c 100644 (file)
@@ -24,8 +24,8 @@ const cache: { [path: string]: string } = {
 
 class YangService {
 
-  public async getCapability(capability: string, version?: string) {
-    const url = `/yang-schema/${capability}${version ? `/${version}` : ""}`;
+  public async getCapability(capability: string, nodeId: string, version?: string) {
+    const url = `/yang-schema/${capability}${version ? `/${version}` : ""}?node=${nodeId}`;
 
     const cacheHit = cache[url];
     if (cacheHit) return cacheHit;
index 2879899..12815a5 100644 (file)
@@ -639,7 +639,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
     }
 
     return (
-      <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} customActionButtons={apiDocPathCreate ? [addNewElementAction, addWithApiDocElementAction] : [addNewElementAction]} columns={
+      <SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} rows={listData} customActionButtons={apiDocPathCreate ? [addNewElementAction, addWithApiDocElementAction] : [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)) {
@@ -822,7 +822,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
 
     return (
       <div className={this.props.classes.container}>
-        <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} columns={
+        <SelectElementTable stickyHeader idProperty={listKeyProperty} tableId={null} 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)) {
index 5cac22e..1a1008d 100644 (file)
@@ -54,7 +54,7 @@ class NetworkElementSelectorComponent extends React.Component<NetworkElementSele
 
   render() {
     return (
-      <ConnectedElementTable stickyHeader onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
+      <ConnectedElementTable stickyHeader tableId="configurable-elements-table" onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
         { property: "nodeId", title: "Node Name", type: ColumnType.text },
         { property: "isRequired", title: "Required", type: ColumnType.boolean },
         { property: "host", title: "Host", type: ColumnType.text },
index c80bd4c..965935a 100644 (file)
@@ -286,7 +286,7 @@ export class YangParser {
 
   public static ResolveStack = Symbol("ResolveStack");
 
-  constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = [], private _importOnlyModules: { name: string; revision: string; }[] = []) {
+  constructor(private _unavailableCapabilities: { failureReason: string; capability: string; }[] = [], private _importOnlyModules: { name: string; revision: string; }[] = [], private nodeId: string) {
    
   }
 
@@ -310,8 +310,7 @@ export class YangParser {
     //   // console.warn(`Skipped capability: ${capability} since it is marked as unavailable.` );
     //   return;
     // }
-
-    const data = await yangService.getCapability(capability, version);
+    const data = await yangService.getCapability(capability, this.nodeId, version);
     if (!data) {
       throw new Error(`Could not load yang file for ${capability}.`);
     }
@@ -409,6 +408,8 @@ export class YangParser {
     // import all required files and set module state 
     if (imports) for (let ind = 0; ind < imports.length; ++ind) {
       const moduleName = imports[ind].arg!; 
+
+      //TODO: Fix imports getting loaded without revision
       await this.addCapability(moduleName, undefined, module.state === ModuleState.importOnly);
       const importedModule = this._modules[imports[ind].arg!];
       if (importedModule && importedModule.state > ModuleState.stable) {
index 5461c14..57caf07 100644 (file)
@@ -135,49 +135,49 @@ module.exports = (env) => {
       },
        proxy: {
         "/about": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         }, 
         "/yang-schema/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },   
         "/oauth/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/database/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/restconf/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/rests/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/help/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
          "/about/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/tree/": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/websocket": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           ws: true,
           changeOrigin: true,
           secure: false
         },
         "/apidoc": {
-          target: "http://localhost:18181",
+          target: "http://sdnr:8181",
           ws: true,
           changeOrigin: true,
           secure: false
index 9ecdaf8..a31824a 100644 (file)
@@ -1,7 +1,7 @@
 {
   "name": "@odlux/connect-app",
   "version": "0.1.1",
-  "description": "A react based modular UI to display network connect data from a database.",
+  "description": "A react based modular UI to display network element/node connect data from a database.",
   "main": "index.js",
   "scripts": {
     "start": "webpack-dev-server --env debug",
@@ -26,9 +26,7 @@
     "@mui/icons-material": "^5.2.0",
     "@mui/material": "^5.2.2",
     "@mui/styles": "^5.2.2",
-    "@odlux/framework": "*",
-    "react-chartjs-2": "2.7.6",
-    "chart.js": "2.8.0"
+    "@odlux/framework": "*"
   },
   "peerDependencies": {
     "@types/classnames": "2.2.6",
diff --git a/sdnr/wt/odlux/apps/connectApp/src/actions/connectionStatusCountActions.ts b/sdnr/wt/odlux/apps/connectApp/src/actions/connectionStatusCountActions.ts
deleted file mode 100644 (file)
index 43bae72..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * ============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 { getConnectionStatusCountStateFromDatabase } from '../services/connectionStatusCountService';
-import { Dispatch } from '../../../../framework/src/flux/store';
-
-import { Action } from '../../../../framework/src/flux/action';
-
-
-export class ConnectionStatusCountBaseAction extends Action { }
-
-
-export class SetConnectionStatusCountAction extends ConnectionStatusCountBaseAction {
-  constructor(public ConnectedCount: number, public ConnectingCount: number, public DisconnectedCount: number,
-    public MountedCount: number, public UnableToConnectCount: number, public UndefinedCount: number, public UnmountedCount: number, public totalCount: number, public isLoadingConnectionStatusChart: boolean) {
-    super();
-  }
-}
-
-
-export const refreshConnectionStatusCountAsyncAction = async (dispatch: Dispatch) => {
-  dispatch(new SetConnectionStatusCountAction(0, 0, 0, 0, 0, 0, 0, 0, true));
-  const result = await getConnectionStatusCountStateFromDatabase().catch(_ => null);
-  if (result) {
-    const statusAction = new SetConnectionStatusCountAction(
-      result["Connected"] || 0,
-      result["Connecting"] || 0,
-      result["Disconnected"] || 0,
-      result["Mounted"] || 0,
-      result["UnableToConnect"] || 0,
-      result["Undefined"] || 0,
-      result["Unmounted"] || 0,
-      result["total"] || 0,
-      false
-    );
-    dispatch(statusAction);
-    return;
-  } else {
-    dispatch(new SetConnectionStatusCountAction(0, 0, 0, 0, 0, 0, 0, 0, false));
-  }
-}
index 84e73ae..26ee767 100644 (file)
@@ -27,7 +27,7 @@ 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. */
+/** Represents an action creator for a async thunk action to mount a network element/node. */
 export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkElementConnection) => (dispatch: Dispatch) => {
   return connectService.mountNetworkElement(networkElement).then((success) => {
     if (success) {
@@ -42,7 +42,7 @@ export const mountNetworkElementAsyncActionCreator = (networkElement: NetworkEle
   });
 };
 
-/** Represents an action crator for a async thunk action to unmount a network element. */
+/** Represents an action creator for a async thunk action to unmount a network element/node. */
 export const unmountNetworkElementAsyncActionCreator = (nodeId: string) => (dispatch: Dispatch) => {
   return connectService.unmountNetworkElement(nodeId).then((success) => {
     if (success) {
index 041cff9..57f036e 100644 (file)
@@ -28,14 +28,14 @@ import { unmountNetworkElementAsyncActionCreator } from './mountedNetworkElement
 /** Represents the base action. */
 export class BaseAction extends Action { }
 
-/** Represents an async thunk action creator to add an element to the network elements. */
+/** Represents an async thunk action creator to add an element to the network elements/nodes. */
 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. */
+/** Represents an async thunk action creator to edit network element/node. */
 export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
   const connectionStatus: ConnectionStatus[] = (await connectService.getNetworkElementConnectionStatus(element.id).then(ne => (ne))) || [];
   const currentConnectionStatus = connectionStatus[0].status;
@@ -50,7 +50,7 @@ export const editNetworkElementAsyncActionCreator = (element: UpdateNetworkEleme
 };
 
 
-/** Represents an async thunk action creator to delete an element from network elements. */
+/** Represents an async thunk action creator to delete an element from network elements/nodes. */
 export const removeNetworkElementAsyncActionCreator = (element: UpdateNetworkElement) => async (dispatch: Dispatch) => {
   const res = await connectService.deleteNetworkElement(element);
   await dispatch(unmountNetworkElementAsyncActionCreator(element && element.id));
index a7d96d0..b240b24 100644 (file)
@@ -65,7 +65,7 @@ class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogCo
     <>
       <ConnectionStatusTable stickyHeader tableId="connection-status-table" customActionButtons={[refreshConnectionStatusLogAction]}  columns={[
         { property: "timestamp", title: "Timestamp", type: ColumnType.text },
-        { property: "nodeId", title: "Node Name", type: ColumnType.text },
+        { property: "nodeId", title: "Node ID", type: ColumnType.text },
         { property: "status", title: "Connection Status", type: ColumnType.text },
       ]} idProperty="id" {...this.props.connectionStatusLogActions} {...this.props.connectionStatusLogProperties} >
       </ConnectionStatusTable>
index 7324ffa..5740ebd 100644 (file)
@@ -72,10 +72,10 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
 
 
     if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
-      // do not mount network element, if only isRequired is changed
+      // do not mount network element/node, if only isRequired is changed
       await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
 
-    } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount element, if only id was saved into object (no changes made!)
+    } else if (!(values.length === 1 && values.includes(idProperty as string))) { //do not edit or mount network element/node , if only id was saved into object (no changes made!)
       await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
       await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
     }
@@ -109,35 +109,35 @@ const settings: { [key: string]: DialogSettings } = {
   },
 
   [EditNetworkElementDialogMode.AddNewNetworkElement]: {
-    dialogTitle: "Add new network element",
-    dialogDescription: "Add this new network element:",
-    applyButtonText: "Add network element",
+    dialogTitle: "Add New Node",
+    dialogDescription: "Add this new node:",
+    applyButtonText: "Add node",
     cancelButtonText: "Cancel",
     enableMountIdEditor: true,
     enableUsernameEditor: true,
     enableExtendedEditor: true,
   },
   [EditNetworkElementDialogMode.MountNetworkElement]: {
-    dialogTitle: "Mount network element",
-    dialogDescription: "mount this network element:",
-    applyButtonText: "mount network element",
+    dialogTitle: "Mount Node",
+    dialogDescription: "Mount this node:",
+    applyButtonText: "Mount node",
     cancelButtonText: "Cancel",
     enableMountIdEditor: false,
     enableUsernameEditor: false,
     enableExtendedEditor: false,
   },
   [EditNetworkElementDialogMode.UnmountNetworkElement]: {
-    dialogTitle: "Unmount network element",
-    dialogDescription: "unmount this network element:",
-    applyButtonText: "Unmount network element",
+    dialogTitle: "Unmount Node",
+    dialogDescription: "Unmount this node:",
+    applyButtonText: "Unmount node",
     cancelButtonText: "Cancel",
     enableMountIdEditor: false,
     enableUsernameEditor: false,
     enableExtendedEditor: false,
   },
   [EditNetworkElementDialogMode.EditNetworkElement]: {
-    dialogTitle: "Modify the network elements",
-    dialogDescription: "Modify this network element",
+    dialogTitle: "Modify Node",
+    dialogDescription: "Modify this node",
     applyButtonText: "Modify",
     cancelButtonText: "Cancel",
     enableMountIdEditor: false,
@@ -145,9 +145,9 @@ const settings: { [key: string]: DialogSettings } = {
     enableExtendedEditor: false,
   },
   [EditNetworkElementDialogMode.RemoveNetworkElement]: {
-    dialogTitle: "Remove network element",
-    dialogDescription: "Do you really want to remove this network element:",
-    applyButtonText: "Remove network element",
+    dialogTitle: "Remove Node",
+    dialogDescription: "Do you really want to remove this node?",
+    applyButtonText: "Remove node",
     cancelButtonText: "Cancel",
     enableMountIdEditor: false,
     enableUsernameEditor: false,
@@ -176,9 +176,11 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
   constructor(props: EditNetworkElementDialogComponentProps) {
     super(props);
     this.handleRadioChange = this.handleRadioChange.bind(this);
+    // Initialization of state is partly overwritten by update via react getDerivedStateFromProps() below.
+    // Change initialization values in parent "networkElements.tsx" in "const emptyRequireNetworkElement"
     this.state = {
       nodeId: this.props.initialNetworkElement.nodeId,
-      isRequired: false,
+      isRequired: this.props.initialNetworkElement.isRequired,
       host: this.props.initialNetworkElement.host,
       port: this.props.initialNetworkElement.port,
       isNameValid: true,
@@ -222,12 +224,12 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
           <DialogContentText>
             {setting.dialogDescription}
           </DialogContentText>
-          <TextField variant="standard" 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 }); }} />
-          {!this.state.isNameValid && <Typography variant="body1" color="error">Name cannot be empty.</Typography>}
-          <TextField variant="standard" 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 }); }} />
-          {!this.state.isHostSet && <Typography variant="body1" color="error">IP Adress cannot be empty.</Typography>}
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Node ID" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+          {!this.state.isNameValid && <Typography variant="body1" color="error">Node ID cannot be empty.</Typography>}
+          <TextField variant="standard" disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="Host/IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
+          {!this.state.isHostSet && <Typography variant="body1" color="error">Host/IP address cannot be empty.</Typography>}
 
-          <TextField variant="standard" 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 }); }} />
+          <TextField variant="standard" 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 variant="standard" 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 &&
index 5514fa5..b0c7840 100644 (file)
@@ -51,7 +51,7 @@
      cancelButtonText: "",
    },
    [InfoNetworkElementDialogMode.InfoNetworkElement]: {
-     dialogTitle: "Yang capabilities of the network element",
+     dialogTitle: "YANG Capabilities of the Node",
      dialogDescription: "",
      cancelButtonText: "OK",
    }
@@ -88,7 +88,7 @@
        const indexRevision = capabilty.indexOf("revision=");
        const indexModule = capabilty.indexOf(")", indexRevision);
        if (indexRevision > 0 && indexModule > 0) {
-         let moduleName = capabilty.substr(indexModule + 1);
+         let moduleName = capabilty.substring(indexModule + 1);
          let ModuleFeaturesList;
          for(let index = 0; index < yangFeatures.length; index++) {
            if(yangFeatures[index].name == moduleName) {
  
          yangCapabilities.push({
            module: moduleName,
-           revision: capabilty.substr(indexRevision + 9, 10),
+           revision: capabilty.substring(indexRevision + 9, indexRevision + 19),
            features: featuresList 
           });
        }
      return (
        <>
          <Dialog open={this.props.mode !== InfoNetworkElementDialogMode.None}  >
-           <DialogTitle id="form-dialog-title">{setting.dialogTitle + ' - ' + this.state.nodeId}</DialogTitle>
+           <DialogTitle id="form-dialog-title">{`${setting.dialogTitle}: "${this.state.nodeId}"`}</DialogTitle>
            <InfoElementTable stickyHeader isPopup tableId="info-element-table" asynchronus columns={[
-             { property: "module", title: "Module", type: ColumnType.text, width:900 },
+             { property: "module", title: "YANG Capability", type: ColumnType.text, width:900 },
              {
                property: "revision", title: "Revision", type: ColumnType.custom, customControl: ({ rowData }) => {
                  return (
                    <div>
-                     <a href={'/yang-schema/' + rowData.module + '/' + rowData.revision} target="_blank"  > {rowData.revision} </a>
+                     <a href={`/yang-schema/${rowData.module}/${rowData.revision}`} target="_blank"  > {rowData.revision} </a>
                    </div>
                  )
                }
index a17a247..67fdef6 100644 (file)
@@ -109,7 +109,7 @@ type NetworkElementsListComponentState = {
   elementInfoFeature: ModuleSet | null
 }
 
-const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false };
+const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 830, status: "Disconnected", isRequired: true };
 let initialSorted = false;
 const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
 
@@ -138,7 +138,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
       <MenuItemExt aria-label={"mount-button"} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkIcon /><Typography>Mount</Typography></MenuItemExt>,
       <MenuItemExt aria-label={"unmount-button"} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)} disabled={!canMount} ><LinkOffIcon /><Typography>Unmount</Typography></MenuItemExt>,
       <Divider />,
-      <MenuItem aria-label={"info-button"} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} ><Info /><Typography>Info</Typography></MenuItem>,
+      <MenuItem aria-label={"info-button"} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status !== "Connected"} ><Info /><Typography>Info</Typography></MenuItem>,
       <MenuItem aria-label={"edit-button"} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
       <MenuItem aria-label={"remove-button"} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
       <Divider />,
@@ -177,7 +177,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
     const canAdd = true;
 
     const addRequireNetworkElementAction = {
-      icon: AddIcon, tooltip: 'Add', ariaLabel: "add-element", onClick: () => {
+      icon: AddIcon, tooltip: 'Add node', ariaLabel: "add-element", onClick: () => {
         this.setState({
           networkElementEditorMode: EditNetworkElementDialogMode.AddNewNetworkElement,
           networkElementToEdit: emptyRequireNetworkElement,
@@ -186,7 +186,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
     };
 
     const refreshNetworkElementsAction = {
-      icon: Refresh, tooltip: 'Refresh Network Elements table', ariaLabel: 'refresh', onClick: () => {
+      icon: Refresh, tooltip: 'Refresh table', ariaLabel: 'refresh', onClick: () => {
         this.setState({
           refreshNetworkElementsEditorMode: RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable
         });
@@ -195,20 +195,20 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
 
     return <>
       <NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[refreshNetworkElementsAction, ...(canAdd ? [addRequireNetworkElementAction] : [])]} columns={[
-        { property: "nodeId", title: "Node Name", type: ColumnType.text },
-        { property: "isRequired", title: "Required", type: ColumnType.boolean },
+        { property: "nodeId", title: "Node ID", type: ColumnType.text },
         { property: "status", title: "Connection Status", type: ColumnType.text, width:'15%' },
         { 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: "Device Type", type: ColumnType.text },
-        { property: "deviceFunction", title: "Device Function", type: ColumnType.text, width: '15%' }
+        { property: "isRequired", title: "Required", type: ColumnType.boolean },
+        { property: "deviceType", title: "Type", type: ColumnType.text },
+      //  { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+        { property: "deviceFunction", title: "Function", type: ColumnType.text, width: '25%' }
       ]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus createContextMenu={rowData => {
 
         return this.getContextMenu(rowData);
       }} >
       </NetworkElementTable>
-      <EditNetworkElementDialog
+      <EditNetworkElementDialog 
         initialNetworkElement={networkElementToEdit}
         mode={this.state.networkElementEditorMode}
         onClose={this.onCloseEditNetworkElementDialog}
index 27288fa..abf5938 100644 (file)
@@ -59,7 +59,7 @@ const settings: { [key: string]: DialogSettings } = {
     enableExtendedEditor: false,
   },
   [RefreshNetworkElementsDialogMode.RefreshNetworkElementsTable]: {
-    dialogTitle: "Do you want to refresh the Network Elements table?",
+    dialogTitle: "Do you want to refresh the nodes table?",
     dialogDescription: "",
     applyButtonText: "Yes",
     cancelButtonText: "Cancel",
index dbb9b2c..6a18252 100644 (file)
@@ -24,7 +24,6 @@ import { IInfoNetworkElementsState, infoNetworkElementsActionHandler, IInfoNetwo
 import { SetPanelAction, AddWebUriList, RemoveWebUri, SetWeburiSearchBusy } from '../actions/commonNetworkElementsActions';
 import { PanelId } from '../models/panelId';
 import { guiCutThrough } from '../models/guiCutTrough';
-import { connectionStatusCountHandler, IConnectionStatusCount } from './connectionStatusCountHandler';
 import { availableTlsKeysActionHandler, IAvailableTlsKeysState } from './tlsKeyHandler';
 
 export interface IConnectAppStoreState {
@@ -34,7 +33,6 @@ export interface IConnectAppStoreState {
   elementInfo: IInfoNetworkElementsState;
   elementFeatureInfo: IInfoNetworkElementFeaturesState;
   guiCutThrough: guiCutThroughState;
-  connectionStatusCount: IConnectionStatusCount;
   availableTlsKeys: IAvailableTlsKeysState
 }
 
@@ -94,7 +92,6 @@ const actionHandlers = {
   elementInfo: infoNetworkElementsActionHandler,
   elementFeatureInfo: infoNetworkElementFeaturesActionHandler,
   guiCutThrough: guiCutThroughHandler,
-  connectionStatusCount: connectionStatusCountHandler,
   availableTlsKeys: availableTlsKeysActionHandler
 };
 
diff --git a/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusCountHandler.ts b/sdnr/wt/odlux/apps/connectApp/src/handlers/connectionStatusCountHandler.ts
deleted file mode 100644 (file)
index 219a096..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * ============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 { SetConnectionStatusCountAction } from "../actions/connectionStatusCountActions";
-
-export interface IConnectionStatusCount {
-   Connected: number,
-   Connecting: number,
-   Disconnected: number,
-   Mounted: number,
-   UnableToConnect: number,
-   Undefined: number,
-   Unmounted: number,
-   total: number,
-   isLoadingConnectionStatusChart: boolean
-}
-
-const connectionStatusCountInit: IConnectionStatusCount = {
-   Connected: 0,
-   Connecting: 0,
-   Disconnected: 0,
-   Mounted: 0,
-   UnableToConnect: 0,
-   Undefined: 0,
-   Unmounted: 0,
-   total: 0,
-   isLoadingConnectionStatusChart: false
-};
-
-export const connectionStatusCountHandler: IActionHandler<IConnectionStatusCount> = (state = connectionStatusCountInit, action) => {
-   if (action instanceof SetConnectionStatusCountAction) {
-      state = {
-         Connected: action.ConnectedCount,
-         Connecting: action.ConnectingCount,
-         Disconnected: action.DisconnectedCount,
-         Mounted: action.MountedCount,
-         UnableToConnect: action.UnableToConnectCount,
-         Undefined: action.UndefinedCount,
-         Unmounted: action.UnmountedCount,
-         total: action.totalCount,
-         isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart
-      }
-   }
-
-   return state;
-}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusCount.ts b/sdnr/wt/odlux/apps/connectApp/src/models/connectionStatusCount.ts
deleted file mode 100644 (file)
index 125a6e3..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * ============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.number (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.number
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 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 ConnectionStatusCountReturnType = {
-  Connected: number,
-  Connecting: number,
-  Disconnected: number,
-  Mounted: number,
-  UnableToConnect: number,
-  Undefined: number,
-  Unmounted: number,
-  total: number
-};
-
-export type ConnectionStatusCountType = {
-  Connected: number,
-  Connecting: number,
-  Disconnected: number,
-  Mounted: number,
-  UnableToConnect: number,
-  Undefined: number,
-  Unmounted: number,
-  total: number
-};
-
-export type ConnectionStatusCount = {
-  'network-element-connections': ConnectionStatusCountReturnType
-};
index 8376348..2a9a46d 100644 (file)
@@ -27,13 +27,12 @@ import { IApplicationStoreState } from "../../../framework/src/store/application
 import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
 
 import { findWebUrisForGuiCutThroughAsyncAction, updateCurrentViewAsyncAction, SetPanelAction } from './actions/commonNetworkElementsActions';
-import { refreshConnectionStatusCountAsyncAction } from './actions/connectionStatusCountActions';
 import { createNetworkElementsActions, createNetworkElementsProperties, networkElementsReloadAction } from './handlers/networkElementsHandler';
 import connectAppRootHandler from './handlers/connectAppRootHandler';
 import ConnectApplication from './views/connectView';
 import { PanelId } from "./models/panelId";
 import { NetworkElementsList } from './components/networkElements';
-import DashboardHome from "./components/dashboardHome";
+
 
 let currentStatus: string | undefined = undefined;
 let refreshInterval: ReturnType<typeof window.setInterval> | null = null;
@@ -84,7 +83,6 @@ export function register() {
     icon: faPlug,
     rootComponent: App,
     rootActionHandler: connectAppRootHandler,
-    dashbaordElement: DashboardHome,
     menuEntry: "Connect"
   });
 
@@ -92,9 +90,9 @@ export function register() {
   subscribe<IFormatedMessage>(["object-creation-notification", "object-deletion-notification", "attribute-value-changed-notification"], (msg => {
     const store = applicationApi.applicationStore;
     if (msg && msg.type.type === "object-creation-notification" && store) {
-      store.dispatch(new AddSnackbarNotification({ message: `Adding network element [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
+      store.dispatch(new AddSnackbarNotification({ message: `Adding node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
     } else if (msg && (msg.type.type === "object-deletion-notification" || msg.type.type === "attribute-value-changed-notification") && store) {
-      store.dispatch(new AddSnackbarNotification({ message: `Updating network element [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
+      store.dispatch(new AddSnackbarNotification({ message: `Updating node [${msg.data['object-id-ref']}]`, options: { variant: 'info' } }));
     }
     if (store) {
       store.dispatch(updateCurrentViewAsyncAction() as any).then(() => {
@@ -109,29 +107,4 @@ export function register() {
     store.dispatch(networkElementsReloadAction);
   });
 
-  applicationApi.applicationStoreInitialized.then(store => {
-    store.dispatch(refreshConnectionStatusCountAsyncAction);
-  });
-
-
-  applicationApi.loginEvent.addHandler(e=>{
-    refreshInterval = startRefreshInterval() as any;
-  })
-
-  applicationApi.logoutEvent.addHandler(e=>{
-
-    applicationApi.applicationStoreInitialized.then(store => {
-      clearInterval(refreshInterval!);
-    });
-  })
-
-  const startRefreshInterval =() =>{
-    const refresh = window.setInterval(() => {
-      applicationApi.applicationStoreInitialized.then(store => {
-        store.dispatch(refreshConnectionStatusCountAsyncAction);
-      });
-    }, 15000);
-
-    return refresh;
-  }
 }
\ No newline at end of file
index 427acd3..08cc580 100644 (file)
@@ -26,7 +26,7 @@ import { FeatureTopology, Topology, TopologyNode, Module } from '../models/topol
 import { guiCutThrough } from '../models/guiCutTrough';
 
 /**
-* Represents a web api accessor service for all Network Elements actions.
+* Represents a web api accessor service for all network element/node actions.
 */
 class ConnectService {
   public getNetworkElementUri = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId;
@@ -35,7 +35,7 @@ class ConnectService {
   public getNetworkElementYangLibraryFeature = (nodeId: string) => '/rests/data/network-topology:network-topology/topology=topology-netconf/node=' + nodeId + '/yang-ext:mount/ietf-yang-library:yang-library?content=nonconfig'
 
   /**
-   * Inserts a network elements.
+   * Inserts a network element/node.
    */
   public async createNetworkElement(element: NetworkElementConnection): Promise<NetworkElementConnection | null> {
     const path = this.getNetworkElementConnectDataProviderUri("create");
@@ -46,7 +46,7 @@ class ConnectService {
   }
 
   /**
-  * Updates a network element.
+  * Updates a network element/node.
   */
   public async updateNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
     const path = this.getNetworkElementConnectDataProviderUri("update");
@@ -57,7 +57,7 @@ class ConnectService {
   }
 
   /**
-    * Deletes a network element.
+    * Deletes a network element/node.
     */
   public async deleteNetworkElement(element: UpdateNetworkElement): Promise<NetworkElementConnection | null> {
     const query = {
@@ -70,7 +70,7 @@ class ConnectService {
     return result || null;
   }
 
-  /** Mounts network element. */
+  /** Mounts network element/node */
   public async mountNetworkElement(networkElement: NetworkElementConnection): Promise<boolean> {
     const path = this.getNetworkElementUri(networkElement.nodeId);
     const mountXml = [
@@ -152,7 +152,7 @@ class ConnectService {
     }
   };
 
-  /** Yang capabilities of the selected network elements. */
+  /** Yang capabilities of the selected network element/node */
   public async infoNetworkElement(nodeId: string): Promise<TopologyNode | null> {
     const path = this.getNetworkElementUri(nodeId);
     const topologyRequestPomise = requestRest<Topology>(path, { method: "GET" });
@@ -163,7 +163,7 @@ class ConnectService {
   }
 
 
-  /** Yang features of the selected network element module. */
+  /** Yang features of the selected network element/node module */
   public async infoNetworkElementFeatures(nodeId: string): Promise<Module[] | null | undefined> {
     const path = this.getNetworkElementYangLibraryFeature(nodeId);
     const topologyRequestPomise = requestRest<FeatureTopology>(path, { method: "GET" });
@@ -180,7 +180,7 @@ class ConnectService {
 
 
   /**
-   * Get the connection state of the network element.
+   * Get the connection state of the network element/ node
    */
   public async getNetworkElementConnectionStatus(element: string): Promise<(ConnectionStatus)[] | null> {
     const path = `/rests/operations/data-provider:read-network-element-connection-list`;
diff --git a/sdnr/wt/odlux/apps/connectApp/src/services/connectionStatusCountService.ts b/sdnr/wt/odlux/apps/connectApp/src/services/connectionStatusCountService.ts
deleted file mode 100644 (file)
index 519c965..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * ============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 { ConnectionStatusCountType, ConnectionStatusCount } from "../models/connectionStatusCount";
-
-
-
-export const getConnectionStatusCountStateFromDatabase = async (): Promise<ConnectionStatusCountType | null> => {
-  const path = 'rests/operations/data-provider:read-status';
-  const result = await requestRest<Result<ConnectionStatusCount>>(path, { method: "POST" });
-  let connectionStatusCountType: ConnectionStatusCountType = {
-    Connected: 0,
-    Connecting: 0,
-    Disconnected: 0,
-    Mounted: 0,
-    UnableToConnect: 0,
-    Undefined: 0,
-    Unmounted: 0,
-    total: 0
-  }
-  let connectionStatusCount: ConnectionStatusCount[] | null = null;
-
-  if (result && result["data-provider:output"] && result["data-provider:output"].data) {
-    connectionStatusCount = result["data-provider:output"].data;
-    connectionStatusCountType = {
-      Connected: connectionStatusCount[0]["network-element-connections"].Connected,
-      Connecting: connectionStatusCount[0]["network-element-connections"].Connecting,
-      Disconnected: connectionStatusCount[0]["network-element-connections"].Disconnected,
-      Mounted: connectionStatusCount[0]["network-element-connections"].Mounted,
-      UnableToConnect: connectionStatusCount[0]["network-element-connections"].UnableToConnect,
-      Undefined: connectionStatusCount[0]["network-element-connections"].Undefined,
-      Unmounted: connectionStatusCount[0]["network-element-connections"].Unmounted,
-      total: connectionStatusCount[0]["network-element-connections"].total,
-    }
-  }
-  return connectionStatusCountType;
-}
index e99b6af..0828397 100644 (file)
@@ -107,7 +107,7 @@ class ConnectApplicationComponent extends React.Component<ConnectApplicationComp
       <>
         <AppBar enableColorOnDark position="static">
           <Tabs indicatorColor="secondary" textColor="inherit" value={activePanelId} onChange={this.onHandleTabChange} aria-label="connect-app-tabs">
-            <Tab aria-label="network-elements-list-tab" label="Network Elements" value="NetworkElements" />
+            <Tab aria-label="network-elements-list-tab" label="NODES" value="NetworkElements" />
             <Tab aria-label="connection-status-log-tab" label="Connection Status Log" value="ConnectionStatusLog" />
           </Tabs>
         </AppBar>
index b283e42..ff76904 100644 (file)
@@ -154,6 +154,14 @@ module.exports = (env) => {
           target: "http://sdnr:8181",
           secure: false
         },
+        "/userdata": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/userdata/": {
+          target: "http://sdnr:8181",
+          secure: false
+        },
         "/help/": {
           target: "http://sdnr:8181",
           secure: false
index c50c08e..54fea6a 100644 (file)
@@ -21,15 +21,18 @@ 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, public isLoadingAlarmStatusChart: boolean) {
+  constructor(public criticalFaults: number, public majorFaults: number, public minorFaults: number, public warnings: number,
+    public isLoadingAlarmStatusChart: boolean, public ConnectedCount: number, public ConnectingCount: number, public DisconnectedCount: number,
+    public MountedCount: number, public UnableToConnectCount: number, public UndefinedCount: number, public UnmountedCount: number,
+    public totalCount: number, public isLoadingConnectionStatusChart: boolean) {
     super();
   }
 }
 
 
 export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch) => {
-  
-  dispatch(new SetFaultStatusAction(0, 0, 0, 0, true));
+
+  dispatch(new SetFaultStatusAction(0, 0, 0, 0, true, 0, 0, 0, 0, 0, 0, 0, 0, true));
   const result = await getFaultStateFromDatabase().catch(_ => null);
   if (result) {
     const statusAction = new SetFaultStatusAction(
@@ -37,12 +40,21 @@ export const refreshFaultStatusAsyncAction = async (dispatch: Dispatch) => {
       result["Major"] || 0,
       result["Minor"] || 0,
       result["Warning"] || 0,
+      false,
+      result["Connected"] || 0,
+      result["Connecting"] || 0,
+      result["Disconnected"] || 0,
+      result["Mounted"] || 0,
+      result["UnableToConnect"] || 0,
+      result["Undefined"] || 0,
+      result["Unmounted"] || 0,
+      result["total"] || 0,
       false
     );
     dispatch(statusAction);
     return;
   }
   else {
-    dispatch(new SetFaultStatusAction(0, 0, 0, 0, false));
+    dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
   }
 }
@@ -47,7 +47,6 @@ let alarmStatusDataLoad: number[] = [0, 0, 0, 0];
 let alarmTotalCount = 0;
 
 const mapProps = (state: IApplicationStoreState) => ({
-  connectionStatusCount: state.connect.connectionStatusCount,
   alarmStatus: state.fault.faultStatus
 });
 
@@ -67,15 +66,16 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
   render(): JSX.Element {
     const { classes } = this.props;
 
-    if (!this.props.connectionStatusCount.isLoadingConnectionStatusChart) {
+    if (!this.props.alarmStatus.isLoadingConnectionStatusChart) {
       connectionStatusDataLoad = [
-        this.props.connectionStatusCount.Connected,
-        this.props.connectionStatusCount.Connecting,
-        this.props.connectionStatusCount.Disconnected,
-        this.props.connectionStatusCount.UnableToConnect
+        this.props.alarmStatus.Connected,
+        this.props.alarmStatus.Connecting,
+        this.props.alarmStatus.Disconnected,
+        this.props.alarmStatus.UnableToConnect,
+        this.props.alarmStatus.Undefined
       ];
-      connectionTotalCount = this.props.connectionStatusCount.Connected + this.props.connectionStatusCount.Connecting
-        + this.props.connectionStatusCount.Disconnected + this.props.connectionStatusCount.UnableToConnect;
+      connectionTotalCount = this.props.alarmStatus.Connected + this.props.alarmStatus.Connecting
+        + this.props.alarmStatus.Disconnected + this.props.alarmStatus.UnableToConnect + this.props.alarmStatus.Undefined;
 
     }
 
@@ -92,14 +92,22 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
 
     /** Available Network Connection Status chart data */
     const connectionStatusData = {
-      labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect'],
+      labels: [
+        'Connected: ' + this.props.alarmStatus.Connected,
+        'Connecting: ' + this.props.alarmStatus.Connecting,
+        'Disconnected: ' + this.props.alarmStatus.Disconnected,
+        'UnableToConnect: ' + this.props.alarmStatus.UnableToConnect,
+        'Undefined: ' + this.props.alarmStatus.Undefined
+      ],
       datasets: [{
+        labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'],
         data: connectionStatusDataLoad,
         backgroundColor: [
           'rgb(0, 153, 51)',
           'rgb(255, 102, 0)',
           'rgb(191, 191, 191)',
-          'rgb(191, 191, 191)'
+          'rgb(191, 191, 191)',
+          'rgb(242, 240, 240)'
         ]
       }]
     };
@@ -139,8 +147,29 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
     };
 
     /** Connection status options */
-    let labels: String[] = ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect'];
+    let labels: String[] = ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect', 'Undefined'];
     const connectionStatusOptions = {
+      tooltips: {
+        callbacks: {
+          label: (tooltipItem: any, data: any) => {
+            let label =
+              (data.datasets[tooltipItem.datasetIndex].labels &&
+                data.datasets[tooltipItem.datasetIndex].labels[
+                tooltipItem.index
+                ]) ||
+              data.labels[tooltipItem.index] ||
+              "";
+            if (label) {
+              label += ": ";
+            }
+            label +=
+              data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+              (data.datasets[tooltipItem.datasetIndex].labelSuffix || "");
+
+            return label;
+          }
+        }
+      },
       responsive: true,
       maintainAspectRatio: false,
       animation: {
@@ -199,12 +228,13 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
     /** Alarm status Data */
     const alarmStatusData = {
       labels: [
-        'Critical',
-        'Major',
-        'Minor',
-        'Warning'
+        'Critical : ' + this.props.alarmStatus.critical,
+        'Major : ' + this.props.alarmStatus.major,
+        'Minor : ' + this.props.alarmStatus.minor,
+        'Warning : ' + this.props.alarmStatus.warning
       ],
       datasets: [{
+        labels: ['Critical', 'Major', 'Minor', 'Warning'],
         data: alarmStatusDataLoad,
         backgroundColor: [
           'rgb(240, 25, 10)',
@@ -229,6 +259,27 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
     /** Alarm status Options */
     let alarmLabels: String[] = ['Critical', 'Major', 'Minor', 'Warning'];
     const alarmStatusOptions = {
+      tooltips: {
+        callbacks: {
+          label: (tooltipItem: any, data: any) => {
+            let label =
+              (data.datasets[tooltipItem.datasetIndex].labels &&
+                data.datasets[tooltipItem.datasetIndex].labels[
+                tooltipItem.index
+                ]) ||
+              data.labels[tooltipItem.index] ||
+              "";
+            if (label) {
+              label += ": ";
+            }
+            label +=
+              data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index] +
+              (data.datasets[tooltipItem.datasetIndex].labelSuffix || "");
+
+            return label;
+          }
+        }
+      },
       responsive: true,
       maintainAspectRatio: false,
       animation: {
@@ -242,7 +293,7 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
       },
       onClick: (event: MouseEvent, item: any) => {
         if (item[0]) {
-          let severity = alarmLabels[item[0].index] + '';
+          let severity = alarmLabels[item[0]._index] + '';
           this.props.navigateToApplication("fault", '/alarmStatus/' + severity);
         }
       },
@@ -286,7 +337,7 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
     return (
       <>
         <div style={scrollbar} >
-          <h1>Welcome to ODLUX</h1>
+          <h1 aria-label="welcome-to-odlux">Welcome to ODLUX</h1>
           <div style={{ width: '50%', float: 'left' }}>
             {this.checkElementsAreLoaded() ?
               this.checkConnectionStatus() && connectionTotalCount != 0 ?
@@ -351,12 +402,12 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
 
   /** Check if connection status data available */
   public checkConnectionStatus = () => {
-    let statusCount = this.props.connectionStatusCount;
+    let statusCount = this.props.alarmStatus;
     if (statusCount.isLoadingConnectionStatusChart) {
       return true;
     }
     if (statusCount.Connected == 0 && statusCount.Connecting == 0 && statusCount.Disconnected == 0
-      && statusCount.UnableToConnect == 0) {
+      && statusCount.UnableToConnect == 0 && statusCount.Undefined == 0) {
       return false;
     } else {
       return true;
@@ -365,7 +416,7 @@ class DashboardHome extends React.Component<HomeComponentProps>  {
 
   /** Check if connection status chart data is loaded */
   public checkElementsAreLoaded = () => {
-    let isLoadingCheck = this.props.connectionStatusCount;
+    let isLoadingCheck = this.props.alarmStatus;
     if (connectionStatusinitialLoad && !isLoadingCheck.isLoadingConnectionStatusChart) {
       if (this.checkConnectionStatus()) {
         connectionStatusinitialLoad = false;
index e1fceb4..6fa95b6 100644 (file)
@@ -23,7 +23,16 @@ export interface IFaultStatus {
   major: number,
   minor: number,
   warning: number,
-  isLoadingAlarmStatusChart: boolean
+  isLoadingAlarmStatusChart: boolean,
+  Connected: number,
+  Connecting: number,
+  Disconnected: number,
+  Mounted: number,
+  UnableToConnect: number,
+  Undefined: number,
+  Unmounted: number,
+  total: number,
+  isLoadingConnectionStatusChart: boolean
 }
 
 const faultStatusInit: IFaultStatus = {
@@ -31,7 +40,16 @@ const faultStatusInit: IFaultStatus = {
   major: 0,
   minor: 0,
   warning: 0,
-  isLoadingAlarmStatusChart: false
+  isLoadingAlarmStatusChart: false,
+  Connected: 0,
+  Connecting: 0,
+  Disconnected: 0,
+  Mounted: 0,
+  UnableToConnect: 0,
+  Undefined: 0,
+  Unmounted: 0,
+  total: 0,
+  isLoadingConnectionStatusChart: false
 };
 
 export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultStatusInit, action) => {
@@ -41,7 +59,16 @@ export const faultStatusHandler: IActionHandler<IFaultStatus> = (state = faultSt
       major: action.majorFaults,
       minor: action.minorFaults,
       warning: action.warnings,
-      isLoadingAlarmStatusChart: action.isLoadingAlarmStatusChart
+      isLoadingAlarmStatusChart: action.isLoadingAlarmStatusChart,
+      Connected: action.ConnectedCount,
+      Connecting: action.ConnectingCount,
+      Disconnected: action.DisconnectedCount,
+      Mounted: action.MountedCount,
+      UnableToConnect: action.UnableToConnectCount,
+      Undefined: action.UndefinedCount,
+      Unmounted: action.UnmountedCount,
+      total: action.totalCount,
+      isLoadingConnectionStatusChart: action.isLoadingConnectionStatusChart
     }
   }
 
index 2ba8da0..5f38e5f 100644 (file)
@@ -61,18 +61,35 @@ export type FaultsReturnType = {
   criticals: number,
   majors: number,
   minors: number,
-  warnings: number
+  warnings: number,
+  Connected: number,
+  Connecting: number,
+  Disconnected: number,
+  Mounted: number,
+  UnableToConnect: number,
+  Undefined: number,
+  Unmounted: number,
+  total: number
 };
 
 export type FaultType = {
   Critical: number,
   Major: number,
   Minor: number,
-  Warning: number
+  Warning: number,
+  Connected: number,
+  Connecting: number,
+  Disconnected: number,
+  Mounted: number,
+  UnableToConnect: number,
+  Undefined: number,
+  Unmounted: number,
+  total: number
 };
 
 export type Faults = {
-  faults: FaultsReturnType
+  faults: FaultsReturnType,
+  'network-element-connections': FaultsReturnType
 };
 
 export type DeletedStuckAlarms = {
index 0c5fdde..ff901b0 100644 (file)
@@ -41,6 +41,8 @@ import { createCurrentProblemsProperties, createCurrentProblemsActions, currentP
 import { FaultStatus } from "./components/faultStatus";
 import { refreshFaultStatusAsyncAction, SetFaultStatusAction } from "./actions/statusActions";
 
+import DashboardHome from "./components/dashboardHome";
+
 let currentMountId: string | undefined = undefined;
 let currentSeverity: string | undefined = undefined;
 let refreshInterval: ReturnType<typeof window.setInterval> | null = null;
@@ -113,6 +115,7 @@ export function register() {
     rootComponent: App,
     rootActionHandler: faultAppRootHandler,
     statusBarElement: FaultStatus,
+    dashbaordElement: DashboardHome,
     menuEntry: "Fault"
   });
 
@@ -149,14 +152,14 @@ export function register() {
   applicationApi.logoutEvent.addHandler(e=>{
 
     applicationApi.applicationStoreInitialized.then(store => {
-      store.dispatch(new SetFaultStatusAction(0, 0, 0, 0, false));
+      store.dispatch(new SetFaultStatusAction(0, 0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, false));
       clearInterval(refreshInterval!);
     });
   })
   
  
 
-  function startRefreshInterval(){
+  function startRefreshInterval()  {
     const refreshFaultStatus = window.setInterval(() => {
       applicationApi.applicationStoreInitialized.then(store => {
   
index 663def0..880ed77 100644 (file)
@@ -28,7 +28,15 @@ export const getFaultStateFromDatabase = async (): Promise<FaultType | null> =>
     Critical: 0,
     Major: 0,
     Minor: 0,
-    Warning: 0
+    Warning: 0,
+    Connected: 0,
+    Connecting: 0,
+    Disconnected: 0,
+    Mounted: 0,
+    UnableToConnect: 0,
+    Undefined: 0,
+    Unmounted: 0,
+    total: 0
   }
   let faults: Faults[] | null = null;
 
@@ -38,7 +46,15 @@ export const getFaultStateFromDatabase = async (): Promise<FaultType | null> =>
       Critical: faults[0].faults.criticals,
       Major: faults[0].faults.majors,
       Minor: faults[0].faults.minors,
-      Warning: faults[0].faults.warnings
+      Warning: faults[0].faults.warnings,
+      Connected: faults[0]["network-element-connections"].Connected,
+      Connecting: faults[0]["network-element-connections"].Connecting,
+      Disconnected: faults[0]["network-element-connections"].Disconnected,
+      Mounted: faults[0]["network-element-connections"].Mounted,
+      UnableToConnect: faults[0]["network-element-connections"].UnableToConnect,
+      Undefined: faults[0]["network-element-connections"].Undefined,
+      Unmounted: faults[0]["network-element-connections"].Unmounted,
+      total: faults[0]["network-element-connections"].total,
     }
   }
 
index 456e05e..b9cd5e4 100644 (file)
@@ -173,13 +173,13 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
           activePanelId === 'CurrentProblem' &&
           <>
             <FaultTable stickyHeader tableId="current-problems-table" idProperty="id" customActionButtons={customActions} columns={[
-              { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+              // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+              { property: "severity", title: "Severity", type: ColumnType.text, width: "140px" },
               { property: "timestamp", type: ColumnType.text, title: "Timestamp" },
               { 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} />
             <RefreshCurrentProblemsDialog
               mode={this.state.refreshCurrentProblemsEditorMode}
@@ -190,13 +190,13 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
         {activePanelId === 'AlarmNotifications' &&
 
           <FaultAlarmNotificationTable stickyHeader tableId="alarm-notifications-table" idProperty="id" defaultSortColumn='timeStamp' defaultSortOrder='desc' rows={this.props.faultNotifications.faults} asynchronus columns={[
-            { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+            // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+            { property: "severity", title: "Severity", width: "140px" },
             { property: "timeStamp", title: "Timestamp" },
             { property: "nodeName", title: "Node Name" },
             { property: "counter", title: "Count", width: "100px", type: ColumnType.numeric },
             { property: "objectId", title: "Object Id" },
             { property: "problem", title: "Alarm Type" },
-            { property: "severity", title: "Severity", width: "140px" },
           ]} />
         }
 
@@ -204,13 +204,13 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
           <>
             <FaultTable stickyHeader idProperty={'id'} tableId="alarm-log-table" customActionButtons={[refreshAlarmLogAction]}
               columns={[
-                { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+                // { property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
+                { property: "severity", title: "Severity", width: "140px" },
                 { property: "timestamp", title: "Timestamp" },
                 { 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} />
             <RefreshAlarmLogDialog
index 2d8b036..e1de4d0 100644 (file)
@@ -37,7 +37,7 @@ const HelpTocComponent: FunctionComponent<Connect<typeof mapProps, typeof mapDis
 
     return (
         <div>
-            <Typography style={{ marginBottom: '30px' }} variant="h5">
+            <Typography aria-label="help" style={{ marginBottom: '30px' }} variant="h5">
                 Help &amp; FAQ
             </Typography>
             <Typography style={{ marginBottom: '30px' }} variant="body1">
index 963a99e..b069c2a 100644 (file)
@@ -143,23 +143,32 @@ module.exports = (env) => {
       },
       proxy: {
         "/oauth2/": {
-          target: "http://10.20.6.29:48181",
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/database/": {
-          target: "http://10.20.6.29:48181",
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/restconf/": {
-          target: "http://10.20.6.29:48181",
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
+          secure: false
+        },
+        "/rests/": {
+          target: "http://sdnr:8181",
           secure: false
         },
         "/help/": {
-          target: "http://10.20.6.29:48181",
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
           secure: false
         },
         "/websocket/": {
-          target: "http://10.20.6.29:48181",
+          //target: "http://10.20.6.29:48181",
+          target: "http://sdnr:8181",
           ws: true,
           changeOrigin: true,
           secure: false
index 79c12d6..e6138cc 100644 (file)
@@ -24,7 +24,7 @@ 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" });
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', false, { status: "Connected" });
 
 export const {
   actionHandler: connectedNetworkElementsActionHandler,
index 604ba86..e0f7cc4 100644 (file)
@@ -31,7 +31,7 @@
 
     <groupId>org.onap.ccsdk.features.sdnr.wt</groupId>
     <artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId>
-    <version>1.3.0-SNAPSHOT</version>
+    <version>1.4.0-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
     <name>ccsdk-features :: ${project.artifactId}</name>
index da0ffa0..55d9b40 100644 (file)
@@ -176,7 +176,7 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo
 
           this.props.isReachable ?
 
-            <MediatorServerConfigurationsTable defaultSortColumn={"Name"} defaultSortOrder="asc" stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
+            <MediatorServerConfigurationsTable defaultSortColumn={"Name"} tableId={null} defaultSortOrder="asc" stickyHeader 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 },
@@ -191,7 +191,7 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo
               { 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={[
+            <MediatorServerUnreachableTable title={this.props.serverName || ''} tableId={null} 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 },
index c44e2cc..456ed6d 100644 (file)
@@ -110,7 +110,7 @@ class MediatorServerSelectionComponent extends React.Component<MediatorServerSel
       }
     };
     return <>
-      <MediatorServersTable stickyHeader title={"Mediator"} customActionButtons={[refreshMediatorAction, addMediatorServerActionButton]} idProperty={"id"}
+      <MediatorServersTable stickyHeader title={"Mediator"} tableId={null} customActionButtons={[refreshMediatorAction, addMediatorServerActionButton]} idProperty={"id"}
         {...this.props.mediatorServersActions} {...this.props.mediatorServersProperties} columns={[
           { property: "name", title: "Name", type: ColumnType.text },
           { property: "url", title: "Url", type: ColumnType.text },
index 3548bf4..8857845 100644 (file)
@@ -26,7 +26,7 @@ export interface IAdaptiveModulationState extends IExternalTableState<AdaptiveMo
 /**
  * Creates elastic search material data fetch handler for Adaptive modulation from historicalperformance database.
  */
-const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, null)
+const adaptiveModulationSearchHandler = createSearchDataHandler<AdaptiveModulationDataType>(getFilter, false, null)
 export const {
     actionHandler: adaptiveModulationActionHandler,
     createActions: createAdaptiveModulationActions,
index 1e6c6d0..5008dd5 100644 (file)
@@ -26,7 +26,7 @@ export interface ICrossPolarDiscriminationState extends IExternalTableState<Cros
 /**
  * Creates elastic search material data fetch handler for CPD from historicalperformance database.
  */
-const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, null)
+const crossPolarDiscriminationSearchHandler = createSearchDataHandler<CrossPolarDiscriminationDataType>(getFilter, false, null)
 
 export const {
     actionHandler: crossPolarDiscriminationActionHandler,
index 1315663..a7b63a3 100644 (file)
@@ -28,7 +28,7 @@ export interface IPerformanceDataState extends IExternalTableState<PerformanceDa
 /**
 * Creates elastic search material data fetch handler for performance data from historicalperformance15min database.
 */
-const performanceDataSearchHandler = createSearchDataHandler<PerformanceDataType>(getFilter, null);
+const performanceDataSearchHandler = createSearchDataHandler<PerformanceDataType>(getFilter, false, null);
 
 export const {
     actionHandler: performanceDataActionHandler,
index 91595cc..34fd3eb 100644 (file)
@@ -26,7 +26,7 @@ export interface IReceiveLevelState extends IExternalTableState<ReceiveLevelData
 /**
  * Creates elastic search material data fetch handler for receiveLevel from historicalperformance database.
  */
-const receiveLevelSearchHandler = createSearchDataHandler<ReceiveLevelDataType>(getFilter, null);
+const receiveLevelSearchHandler = createSearchDataHandler<ReceiveLevelDataType>(getFilter, false, null);
 
 export const {
     actionHandler: receiveLevelActionHandler,
index e0f8040..5fd5c0c 100644 (file)
@@ -26,7 +26,7 @@ export interface ISignalToInterferenceState extends IExternalTableState<SignalTo
 /**
  * Creates elastic search material data fetch handler for SINR from historicalperformance database.
  */
-const signalToInterferenceSearchHandler = createSearchDataHandler<SignalToInterferenceDataType>(getFilter, null);
+const signalToInterferenceSearchHandler = createSearchDataHandler<SignalToInterferenceDataType>(getFilter, false, null);
 
 export const {
     actionHandler: signalToInterferenceActionHandler,
index 0a6c73a..130b818 100644 (file)
@@ -26,7 +26,7 @@ export interface ITemperatureState extends IExternalTableState<TemperatureDataTy
 /**
  * Creates elastic search material data fetch handler for Temperature from historicalperformance database.
  */
-const temperatureSearchHandler = createSearchDataHandler< TemperatureDataType>(getFilter, null);
+const temperatureSearchHandler = createSearchDataHandler< TemperatureDataType>(getFilter, false, null);
 
 export const {
     actionHandler: temperatureActionHandler,
index 32bef81..2a09e58 100644 (file)
@@ -26,7 +26,7 @@ export interface ITransmissionPowerState extends IExternalTableState<Transmissio
 /**
  * Creates elastic search material data fetch handler for Transmission power from historicalperformance database.
  */
-const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, null)
+const transmissionPowerSearchHandler = createSearchDataHandler<TransmissionPowerDataType>(getFilter, false, null)
 
 export const {
     actionHandler: transmissionPowerActionHandler,
index a3f8dd7..c9d8a2d 100644 (file)
@@ -55,7 +55,12 @@ public class ResFilesServlet extends HttpServlet {
             if(f.exists()) {
                 resp.setStatus(HttpURLConnection.HTTP_OK);
                 resp.setContentType("image/gif");
-                Files.copy(f, resp.getOutputStream());
+                try {
+                    Files.copy(f, resp.getOutputStream());
+                } catch (IOException e) {
+                    LOG.warn("Can not copy data", e);
+                    resp.setStatus(500);
+                }
                 return;
             }
         }
@@ -73,16 +78,19 @@ public class ResFilesServlet extends HttpServlet {
                 resp.setContentType(mimeType);
                 resp.setContentLength(length);
                 resp.setStatus(HttpURLConnection.HTTP_OK);
-                OutputStream os = resp.getOutputStream();
-                os.write(byteContent);
-                os.flush();
-                os.close();
+                try (OutputStream os = resp.getOutputStream()) {
+                    os.write(byteContent);
+                    os.flush();
+                } catch (IOException e) {
+                    LOG.warn("Can not write data", e);
+                    resp.setStatus(500);
+                }
             } else {
                 LOG.debug("File {} not found in res.", fn);
                 resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
             }
         } else {
-            LOG.debug("BundleLoaderInstance to found.", fn);
+            LOG.debug("BundleLoaderInstance not found. {}", fn);
             resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
         }
     }
index 48b0d95..6f0285a 100644 (file)
                             <token>##odlux.apps.inventoryApp.buildno##</token>
                             <value>${odlux.apps.inventoryApp.buildno}</value>
                         </replacement>
-                        <replacement>
-                            <token>##odlux.apps.linkCalculationApp.buildno##</token>
-                            <value>${odlux.apps.linkCalculationApp.buildno}</value>
-                        </replacement>
                         <replacement>
                             <token>##odlux.apps.maintenanceApp.buildno##</token>
                             <value>${odlux.apps.maintenanceApp.buildno}</value>
                             <token>##odlux.apps.mediatorApp.buildno##</token>
                             <value>${odlux.apps.mediatorApp.buildno}</value>
                         </replacement>
-                        <replacement>
-                            <token>##odlux.apps.networkMapApp.buildno##</token>
-                            <value>${odlux.apps.networkMapApp.buildno}</value>
-                        </replacement>
                         <replacement>
                             <token>##odlux.apps.permanceHistoryApp.buildno##</token>
                             <value>${odlux.apps.permanceHistoryApp.buildno}</value>
index 20a248d..f1d11de 100644 (file)
 import { Dispatch } from '../flux/store';
 import { Action } from '../flux/action';
 import { AuthPolicy, User } from '../models/authentication';
-import { GeneralSettings } from '../models/settings';
-import { SetGeneralSettingsAction, setGeneralSettingsAction } from './settingsAction';
+import { GeneralSettings, Settings } from '../models/settings';
+import { saveInitialSettings, SetGeneralSettingsAction, setGeneralSettingsAction } from './settingsAction';
 import { endWebsocketSession } from '../services/notificationService';
+import { endUserSession, startUserSession } from '../services/userSessionService';
+import { IApplicationStoreState } from '../store/applicationStore';
 
 export class UpdateUser extends Action {
 
@@ -40,16 +42,30 @@ export class UpdatePolicies extends Action {
 export const loginUserAction = (user?: User) => (dispatcher: Dispatch) =>{
   
   dispatcher(new UpdateUser(user));
-  loadUserSettings(user, dispatcher);
-
-
+  if(user){
+    startUserSession(user);
+    loadUserSettings(user, dispatcher);
+    localStorage.setItem("userToken", user.toString());
+  }
 }
 
-export const logoutUser = () => (dispatcher: Dispatch) =>{
+export const logoutUser = () => (dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{
+
+  const {framework:{applicationState:{ authentication }, authenticationState: {user}}} = getState();
   
   dispatcher(new UpdateUser(undefined));
   dispatcher(new SetGeneralSettingsAction(null));
   endWebsocketSession();
+  endUserSession();
+  localStorage.removeItem("userToken");
+
+
+  //only call if a user is currently logged in
+  if (authentication === "oauth" && user) {
+
+    const url = window.location.origin;
+    window.location.href=`${url}/oauth/logout`;
+  }
 }
 
 const loadUserSettings = (user: User | undefined, dispatcher: Dispatch) =>{
@@ -74,14 +90,8 @@ const loadUserSettings = (user: User | undefined, dispatcher: Dispatch) =>{
       }else{
         return null;
       }
-    }).then((result:GeneralSettings)=>{
-      if(result?.general){
-        //will start websocket session if applicable
-        dispatcher(setGeneralSettingsAction(result.general.areNotificationsEnabled!));
-  
-      }else{
-        dispatcher(setGeneralSettingsAction(false));
-      }
+    }).then((result:Settings)=>{
+        dispatcher(saveInitialSettings(result));
     })
   }  
 }
\ No newline at end of file
index ffcdfc2..1c18ddc 100644 (file)
 
 import { Dispatch } from "../flux/store";
 import { Action } from "../flux/action";
-import { GeneralSettings } from "../models/settings";
+import { GeneralSettings, Settings, TableSettings, TableSettingsColumn } from "../models/settings";
 import { getSettings, putSettings } from "../services/settingsService";
 import { startWebsocketSession, suspendWebsocketSession } from "../services/notificationService";
+import { IApplicationStoreState } from "../store/applicationStore";
 
 
-export class SetGeneralSettingsAction extends Action{
+export class SetGeneralSettingsAction extends Action {
     /**
      *
      */
-    constructor(public areNoticationsActive: boolean|null) {
+    constructor(public areNoticationsActive: boolean | null) {
         super();
-        
     }
 }
 
-export const setGeneralSettingsAction = (value: boolean) => (dispatcher: Dispatch) =>{
+export class SetTableSettings extends Action {
+
+    constructor(public tableName: string, public updatedColumns: TableSettingsColumn[]) {
+        super();
+    }
+}
+
+export class LoadSettingsAction extends Action {
+
+    constructor(public settings: Settings & { isInitialLoadDone: true }) {
+        super();
+    }
+
+}
+
+export class SettingsDoneLoadingAction extends Action {
+
+}
+
+export const setGeneralSettingsAction = (value: boolean) => (dispatcher: Dispatch) => {
 
     dispatcher(new SetGeneralSettingsAction(value));
 
-    if(value){
+    if (value) {
         startWebsocketSession();
-    }else{
+    } else {
         suspendWebsocketSession();
     }
 }
 
 
-export const updateGeneralSettingsAction = (activateNotifications: boolean) => async (dispatcher: Dispatch) =>{
+export const updateGeneralSettingsAction = (activateNotifications: boolean) => async (dispatcher: Dispatch) => {
 
-    const value: GeneralSettings = {general:{areNotificationsEnabled: activateNotifications}};
+    const value: GeneralSettings = { general: { areNotificationsEnabled: activateNotifications } };
     const result = await putSettings("/general", JSON.stringify(value.general));
     dispatcher(setGeneralSettingsAction(activateNotifications));
 
 }
 
+export const updateTableSettings = (tableName: string, columns: TableSettingsColumn[]) => async (dispatcher: Dispatch, getState: () => IApplicationStoreState) => {
+
+
+    //TODO: ask micha how to handle object with variable properties!
+    //fix for now: just safe everything!
+
+     let {framework:{applicationState:{settings:{tables}}}} = getState();
+
+     tables[tableName] = { columns: columns };
+     const json=JSON.stringify(tables);
+
+    // would only save latest entry
+    //const json = JSON.stringify({ [tableName]: { columns: columns } });
+
+    const result = await putSettings("/tables", json);
+
+    dispatcher(new SetTableSettings(tableName, columns));
+}
+
 export const getGeneralSettingsAction = () => async (dispatcher: Dispatch) => {
 
     const result = await getSettings<GeneralSettings>();
 
-    if(result && result.general){
+    if (result && result.general) {
         dispatcher(new SetGeneralSettingsAction(result.general.areNotificationsEnabled!))
     }
+}
+
+export const saveInitialSettings = (settings: any) => async (dispatcher: Dispatch) => {
+
+    const defaultSettings = {general:{ areNotificationsEnabled: false }, tables:{}};
+
+    const initialSettings = {...defaultSettings, ...settings};
+
+    if (initialSettings) {
+        if (initialSettings.general) {
+            const settingsActive = initialSettings.general.areNotificationsEnabled;
+
+            if (settingsActive) {
+                startWebsocketSession();
+            } else {
+                suspendWebsocketSession();
+            }
+        }
+
+        dispatcher(new LoadSettingsAction(initialSettings));
+    }
+    else {
+        dispatcher(new SettingsDoneLoadingAction());
+
+    }
+
+
+
 
 }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/framework/src/assets/images/home.svg b/sdnr/wt/odlux/framework/src/assets/images/home.svg
new file mode 100644 (file)
index 0000000..080d050
--- /dev/null
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="460.298px" height="460.297px" viewBox="0 0 460.298 460.297" style="enable-background:new 0 0 460.298 460.297;"
+        xml:space="preserve">
+<g>
+       <g>
+               <path fill="#565656" d="M230.149,120.939L65.986,256.274c0,0.191-0.048,0.472-0.144,0.855c-0.094,0.38-0.144,0.656-0.144,0.852v137.041
+                       c0,4.948,1.809,9.236,5.426,12.847c3.616,3.613,7.898,5.431,12.847,5.431h109.63V303.664h73.097v109.64h109.629
+                       c4.948,0,9.236-1.814,12.847-5.435c3.617-3.607,5.432-7.898,5.432-12.847V257.981c0-0.76-0.104-1.334-0.288-1.707L230.149,120.939
+                       z"/>
+               <path fill="#565656" d="M457.122,225.438L394.6,173.476V56.989c0-2.663-0.856-4.853-2.574-6.567c-1.704-1.712-3.894-2.568-6.563-2.568h-54.816
+                       c-2.666,0-4.855,0.856-6.57,2.568c-1.711,1.714-2.566,3.905-2.566,6.567v55.673l-69.662-58.245
+                       c-6.084-4.949-13.318-7.423-21.694-7.423c-8.375,0-15.608,2.474-21.698,7.423L3.172,225.438c-1.903,1.52-2.946,3.566-3.14,6.136
+                       c-0.193,2.568,0.472,4.811,1.997,6.713l17.701,21.128c1.525,1.712,3.521,2.759,5.996,3.142c2.285,0.192,4.57-0.476,6.855-1.998
+                       L230.149,95.817l197.57,164.741c1.526,1.328,3.521,1.991,5.996,1.991h0.858c2.471-0.376,4.463-1.43,5.996-3.138l17.703-21.125
+                       c1.522-1.906,2.189-4.145,1.991-6.716C460.068,229.007,459.021,226.961,457.122,225.438z"/>
+
+<path fill="#D81036" d="M 457.122 225.438 L 251.849 54.417 L 251.849 54.417 C 245.765 49.468 238.531 46.994 230.155 46.994 C 221.78 46.994 214.547 49.468 208.457 54.417 L 3.172 225.438 C 1.269 226.958 0.226 229.004 0.032 231.574 C -0.161 234.142 0.504 236.385 2.029 238.287 L 19.73 259.415 C 21.255 261.127 23.251 262.174 25.726 262.557 C 28.011 262.749 30.296 262.081 32.581 260.559 L 230.149 95.817 L 427.719 260.558 C 429.245 261.886 431.24 262.549 433.715 262.549 H 434.573 C 437.044 262.173 439.036 261.119 440.569 259.411 L 458.272 238.286 C 459.794 236.38 460.461 234.141 460.263 231.57 C 460.068 229.007 459.021 226.961 457.122 225.438 Z"/>
+       </g>
+</g>
+</svg>
@@ -2,7 +2,7 @@
  * ============LICENSE_START========================================================================
  * ONAP : ccsdk feature sdnr wt odlux
  * =================================================================================================
- * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * 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
  * ============LICENSE_END==========================================================================
  */
 
-import { Action } from "../../../../framework/src/flux/action";
-
-export class SetPartialUpdatesAction extends Action {
-    constructor(public isActive: boolean) {
-        super();
-    }
-}
\ No newline at end of file
+ declare const home: string;
+ export default home;
\ No newline at end of file
index ce5b2cd..3ed3134 100644 (file)
@@ -37,6 +37,7 @@ export type ColumnModel<TData> = {
   disablePadding?: boolean;
   width?: string | number ;
   className?: string;
+  hide?: boolean;
   style?: React.CSSProperties;
   align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
   disableSorting?: boolean;
index aac2a12..8541cfe 100644 (file)
@@ -36,7 +36,7 @@ import { EnhancedTableHead } from './tableHead';
 import { EnhancedTableFilter } from './tableFilter';
 
 import { ColumnModel, ColumnType } from './columnModel';
-import { Menu } from '@mui/material';
+import { Menu, Typography } from '@mui/material';
 import { DistributiveOmit } from '@mui/types';
 
 import makeStyles from '@mui/styles/makeStyles';
@@ -151,19 +151,23 @@ export type MaterialTableComponentState<TData = {}> = {
   rowsPerPage: number;
   loading: boolean;
   showFilter: boolean;
+  hiddenColumns: string[];
   filter: { [property: string]: string };
 };
 
 export type TableApi = { forceRefresh?: () => Promise<void> };
 
-type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
+type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles>  & {
   className?: string;
   columns: ColumnModel<TData>[];
   idProperty: keyof TData | ((data: TData) => React.Key);
-  tableId?: string;
+  
+  //Note: used to save settings as well. Must be unique across apps. Null tableIds will not get saved to the settings
+  tableId: string | null;
   isPopup?: boolean;
   title?: string;
   stickyHeader?: boolean;
+  allowHtmlHeader?: boolean;
   defaultSortOrder?: 'asc' | 'desc';
   defaultSortColumn?: keyof TData;
   enableSelection?: boolean;
@@ -182,6 +186,8 @@ type MaterialTableComponentPropsWithExternalState<TData = {}> = MaterialTableCom
   onHandleChangePage: (page: number) => void;
   onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
   onHandleRequestSort: (property: string) => void;
+  onHideColumns : (columnNames: string[]) => void
+  onShowColumns:  (columnNames: string[]) => void
 };
 
 type MaterialTableComponentProps<TData = {}> =
@@ -203,13 +209,18 @@ function isMaterialTableComponentPropsWithRowsAndRequestData(props: MaterialTabl
     propsWithExternalState.onHandleChangePage instanceof Function ||
     propsWithExternalState.onHandleChangeRowsPerPage instanceof Function ||
     propsWithExternalState.onToggleFilter instanceof Function ||
+    propsWithExternalState.onHideColumns instanceof Function ||
     propsWithExternalState.onHandleRequestSort instanceof Function
 }
 
+// get settings in here!
+
+
 class MaterialTableComponent<TData extends {} = {}> extends React.Component<MaterialTableComponentProps, MaterialTableComponentState & { contextMenuInfo: { index: number; mouseX?: number; mouseY?: number }; }> {
 
   constructor(props: MaterialTableComponentProps) {
     super(props);
+    
 
     const page = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.page : 0;
     const rowsPerPage = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.rowsPerPage || 10 : 10;
@@ -224,6 +235,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
       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,
+      hiddenColumns: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) && this.props.hiddenColumns || [],
       page,
       rowsPerPage,
     };
@@ -237,18 +249,27 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
     }
   }
   render(): JSX.Element {
-    const { classes, columns } = this.props;
+    const { classes, columns, allowHtmlHeader } = 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) }
+
+    const hideColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onHideColumns : (data: string[]) => { const newArray = [...new Set([...this.state.hiddenColumns, ...data])]; this.setState({hiddenColumns:newArray}); }
+    const showColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onShowColumns : (data: string[]) => { const newArray = this.state.hiddenColumns.filter(el=> !data.includes(el));   this.setState({hiddenColumns:newArray}); }
+
+    const allColumnsHidden = this.props.columns.length === this.state.hiddenColumns.length;
     return (
       <Paper className={this.props.className ? `${classes.root} ${this.props.className}` : classes.root}>
         <TableContainer className={classes.container}>
           <TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv}
-            onToggleFilter={toggleFilter} />
+            onToggleFilter={toggleFilter}
+            columns={columns}
+            onHideColumns={hideColumns}
+            onShowColumns={showColumns} />
           <Table padding="normal" aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'} stickyHeader={this.props.stickyHeader || false} >
             <EnhancedTableHead
+              allowHtmlHeader={allowHtmlHeader || false}
               columns={columns}
               numSelected={selected && selected.length}
               order={order}
@@ -257,10 +278,14 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
               onRequestSort={this.onHandleRequestSort}
               rowCount={rows.length}
               enableSelection={this.props.enableSelection}
+              hiddenColumns={this.state.hiddenColumns}
             />
             <TableBody>
-              {showFilter && <EnhancedTableFilter columns={columns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
-              {rows // may need ordering here
+              {showFilter && <EnhancedTableFilter columns={columns} hiddenColumns={this.state.hiddenColumns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
+              
+              {allColumnsHidden ? <Typography variant="body1" textAlign="center">All columns of this table are hidden.</Typography> :
+              
+              rows // may need ordering here
                 .map((entry: TData & { [RowDisabled]?: boolean, [kex: string]: any }, index) => {
                   const entryId = getId(entry);
                   const contextMenu = (this.props.createContextMenu && this.state.contextMenuInfo.index === index && this.props.createContextMenu(entry)) || null;
@@ -295,15 +320,17 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
                     >
                       {this.props.enableSelection
                         ? <TableCell padding="checkbox" style={{ width: "50px", color:  entry[RowDisabled] || false ? "inherit" : undefined } }>
-                          <Checkbox checked={isSelected} />
+                          <Checkbox color='secondary' checked={isSelected} />
                         </TableCell>
                         : null
                       }
                       {
+                        
                         this.props.columns.map(
                           col => {
                             const style = col.width ? { width: col.width } : {};
-                            return (
+                            const tableCell = (
+
                               <TableCell style={ entry[RowDisabled] || false ? { ...style, color: "inherit"  } : style } aria-label={col.title? toAriaLabel(col.title) : toAriaLabel(col.property)} key={col.property} align={col.type === ColumnType.numeric && !col.align ? "right" : col.align} >
                                 {col.type === ColumnType.custom && col.customControl
                                   ? <col.customControl className={col.className} style={col.style} rowData={entry} />
@@ -313,6 +340,10 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
                                 }
                               </TableCell>
                             );
+                            
+                            //show column if...
+                            const showColumn = !this.state.hiddenColumns.includes(col.property);
+                            return showColumn && tableCell
                           }
                         )
                       }
@@ -352,6 +383,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
   }
 
   static getDerivedStateFromProps(props: MaterialTableComponentProps, state: MaterialTableComponentState & { _rawRows: {}[] }): MaterialTableComponentState & { _rawRows: {}[] } {
+   
     if (isMaterialTableComponentPropsWithRowsAndRequestData(props)) {
       return {
         ...state,
@@ -363,6 +395,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
         loading: props.loading,
         showFilter: props.showFilter,
         page: props.page,
+        hiddenColumns: props.hiddenColumns,
         rowsPerPage: props.rowsPerPage
       }
     } else if (isMaterialTableComponentPropsWithRows(props) && props.asynchronus && state._rawRows !== props.rows) {
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx b/sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx
new file mode 100644 (file)
index 0000000..f8ae6ea
--- /dev/null
@@ -0,0 +1,188 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2022 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 { Button, Checkbox, FormControlLabel, MenuItem, Popover, Switch, Typography } from '@mui/material';
+import connect, { Connect, IDispatcher } from '../../flux/connect';
+import * as React from 'react';
+
+import { ColumnModel } from './columnModel';
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { TableSettingsColumn } from '../../models/settings';
+import { updateTableSettings } from '../../actions/settingsAction';
+
+const mapStateToProps = (state: IApplicationStoreState) => ({
+    settings: state.framework.applicationState.settings,
+    settingsDoneLoading: state.framework.applicationState.settings.isInitialLoadDone
+});
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+    saveToSettings: (tableName: string, columns: TableSettingsColumn[]) => dispatcher.dispatch(updateTableSettings(tableName, columns))
+})
+
+type DialogProps = {
+    columns: ColumnModel<{}>[],
+    settingsName: string | null,
+    anchorEl: HTMLElement | null;
+    hideColumns: (columnNames: string[]) => void
+    showColumns: (columnNames: string[]) => void
+    onClose(): void
+
+} & Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
+        //TODO: figure out why everything gets triggered twice...
+
+const ShowColumnsDialog: React.FunctionComponent<DialogProps> = (props) => {
+
+    const savedSettings = props.settingsName && props.settings.tables[props.settingsName];
+
+    const [checkedColumns, setCheckedColumns] = React.useState<{ property: string, display: boolean, title: string | undefined }[]>([]);
+
+    const open = Boolean(props.anchorEl);
+    const allColumnNames = props.columns.map(e => e.property);
+
+    React.useEffect(() => {
+
+        createHideShowSelection();
+
+    }, []);
+
+    React.useEffect(() => {
+
+        createHideShowSelection();
+
+    }, [props.settings.isInitialLoadDone]);
+
+
+    const createHideShowSelection = () => {
+        let columns = props.columns.map(e => { return { property: e.property, display: !Boolean(e.hide), title: e.title } });
+
+
+        if (savedSettings) {
+
+            if (columns.length !== savedSettings.columns.length) {
+                console.error("saved column length does not match current column length. Maybe a settings entry got wrongly overridden?")
+            }
+
+            //overwrite column data with settings
+            savedSettings?.columns.forEach(el => {
+                let foundIndex = columns.findIndex(e => e.property == el.property);
+                if (columns[foundIndex] !== undefined)
+                    columns[foundIndex].display = el.displayed;
+            });
+
+        } else {
+            console.warn("No settingsName set, changes will not be saved.")
+        }
+
+        setCheckedColumns(columns);
+
+        const hideColumns = columns.filter(el => !el.display).map(e => e.property);
+        props.hideColumns(hideColumns);
+    }
+
+
+    const handleChange = (propertyName: string, checked: boolean) => {
+        if (!checked) {
+            props.hideColumns([propertyName]);
+        } else {
+            props.showColumns([propertyName])
+
+        }
+     
+        let updatedList = checkedColumns.map(item => {
+            if (item.property == propertyName) {
+                return { ...item, display: checked }; 
+            }
+            return item; 
+        });
+
+        setCheckedColumns(updatedList);
+    };
+
+    const onHideAll = () => {
+
+        switchCheckedColumns(false);
+        props.hideColumns(allColumnNames);
+    }
+
+    const onShowAll = () => {
+
+        switchCheckedColumns(true);
+        props.showColumns(allColumnNames);
+    }
+
+    const onClose = () => {
+
+        const tableColumns: TableSettingsColumn[] = checkedColumns.map(el => {
+            return {
+                property: el.property,
+                displayed: el.display
+            }
+        });
+
+        if (props.settingsName) {
+            props.saveToSettings(props.settingsName, tableColumns);
+        }
+        props.onClose();
+
+    }
+
+    const switchCheckedColumns = (changeToValue: boolean) => {
+        let updatedList = checkedColumns.map(item => {
+            return { ...item, display: changeToValue };
+        });
+
+        setCheckedColumns(updatedList);
+
+    }
+
+    return (<Popover open={open} onClose={onClose}
+        anchorEl={props.anchorEl}
+        anchorOrigin={{
+            vertical: 'top',
+            horizontal: 'left',
+        }} >
+        <div>
+            <Typography fontWeight={600} style={{ margin: 10 }} >Hide / Show Columns</Typography>
+        </div>
+        <div style={{ display: "flex", flexDirection: "column", margin: 10 }}>
+            {
+                checkedColumns?.map((el, i) => {
+
+                    return <>
+
+                        <FormControlLabel
+                            value="end"
+                            key={"hide-show-column-"+i}
+                            aria-label={"hide-or-show-column-button"}
+                            control={<Switch color="secondary" checked={el.display} onChange={e => handleChange(el.property, e.target.checked)} />}
+                            label={el.title || el.property}
+                            labelPlacement="end"
+                        />
+                    </>
+                })
+            }
+            <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between" }}>
+                <Button color="secondary" aria-label="hide-all-columns-button" onClick={(e) => onHideAll()}>Hide all</Button>
+                <Button color="secondary" aria-label="show-all-columns-button" onClick={(e) => onShowAll()}>Show all</Button>
+            </div>
+        </div>
+    </Popover>)
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ShowColumnsDialog);
index a46dd18..1b91368 100644 (file)
@@ -50,6 +50,7 @@ interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
   onFilterChanged: (property: string, filterTerm: string) => void;
   filter: { [property: string]: string };
   columns: ColumnModel<{}>[];
+  hiddenColumns: string[];
   enableSelection?: boolean;
 }
 
@@ -73,7 +74,7 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
         }
         {columns.map((col, ind) => {
           const style = col.width ? { width: col.width } : {};
-          return (
+          const tableCell = (
             <TableCell
               className={col.type === ColumnType.numeric ? classes.numberInput : ''}
               key={col.property}
@@ -99,6 +100,10 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
                     onChange={this.createInputFilterHandler(col.property)} />}
             </TableCell>
           );
+
+          const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+          return showColumn && tableCell;
         }, this)}
       </TableRow>
     );
index c500f44..d6f7b7d 100644 (file)
@@ -50,7 +50,9 @@ interface IEnhancedTableHeadComponentProps extends styles_header {
   orderBy: string | null;
   rowCount: number;
   columns: ColumnModel<{}>[];
+  hiddenColumns: string[];
   enableSelection?: boolean;
+  allowHtmlHeader?: boolean;
 }
 
 class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadComponentProps> {
@@ -77,7 +79,7 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo
           }
           { columns.map(col => {
             const style = col.width ? { width: col.width } : {};
-            return (
+            const tableCell = (
               <TableCell className= {classes.header}
                 key={ col.property }
                 align={ col.type === ColumnType.numeric ? 'right' : 'left' } 
@@ -102,11 +104,19 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo
                       direction={ order || undefined }
                       onClick={ this.createSortHandler(col.property) }
                     >
-                      { col.title || col.property }
+                      {
+                        this.props.allowHtmlHeader ? <div className="content" dangerouslySetInnerHTML={{__html: col.title || col.property}}></div>
+                       :  (col.title || col.property )
+                      }
                     </TableSortLabel>
                   </Tooltip> }
               </TableCell>
             );
+
+            //show column if...
+            const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+            return showColumn && tableCell;
           }, this) }
         </TableRow>
       </TableHead>
index 426436d..143b802 100644 (file)
@@ -33,6 +33,8 @@ import MenuItem from '@mui/material/MenuItem';
 import Menu from '@mui/material/Menu';
 import { SvgIconProps } from '@mui/material/SvgIcon';
 import { Button } from '@mui/material';
+import { ColumnModel } from './columnModel';
+import  ShowColumnsDialog  from './showColumnDialog'
 
 const styles = (theme: Theme) => createStyles({
   root: {
@@ -69,18 +71,24 @@ const styles = (theme: Theme) => createStyles({
 interface ITableToolbarComponentProps extends WithStyles<typeof styles> {
   numSelected: number | null;
   title?: string;
-  tableId?: string;
+  tableId: string | null;
   customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, ariaLabel: string, onClick: () => void, disabled?: boolean }[];
+  columns: ColumnModel<{}>[];
+  onHideColumns: (columnNames: string[]) => void
+  onShowColumns: (columnNames: string[]) => void
   onToggleFilter: () => void;
   onExportToCsv: () => void;
 }
 
-class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null }> {
+class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null, anchorElDialog: HTMLElement | null }> {
+
+  
   constructor(props: ITableToolbarComponentProps) {
     super(props);
 
     this.state = {
-      anchorEl: null
+      anchorEl: null,
+      anchorElDialog: null
     };
   }
 
@@ -91,11 +99,22 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps,
   private handleClose = () => {
     this.setState({ anchorEl: null });
   };
+
+  private showColumnsDialog = (event: React.MouseEvent<HTMLElement>) =>{
+    this.setState({ anchorElDialog: this.state.anchorEl });
+  }
+
+  private onCloseDialog = () =>{
+    this.setState({ anchorElDialog: null });
+
+  }
+
   render() {
     const { numSelected, classes } = this.props;
     const open = !!this.state.anchorEl;
-    const buttonPrefix = this.props.tableId !== undefined ? this.props.tableId : 'table';
+    const buttonPrefix = this.props.tableId !== null ? this.props.tableId : 'table';
     return (
+      <>
       <Toolbar className={`${classes.root} ${numSelected && numSelected > 0 ? classes.highlight : ''} `} >
         <div className={classes.title}>
           {numSelected && numSelected > 0 ? (
@@ -153,9 +172,18 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps,
           <Menu id="menu-appbar" anchorEl={this.state.anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
             transformOrigin={{ vertical: 'top', horizontal: 'right' }} open={open} onClose={this.handleClose} >
             <MenuItem aria-label="export-table-as-csv" onClick={(e) =>{ this.props.onExportToCsv(); this.handleClose()}}>Export as CSV</MenuItem>
+            <MenuItem aria-label="hide-show-table-columns" onClick={(e) =>{ this.showColumnsDialog(e); this.handleClose()}}>Hide/show columns</MenuItem>
           </Menu>
         </div>
       </Toolbar>
+      <ShowColumnsDialog 
+        anchorEl={this.state.anchorElDialog} 
+        onClose={this.onCloseDialog}
+        settingsName={this.props.tableId} 
+        columns={this.props.columns} 
+        hideColumns={this.props.onHideColumns} 
+        showColumns={this.props.onShowColumns} />
+      </>
     );
   }
 }
index 544e14e..f901549 100644 (file)
@@ -28,6 +28,7 @@ export interface IExternalTableState<TData> {
   order: 'asc' | 'desc';
   orderBy: string | null;
   selected: any[] | null;
+  hiddenColumns: string[]
   rows: (TData & { [RowDisabled]?: boolean })[];
   total: number;
   page: number;
@@ -48,7 +49,9 @@ export type ExternalMethodes<TData> = {
     onFilterChanged: (property: string, filterTerm: string) => void;
     onHandleChangePage: (page: number) => void;
     onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
- };
+    onHideColumns: (columnName: string[]) => void;
+    onShowColumns: (columnName: string[]) => void;
+  },
  createPreActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
   onPreFilterChanged: (preFilter: {
       [key: string]: string;
@@ -128,6 +131,18 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
     }
   }
 
+  class HideColumnsAction extends TableAction{
+    constructor(public property: string[]){
+      super();
+    }
+  }
+
+  class ShowColumnsAction extends TableAction{
+    constructor(public property: string[]){
+      super();
+    }
+  }
+
   // #endregion
 
   //#region Action Handler
@@ -135,6 +150,7 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
     order: 'asc',
     orderBy: null,
     selected: null,
+    hiddenColumns:[],
     rows: [],
     total: 0,
     page: 0,
@@ -208,6 +224,18 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
         rowsPerPage: action.rowsPerPage
       }
     }
+    else if (action instanceof HideColumnsAction){
+      
+      //merge arrays, remove duplicates
+      const newArray = [...new Set([...state.hiddenColumns, ...action.property])]
+      state = {...state, hiddenColumns: newArray};
+    }
+    else if(action instanceof ShowColumnsAction){
+
+      const newArray = state.hiddenColumns.filter(el=> !action.property.includes(el));
+      state = {...state, hiddenColumns: newArray};
+    }
+
     return state;
   }
 
@@ -290,6 +318,16 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
           dispatch(new SetRowsPerPageAction(rowsPerPage || 10));
           (!skipRefresh) && dispatch(reloadAction);
         });
+      },
+      onHideColumns: (columnName: string[]) =>{
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new HideColumnsAction(columnName));
+        })
+      },
+      onShowColumns: (columnName: string[]) =>{
+        dispatch((dispatch: Dispatch) => {
+          dispatch(new ShowColumnsAction(columnName));
+        })
       }
       // selected:
     };
index 1134e23..195706d 100644 (file)
@@ -64,9 +64,9 @@ const styles = (theme: Theme) => createStyles({
       duration: theme.transitions.duration.leavingScreen,
     }),
     overflowX: 'hidden',
-    width: theme.spacing(7) + 1,
+    width: theme.spacing(7),
     [theme.breakpoints.up('sm')]: {
-      width: theme.spacing(9) + 1,
+      width: theme.spacing(9),
     },
   },
   drawer: {
@@ -101,7 +101,7 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
   //collapse menu on mount if necessary
   React.useEffect(()=>{
 
-    if(isOpen && window.innerWidth < tabletWidthBreakpoint){
+    if(isOpen && window.innerWidth <= tabletWidthBreakpoint){
 
       setResponsive(true);
       dispatch(new MenuAction(false));
@@ -116,14 +116,12 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
         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));
           }
 
@@ -145,13 +143,14 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
 
   let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
     const reg = state.framework.applicationRegistraion[key];
+    const icon = !reg.icon ? null :( typeof reg.icon === 'string' ? <img height={22} src={reg.icon} /> : <FontAwesomeIcon icon={reg.icon} /> )
     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} />
+        icon={icon} />
     ) || null;
   }) || null;
 
index 7872e51..19d3bdf 100644 (file)
@@ -131,6 +131,10 @@ class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLE
       }
     }
 
+    const stateIcon = state.framework.applicationState.icon;
+    const icon = !stateIcon ? null :( typeof stateIcon === 'string' ? <img className={classes.icon} height={22} src={stateIcon} /> : <FontAwesomeIcon className={classes.icon} icon={stateIcon} /> )
+    
+
     return (
       <AppBar enableColorOnDark position="absolute" className={classes.appBar}>
         <Toolbar>
@@ -144,9 +148,7 @@ class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLE
           </IconButton>
           <Logo />
           <Typography variant="h6" color="inherit" >
-            {state.framework.applicationState.icon
-              ? (<FontAwesomeIcon className={classes.icon} icon={state.framework.applicationState.icon} />)
-              : null}
+            {icon}
             {state.framework.applicationState.title}
           </Typography>
           <div className={classes.grow}></div>
index 16c6ed5..d0a0724 100644 (file)
@@ -31,8 +31,8 @@ import { ExternalLoginProvider } from '../models/externalLoginProvider';
 import { ApplicationConfig } from '../models/applicationConfig';
 import { IConnectAppStoreState } from '../../../apps/connectApp/src/handlers/connectAppRootHandler';
 import { IFaultAppStoreState } from '../../../apps/faultApp/src/handlers/faultAppRootHandler';
-import { GeneralSettings } from '../models/settings';
-import { SetGeneralSettingsAction } from '../actions/settingsAction';
+import { GeneralSettings, Settings } from '../models/settings';
+import { LoadSettingsAction, SetGeneralSettingsAction, SetTableSettings, SettingsDoneLoadingAction } from '../actions/settingsAction';
 import { startWebsocketSession, suspendWebsocketSession } from '../services/notificationService';
 
 
@@ -55,7 +55,7 @@ export interface IApplicationState {
   authentication: "basic"|"oauth",  // basic 
   enablePolicy: boolean,             // false 
   transportpceUrl : string,
-  settings: GeneralSettings
+  settings: Settings & { isInitialLoadDone: boolean }
 }
 
 const applicationStateInit: IApplicationState = {
@@ -69,7 +69,11 @@ const applicationStateInit: IApplicationState = {
   authentication: "basic",
   enablePolicy: false,
   transportpceUrl: "",
-  settings:{ general: { areNotificationsEnabled: null }}
+  settings:{ 
+    general: { areNotificationsEnabled: null },
+    tables: {},
+    isInitialLoadDone: false
+  }
 };
 
 export const configureApplication = (config: ApplicationConfig) => {
@@ -150,8 +154,23 @@ export const applicationStateHandler: IActionHandler<IApplicationState> = (state
 
     state = {
       ...state,
-      settings:{general:{areNotificationsEnabled: action.areNoticationsActive}}
+      settings:{tables: state.settings.tables, isInitialLoadDone:state.settings.isInitialLoadDone, general:{areNotificationsEnabled: action.areNoticationsActive}}
     }
   }
+  else if(action instanceof SetTableSettings){
+
+    let tableUpdate = state.settings.tables;
+    tableUpdate[action.tableName] = {columns: action.updatedColumns};
+
+    state = {...state, settings:{general: state.settings.general, isInitialLoadDone:state.settings.isInitialLoadDone, tables: tableUpdate}}
+    
+  }else if(action instanceof LoadSettingsAction){
+    
+    state = {...state, settings:action.settings}
+  }
+  else if(action instanceof SettingsDoneLoadingAction){
+    state= {...state, settings: {...state.settings, isInitialLoadDone: true}}
+  }
+
   return state;
 };
index 1bcb435..f98d774 100644 (file)
@@ -39,12 +39,8 @@ export const authenticationStateHandler: IActionHandler<IAuthenticationState> =
     const {user} = action;
     
     if (user) {
-      localStorage.setItem("userToken", user.toString());
-      startUserSession(user);
       onLogin();
     } else {
-      localStorage.removeItem("userToken");
-      endUserSession();
       onLogout();
     }
 
index 4dc353c..69c5f06 100644 (file)
@@ -26,7 +26,7 @@
       faultApp.register();
       // inventoryApp.register();
       // helpApp.register();
-      app("./app.tsx").configureApplication({ authentication:"oauth",  enablePolicy:  false, transportpceUrl:"http://test.de"});
+      app("./app.tsx").configureApplication({ authentication:"basic",  enablePolicy:  false, transportpceUrl:"http://test.de"});
       app("./app.tsx").runApplication();
     });
   </script>
index 5cd2805..7196b5c 100644 (file)
@@ -16,7 +16,7 @@
 <script>
     // run the application
     require(["run"], function (run) {
-      run.configureApplication({ authentication:"oauth",  enablePolicy:  true,});
+      run.configureApplication({ authentication:"basic",  enablePolicy:  false,});
       run.runApplication();
     });
 
index 41d29fb..fc43836 100644 (file)
@@ -31,6 +31,17 @@ export type SingeResult<TSource extends {}> = {
 }
 
 
+export type ResultTopology<TSource extends {}> = {
+  "output": {
+    pagination?: {
+      size: number;
+      page: number;
+      total: number;
+    },
+    data: TSource[];
+  }
+}
+
 export type HitEntry<TSource extends {}> = {
   _index: string;
   _type: string;
index e93d20e..ff50aa7 100644 (file)
@@ -18,4 +18,4 @@
 
 import { IconDefinition } from '@fortawesome/free-solid-svg-icons';
 
-export type IconType = IconDefinition;
\ No newline at end of file
+export type IconType = IconDefinition | string;
\ No newline at end of file
index 6d01a34..11ba2f9 100644 (file)
  * ============LICENSE_END==========================================================================
  */
 
+export type TableSettingsColumn = {
+    property: string,
+    displayed: boolean
+}
+
+export type TableSettings = {
+    tables:{
+        [key: string]: {
+            columns: TableSettingsColumn[]
+            
+            //match prop names, hide them
+            //via property name! -> only those which are hidden!
+            //all others default false, oh yeah
+            //or maybe the other way around, gotta think about that
+    
+        }
+    }
+    
+
+    
+}
+
 export type GeneralSettings = {
     general:{
         areNotificationsEnabled: boolean | null
     }
 };
 
+export type Settings= TableSettings & GeneralSettings;
+
 export type SettingsComponentProps = {
     onClose(): void
 };
\ No newline at end of file
index a7691bf..39f407e 100644 (file)
@@ -18,7 +18,7 @@
 import { AuthPolicy, AuthToken } from "../models/authentication";
 import { ExternalLoginProvider } from "../models/externalLoginProvider";
 
-import { requestRest, formEncode } from "./restService";
+import { requestRest, formEncode, requestRestExt } from "./restService";
 
 type AuthTokenResponse = {
   access_token: string;
@@ -85,6 +85,12 @@ class AuthenticationService {
   public async getAccessPolicies(){
     return await requestRest<AuthPolicy[]>(`oauth/policies`, { method: "GET" }, true);
   }
+
+  public async getServerReadyState(){
+
+    const result = await fetch("/ready", {method: "GET"});
+    return result.status == (200 || 304) ? true : false;
+  }
 }
 
 export const authenticationService = new AuthenticationService();
index 85ae3e6..f2c3ebc 100644 (file)
@@ -33,7 +33,7 @@ export type SettingsMessage={key: SettingsType, enableNotifications: boolean, us
 let channels: Broadcaster[] = [];
 let store : ApplicationStore | null = null;
 
-export const subscribe = (channel: BroadcastChannel, channelName: string) => {
+export const saveChannel = (channel: BroadcastChannel, channelName: string) => {
     channels.push({channel: channel, key: channelName});
 }
 
diff --git a/sdnr/wt/odlux/framework/src/services/forceLogoutService.ts b/sdnr/wt/odlux/framework/src/services/forceLogoutService.ts
deleted file mode 100644 (file)
index a577390..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * ============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 { UpdateUser } 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;
-    if (process.env.NODE_ENV === "development") {
-        console.warn("logout timer not started in development mode");
-    } else {
-        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 UpdateUser(undefined));
-                    applicationStore.dispatch(new ReplaceAction("/login"));
-                }
-            }
-        }
-
-    }, 1 * 60000)
-}
-
-document.addEventListener("mousemove", function () { tickTimer = maxMinutesTillLogout; }, false)
\ No newline at end of file
index b21e3ec..d727e4c 100644 (file)
@@ -19,6 +19,7 @@
 
 import { ApplicationStore } from "../store/applicationStore";
 import { ReplaceAction } from "../actions/navigationActions";
+import { AddErrorInfoAction } from "../actions/errorActions";
 
 const baseUri = `${ window.location.origin }`;
 const absUrlPattern = /^https?:\/\//;
@@ -118,12 +119,22 @@ export async function requestRestExt<TData>(path: string = '', init: RequestInit
       //'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}`));
+
+  if(fetchResult.status === 403){
+    applicationStore && applicationStore.dispatch(new AddErrorInfoAction({title: "Forbidden", message:"Status: [403], access denied."}));
     return {
       ...result,
       status: 403,
+      message: "Forbidden."
+    };
+  }
+  else if (fetchResult.status === 401) {
+    applicationStore && applicationStore.dispatch(new ReplaceAction(`/login?returnTo=${applicationStore.state.framework.navigationState.pathname}`));
+    return {
+      ...result,
+      status: 401,
       message: "Authentication requested by server."
     };
   }
index 0d5936a..8d899c4 100644 (file)
@@ -24,7 +24,7 @@ import { User } from "../models/authentication";
 
 let currentUser: User | null;
 let applicationStore: ApplicationStore | null = null;
-let timer : NodeJS.Timeout | null = null;
+let timer : null | ReturnType<typeof setTimeout> = null;
 
 export const startUserSessionService = (store: ApplicationStore) =>{
     applicationStore=store;
index 6f4c71e..e1d3752 100644 (file)
@@ -16,7 +16,7 @@
  * ============LICENSE_END==========================================================================
  */
 
-import { Result } from '../models';
+import { Result, ResultTopology } from '../models';
 import { DataCallback } from '../components/material-table';
 
 import { requestRest } from '../services/restService';
@@ -31,43 +31,79 @@ type dataType = { [prop: string]: propType };
  *  @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)> {
+export function createSearchDataHandler<TResult>(typeName: (() => string) | string, connectToTopologyServer?: boolean, additionalFilters?: {} | null | undefined): DataCallback<(TResult)> {
   const fetchData: DataCallback<(TResult)> = async (pageIndex, rowsPerPage, orderBy, order, filter) => {
-    const url = `/rests/operations/data-provider:read-${typeof typeName === "function" ? typeName(): typeName}-list`;
+
+    const topologyUrl = `/topology/network/read-${typeof typeName === "function" ? typeName() : typeName}-list`;
+    const dataProviderUrl = `/rests/operations/data-provider:read-${typeof typeName === "function" ? typeName() : typeName}-list`;
+
+    const url = connectToTopologyServer ? topologyUrl : dataProviderUrl;
 
     filter = { ...filter, ...additionalFilters };
 
     const filterKeys = filter && Object.keys(filter) || [];
 
-    const query = {
-      "data-provider: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["data-provider:output"] && result["data-provider:output"].data) {
-        rows = result["data-provider:output"].data.map(obj => convertPropertyNames(obj, replaceHyphen)) || []
+    const 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 }
+    }
+
+    if (url.includes('data-provider')) {
+      const query = {
+        "data-provider:input": input
+      };
+
+      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["data-provider:output"] && result["data-provider:output"].data) {
+          rows = result["data-provider:output"].data.map(obj => convertPropertyNames(obj, replaceHyphen)) || []
+        }
+
+        const data = {
+          page: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.page != null && result["data-provider:output"].pagination.page - 1 || 0), total: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.total || 0), rows: rows
+        };
+        return data;
       }
+    } else if (url.includes('topology')) {
 
-      const data = {
-        page: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.page != null && result["data-provider:output"].pagination.page - 1  || 0) , total: +(result["data-provider:output"].pagination && result["data-provider:output"].pagination.total || 0), rows: rows
+      const queryTopology = {
+        "input": input
       };
-      return data;
+
+      const resultTopology = await requestRest<ResultTopology<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(queryTopology), // body data type must match "Content-Type" header
+      });
+      if (resultTopology) {
+        let rows: TResult[] = [];
+
+        if (resultTopology && resultTopology.output && resultTopology.output.data) {
+          rows = resultTopology.output.data.map(obj => obj) || []
+        }
+
+        const data = {
+          page: +(resultTopology.output.pagination && resultTopology.output.pagination.page != null && resultTopology.output.pagination.page - 1 || 0), total: +(resultTopology.output.pagination && resultTopology.output.pagination.total || 0), rows: rows
+        };
+        return data;
+      }
     }
 
     return { page: 1, total: 0, rows: [] };
index 1b6135e..ac21970 100644 (file)
@@ -38,10 +38,8 @@ type odluxVersion= {version:string,build:string, framework: string,
     faultApp: string,
     helpApp: string,
     inventoryApp: string,
-    linkCalculationApp: string,
     maintenanceApp: string,
     mediatorApp: string,
-    networkMapApp: string,
     permanceHistoryApp: string
   }};
 
@@ -74,8 +72,6 @@ class AboutComponent extends React.Component<any, AboutState> {
         `| InventoryApp | ${data.applications.inventoryApp}|\n `+
         `| EventLogApp | ${data.applications.eventLogApp}|\n `+
         `| MediatorApp | ${data.applications.mediatorApp}|\n `+
-        `| NetworkMapApp | ${data.applications.networkMapApp}|\n `+
-        `| LinkCalculatorApp | ${data.applications.linkCalculationApp}|\n `+
         `| HelpApp | ${data.applications.helpApp}|\n `;
       }
     
@@ -167,7 +163,7 @@ class AboutComponent extends React.Component<any, AboutState> {
       <div style={containerStyle}>
         { this.state.isContentLoadedSucessfully &&
         <div style={{float: "right", marginRight: "10px"}}>
-        <Button color="inherit" variant="contained" onClick={e => this.copyToClipboard(e)}>
+        <Button aria-label="copy-version-information-button" color="inherit" variant="contained" onClick={e => this.copyToClipboard(e)}>
            Copy to clipboard
         </Button>
           {
index 278fbe1..4676f5a 100644 (file)
@@ -22,7 +22,8 @@ import { Theme } from '@mui/material/styles';
 import { WithStyles } from '@mui/styles';
 import withStyles from '@mui/styles/withStyles';
 import createStyles from '@mui/styles/createStyles';
-import { faHome, faAddressBook, faSignInAlt, faCog } from '@fortawesome/free-solid-svg-icons';
+import { faHome, faAddressBook, faSignInAlt, faCog } from '@fortawesome/free-solid-svg-icons'
+
 
 import { SnackbarProvider } from 'notistack';
 import { ConfirmProvider } from 'material-ui-confirm';
index 8eb7a6c..e037edf 100644 (file)
@@ -119,6 +119,7 @@ interface ILoginState {
   password: string;
   scope: string;
   message: string;
+  isServerReady: boolean;
   providers: {
     id: string;
     title: string;
@@ -141,6 +142,7 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
       scope: 'sdn',
       message: '',
       providers: null,
+      isServerReady: false
     };
   }
 
@@ -148,6 +150,13 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
      if (this.props.authentication === "oauth" && (this.props.externalLoginProviders == null || this.props.externalLoginProviders.length === 0)){
        this.props.updateExternalProviders();
      }
+
+    authenticationService.getServerReadyState().then(result =>{
+      this.setState({isServerReady: result});
+    })
+
+
+
   }
 
   private setExternalProviderAnchor = (el: HTMLElement | null) => {
@@ -262,10 +271,21 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
       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: ""
-      })
+
+      if(!this.state.isServerReady){
+        const ready = await authenticationService.getServerReadyState();
+        if(ready){
+          this.setState({isServerReady: true});
+        }else{
+          this.setState({message: "Login is currently not possible. Please re-try in a few minutes. If the problem persits, ask your administrator for assistence."});
+        }
+  
+      }else{
+        this.setState({
+          message: "Could not log in. Please check your credentials or ask your administrator for assistence.",
+          password: ""
+        })
+      }
     }
   }
 }
index 84c4094..72f8d2c 100644 (file)
@@ -848,7 +848,7 @@ const TestComponent = (props: WithComponents<typeof components> & WithStyles<typ
           <Typography className={props.classes.heading}>Client Side Table Demo</Typography>
         </AccordionSummary>
         <AccordionDetails>
-          <SampleDataMaterialTable rows={tableData} columns={
+          <SampleDataMaterialTable rows={tableData} tableId={null} columns={
             [
               { property: "index", type: ColumnType.text, title: "Index", width: "80px", disableFilter: true, disableSorting: true },
               { property: "firstName", type: ColumnType.text, title: "First Name" },
index 1d9af90..f9e9746 100644 (file)
@@ -9,10 +9,8 @@
         "faultApp":"##odlux.apps.faultApp.buildno##",
         "helpApp":"##odlux.apps.helpApp.buildno##",
         "inventoryApp":"##odlux.apps.inventoryApp.buildno##",
-        "linkCalculationApp":"##odlux.apps.linkCalculationApp.buildno##",
         "maintenanceApp":"##odlux.apps.maintenanceApp.buildno##",
         "mediatorApp":"##odlux.apps.mediatorApp.buildno##",
-        "networkMapApp":"##odlux.apps.networkMapApp.buildno##",
         "permanceHistoryApp":"##odlux.apps.permanceHistoryApp.buildno##"
     
     }
index b880292..2d618b7 100644 (file)
@@ -73,10 +73,7 @@ module.exports = (env) => {
       {
         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'
       },
index 744f9e3..2ee1b49 100644 (file)
@@ -1,5 +1,4 @@
 {
-  "lerna": "2.9.0",
   "version": "independent",
   "command": {
     "init": {
@@ -8,5 +7,8 @@
   },
   "npmClient": "yarn",
   "useWorkspaces": true,
-  "packages": ["framework","apps/*"]
-}
\ No newline at end of file
+  "packages": [
+    "framework",
+    "apps/*"
+  ]
+}
index b02a0a9..8a49bde 100644 (file)
@@ -1,11 +1,10 @@
-odlux.framework.buildno=142.63ceae1(22/01/31)
-odlux.apps.configurationApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.connectApp.buildno=142.63ceae1(22/01/31)
+odlux.framework.buildno=166.7b222ec(22/08/26)
+odlux.apps.configurationApp.buildno=165.93e23ca(22/08/12)
+odlux.apps.connectApp.buildno=166.7b222ec(22/08/26)
 odlux.apps.eventLogApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.faultApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.helpApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.inventoryApp.buildno=142.63ceae1(22/01/31)
+odlux.apps.faultApp.buildno=158.f3ad6e0(22/07/18)
+odlux.apps.helpApp.buildno=166.7b222ec(22/08/26)
+odlux.apps.inventoryApp.buildno=161.f556fbb(22/07/29)
 odlux.apps.maintenanceApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.mediatorApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.lineOfSightApp.buildno=142.63ceae1(22/01/31)
-odlux.apps.permanceHistoryApp.buildno=142.63ceae1(22/01/31)
+odlux.apps.mediatorApp.buildno=158.f3ad6e0(22/07/18)
+odlux.apps.permanceHistoryApp.buildno=81.1c38886(20/12/04)
index a98d4b8..65d52d5 100644 (file)
   dependencies:
     "@babel/types" "^7.16.0"
 
+"@babel/helper-module-imports@^7.16.7":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
+  integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
 "@babel/helper-module-transforms@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz#7de42f10d789b423eb902ebd24031ca77cb1e10e"
   resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
   integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
 
+"@babel/helper-plugin-utils@^7.18.6":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f"
+  integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==
+
 "@babel/helper-remap-async-to-generator@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz#51439c913612958f54a987a4ffc9ee587a2045d6"
   dependencies:
     "@babel/types" "^7.14.5"
 
+"@babel/helper-string-parser@^7.18.10":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
+  integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
+
 "@babel/helper-validator-identifier@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
   integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
 
+"@babel/helper-validator-identifier@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
+  integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
+
 "@babel/helper-validator-option@^7.14.5":
   version "7.14.5"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
 
+"@babel/plugin-syntax-jsx@^7.17.12":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0"
+  integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
 "@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
   dependencies:
     regenerator-runtime "^0.13.4"
 
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
+  integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
 "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
   version "7.14.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
     "@babel/helper-validator-identifier" "^7.15.7"
     to-fast-properties "^2.0.0"
 
-"@date-io/core@^2.11.0":
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.11.0.tgz#28580cda1c8228ab2c7ed6aee673ef0495f913e6"
-  integrity sha512-DvPBnNoeuLaoSJZaxgpu54qzRhRKjSYVyQjhznTFrllKuDpm0sDFjHo6lvNLCM/cfMx2gb2PM2zY2kc9C8nmuw==
-
-"@date-io/date-fns@^2.11.0":
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.11.0.tgz#142fbf954eda7ad66514af7a2802d78c4ea40053"
-  integrity sha512-mPQ71plBeFrArvBSHtjWMHXA89IUbZ6kuo2dsjlRC/1uNOybo91spIb+wTu03NxKTl8ut07s0jJ9svF71afpRg==
-  dependencies:
-    "@date-io/core" "^2.11.0"
-
-"@date-io/dayjs@^2.11.0":
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.11.0.tgz#41f4b4b9629612e6012accffd848875d1aeffb74"
-  integrity sha512-w67vRK56NZJIKhJM/CrNbfnIcuMvR3ApfxzNZiCZ5w29sxgBDeKuX4M+P7A9r5HXOMGcsOcpgaoTDINNGkdpGQ==
+"@babel/types@^7.18.6":
+  version "7.18.13"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.13.tgz#30aeb9e514f4100f7c1cb6e5ba472b30e48f519a"
+  integrity sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==
   dependencies:
-    "@date-io/core" "^2.11.0"
-
-"@date-io/luxon@^2.11.1":
-  version "2.11.1"
-  resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.11.1.tgz#31a72f7b5e163c74e8a3b29d8f16c4c30de6ed43"
-  integrity sha512-JUXo01kdPQxLORxqdENrgdUhooKgDUggsNRSdi2BcUhASIY2KGwwWXu8ikVHHGkw+DUF4FOEKGfkQd0RHSvX6g==
-  dependencies:
-    "@date-io/core" "^2.11.0"
+    "@babel/helper-string-parser" "^7.18.10"
+    "@babel/helper-validator-identifier" "^7.18.6"
+    to-fast-properties "^2.0.0"
 
-"@date-io/moment@^2.11.0":
-  version "2.11.0"
-  resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.11.0.tgz#850f8dd090d401845b39276d034dbabe20224ef5"
-  integrity sha512-QSL+83qezQ9Ty0dtFgAkk6eC0GMl/lgYfDajeVUDB3zVA2A038hzczRLBg29ifnBGhQMPABxuOafgWwhDjlarg==
-  dependencies:
-    "@date-io/core" "^2.11.0"
+"@emotion/babel-plugin@^11.10.0":
+  version "11.10.2"
+  resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz#879db80ba622b3f6076917a1e6f648b1c7d008c7"
+  integrity sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==
+  dependencies:
+    "@babel/helper-module-imports" "^7.16.7"
+    "@babel/plugin-syntax-jsx" "^7.17.12"
+    "@babel/runtime" "^7.18.3"
+    "@emotion/hash" "^0.9.0"
+    "@emotion/memoize" "^0.8.0"
+    "@emotion/serialize" "^1.1.0"
+    babel-plugin-macros "^3.1.0"
+    convert-source-map "^1.5.0"
+    escape-string-regexp "^4.0.0"
+    find-root "^1.1.0"
+    source-map "^0.5.7"
+    stylis "4.0.13"
 
 "@emotion/babel-plugin@^11.3.0":
   version "11.3.0"
     source-map "^0.5.7"
     stylis "^4.0.3"
 
+"@emotion/cache@^11.10.0", "@emotion/cache@^11.10.3":
+  version "11.10.3"
+  resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.3.tgz#c4f67904fad10c945fea5165c3a5a0583c164b87"
+  integrity sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==
+  dependencies:
+    "@emotion/memoize" "^0.8.0"
+    "@emotion/sheet" "^1.2.0"
+    "@emotion/utils" "^1.2.0"
+    "@emotion/weak-memoize" "^0.3.0"
+    stylis "4.0.13"
+
 "@emotion/cache@^11.6.0":
   version "11.6.0"
   resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.6.0.tgz#65fbdbbe4382f1991d8b20853c38e63ecccec9a1"
   resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
   integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
 
+"@emotion/hash@^0.9.0":
+  version "0.9.0"
+  resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7"
+  integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==
+
 "@emotion/is-prop-valid@^1.1.1":
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.1.tgz#cbd843d409dfaad90f9404e7c0404c55eae8c134"
   dependencies:
     "@emotion/memoize" "^0.7.4"
 
+"@emotion/is-prop-valid@^1.1.3", "@emotion/is-prop-valid@^1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83"
+  integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==
+  dependencies:
+    "@emotion/memoize" "^0.8.0"
+
 "@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5":
   version "0.7.5"
   resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
   integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
 
+"@emotion/memoize@^0.8.0":
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f"
+  integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==
+
+"@emotion/react@11.10.0":
+  version "11.10.0"
+  resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.0.tgz#53c577f063f26493f68a05188fb87528d912ff2e"
+  integrity sha512-K6z9zlHxxBXwN8TcpwBKcEsBsOw4JWCCmR+BeeOWgqp8GIU1yA2Odd41bwdAAr0ssbQrbJbVnndvv7oiv1bZeQ==
+  dependencies:
+    "@babel/runtime" "^7.18.3"
+    "@emotion/babel-plugin" "^11.10.0"
+    "@emotion/cache" "^11.10.0"
+    "@emotion/serialize" "^1.1.0"
+    "@emotion/utils" "^1.2.0"
+    "@emotion/weak-memoize" "^0.3.0"
+    hoist-non-react-statics "^3.3.1"
+
 "@emotion/react@^11.7.0":
   version "11.7.0"
   resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.7.0.tgz#b179da970ac0e8415de3ac165deadf8d9c4bf89f"
     "@emotion/utils" "^1.0.0"
     csstype "^3.0.2"
 
+"@emotion/serialize@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8"
+  integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==
+  dependencies:
+    "@emotion/hash" "^0.9.0"
+    "@emotion/memoize" "^0.8.0"
+    "@emotion/unitless" "^0.8.0"
+    "@emotion/utils" "^1.2.0"
+    csstype "^3.0.2"
+
 "@emotion/sheet@^1.1.0":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.0.tgz#56d99c41f0a1cda2726a05aa6a20afd4c63e58d2"
   integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g==
 
+"@emotion/sheet@^1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5"
+  integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==
+
+"@emotion/styled@11.10.0":
+  version "11.10.0"
+  resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.0.tgz#c19484dab4206ae46727c07efb4316423dd21312"
+  integrity sha512-V9oaEH6V4KePeQpgUE83i8ht+4Ri3E8Djp/ZPJ4DQlqWhSKITvgzlR3/YQE2hdfP4Jw3qVRkANJz01LLqK9/TA==
+  dependencies:
+    "@babel/runtime" "^7.18.3"
+    "@emotion/babel-plugin" "^11.10.0"
+    "@emotion/is-prop-valid" "^1.2.0"
+    "@emotion/serialize" "^1.1.0"
+    "@emotion/utils" "^1.2.0"
+
 "@emotion/styled@^11.6.0":
   version "11.6.0"
   resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.6.0.tgz#9230d1a7bcb2ebf83c6a579f4c80e0664132d81d"
   resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
   integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
 
+"@emotion/unitless@^0.8.0":
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db"
+  integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==
+
 "@emotion/utils@^1.0.0":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af"
   integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==
 
+"@emotion/utils@^1.2.0":
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561"
+  integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==
+
 "@emotion/weak-memoize@^0.2.5":
   version "0.2.5"
   resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
   integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
 
+"@emotion/weak-memoize@^0.3.0":
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb"
+  integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
+
 "@evocateur/libnpmaccess@^3.1.2":
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
     npmlog "^4.1.2"
     write-file-atomic "^2.3.0"
 
+"@mapbox/geojson-rewind@^0.5.0":
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.1.tgz#adbe16dc683eb40e90934c51a5e28c7bbf44f4e1"
+  integrity sha512-eL7fMmfTBKjrb+VFHXCGv9Ot0zc3C0U+CwXo1IrP+EPwDczLoXv34Tgq3y+2mPSFNVUXgU42ILWJTC7145KPTA==
+  dependencies:
+    get-stream "^6.0.1"
+    minimist "^1.2.5"
+
+"@mapbox/geojson-types@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz#9aecf642cb00eab1080a57c4f949a65b4a5846d6"
+  integrity sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==
+
+"@mapbox/jsonlint-lines-primitives@^2.0.2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234"
+  integrity sha1-zlblOfg1UrWNENZy6k1vya3HsjQ=
+
+"@mapbox/mapbox-gl-supported@^1.5.0":
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz#f60b6a55a5d8e5ee908347d2ce4250b15103dc8e"
+  integrity sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==
+
+"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0":
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2"
+  integrity sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI=
+
+"@mapbox/tiny-sdf@^1.1.1":
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz#424c620a96442b20402552be70a7f62a8407cc59"
+  integrity sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==
+
+"@mapbox/unitbezier@^0.0.0":
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz#15651bd553a67b8581fb398810c98ad86a34524e"
+  integrity sha1-FWUb1VOme4WB+zmIEMmK2Go0Uk4=
+
+"@mapbox/vector-tile@^1.3.1":
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666"
+  integrity sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==
+  dependencies:
+    "@mapbox/point-geometry" "~0.1.0"
+
+"@mapbox/whoots-js@^3.1.0":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
+  integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
+
 "@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"
     prop-types "^15.7.2"
     react-is "^17.0.2"
 
+"@mui/base@5.0.0-alpha.93":
+  version "5.0.0-alpha.93"
+  resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.93.tgz#b13310ee4bbf423ae74f1a82befd57469778fa9f"
+  integrity sha512-IVUWO0NNlELDc9FD7mM+fWTS1/6n5sJYdIbXpLQ00NjWdVEYmTyRgUAZDlJJJrz+tbF0eeffx0kOsvJvyTZlsA==
+  dependencies:
+    "@babel/runtime" "^7.17.2"
+    "@emotion/is-prop-valid" "^1.1.3"
+    "@mui/types" "^7.1.5"
+    "@mui/utils" "^5.9.3"
+    "@popperjs/core" "^2.11.6"
+    clsx "^1.2.1"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
+"@mui/core-downloads-tracker@^5.10.1":
+  version "5.10.3"
+  resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.3.tgz#e17a3cd87c7814ff35592284b19ae39ad52b85ac"
+  integrity sha512-mX2S0d1oboKBbWQqWIgRmyALAEzh37yiknpD3mKx8bcoMKbp1VtqzIt0aeHP16Uhsd0eValDFILxLNHWi0oddQ==
+
+"@mui/icons-material@5.8.4":
+  version "5.8.4"
+  resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.8.4.tgz#3f2907c9f8f5ce4d754cb8fb4b68b5a1abf4d095"
+  integrity sha512-9Z/vyj2szvEhGWDvb+gG875bOGm8b8rlHBKOD1+nA3PcgC3fV6W1AU6pfOorPeBfH2X4mb9Boe97vHvaSndQvA==
+  dependencies:
+    "@babel/runtime" "^7.17.2"
+
 "@mui/icons-material@^5.2.0":
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.2.0.tgz#6c6135bb2d7891e29d6f9419df402b82dd663517"
   dependencies:
     "@babel/runtime" "^7.16.3"
 
-"@mui/lab@^5.0.0-alpha.58":
-  version "5.0.0-alpha.58"
-  resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.58.tgz#47c3b2976df066119fa040131a63139677ba5a66"
-  integrity sha512-Vn3bWlID2SgCb7KX3d29uSLWv3JDEHJ+QiApnaPuUqqymwHARbQUk+b2h6wfQCz/WqaR0MtmsRwA6OrrLsL3Eg==
-  dependencies:
-    "@babel/runtime" "^7.16.3"
-    "@date-io/date-fns" "^2.11.0"
-    "@date-io/dayjs" "^2.11.0"
-    "@date-io/luxon" "^2.11.1"
-    "@date-io/moment" "^2.11.0"
-    "@mui/base" "5.0.0-alpha.58"
-    "@mui/system" "^5.2.2"
-    "@mui/utils" "^5.2.2"
-    clsx "^1.1.1"
-    prop-types "^15.7.2"
-    react-is "^17.0.2"
-    react-transition-group "^4.4.2"
-    rifm "^0.12.1"
+"@mui/lab@5.0.0-alpha.95":
+  version "5.0.0-alpha.95"
+  resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.95.tgz#e710ed713fb58ec2aa216096d34cc577fac0068f"
+  integrity sha512-JdJKhn0qJjk0ejtmsiZ/8e08uUzr8MZsASGbmY2VbGC7WlCntgjZrWmhuvQf3hWCtSfuD6tbCdPpz6A2NL5nVQ==
+  dependencies:
+    "@babel/runtime" "^7.17.2"
+    "@mui/base" "5.0.0-alpha.93"
+    "@mui/system" "^5.10.1"
+    "@mui/utils" "^5.9.3"
+    clsx "^1.2.1"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
+"@mui/material@5.10.1":
+  version "5.10.1"
+  resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.10.1.tgz#4a980c1fc34e2853d674dd0eff2723618402a4f4"
+  integrity sha512-E9fhskX6TwUdAzpL5+yoAzRxb6wY4oBqmBVlgUuLndSwPRYxXoGu+z74NxbDEkxUoHdb7vrDcRTswpB6ykDITQ==
+  dependencies:
+    "@babel/runtime" "^7.17.2"
+    "@mui/base" "5.0.0-alpha.93"
+    "@mui/core-downloads-tracker" "^5.10.1"
+    "@mui/system" "^5.10.1"
+    "@mui/types" "^7.1.5"
+    "@mui/utils" "^5.9.3"
+    "@types/react-transition-group" "^4.4.5"
+    clsx "^1.2.1"
+    csstype "^3.1.0"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+    react-transition-group "^4.4.5"
 
 "@mui/material@^5.2.2":
   version "5.2.2"
     react-is "^17.0.2"
     react-transition-group "^4.4.2"
 
+"@mui/private-theming@^5.10.3", "@mui/private-theming@^5.9.3":
+  version "5.10.3"
+  resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.10.3.tgz#7325eef3e480caaaa2d866b9057943ec4fbcb8ce"
+  integrity sha512-LCYIKlkGz2BTSng2BFzzwSJBRZbChIUri2x2Nh8ryk2B1Ho7zpvE7ex6y39LlStG2Frf92NFC/V4YQbmMAjD5A==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    "@mui/utils" "^5.10.3"
+    prop-types "^15.8.1"
+
 "@mui/private-theming@^5.2.2":
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.2.2.tgz#ede801bc4b6939aedf5900edcece981fde8fa210"
     "@mui/utils" "^5.2.2"
     prop-types "^15.7.2"
 
+"@mui/styled-engine@^5.10.3":
+  version "5.10.3"
+  resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.10.3.tgz#c3e061548951568936b749a58531fb269af48948"
+  integrity sha512-9Uz7eB8xXoiDvpJ9qBxZ/2xGO8xKfA2T23dw4AsQ69SQtGatrOLAapzP2lNr0tfB9xvKucclPFhRO5aLhDFOVQ==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    "@emotion/cache" "^11.10.3"
+    csstype "^3.1.0"
+    prop-types "^15.8.1"
+
 "@mui/styled-engine@^5.2.0":
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.2.0.tgz#5c97e2b1b6c4c2d9991f07517ed862972d362b85"
     "@emotion/cache" "^11.6.0"
     prop-types "^15.7.2"
 
+"@mui/styles@5.9.3":
+  version "5.9.3"
+  resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.9.3.tgz#7cd0cb49247325e1e88dbc29008cc17c183cc4cc"
+  integrity sha512-omENe7oZxj6TYXYXYsSjwefmiXcU2pdy7QmXRtiD6MdTmw5+5WrDjrDRlFo2bHCFxjqNfUiXT1oEWAhV3pERww==
+  dependencies:
+    "@babel/runtime" "^7.17.2"
+    "@emotion/hash" "^0.8.0"
+    "@mui/private-theming" "^5.9.3"
+    "@mui/types" "^7.1.5"
+    "@mui/utils" "^5.9.3"
+    clsx "^1.2.1"
+    csstype "^3.1.0"
+    hoist-non-react-statics "^3.3.2"
+    jss "^10.9.1"
+    jss-plugin-camel-case "^10.9.1"
+    jss-plugin-default-unit "^10.9.1"
+    jss-plugin-global "^10.9.1"
+    jss-plugin-nested "^10.9.1"
+    jss-plugin-props-sort "^10.9.1"
+    jss-plugin-rule-value-function "^10.9.1"
+    jss-plugin-vendor-prefixer "^10.9.1"
+    prop-types "^15.8.1"
+
 "@mui/styles@^5.2.2":
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.2.2.tgz#34c9ba1d6d5a0b9399fbd0c6e85b8f2dcfe54fbd"
     jss-plugin-vendor-prefixer "^10.8.2"
     prop-types "^15.7.2"
 
+"@mui/system@^5.10.1":
+  version "5.10.3"
+  resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.10.3.tgz#26f82e506af506f4fddde265c20e1100baaca03e"
+  integrity sha512-uLW/CIz3zk1jr5zH0ahOUqJIrpWP02Mv4emfrplh7Mh5JCb/oumhYaC/ALJJEjzUHKg9wwiyuM0pCwK/kSf1jQ==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    "@mui/private-theming" "^5.10.3"
+    "@mui/styled-engine" "^5.10.3"
+    "@mui/types" "^7.2.0"
+    "@mui/utils" "^5.10.3"
+    clsx "^1.2.1"
+    csstype "^3.1.0"
+    prop-types "^15.8.1"
+
 "@mui/system@^5.2.2":
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.2.2.tgz#81ef74f0c269d18b99a2d0253833d6554bbf5198"
   resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.1.0.tgz#5ed928c5a41cfbf9a4be82ea3bbdc47bcc9610d5"
   integrity sha512-Hh7ALdq/GjfIwLvqH3XftuY3bcKhupktTm+S6qRIDGOtPtRuq2L21VWzOK4p7kblirK0XgGVH5BLwa6u8z/6QQ==
 
+"@mui/types@^7.1.5", "@mui/types@^7.2.0":
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.0.tgz#91380c2d42420f51f404120f7a9270eadd6f5c23"
+  integrity sha512-lGXtFKe5lp3UxTBGqKI1l7G8sE2xBik8qCfrLHD5olwP/YU0/ReWoWT7Lp1//ri32dK39oPMrJN8TgbkCSbsNA==
+
+"@mui/utils@^5.10.3", "@mui/utils@^5.9.3":
+  version "5.10.3"
+  resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.10.3.tgz#ce2a96f31de2a5e717f507b5383dbabbddbc4dfc"
+  integrity sha512-4jXMDPfx6bpMVuheLaOpKTjpzw39ogAZLeaLj5+RJec3E37/hAZMYjURfblLfTWMMoGoqkY03mNsZaEwNobBow==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    "@types/prop-types" "^15.7.5"
+    "@types/react-is" "^16.7.1 || ^17.0.0"
+    prop-types "^15.8.1"
+    react-is "^18.2.0"
+
 "@mui/utils@^5.2.2":
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.2.2.tgz#972aab7d2564e77c06e0c3c11e7b1aec6e37c927"
   dependencies:
     "@octokit/openapi-types" "^8.2.1"
 
+"@popperjs/core@^2.11.6":
+  version "2.11.6"
+  resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
+  integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
+
 "@popperjs/core@^2.4.4":
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7"
   resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.6.tgz#dbe8a666156d556ed018e15a4c65f08937c3f628"
   integrity sha512-XHcYvVdbtAxVstjKxuULYqYaWIzHR15yr1pZj4fnGChuBVJlIAp9StJna0ZJNSgxPh4Nac2FL4JM3M11Tm6fqQ==
 
+"@types/d3-array@^2":
+  version "2.12.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.12.3.tgz#8d16d51fb04ad5a5a8ebe14eb8263a579f1efdd1"
+  integrity sha512-hN879HLPTVqZV3FQEXy7ptt083UXwguNbnxdTGzVW4y4KjX5uyNKljrQixZcSJfLyFirbpUokxpXtvR+N5+KIg==
+
+"@types/d3-axis@^2":
+  version "2.1.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-2.1.3.tgz#348cca877f6643030aa8c866d08ccae06821a0e2"
+  integrity sha512-QjXjwZ0xzyrW2ndkmkb09ErgWDEYtbLBKGui73QLMFm3woqWpxptfD5Y7vqQdybMcu7WEbjZ5q+w2w5+uh2IjA==
+  dependencies:
+    "@types/d3-selection" "^2"
+
+"@types/d3-brush@^2":
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-2.1.2.tgz#c75890d1ccaef24fba1811daae3f896c1806418b"
+  integrity sha512-DnZmjdK1ycX1CMiW9r5E3xSf1tL+bp3yob1ON8bf0xB0/odfmGXeYOTafU+2SmU1F0/dvcqaO4SMjw62onOu6A==
+  dependencies:
+    "@types/d3-selection" "^2"
+
+"@types/d3-chord@^2":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-2.0.3.tgz#3009b792b754da964d893b4269d1fe7757f21370"
+  integrity sha512-koIqSNQLPRQPXt7c55hgRF6Lr9Ps72r1+Biv55jdYR+SHJ463MsB2lp4ktzttFNmrQw/9yWthf/OmSUj5dNXKw==
+
+"@types/d3-color@^2":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-2.0.3.tgz#8bc4589073c80e33d126345542f588056511fe82"
+  integrity sha512-+0EtEjBfKEDtH9Rk3u3kLOUXM5F+iZK+WvASPb0MhIZl8J8NUvGeZRwKCXl+P3HkYx5TdU4YtcibpqHkSR9n7w==
+
+"@types/d3-contour@^2":
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-2.0.4.tgz#2fc5aa8949c1a1d12d183633603923025e3d14fd"
+  integrity sha512-WMac1xV/mXAgkgr5dUvzsBV5OrgNZDBDpJk9s3v2SadTqGgDRirKABb2Ek2H1pFlYVH4Oly9XJGnuzxKDduqWA==
+  dependencies:
+    "@types/d3-array" "^2"
+    "@types/geojson" "*"
+
+"@types/d3-delaunay@^5":
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-5.3.1.tgz#47ae03af6b78cb3aa39d3d3c42ca71daca488aef"
+  integrity sha512-F6itHi2DxdatHil1rJ2yEFUNhejj8+0Acd55LZ6Ggwbdoks0+DxVY2cawNj16sjCBiWvubVlh6eBMVsYRNGLew==
+
+"@types/d3-dispatch@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-2.0.1.tgz#d7dc50f9b679996ccf70f3c79dbbf99505a93107"
+  integrity sha512-eT2K8uG3rXkmRiCpPn0rNrekuSLdBfV83vbTvfZliA5K7dbeaqWS/CBHtJ9SQoF8aDTsWSY4A0RU67U/HcKdJQ==
+
+"@types/d3-drag@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-2.0.2.tgz#ed538d24456c839967a9ac7aab5e1b63b28bac7f"
+  integrity sha512-m9USoFaTgVw2mmE7vLjWTApT9dMxMlql/dl3Gj503x+1a2n6K455iDWydqy2dfCpkUBCoF82yRGDgcSk9FUEyQ==
+  dependencies:
+    "@types/d3-selection" "^2"
+
+"@types/d3-dsv@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-2.0.2.tgz#e10fa57576b50ded27e261db9984b9a92efec2f3"
+  integrity sha512-T4aL2ZzaILkLGKbxssipYVRs8334PSR9FQzTGftZbc3jIPGkiXXS7qUCh8/q8UWFzxBZQ92dvR0v7+AM9wL2PA==
+
+"@types/d3-ease@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-2.0.1.tgz#be03d29980ed7359be1d5b93ff666f95ddcbcf48"
+  integrity sha512-Af1ftZXv82ktPCk1+Vxe7f+VSfxDsQ1mwwakDl17+UzI/ii3vsDIAzaBDDSEQd2Cg9BYPTSx8wXH8rJNDuSjeg==
+
+"@types/d3-fetch@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-2.0.2.tgz#628c65d14b3a0d02fe1b9c2f3098b81a47e370bc"
+  integrity sha512-sllsCSWrNdSvzOJWN5RnxkmtvW9pCttONGajSxHX9FUQ9kOkGE391xlz6VDBdZxLnpwjp3I+mipbwsaCjq4m5A==
+  dependencies:
+    "@types/d3-dsv" "^2"
+
+"@types/d3-force@^2":
+  version "2.1.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-2.1.3.tgz#7b0d9ff608e394e6675cce5163eda8368fba7a07"
+  integrity sha512-b/1KrS7hESsMXZ3dOh5KrWPoDcQQbQKey344HO7F3o0tEcVzWHIgp1UMfHv8MLcysfHsRSPGpO7dRyLOVhMQnw==
+
+"@types/d3-format@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-2.0.2.tgz#97b2ac314430ae9f7768cc9efba8b23b63af82ef"
+  integrity sha512-OhQPuTeeMhD9A0Ksqo4q1S9Z1Q57O/t4tTPBxBQxRB4IERnxeoEYLPe72fA/GYpPSUrfKZVOgLHidkxwbzLdJA==
+
+"@types/d3-geo@^2":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-2.0.3.tgz#4af0f33c9e796aad6c3fc0dd8cadda9886d1fea9"
+  integrity sha512-kFwLEMXq1mGJ2Eho7KrOUYvLcc2YTDeKj+kTFt87JlEbRQ0rgo8ZENNb5vTYmZrJ2xL/vVM5M7yqVZGOPH2JFg==
+  dependencies:
+    "@types/geojson" "*"
+
+"@types/d3-hierarchy@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-2.0.2.tgz#afd09d509c36e8cd4907333556f8b591f23589e9"
+  integrity sha512-6PlBRwbjUPPt0ZFq/HTUyOAdOF3p73EUYots74lHMUyAVtdFSOS/hAeNXtEIM9i7qRDntuIblXxHGUMb9MuNRA==
+
+"@types/d3-interpolate@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-2.0.2.tgz#78eddf7278b19e48e8652603045528d46897aba0"
+  integrity sha512-lElyqlUfIPyWG/cD475vl6msPL4aMU7eJvx1//Q177L8mdXoVPFl1djIESF2FKnc0NyaHvQlJpWwKJYwAhUoCw==
+  dependencies:
+    "@types/d3-color" "^2"
+
+"@types/d3-path@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-2.0.1.tgz#ca03dfa8b94d8add97ad0cd97e96e2006b4763cb"
+  integrity sha512-6K8LaFlztlhZO7mwsZg7ClRsdLg3FJRzIIi6SZXDWmmSJc2x8dd2VkESbLXdk3p8cuvz71f36S0y8Zv2AxqvQw==
+
+"@types/d3-polygon@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-2.0.1.tgz#c2056594f85b512bc2b4f741caddd4b5448bc115"
+  integrity sha512-X3XTIwBxlzRIWe4yaD1KsmcfItjSPLTGL04QDyP08jyHDVsnz3+NZJMwtD4vCaTAVpGSjbqS+jrBo8cO2V/xMA==
+
+"@types/d3-quadtree@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-2.0.2.tgz#e3cd92b4e05318f98b0a16e780ba99ce7b13eb77"
+  integrity sha512-KgWL4jlz8QJJZX01E4HKXJ9FLU94RTuObsAYqsPp8YOAcYDmEgJIQJ+ojZcnKUAnrUb78ik8JBKWas5XZPqJnQ==
+
+"@types/d3-random@^2":
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.1.tgz#551edbb71cb317dea2cf9c76ebe059d311eefacb"
+  integrity sha512-5vvxn6//poNeOxt1ZwC7QU//dG9QqABjy1T7fP/xmFHY95GnaOw3yABf29hiu5SR1Oo34XcpyHFbzod+vemQjA==
+
+"@types/d3-scale-chromatic@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.1.tgz#495cbbae7273e0d0ff564cdc19aa6d2b9928da83"
+  integrity sha512-3EuZlbPu+pvclZcb1DhlymTWT2W+lYsRKBjvkH2ojDbCWDYavifqu1vYX9WGzlPgCgcS4Alhk1+zapXbGEGylQ==
+
+"@types/d3-scale@^3":
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.3.2.tgz#18c94e90f4f1c6b1ee14a70f14bfca2bd1c61d06"
+  integrity sha512-gGqr7x1ost9px3FvIfUMi5XA/F/yAf4UkUDtdQhpH92XCT0Oa7zkkRzY61gPVJq+DxpHn/btouw5ohWkbBsCzQ==
+  dependencies:
+    "@types/d3-time" "^2"
+
+"@types/d3-selection@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-2.0.1.tgz#bc2816c96faff285d204dda72b79734d4f37d583"
+  integrity sha512-3mhtPnGE+c71rl/T5HMy+ykg7migAZ4T6gzU0HxpgBFKcasBrSnwRbYV1/UZR6o5fkpySxhWxAhd7yhjj8jL7g==
+
+"@types/d3-shape@^2":
+  version "2.1.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-2.1.3.tgz#35d397b9e687abaa0de82343b250b9897b8cacf3"
+  integrity sha512-HAhCel3wP93kh4/rq+7atLdybcESZ5bRHDEZUojClyZWsRuEMo3A52NGYJSh48SxfxEU6RZIVbZL2YFZ2OAlzQ==
+  dependencies:
+    "@types/d3-path" "^2"
+
+"@types/d3-time-format@^3":
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-3.0.1.tgz#1680fb6c41ab3a85db261ede296626668592246a"
+  integrity sha512-5GIimz5IqaRsdnxs4YlyTZPwAMfALu/wA4jqSiuqgdbCxUZ2WjrnwANqOtoBJQgeaUTdYNfALJO0Yb0YrDqduA==
+
+"@types/d3-time@^2":
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.1.1.tgz#743fdc821c81f86537cbfece07093ac39b4bc342"
+  integrity sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg==
+
+"@types/d3-timer@^2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-2.0.1.tgz#ffb6620d290624f3726aa362c0c8a4b44c8d7200"
+  integrity sha512-TF8aoF5cHcLO7W7403blM7L1T+6NF3XMyN3fxyUolq2uOcFeicG/khQg/dGxiCJWoAcmYulYN7LYSRKO54IXaA==
+
+"@types/d3-transition@^2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-2.0.2.tgz#d5ba1c26a3daeb0c5527d573d44b4c5ca9fae027"
+  integrity sha512-376TICEykdXOEA9uUIYpjshEkxfGwCPnkHUl8+6gphzKbf5NMnUhKT7wR59Yxrd9wtJ/rmE3SVLx6/8w4eY6Zg==
+  dependencies:
+    "@types/d3-selection" "^2"
+
+"@types/d3-zoom@^2":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-2.0.3.tgz#9eef8763600fa8be11b8cb0ed9144a395df6dffb"
+  integrity sha512-9X9uDYKk2U8w775OHj36s9Q7GkNAnJKGw6+sbkP5DpHSjELwKvTGzEK6+IISYfLpJRL/V3mRXMhgDnnJ5LkwJg==
+  dependencies:
+    "@types/d3-interpolate" "^2"
+    "@types/d3-selection" "^2"
+
+"@types/d3@^6.7.0":
+  version "6.7.5"
+  resolved "https://registry.yarnpkg.com/@types/d3/-/d3-6.7.5.tgz#6ae8034ea21db10fa3e31db1f670c5887d91d8a3"
+  integrity sha512-TUZ6zuT/KIvbHSv81kwAiO5gG5aTuoiLGnWR/KxHJ15Idy/xmGUXaaF5zMG+UMIsndcGlSHTmrvwRgdvZlNKaA==
+  dependencies:
+    "@types/d3-array" "^2"
+    "@types/d3-axis" "^2"
+    "@types/d3-brush" "^2"
+    "@types/d3-chord" "^2"
+    "@types/d3-color" "^2"
+    "@types/d3-contour" "^2"
+    "@types/d3-delaunay" "^5"
+    "@types/d3-dispatch" "^2"
+    "@types/d3-drag" "^2"
+    "@types/d3-dsv" "^2"
+    "@types/d3-ease" "^2"
+    "@types/d3-fetch" "^2"
+    "@types/d3-force" "^2"
+    "@types/d3-format" "^2"
+    "@types/d3-geo" "^2"
+    "@types/d3-hierarchy" "^2"
+    "@types/d3-interpolate" "^2"
+    "@types/d3-path" "^2"
+    "@types/d3-polygon" "^2"
+    "@types/d3-quadtree" "^2"
+    "@types/d3-random" "^2"
+    "@types/d3-scale" "^3"
+    "@types/d3-scale-chromatic" "^2"
+    "@types/d3-selection" "^2"
+    "@types/d3-shape" "^2"
+    "@types/d3-time" "^2"
+    "@types/d3-time-format" "^3"
+    "@types/d3-timer" "^2"
+    "@types/d3-transition" "^2"
+    "@types/d3-zoom" "^2"
+
 "@types/fbemitter@*":
   version "2.0.32"
   resolved "https://registry.yarnpkg.com/@types/fbemitter/-/fbemitter-2.0.32.tgz#8ed204da0f54e9c8eaec31b1eec91e25132d082c"
     "@types/fbemitter" "*"
     "@types/react" "*"
 
+"@types/geojson@*":
+  version "7946.0.8"
+  resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
+  integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
+
 "@types/glob-to-regexp@0.4.0":
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/@types/glob-to-regexp/-/glob-to-regexp-0.4.0.tgz#a295047724f4554be8192b4c779c5e44920a2fdc"
   dependencies:
     "@types/node" "*"
 
+"@types/mapbox-gl@^1.10.2":
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/@types/mapbox-gl/-/mapbox-gl-1.13.2.tgz#d20959d02b9ca17a2a3244387f1da763992ed11d"
+  integrity sha512-sv69WkijddNCIdLLyUsG90+X3Lh67a26lKsqaL8WbmXMkWITDrshe+sc9BI8oUV7sh+XD0jraI3qBe0NtJs7dw==
+  dependencies:
+    "@types/geojson" "*"
+
 "@types/marked@0.6.0":
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.6.0.tgz#e4ac316144a84afda5c2474488d7b9fef3ab9995"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
   integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
 
+"@types/prop-types@^15.7.5":
+  version "15.7.5"
+  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+  integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
 "@types/react-dom@17.0.11":
   version "17.0.11"
   resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.11.tgz#e1eadc3c5e86bdb5f7684e00274ae228e7bcc466"
   dependencies:
     "@types/react" "*"
 
+"@types/react-transition-group@^4.4.5":
+  version "4.4.5"
+  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416"
+  integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==
+  dependencies:
+    "@types/react" "*"
+
 "@types/react@*":
   version "17.0.14"
   resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.14.tgz#f0629761ca02945c4e8fea99b8177f4c5c61fb0f"
     "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
     "@webassemblyjs/wast-parser" "1.7.11"
 
+"@webassemblyjs/ast@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
+  integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==
+  dependencies:
+    "@webassemblyjs/helper-module-context" "1.9.0"
+    "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+    "@webassemblyjs/wast-parser" "1.9.0"
+
 "@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/floating-point-hex-parser@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4"
+  integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==
+
 "@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-api-error@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2"
+  integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==
+
 "@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-buffer@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00"
+  integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==
+
 "@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"
   dependencies:
     "@webassemblyjs/wast-printer" "1.7.11"
 
+"@webassemblyjs/helper-code-frame@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27"
+  integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==
+  dependencies:
+    "@webassemblyjs/wast-printer" "1.9.0"
+
 "@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-fsm@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8"
+  integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==
+
 "@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-module-context@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07"
+  integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+
 "@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-bytecode@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790"
+  integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==
+
 "@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"
     "@webassemblyjs/helper-wasm-bytecode" "1.7.11"
     "@webassemblyjs/wasm-gen" "1.7.11"
 
+"@webassemblyjs/helper-wasm-section@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346"
+  integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-buffer" "1.9.0"
+    "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+    "@webassemblyjs/wasm-gen" "1.9.0"
+
 "@webassemblyjs/ieee754@1.7.11":
   version "1.7.11"
   resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b"
   dependencies:
     "@xtuc/ieee754" "^1.2.0"
 
+"@webassemblyjs/ieee754@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4"
+  integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==
+  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"
   dependencies:
     "@xtuc/long" "4.2.1"
 
+"@webassemblyjs/leb128@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95"
+  integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==
+  dependencies:
+    "@xtuc/long" "4.2.2"
+
 "@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/utf8@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab"
+  integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==
+
 "@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"
     "@webassemblyjs/wasm-parser" "1.7.11"
     "@webassemblyjs/wast-printer" "1.7.11"
 
+"@webassemblyjs/wasm-edit@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf"
+  integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-buffer" "1.9.0"
+    "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+    "@webassemblyjs/helper-wasm-section" "1.9.0"
+    "@webassemblyjs/wasm-gen" "1.9.0"
+    "@webassemblyjs/wasm-opt" "1.9.0"
+    "@webassemblyjs/wasm-parser" "1.9.0"
+    "@webassemblyjs/wast-printer" "1.9.0"
+
 "@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"
     "@webassemblyjs/leb128" "1.7.11"
     "@webassemblyjs/utf8" "1.7.11"
 
+"@webassemblyjs/wasm-gen@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c"
+  integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+    "@webassemblyjs/ieee754" "1.9.0"
+    "@webassemblyjs/leb128" "1.9.0"
+    "@webassemblyjs/utf8" "1.9.0"
+
 "@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"
     "@webassemblyjs/wasm-gen" "1.7.11"
     "@webassemblyjs/wasm-parser" "1.7.11"
 
+"@webassemblyjs/wasm-opt@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61"
+  integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-buffer" "1.9.0"
+    "@webassemblyjs/wasm-gen" "1.9.0"
+    "@webassemblyjs/wasm-parser" "1.9.0"
+
 "@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"
     "@webassemblyjs/leb128" "1.7.11"
     "@webassemblyjs/utf8" "1.7.11"
 
+"@webassemblyjs/wasm-parser@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e"
+  integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-api-error" "1.9.0"
+    "@webassemblyjs/helper-wasm-bytecode" "1.9.0"
+    "@webassemblyjs/ieee754" "1.9.0"
+    "@webassemblyjs/leb128" "1.9.0"
+    "@webassemblyjs/utf8" "1.9.0"
+
 "@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"
     "@webassemblyjs/helper-fsm" "1.7.11"
     "@xtuc/long" "4.2.1"
 
+"@webassemblyjs/wast-parser@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914"
+  integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/floating-point-hex-parser" "1.9.0"
+    "@webassemblyjs/helper-api-error" "1.9.0"
+    "@webassemblyjs/helper-code-frame" "1.9.0"
+    "@webassemblyjs/helper-fsm" "1.9.0"
+    "@xtuc/long" "4.2.2"
+
 "@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"
     "@webassemblyjs/wast-parser" "1.7.11"
     "@xtuc/long" "4.2.1"
 
+"@webassemblyjs/wast-printer@1.9.0":
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899"
+  integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/wast-parser" "1.9.0"
+    "@xtuc/long" "4.2.2"
+
 "@xtuc/ieee754@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8"
   integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==
 
+"@xtuc/long@4.2.2":
+  version "4.2.2"
+  resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+  integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
 "@zkochan/cmd-shim@^3.1.0":
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e"
@@ -2310,7 +2972,7 @@ acorn@^5.0.0, acorn@^5.5.3, acorn@^5.6.2:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
   integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
 
-acorn@^6.0.1:
+acorn@^6.0.1, acorn@^6.4.1:
   version "6.4.2"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
   integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
@@ -2341,12 +3003,12 @@ ajv-errors@^1.0.0:
   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:
+ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
   version "3.5.2"
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
   integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
 
-ajv@^6.1.0, ajv@^6.12.3:
+ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.3:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
   integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2356,11 +3018,6 @@ ajv@^6.1.0, ajv@^6.12.3:
     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"
@@ -2535,7 +3192,7 @@ arrify@^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:
+asap@^2.0.0:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
   integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
@@ -2585,11 +3242,6 @@ async-each@^1.0.1:
   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"
@@ -2751,6 +3403,15 @@ babel-plugin-macros@^2.6.1:
     cosmiconfig "^6.0.0"
     resolve "^1.12.0"
 
+babel-plugin-macros@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
+  integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+  dependencies:
+    "@babel/runtime" "^7.12.5"
+    cosmiconfig "^7.0.0"
+    resolve "^1.19.0"
+
 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"
@@ -2893,13 +3554,6 @@ bindings@^1.5.0:
   dependencies:
     file-uri-to-path "1.0.0"
 
-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.3, bluebird@^3.5.5:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -3311,11 +3965,6 @@ camelcase@^2.0.0:
   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"
@@ -3343,7 +3992,7 @@ caseless@~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:
+chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
@@ -3435,7 +4084,7 @@ chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
   integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
 
-chrome-trace-event@^1.0.0:
+chrome-trace-event@^1.0.0, chrome-trace-event@^1.0.2:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
   integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
@@ -3492,15 +4141,6 @@ cli-width@^2.0.0:
   resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
   integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
 
-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"
@@ -3519,16 +4159,6 @@ cliui@^5.0.0:
     strip-ansi "^5.2.0"
     wrap-ansi "^5.1.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-deep@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
@@ -3543,16 +4173,16 @@ clone@^1.0.2:
   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.1.0, clsx@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
   integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
 
+clsx@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
+  integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
 co@^4.6.0:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -3623,6 +4253,11 @@ commander@2.17.x:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
   integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
 
+commander@7:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+  integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
 commander@^2.12.1, commander@^2.19.0, commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -3903,6 +4538,17 @@ cosmiconfig@^6.0.0:
     path-type "^4.0.0"
     yaml "^1.7.2"
 
+cosmiconfig@^7.0.0:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
+  integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
+  dependencies:
+    "@types/parse-json" "^4.0.0"
+    import-fresh "^3.2.1"
+    parse-json "^5.0.0"
+    path-type "^4.0.0"
+    yaml "^1.10.0"
+
 create-ecdh@^4.0.0:
   version "4.0.4"
   resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@@ -3934,14 +4580,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
     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"
@@ -4020,6 +4658,11 @@ css-what@^5.0.0:
   resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.1.tgz#3efa820131f4669a8ac2408f9c32e7c7de9f4cad"
   integrity sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==
 
+csscolorparser@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b"
+  integrity sha1-s085HupNqPPpgjHizNjfnAQfFxs=
+
 cssesc@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
@@ -4057,17 +4700,266 @@ csstype@^3.0.2:
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.8.tgz#d2266a792729fb227cd216fb572f43728e1ad340"
   integrity sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==
 
-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=
+csstype@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
+  integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
+
+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=
+
+"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.0.1.tgz#ca45c263f5bb780ab5a34a6e1d3d5883fe4a8d14"
+  integrity sha512-l3Bh5o8RSoC3SBm5ix6ogaFW+J6rOUm42yOtZ2sQPCEvCqUMepeX7zgrlLLGIemxgOyo9s2CsWEidnLv5PwwRw==
+  dependencies:
+    internmap "1 - 2"
+
+d3-axis@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322"
+  integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==
+
+d3-brush@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c"
+  integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==
+  dependencies:
+    d3-dispatch "1 - 3"
+    d3-drag "2 - 3"
+    d3-interpolate "1 - 3"
+    d3-selection "3"
+    d3-transition "3"
+
+d3-chord@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966"
+  integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==
+  dependencies:
+    d3-path "1 - 3"
+
+"d3-color@1 - 3", d3-color@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a"
+  integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw==
+
+d3-contour@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd"
+  integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ==
+  dependencies:
+    d3-array "2 - 3"
+
+d3-delaunay@6:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92"
+  integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==
+  dependencies:
+    delaunator "5"
+
+"d3-dispatch@1 - 3", d3-dispatch@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
+  integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
+
+"d3-drag@2 - 3", d3-drag@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
+  integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
+  dependencies:
+    d3-dispatch "1 - 3"
+    d3-selection "3"
+
+"d3-dsv@1 - 3", d3-dsv@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
+  integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
+  dependencies:
+    commander "7"
+    iconv-lite "0.6"
+    rw "1"
+
+"d3-ease@1 - 3", d3-ease@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
+  integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
+
+d3-fetch@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22"
+  integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==
+  dependencies:
+    d3-dsv "1 - 3"
+
+d3-force@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4"
+  integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==
+  dependencies:
+    d3-dispatch "1 - 3"
+    d3-quadtree "1 - 3"
+    d3-timer "1 - 3"
+
+"d3-format@1 - 3", d3-format@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.0.1.tgz#e41b81b2ab79277141ec1404aa5d05001da64084"
+  integrity sha512-hdL7+HBIohpgfolhBxr1KX47VMD6+vVD/oEFrxk5yhmzV2prk99EkFKYpXuhVkFpTgHdJ6/4bYcjdLPPXV4tIA==
+
+d3-geo@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e"
+  integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==
+  dependencies:
+    d3-array "2.5.0 - 3"
+
+d3-hierarchy@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.0.1.tgz#0365342d54972e38ca05e9143e0ab1c60846b3b5"
+  integrity sha512-RlLTaofEoOrMK1JoXYIGhKTkJFI/6rFrYPgxy6QlZo2BcVc4HGTqEU0rPpzuMq5T/5XcMtAzv1XiLA3zRTfygw==
+
+"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+  integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+  dependencies:
+    d3-color "1 - 3"
+
+"d3-path@1 - 3", d3-path@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e"
+  integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==
+
+d3-polygon@3, d3-polygon@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
+  integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
+
+"d3-quadtree@1 - 3", d3-quadtree@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
+  integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
+
+d3-random@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4"
+  integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==
+
+d3-scale-chromatic@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a"
+  integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==
+  dependencies:
+    d3-color "1 - 3"
+    d3-interpolate "1 - 3"
+
+d3-scale@4:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.0.tgz#294377ea1d7e5a31509ee648b98d7916ac0b34e3"
+  integrity sha512-foHQYKpWQcyndH1CGoHdUC4PECxTxonzwwBXGT8qu+Drb1FIc6ON6dG2P5f4hRRMkLiIKeWK7iFtdznDUrnuPQ==
+  dependencies:
+    d3-array "2.10.0 - 3"
+    d3-format "1 - 3"
+    d3-interpolate "1.2.0 - 3"
+    d3-time "2.1.1 - 3"
+    d3-time-format "2 - 4"
+
+"d3-selection@2 - 3", d3-selection@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
+  integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
+
+d3-shape@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.0.1.tgz#9ccdfb28fd9b0d12f2d8aec234cd5c4a9ea27931"
+  integrity sha512-HNZNEQoDhuCrDWEc/BMbF/hKtzMZVoe64TvisFLDp2Iyj0UShB/E6/lBsLlJTfBMbYgftHj90cXJ0SEitlE6Xw==
+  dependencies:
+    d3-path "1 - 3"
+
+"d3-time-format@2 - 4", d3-time-format@4:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.0.0.tgz#930ded86a9de761702344760d8a25753467f28b7"
+  integrity sha512-nzaCwlj+ZVBIlFuVOT1RmU+6xb/7D5IcnhHzHQcBgS/aTa5K9fWZNN5LCXA27LgF5WxoSNJqKBbLcGMtM6Ca6A==
+  dependencies:
+    d3-time "1 - 3"
+
+"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
+  integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
+  dependencies:
+    d3-array "2 - 3"
+
+"d3-timer@1 - 3", d3-timer@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
+  integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
+
+"d3-transition@2 - 3", d3-transition@3:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
+  integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
+  dependencies:
+    d3-color "1 - 3"
+    d3-dispatch "1 - 3"
+    d3-ease "1 - 3"
+    d3-interpolate "1 - 3"
+    d3-timer "1 - 3"
+
+d3-zoom@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
+  integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
   dependencies:
-    array-find-index "^1.0.1"
+    d3-dispatch "1 - 3"
+    d3-drag "2 - 3"
+    d3-interpolate "1 - 3"
+    d3-selection "2 - 3"
+    d3-transition "2 - 3"
 
-cyclist@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
-  integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
+d3@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/d3/-/d3-7.0.0.tgz#fe6036b38ba2026ff34223e208fd294db1b997da"
+  integrity sha512-t+jEKGO2jQiSBLJYYq6RFc500tsCeXBB4x41oQaSnZD3Som95nQrlw9XJGrFTMUOQOkwSMauWy9+8Tz1qm9UZw==
+  dependencies:
+    d3-array "3"
+    d3-axis "3"
+    d3-brush "3"
+    d3-chord "3"
+    d3-color "3"
+    d3-contour "3"
+    d3-delaunay "6"
+    d3-dispatch "3"
+    d3-drag "3"
+    d3-dsv "3"
+    d3-ease "3"
+    d3-fetch "3"
+    d3-force "3"
+    d3-format "3"
+    d3-geo "3"
+    d3-hierarchy "3"
+    d3-interpolate "3"
+    d3-path "3"
+    d3-polygon "3"
+    d3-quadtree "3"
+    d3-random "3"
+    d3-scale "4"
+    d3-scale-chromatic "3"
+    d3-selection "3"
+    d3-shape "3"
+    d3-time "3"
+    d3-time-format "4"
+    d3-timer "3"
+    d3-transition "3"
+    d3-zoom "3"
 
 dargs@^4.0.1:
   version "4.1.0"
@@ -4240,6 +5132,13 @@ del@^3.0.0:
     pify "^3.0.0"
     rimraf "^2.2.8"
 
+delaunator@5:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b"
+  integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==
+  dependencies:
+    robust-predicates "^3.0.0"
+
 delayed-stream@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -4443,6 +5342,11 @@ duplexify@^3.4.2, duplexify@^3.6.0:
     readable-stream "^2.0.0"
     stream-shift "^1.0.0"
 
+earcut@^2.2.2:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.3.tgz#d44ced2ff5a18859568e327dd9c7d46b16f55cf4"
+  integrity sha512-iRDI1QeCQIhMCZk48DRDMVgQSSBDmbzzNhnxIo+pwx3swkfjMh6vh0nWLq1NdvGHLKH6wIrAM3vQWeTj6qeoug==
+
 ecc-jsbn@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
@@ -4525,7 +5429,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
-enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
+enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0, enhanced-resolve@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
   integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
@@ -4554,7 +5458,7 @@ err-code@^1.0.0:
   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:
+errno@^0.1.3, errno@~0.1.7:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
   integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
@@ -4568,7 +5472,7 @@ error-ex@^1.2.0, error-ex@^1.3.1:
   dependencies:
     is-arrayish "^0.2.1"
 
-es-abstract@^1.18.0-next.2:
+es-abstract@^1.18.0-next.2, es-abstract@^1.18.2:
   version "1.18.3"
   resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.3.tgz#25c4c3380a27aa203c44b2b685bba94da31b63e0"
   integrity sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==
@@ -4648,7 +5552,7 @@ escodegen@^1.9.1:
   optionalDependencies:
     source-map "~0.6.1"
 
-eslint-scope@^4.0.0:
+eslint-scope@^4.0.0, eslint-scope@^4.0.3:
   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==
@@ -5133,11 +6037,6 @@ for-each@^0.3.3:
   dependencies:
     is-callable "^1.1.3"
 
-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"
@@ -5150,13 +6049,6 @@ for-own@^0.1.4:
   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"
@@ -5240,16 +6132,6 @@ fsevents@~2.3.2:
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
   integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
 
-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"
@@ -5269,18 +6151,16 @@ gauge@~2.7.3:
     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==
 
+geojson-vt@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
+  integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
+
 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"
@@ -5333,6 +6213,11 @@ get-stream@^4.0.0, get-stream@^4.1.0:
   dependencies:
     pump "^3.0.0"
 
+get-stream@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+  integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
 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"
@@ -5399,6 +6284,11 @@ github-markdown-css@2.10.0:
   resolved "https://registry.yarnpkg.com/github-markdown-css/-/github-markdown-css-2.10.0.tgz#0612fed22816b33b282f37ef8def7a4ecabfe993"
   integrity sha512-RX5VUC54uX6Lvrm226M9kMzsNeOa81MnKyxb3J0G5KLjyoOySOZgwyKFkUpv6iUhooiUZdogk+OTwQPJ4WttYg==
 
+gl-matrix@^3.2.1:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.3.0.tgz#232eef60b1c8b30a28cbbe75b2caf6c48fd6358b"
+  integrity sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==
+
 glob-base@^0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@@ -5439,7 +6329,7 @@ glob-to-regexp@^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:
+glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
   version "7.1.7"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
   integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
@@ -5523,15 +6413,6 @@ globby@^9.2.0:
     pify "^4.0.1"
     slash "^2.0.0"
 
-globule@^1.0.0:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4"
-  integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==
-  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"
@@ -5542,6 +6423,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
   integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
 
+grid-index@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7"
+  integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==
+
 growly@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -5930,7 +6816,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-iconv-lite@^0.6.2:
+iconv-lite@0.6, iconv-lite@^0.6.2:
   version "0.6.3"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
   integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@@ -5949,7 +6835,7 @@ icss-utils@^2.1.0:
   dependencies:
     postcss "^6.0.1"
 
-ieee754@^1.1.4:
+ieee754@^1.1.12, ieee754@^1.1.4:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@@ -5976,11 +6862,6 @@ ignore@^4.0.3:
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
   integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
 
-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"
@@ -5996,7 +6877,7 @@ import-fresh@^2.0.0:
     caller-path "^2.0.0"
     resolve-from "^3.0.0"
 
-import-fresh@^3.1.0:
+import-fresh@^3.1.0, import-fresh@^3.2.1:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
   integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
@@ -6032,11 +6913,6 @@ imurmurhash@^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.1"
-  resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.1.tgz#948b1a535c8030561cea522f73f78f4be357e00c"
-  integrity sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==
-
 indent-string@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
@@ -6067,7 +6943,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, 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==
@@ -6128,6 +7004,11 @@ internal-ip@^3.0.1:
     default-gateway "^2.6.0"
     ipaddr.js "^1.5.2"
 
+"internmap@1 - 2":
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.1.tgz#33d0fa016185397549fb1a14ea3dbe5a2949d1cd"
+  integrity sha512-Ujwccrj9FkGqjbY3iVoxD1VV+KdZZeENx0rphrtzmRXbFvkFO88L80BL/zeSIguX/7T+y8k04xqtgWgS5vxwxw==
+
 interpret@^1.1.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
@@ -6145,11 +7026,6 @@ inversify@^5.0.0:
   resolved "https://registry.yarnpkg.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730"
   integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ==
 
-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"
@@ -6253,6 +7129,13 @@ is-core-module@^2.2.0:
   dependencies:
     has "^1.0.3"
 
+is-core-module@^2.9.0:
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed"
+  integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==
+  dependencies:
+    has "^1.0.3"
+
 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"
@@ -6950,11 +7833,6 @@ jquery@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.6.4"
-  resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
-  integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
-
 js-levenshtein@^1.1.3:
   version "1.1.6"
   resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
@@ -7125,6 +8003,15 @@ jss-plugin-camel-case@^10.8.2:
     hyphenate-style-name "^1.0.3"
     jss "10.8.2"
 
+jss-plugin-camel-case@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.2.tgz#76dddfa32f9e62d17daa4e3504991fd0933b89e1"
+  integrity sha512-wgBPlL3WS0WDJ1lPJcgjux/SHnDuu7opmgQKSraKs4z8dCCyYMx9IDPFKBXQ8Q5dVYij1FFV0WdxyhuOOAXuTg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    hyphenate-style-name "^1.0.3"
+    jss "10.9.2"
+
 jss-plugin-default-unit@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.8.2.tgz#c66f12e02e0815d911b85c02c2a979ee7b4ce69a"
@@ -7133,6 +8020,14 @@ jss-plugin-default-unit@^10.8.2:
     "@babel/runtime" "^7.3.1"
     jss "10.8.2"
 
+jss-plugin-default-unit@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.2.tgz#3e7f4a1506b18d8fe231554fd982439feb2a9c53"
+  integrity sha512-pYg0QX3bBEFtTnmeSI3l7ad1vtHU42YEEpgW7pmIh+9pkWNWb5dwS/4onSfAaI0kq+dOZHzz4dWe+8vWnanoSg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
 jss-plugin-global@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.8.2.tgz#1a35632a693cf50113bcc5ffe6b51969df79c4ec"
@@ -7141,6 +8036,14 @@ jss-plugin-global@^10.8.2:
     "@babel/runtime" "^7.3.1"
     jss "10.8.2"
 
+jss-plugin-global@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.9.2.tgz#e7f2ad4a5e8e674fb703b04b57a570b8c3e5c2c2"
+  integrity sha512-GcX0aE8Ef6AtlasVrafg1DItlL/tWHoC4cGir4r3gegbWwF5ZOBYhx04gurPvWHC8F873aEGqge7C17xpwmp2g==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
 jss-plugin-nested@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.8.2.tgz#79f3c7f75ea6a36ae72fe52e777035bb24d230c7"
@@ -7150,6 +8053,15 @@ jss-plugin-nested@^10.8.2:
     jss "10.8.2"
     tiny-warning "^1.0.2"
 
+jss-plugin-nested@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.9.2.tgz#3aa2502816089ecf3981e1a07c49b276d67dca63"
+  integrity sha512-VgiOWIC6bvgDaAL97XCxGD0BxOKM0K0zeB/ECyNaVF6FqvdGB9KBBWRdy2STYAss4VVA7i5TbxFZN+WSX1kfQA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
 jss-plugin-props-sort@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.8.2.tgz#e25a7471868652c394562b6dc5433dcaea7dff6f"
@@ -7158,6 +8070,14 @@ jss-plugin-props-sort@^10.8.2:
     "@babel/runtime" "^7.3.1"
     jss "10.8.2"
 
+jss-plugin-props-sort@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.2.tgz#645f6c8f179309667b3e6212f66b59a32fb3f01f"
+  integrity sha512-AP1AyUTbi2szylgr+O0OB7gkIxEGzySLITZ2GpsaoX72YMCGI2jYAc+WUhPfvUnZYiauF4zTnN4V4TGuvFjJlw==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+
 jss-plugin-rule-value-function@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.8.2.tgz#55354b55f1b2968a15976729968f767f02d64049"
@@ -7167,6 +8087,15 @@ jss-plugin-rule-value-function@^10.8.2:
     jss "10.8.2"
     tiny-warning "^1.0.2"
 
+jss-plugin-rule-value-function@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.2.tgz#9afe07596e477123cbf11120776be6a64494541f"
+  integrity sha512-vf5ms8zvLFMub6swbNxvzsurHfUZ5Shy5aJB2gIpY6WNA3uLinEcxYyraQXItRHi5ivXGqYciFDRM2ZoVoRZ4Q==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    jss "10.9.2"
+    tiny-warning "^1.0.2"
+
 jss-plugin-vendor-prefixer@^10.8.2:
   version "10.8.2"
   resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.8.2.tgz#ebb4a482642f34091e454901e21176441dd5f475"
@@ -7176,6 +8105,15 @@ jss-plugin-vendor-prefixer@^10.8.2:
     css-vendor "^2.0.8"
     jss "10.8.2"
 
+jss-plugin-vendor-prefixer@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.2.tgz#410a0f3b9f8dbbfba58f4d329134df4849aa1237"
+  integrity sha512-SxcEoH+Rttf9fEv6KkiPzLdXRmI6waOTcMkbbEFgdZLDYNIP9UKNHFy6thhbRKqv0XMQZdrEsbDyV464zE/dUA==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    css-vendor "^2.0.8"
+    jss "10.9.2"
+
 jss@10.0.3:
   version "10.0.3"
   resolved "https://registry.yarnpkg.com/jss/-/jss-10.0.3.tgz#5c160f96aa8ce8b9f851ee0b33505dcd37f490a4"
@@ -7196,6 +8134,16 @@ jss@10.8.2, jss@^10.8.2:
     is-in-browser "^1.1.3"
     tiny-warning "^1.0.2"
 
+jss@10.9.2, jss@^10.9.1:
+  version "10.9.2"
+  resolved "https://registry.yarnpkg.com/jss/-/jss-10.9.2.tgz#9379be1f195ef98011dfd31f9448251bd61b95a9"
+  integrity sha512-b8G6rWpYLR4teTUbGd4I4EsnWjg7MN0Q5bSsjKhVkJVjhQDy2KzkbD2AW3TuT0RYZVmZZHKIrXDn6kjU14qkUg==
+  dependencies:
+    "@babel/runtime" "^7.3.1"
+    csstype "^3.0.2"
+    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"
@@ -7213,6 +8161,11 @@ jws@^3.1.5:
     jwa "^1.4.1"
     safe-buffer "^5.0.1"
 
+kdbush@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0"
+  integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
+
 killable@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -7247,13 +8200,6 @@ kleur@^2.0.1:
   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"
@@ -7290,31 +8236,6 @@ lerna@3.22.1:
     import-local "^2.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"
@@ -7370,7 +8291,7 @@ load-json-file@^5.3.0:
     strip-bom "^3.0.0"
     type-fest "^0.3.0"
 
-loader-runner@^2.3.0:
+loader-runner@^2.3.0, loader-runner@^2.4.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
   integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
@@ -7395,7 +8316,7 @@ loader-utils@^0.2.16:
     json5 "^0.5.0"
     object-assign "^4.0.1"
 
-loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0:
+loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
   integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@@ -7497,11 +8418,6 @@ lodash.sortby@^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, lodash.template@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
@@ -7522,7 +8438,7 @@ lodash.uniq@^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.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.10:
+lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
   version "4.17.21"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -7552,7 +8468,7 @@ lower-case@^1.1.1:
   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:
+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==
@@ -7657,6 +8573,35 @@ map-visit@^1.0.0:
   dependencies:
     object-visit "^1.0.0"
 
+mapbox-gl@^1.11.0:
+  version "1.13.1"
+  resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-1.13.1.tgz#322efe75ab4c764fc4c776da1506aad58d5a5b9d"
+  integrity sha512-GSyubcoSF5MyaP8z+DasLu5v7KmDK2pp4S5+VQ5WdVQUOaAqQY4jwl4JpcdNho3uWm2bIKs7x1l7q3ynGmW60g==
+  dependencies:
+    "@mapbox/geojson-rewind" "^0.5.0"
+    "@mapbox/geojson-types" "^1.0.2"
+    "@mapbox/jsonlint-lines-primitives" "^2.0.2"
+    "@mapbox/mapbox-gl-supported" "^1.5.0"
+    "@mapbox/point-geometry" "^0.1.0"
+    "@mapbox/tiny-sdf" "^1.1.1"
+    "@mapbox/unitbezier" "^0.0.0"
+    "@mapbox/vector-tile" "^1.3.1"
+    "@mapbox/whoots-js" "^3.1.0"
+    csscolorparser "~1.0.3"
+    earcut "^2.2.2"
+    geojson-vt "^3.2.1"
+    gl-matrix "^3.2.1"
+    grid-index "^1.1.0"
+    minimist "^1.2.5"
+    murmurhash-js "^1.0.0"
+    pbf "^3.2.1"
+    potpack "^1.0.1"
+    quickselect "^2.0.0"
+    rw "^1.3.3"
+    supercluster "^7.1.0"
+    tinyqueue "^2.0.3"
+    vt-pbf "^3.1.1"
+
 marked@0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.0.tgz#a18d01cfdcf8d15c3c455b71c8329e5e0f01faa1"
@@ -7695,23 +8640,23 @@ mem@^4.0.0:
     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==
+memory-fs@^0.4.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"
 
-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=
+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"
 
-meow@^3.3.0, meow@^3.7.0:
+meow@^3.3.0:
   version "3.7.0"
   resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
   integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
@@ -7844,7 +8789,7 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
   dependencies:
     mime-db "1.48.0"
 
-mime@1.6.0, mime@^1.4.1, mime@^1.6.0:
+mime@1.6.0, 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==
@@ -7887,7 +8832,7 @@ minimalistic-crypto-utils@^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.3, minimatch@^3.0.4, minimatch@~3.0.2:
+minimatch@^3.0.3, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -7976,14 +8921,6 @@ mixin-deep@^1.2.0:
     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-promise@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1"
@@ -7996,7 +8933,7 @@ mkdirp@*:
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
   integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 
-mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.0:
+mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.0:
   version "0.5.5"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
   integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
@@ -8068,6 +9005,11 @@ multimatch@^3.0.0:
     arrify "^1.0.1"
     minimatch "^3.0.4"
 
+murmurhash-js@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
+  integrity sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=
+
 mute-stream@0.0.7:
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
@@ -8087,7 +9029,7 @@ mz@^2.5.0:
     object-assign "^4.0.1"
     thenify-all "^1.0.0"
 
-nan@^2.12.1, nan@^2.13.2:
+nan@^2.12.1:
   version "2.14.2"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
   integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
@@ -8119,7 +9061,7 @@ negotiator@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:
+neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
   integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
@@ -8155,24 +9097,6 @@ node-forge@^0.10.0:
   resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
   integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
 
-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@^5.0.2:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e"
@@ -8195,7 +9119,7 @@ node-int64@^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:
+node-libs-browser@^2.0.0, node-libs-browser@^2.2.1:
   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==
@@ -8240,36 +9164,6 @@ node-releases@^1.1.71:
   resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20"
   integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==
 
-node-sass@4.12.0:
-  version "4.12.0"
-  resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.12.0.tgz#0914f531932380114a30cc5fa4fa63233a25f017"
-  integrity sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==
-  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 "^4.17.11"
-    meow "^3.7.0"
-    mkdirp "^0.5.1"
-    nan "^2.13.2"
-    node-gyp "^3.8.0"
-    npmlog "^4.0.0"
-    request "^2.88.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.3"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
@@ -8389,7 +9283,7 @@ npm-run-path@^2.0.0:
   dependencies:
     path-key "^2.0.0"
 
-"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.1.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==
@@ -8499,6 +9393,15 @@ object.pick@^1.3.0:
   dependencies:
     isobject "^3.0.1"
 
+object.values@^1.1.1:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30"
+  integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.3"
+    es-abstract "^1.18.2"
+
 obuf@^1.0.0, obuf@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
@@ -8584,13 +9487,6 @@ os-homedir@^1.0.0:
   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"
@@ -8613,7 +9509,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~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:
+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==
@@ -8883,7 +9779,7 @@ path-key@^2.0.0, path-key@^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:
+path-parse@^1.0.5, path-parse@^1.0.6, path-parse@^1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
   integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
@@ -8921,6 +9817,14 @@ path-type@^4.0.0:
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
   integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
 
+pbf@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.2.1.tgz#b4c1b9e72af966cd82c6531691115cc0409ffe2a"
+  integrity sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==
+  dependencies:
+    ieee754 "^1.1.12"
+    resolve-protobuf-schema "^2.1.0"
+
 pbkdf2@^3.0.3:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
@@ -9074,6 +9978,11 @@ postcss@^7.0.0, postcss@^7.0.2:
     source-map "^0.6.1"
     supports-color "^6.1.0"
 
+potpack@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.1.tgz#d1b1afd89e4c8f7762865ec30bd112ab767e2ebf"
+  integrity sha512-15vItUAbViaYrmaB/Pbw7z6qX2xENbFSTA7Ii4tgbPtasxm5v6ryKhKtL91tpWovDJzTiZqdwzhcFBCwiMVdVw==
+
 prelude-ls@~1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -9128,13 +10037,6 @@ promise-retry@^1.1.1:
     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"
@@ -9159,11 +10061,25 @@ prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.2, prop-types@^15.7.2:
     object-assign "^4.1.1"
     react-is "^16.8.1"
 
+prop-types@^15.8.1:
+  version "15.8.1"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+  integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+  dependencies:
+    loose-envify "^1.4.0"
+    object-assign "^4.1.1"
+    react-is "^16.13.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=
 
+protocol-buffers-schema@^3.3.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.5.1.tgz#8388e768d383ac8cbea23e1280dfadb79f4122ad"
+  integrity sha512-YVCvdhxWNDP8/nJDyXLuM+UFsuPk4+1PB7WGPVDzm3HTHbzFLxQYeW2iZpS4mmnXrQJGBzt230t/BbEb7PrQaw==
+
 protocols@^1.1.0, protocols@^1.4.0:
   version "1.4.8"
   resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
@@ -9313,6 +10229,11 @@ quick-lru@^4.0.1:
   resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
   integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
 
+quickselect@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
+  integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
+
 randomatic@^3.0.0:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
@@ -9376,7 +10297,7 @@ react-dom@17.0.2:
     object-assign "^4.1.1"
     scheduler "^0.20.2"
 
-react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
+react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -9386,6 +10307,11 @@ react-is@^17.0.2:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
   integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
 
+react-is@^18.2.0:
+  version "18.2.0"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+  integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
 react-router-dom@5.2.0:
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
@@ -9435,6 +10361,16 @@ react-transition-group@^4.4.2:
     loose-envify "^1.4.0"
     prop-types "^15.6.2"
 
+react-transition-group@^4.4.5:
+  version "4.4.5"
+  resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
+  integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+  dependencies:
+    "@babel/runtime" "^7.5.5"
+    dom-helpers "^5.0.1"
+    loose-envify "^1.4.0"
+    prop-types "^15.6.2"
+
 react@17.0.2:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@@ -9743,7 +10679,7 @@ request-promise-native@^1.0.5:
     stealthy-require "^1.1.1"
     tough-cookie "^2.3.3"
 
-request@^2.83.0, request@^2.87.0, request@^2.88.0:
+request@^2.87.0, request@^2.88.0:
   version "2.88.2"
   resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
   integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
@@ -9831,6 +10767,13 @@ resolve-pathname@^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-protobuf-schema@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
+  integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==
+  dependencies:
+    protocol-buffers-schema "^3.3.1"
+
 resolve-url@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -9849,6 +10792,15 @@ resolve@1.x, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.20.0, resolve@^1.3.2:
     is-core-module "^2.2.0"
     path-parse "^1.0.6"
 
+resolve@^1.19.0:
+  version "1.22.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
+  integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+  dependencies:
+    is-core-module "^2.9.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
 restore-cursor@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@@ -9867,18 +10819,6 @@ retry@^0.10.0:
   resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
   integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
 
-rifm@^0.12.1:
-  version "0.12.1"
-  resolved "https://registry.yarnpkg.com/rifm/-/rifm-0.12.1.tgz#8fa77f45b7f1cda2a0068787ac821f0593967ac4"
-  integrity sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==
-
-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"
@@ -9886,6 +10826,13 @@ rimraf@2.6.2:
   dependencies:
     glob "^7.0.5"
 
+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"
+
 ripemd160@^2.0.0, ripemd160@^2.0.1:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@@ -9894,6 +10841,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
     hash-base "^3.0.0"
     inherits "^2.0.1"
 
+robust-predicates@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a"
+  integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==
+
 rsvp@^3.3.3:
   version "3.6.2"
   resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
@@ -9911,6 +10863,11 @@ run-queue@^1.0.0, run-queue@^1.0.3:
   dependencies:
     aproba "^1.1.1"
 
+rw@1, rw@^1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
+  integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
+
 rxjs@^6.4.0:
   version "6.6.7"
   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
@@ -9956,28 +10913,6 @@ sane@^2.0.0:
   optionalDependencies:
     fsevents "^1.2.3"
 
-sass-graph@^2.2.4:
-  version "2.2.6"
-  resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.6.tgz#09fda0e4287480e3e4967b72a2d133ba09b8d827"
-  integrity sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g==
-  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"
@@ -10008,14 +10943,6 @@ schema-utils@^1.0.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"
@@ -10045,11 +10972,6 @@ semver@^7.3.4:
   dependencies:
     lru-cache "^6.0.0"
 
-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"
@@ -10142,15 +11064,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
     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"
-
 shallow-clone@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
@@ -10323,13 +11236,6 @@ source-map-url@^0.4.0:
   resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
   integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
 
-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"
@@ -10476,13 +11382,6 @@ static-extend@^0.1.1:
   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"
@@ -10533,7 +11432,7 @@ string-length@^2.0.0:
     astral-regex "^1.0.0"
     strip-ansi "^4.0.0"
 
-string-width@^1.0.1, string-width@^1.0.2:
+string-width@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
   integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
@@ -10663,11 +11562,23 @@ style-loader@0.23.0:
     loader-utils "^1.1.0"
     schema-utils "^0.4.5"
 
+stylis@4.0.13:
+  version "4.0.13"
+  resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91"
+  integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==
+
 stylis@^4.0.10, stylis@^4.0.3:
   version "4.0.10"
   resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240"
   integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==
 
+supercluster@^7.1.0:
+  version "7.1.3"
+  resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-7.1.3.tgz#8c5412c7d7e53b010f7514e87f279544babc3425"
+  integrity sha512-7+bR4FbF5SYsmkHfDp61QiwCKtwNDyPsddk9TzfsDA5DQr5Goii5CVD2SXjglweFCxjrzVZf945ahqYfUIk8UA==
+  dependencies:
+    kdbush "^3.0.0"
+
 supports-color@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -10694,25 +11605,21 @@ supports-color@^6.1.0:
   dependencies:
     has-flag "^3.0.0"
 
+supports-preserve-symlinks-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+  integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
 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:
+tapable@^1.0.0, tapable@^1.1.0, tapable@^1.1.3:
   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.4.10, tar@^4.4.12, tar@^4.4.8:
   version "4.4.13"
   resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
@@ -10757,7 +11664,7 @@ terser-webpack-plugin@1.2.1:
     webpack-sources "^1.1.0"
     worker-farm "^1.5.2"
 
-terser-webpack-plugin@^1.1.0:
+terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.4.3:
   version "1.4.5"
   resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b"
   integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==
@@ -10875,6 +11782,11 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
   resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
   integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
 
+tinyqueue@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
+  integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
+
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -10984,13 +11896,6 @@ trim-right@^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"
@@ -11495,6 +12400,15 @@ vm-browserify@^1.0.1:
   resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
   integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
 
+vt-pbf@^3.1.1:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac"
+  integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==
+  dependencies:
+    "@mapbox/point-geometry" "0.1.0"
+    "@mapbox/vector-tile" "^1.3.1"
+    pbf "^3.2.1"
+
 w3c-hr-time@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
@@ -11524,7 +12438,7 @@ watchpack-chokidar2@^2.0.1:
   dependencies:
     chokidar "^2.1.8"
 
-watchpack@^1.5.0:
+watchpack@^1.5.0, watchpack@^1.7.4:
   version "1.7.5"
   resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453"
   integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==
@@ -11627,7 +12541,7 @@ webpack-log@^2.0.0:
     ansi-colors "^3.0.0"
     uuid "^3.3.2"
 
-webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0:
+webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1:
   version "1.4.3"
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
   integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
@@ -11665,6 +12579,35 @@ webpack@4.28.4:
     watchpack "^1.5.0"
     webpack-sources "^1.3.0"
 
+webpack@^4.44.2:
+  version "4.46.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"
+  integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==
+  dependencies:
+    "@webassemblyjs/ast" "1.9.0"
+    "@webassemblyjs/helper-module-context" "1.9.0"
+    "@webassemblyjs/wasm-edit" "1.9.0"
+    "@webassemblyjs/wasm-parser" "1.9.0"
+    acorn "^6.4.1"
+    ajv "^6.10.2"
+    ajv-keywords "^3.4.1"
+    chrome-trace-event "^1.0.2"
+    enhanced-resolve "^4.5.0"
+    eslint-scope "^4.0.3"
+    json-parse-better-errors "^1.0.2"
+    loader-runner "^2.4.0"
+    loader-utils "^1.2.3"
+    memory-fs "^0.4.1"
+    micromatch "^3.1.10"
+    mkdirp "^0.5.3"
+    neo-async "^2.6.1"
+    node-libs-browser "^2.2.1"
+    schema-utils "^1.0.0"
+    tapable "^1.1.3"
+    terser-webpack-plugin "^1.4.3"
+    watchpack "^1.7.4"
+    webpack-sources "^1.4.1"
+
 websocket-driver@>=0.5.1:
   version "0.7.4"
   resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
@@ -11720,17 +12663,12 @@ which-boxed-primitive@^1.0.2:
     is-string "^1.0.5"
     is-symbol "^1.0.3"
 
-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:
+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==
@@ -11895,7 +12833,7 @@ yallist@^4.0.0:
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
   integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
 
-yaml@^1.7.2:
+yaml@^1.10.0, yaml@^1.7.2:
   version "1.10.2"
   resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
   integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
@@ -11928,14 +12866,6 @@ yargs-parser@^20.2.3:
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
   integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
 
-yargs-parser@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.1.tgz#7ede329c1d8cdbbe209bd25cdb990e9b1ebbb394"
-  integrity sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==
-  dependencies:
-    camelcase "^3.0.0"
-    object.assign "^4.1.0"
-
 yargs-parser@^9.0.2:
   version "9.0.2"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
@@ -12013,22 +12943,3 @@ yargs@^14.2.2:
     which-module "^2.0.0"
     y18n "^4.0.0"
     yargs-parser "^15.0.1"
-
-yargs@^7.0.0:
-  version "7.1.2"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db"
-  integrity sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==
-  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.1"