switch to rfc8040 restconf
change rest interface and some small code cleanups
Issue-ID: CCSDK-2572
Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
Change-Id: I3475bd2574b32950c4bf84fbd1c2a9dac9af208a
diff --git a/sdnr/wt/odlux/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json
index 44dae68..8118f92 100644
--- a/sdnr/wt/odlux/apps/apiDemo/package.json
+++ b/sdnr/wt/odlux/apps/apiDemo/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/configurationApp/package.json b/sdnr/wt/odlux/apps/configurationApp/package.json
index b18d1ce..7b9dce6 100644
--- a/sdnr/wt/odlux/apps/configurationApp/package.json
+++ b/sdnr/wt/odlux/apps/configurationApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
index 45cdfe6..dbe95e0 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/actions/deviceActions.ts
@@ -2,12 +2,14 @@
import { Dispatch } from '../../../../framework/src/flux/store';
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
import { PushAction, ReplaceAction } from "../../../../framework/src/actions/navigationActions";
+import { AddErrorInfoAction } from "../../../../framework/src/actions/errorActions";
+import { DisplayModeType, DisplaySpecification } from '../handlers/viewDescriptionHandler';
import { restService } from "../services/restServices";
import { YangParser } from "../yang/yangParser";
import { Module } from "../models/yang";
-import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList } from "../models/uiModels";
-import { AddErrorInfoAction } from "../../../../framework/src/actions/errorActions";
+import { ViewSpecification, ViewElement, isViewElementReference, isViewElementList, isViewElementObjectOrList, isViewElementRpc, isViewElementChoise, ViewElementChoiseCase } from "../models/uiModels";
+import { element } from 'prop-types';
export class EnableValueSelector extends Action {
constructor(public listSpecification: ViewSpecification, public listData: any[], public keyProperty: string, public onValueSelected : (value: any) => void ) {
@@ -34,7 +36,13 @@
}
export class UpdatViewDescription extends Action {
- constructor(public vPath: string, public view: ViewSpecification, public viewData: any, public displayAsList: boolean = false, public key?: string ) {
+ constructor (public vPath: string, public viewData: any, public displaySpecification: DisplaySpecification = { displayMode: DisplayModeType.doNotDisplay } ) {
+ super();
+ }
+}
+
+export class UpdatOutputData extends Action {
+ constructor (public outputData: any) {
super();
}
}
@@ -159,7 +167,7 @@
return null;
}
-const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification, viewData: any, displayAsList: boolean = false, key?: string): UpdatViewDescription =>{
+const resolveViewDescription = (defaultNS: string | null, vPath: string, view: ViewSpecification): ViewSpecification =>{
// check if-feature | when | and resolve all references.
view = { ...view };
@@ -173,28 +181,72 @@
}
return acc;
}, {});
- return new UpdatViewDescription(vPath, view, viewData, displayAsList, key);
+ return view;
}
+const flatenViewElements = (defaultNS: string | null, parentPath: string, elements: { [name: string]: ViewElement }, views: ViewSpecification[], currentPath: string ): { [name: string]: ViewElement } => {
+ if (!elements) return {};
+ return Object.keys(elements).reduce<{ [name: string]: ViewElement }>((acc, cur) => {
+ const elm = elements[cur];
+
+ // remove the detault namespace, and only the default namespace, sine it seems that this is also not in the restconf response
+ const elmKey = defaultNS && elm.id.replace(new RegExp(`^${defaultNS}:`, "i"), "") || elm.id;
+ const key = parentPath ? `${parentPath}.${elmKey}` : elmKey;
+
+ if (isViewElementRpc(elm)) {
+ console.warn(`Flaten of RFC not supported ! [${currentPath}][${elm.label}]`);
+ return acc;
+ } else if (isViewElementObjectOrList(elm)) {
+ const view = views[+elm.viewId];
+ const inner = view && flatenViewElements(defaultNS, key, view.elements, views, `${currentPath}/${view.name}`);
+ inner && Object.keys(inner).forEach(k => (acc[k] = inner[k]));
+ } else if (isViewElementChoise(elm)) {
+ acc[key] = {
+ ...elm,
+ id: key,
+ cases: Object.keys(elm.cases).reduce<{ [name: string]: ViewElementChoiseCase }>((accCases, curCases) => {
+ const caseElement = elm.cases[curCases];
+ accCases[curCases] = {
+ ...caseElement,
+ // Hint: do not use key it contains elmKey, which shell be omitted for cases.
+ elements: flatenViewElements(defaultNS, /*key*/ parentPath, caseElement.elements, views, `${currentPath}/${elm.label}`)
+ };
+ return accCases;
+ }, {}),
+ };
+ } else {
+ acc[key] = {
+ ...elm,
+ id: key,
+ };
+ }
+ return acc;
+ }, {});
+};
+
export const updateViewActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
const { configuration: { deviceDescription: { nodeId, modules, views } }, framework: { navigationState } } = getState();
let dataPath = `/restconf/config/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount`;
+
+ let inputViewSpecification: ViewSpecification | undefined = undefined;
+ let outputViewSpecification: ViewSpecification | undefined = undefined;
+
let viewSpecification: ViewSpecification = views[0];
let viewElement: ViewElement;
let dataMember: string;
let extractList: boolean = false;
- let currentNS : string | null = null;
- let defaultNS : string | null = null;
+ let currentNS: string | null = null;
+ let defaultNS: string | null = null;
dispatch(new SetCollectingSelectionData(true));
try {
for (let ind = 0; ind < pathParts.length; ++ind) {
const [property, key] = pathParts[ind];
const namespaceInd = property && property.indexOf(":") || -1;
- const namespace : string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+ const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
if (ind === 0) { defaultNS = namespace };
@@ -206,6 +258,7 @@
dispatch(new SetCollectingSelectionData(false));
throw new Error("No key for list [" + property + "]");
} else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+
// empty key is used for new element
if (viewElement && "viewId" in viewElement) viewSpecification = views[+viewElement.viewId];
const data = Object.keys(viewSpecification.elements).reduce<{ [name: string]: any }>((acc, cur) => {
@@ -215,7 +268,16 @@
}
return acc;
}, {});
- return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, false, isViewElementList(viewElement!) && viewElement.key || undefined));
+
+ // create display specification
+ const ds: DisplaySpecification = {
+ displayMode: DisplayModeType.displayAsObject,
+ viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+ keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined
+ };
+
+ // update display specification
+ return dispatch(new UpdatViewDescription(vPath, data, ds));
}
if (viewElement && isViewElementList(viewElement) && viewSpecification.parentView === "0") {
// check if there is a reference as key
@@ -247,11 +309,27 @@
extractList = false;
}
- if (viewElement && "viewId" in viewElement) viewSpecification = views[+viewElement.viewId];
+ if (viewElement && "viewId" in viewElement) {
+ viewSpecification = views[+viewElement.viewId];
+ } else if (viewElement.uiType === "rpc") {
+ viewSpecification = views[+(viewElement.inputViewId || 0)];
+
+ // create new instance & flaten
+ inputViewSpecification = viewElement.inputViewId != null && {
+ ...views[+(viewElement.inputViewId || 0)],
+ elements: flatenViewElements(defaultNS, "", views[+(viewElement.inputViewId || 0)].elements, views, viewElement.label),
+ } || undefined;
+ outputViewSpecification = viewElement.outputViewId != null && {
+ ...views[+(viewElement.outputViewId || 0)],
+ elements: flatenViewElements(defaultNS, "", views[+(viewElement.outputViewId || 0)].elements, views, viewElement.label),
+ } || undefined;
+
+ }
}
let data: any = {};
- if (viewSpecification && viewSpecification.id !== "0") {
+ // do not get any data from netconf if there is no view specified || this is the root element [0] || this is an rpc
+ if (viewSpecification && !(viewSpecification.id === "0" || viewElement!.uiType === "rpc")) {
const restResult = (await restService.getConfigData(dataPath));
if (!restResult.data) {
// special case: if this is a list without any response
@@ -259,7 +337,15 @@
if (!isViewElementList(viewElement!)) {
throw new Error(`vPath: [${vPath}]. ViewElement has no key.`);
}
- return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, [], extractList, viewElement.key));
+ // create display specification
+ const ds: DisplaySpecification = {
+ displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+ viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+ keyProperty: viewElement.key
+ };
+
+ // update display specification
+ 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) {
@@ -278,9 +364,33 @@
data = extractList
? data[viewElement!.label] || [] // if the list is empty, it does not exist
: data;
+
+ } else if (viewElement! && viewElement!.uiType === "rpc") {
+ // set data to defaults
+ data = {};
+ inputViewSpecification && Object.keys(inputViewSpecification.elements).forEach(key => {
+ const elm = inputViewSpecification && inputViewSpecification.elements[key];
+ if (elm && elm.default != undefined) {
+ data[elm.id] = elm.default;
+ }
+ });
}
- return dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, extractList, isViewElementList(viewElement!) && viewElement.key || undefined));
+ // create display specification
+ const ds: DisplaySpecification = viewElement! && viewElement!.uiType === "rpc"
+ ? {
+ displayMode: DisplayModeType.displayAsRPC,
+ inputViewSpecification: inputViewSpecification && resolveViewDescription(defaultNS, vPath, inputViewSpecification),
+ outputViewSpecification: outputViewSpecification && resolveViewDescription(defaultNS, vPath, outputViewSpecification),
+ }
+ : {
+ displayMode: extractList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+ viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+ keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+ };
+
+ // update display specification
+ return dispatch(new UpdatViewDescription(vPath, data, ds));
// https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]
// https://beta.just-run.it/#/configuration/Sim12600/core-model:network-element/ltp[LTP-MWPS-TTP-01]/lp
} catch (error) {
@@ -290,7 +400,7 @@
} finally {
return;
}
-}
+};
export const updateDataActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
@@ -313,7 +423,7 @@
const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
if (ind === 0) { defaultNS = namespace };
- viewElement = viewSpecification.elements[property];
+ viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
if (!viewElement) throw Error("Property [" + property + "] does not exist.");
if (isViewElementList(viewElement) && !key) {
@@ -330,7 +440,7 @@
isNew = key;
if (!key) {
dispatch(new SetCollectingSelectionData(false));
- throw new Error("No value for key [" + viewElement.key +"] in list [" + property + "]");
+ throw new Error("No value for key [" + viewElement.key + "] in list [" + property + "]");
}
}
}
@@ -363,14 +473,183 @@
}
}
- return isNew
- ? dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i,`[${isNew}]`)}`)) // navigate to new element
- : dispatch(resolveViewDescription(defaultNS, vPath, viewSpecification, data, embedList, isViewElementList(viewElement!) && viewElement.key || undefined));
+ if (isNew) {
+ return dispatch(new ReplaceAction(`/configuration/${nodeId}/${vPath.replace(/\[\]$/i, `[${isNew}]`)}`)) // navigate to new element
+ }
+
+ // create display specification
+ const ds: DisplaySpecification = {
+ displayMode: embedList ? DisplayModeType.displayAsList : DisplayModeType.displayAsObject,
+ viewSpecification: resolveViewDescription(defaultNS, vPath, viewSpecification),
+ keyProperty: isViewElementList(viewElement!) && viewElement.key || undefined,
+ };
+
+ // update display specification
+ return dispatch(new UpdatViewDescription(vPath, data, ds));
} catch (error) {
history.back();
dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not change ${dataPath}` }));
- dispatch(new SetCollectingSelectionData(false));
+
} finally {
+ dispatch(new SetCollectingSelectionData(false));
return;
}
-}
\ No newline at end of file
+};
+
+export const removeElementActionAsyncCreator = (vPath: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+ const { configuration: { deviceDescription: { nodeId, views } } } = getState();
+ let dataPath = `/restconf/config/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount`;
+ let viewSpecification: ViewSpecification = views[0];
+ let viewElement: ViewElement;
+
+ let currentNS: string | null = null;
+ let defaultNS: string | null = null;
+
+ dispatch(new SetCollectingSelectionData(true));
+ try {
+ for (let ind = 0; ind < pathParts.length; ++ind) {
+ let [property, key] = pathParts[ind];
+ const namespaceInd = property && property.indexOf(":") || -1;
+ const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+ if (ind === 0) { defaultNS = namespace };
+ viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+ if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+
+ if (isViewElementList(viewElement) && !key) {
+ if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
+ throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ }
+ if (pathParts.length - 1 > ind) {
+ dispatch(new SetCollectingSelectionData(false));
+ throw new Error("No key for list [" + property + "]");
+ } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ // remove the whole table
+ }
+ }
+
+ dataPath += `/${property}${key ? `/${key.replace(/\//ig, "%2F")}` : ""}`;
+
+ if (viewElement && "viewId" in viewElement) {
+ viewSpecification = views[+viewElement.viewId];
+ } else if (viewElement.uiType === "rpc") {
+ viewSpecification = views[+(viewElement.inputViewId || 0)];
+ }
+ }
+
+ const updateResult = await restService.removeConfigElement(dataPath);
+ if (updateResult.status < 200 || updateResult.status > 299) {
+ const message = updateResult.data && updateResult.data.errors && updateResult.data.errors.error && updateResult.data.errors.error[0] && updateResult.data.errors.error[0]["error-message"] || "";
+ throw new Error(`Server Error. Status: [${updateResult.status}]\n${message || updateResult.message || ''}`);
+ }
+ } catch (error) {
+ dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not remove ${dataPath}` }));
+ } finally {
+ dispatch(new SetCollectingSelectionData(false));
+ }
+
+
+};
+
+export const executeRpcActionAsyncCreator = (vPath: string, data: any) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ const pathParts = splitVPath(vPath, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
+ const { configuration: { deviceDescription: { nodeId, views }, viewDescription: oldViewDescription } } = getState();
+ let dataPath = `/restconf/operations/network-topology:network-topology/topology/topology-netconf/node/${nodeId}/yang-ext:mount`;
+ let viewSpecification: ViewSpecification = views[0];
+ let viewElement: ViewElement;
+ let dataMember: string;
+ let embedList: boolean = false;
+ let isNew: string | false = false;
+
+ let currentNS: string | null = null;
+ let defaultNS: string | null = null;
+
+ dispatch(new SetCollectingSelectionData(true));
+ try {
+ for (let ind = 0; ind < pathParts.length; ++ind) {
+ let [property, key] = pathParts[ind];
+ const namespaceInd = property && property.indexOf(":") || -1;
+ const namespace: string | null = namespaceInd > -1 ? (currentNS = property.slice(0, namespaceInd)) : currentNS;
+
+ if (ind === 0) { defaultNS = namespace };
+ viewElement = viewSpecification.elements[property] || viewSpecification.elements[`${namespace}:${property}`];
+ if (!viewElement) throw Error("Property [" + property + "] does not exist.");
+
+ if (isViewElementList(viewElement) && !key) {
+ embedList = true;
+ // if (viewElement && viewElement.isList && viewSpecification.parentView === "0") {
+ // throw new Error("Found a list at root level of a module w/o a refenrece key.");
+ // }
+ // if (pathParts.length - 1 > ind) {
+ // dispatch(new SetCollectingSelectionData(false));
+ // throw new Error("No key for list [" + property + "]");
+ // } else if (vPath.endsWith("[]") && pathParts.length - 1 === ind) {
+ // // handle new element
+ // key = viewElement.key && String(data[viewElement.key]) || "";
+ // isNew = key;
+ // if (!key) {
+ // dispatch(new SetCollectingSelectionData(false));
+ // throw new Error("No value for key [" + viewElement.key + "] in list [" + property + "]");
+ // }
+ // }
+ }
+
+ dataPath += `/${property}${key ? `/${key.replace(/\//ig, "%2F")}` : ""}`;
+ dataMember = viewElement.label;
+ embedList = false;
+
+ if (viewElement && "viewId" in viewElement) {
+ viewSpecification = views[+viewElement.viewId];
+ } else if (viewElement.uiType === "rpc") {
+ viewSpecification = views[+(viewElement.inputViewId || 0)];
+ }
+ }
+
+ // re-inflate formerly flatten rpc data
+ data = data && Object.keys(data).reduce < { [name: string ]: any }>((acc, cur) => {
+ const pathParts = cur.split(".");
+ let pos = 0;
+ const updatePath = (obj: any, key: string) => {
+ obj[key] = (pos >= pathParts.length)
+ ? data[cur]
+ : updatePath(obj[key] || {}, pathParts[pos++]);
+ return obj;
+ }
+ updatePath(acc, pathParts[pos++]);
+ return acc;
+ }, {}) || null;
+
+ // embed the list -> key: list
+ data = embedList
+ ? { [viewElement!.label]: data }
+ : data;
+
+ // embed the first element list[key]
+ data = isNew
+ ? [data]
+ : data;
+
+ // 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) {
+ 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 || ''}`);
+ }
+ const viewData = { ...oldViewDescription.viewData, output: updateResult.data || null};
+ dispatch(new UpdatOutputData(viewData));
+ } else {
+ throw new Error(`There is NO RPC specified.`);
+ }
+
+
+ // // update display specification
+ // return
+ } catch (error) {
+ dispatch(new AddErrorInfoAction({ title: "Problem", message: error.message || `Could not change ${dataPath}` }));
+
+ } finally {
+ dispatch(new SetCollectingSelectionData(false));
+ }
+};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
index d460763..8b0b890 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx
@@ -39,6 +39,7 @@
? (<FormControl style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
<InputLabel htmlFor={`select-${element.id}`} >{element.label}</InputLabel>
<Select
+ title={(element.options.find(o => o.key === value.toString().toLowerCase()) || { description: undefined }).description}
required={!!element.mandatory}
error={!!error}
onChange={(e) => { props.onChange(e.target.value as string) }}
@@ -50,7 +51,9 @@
id: `select-${element.id}`,
}}
>
- {element.options.map(option => (<MenuItem key={option.key} title={option.description} value={option.key}>{option.key}</MenuItem>))}
+ {element.options.map(option => (
+ <MenuItem key={option.key} title={option.description} value={option.key}>{option.key}</MenuItem>
+ ))}
</Select>
<FormHelperText>{error}</FormHelperText>
</FormControl>)
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
index 9af640f..5b2d55e 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/valueSelectorHandler.ts
@@ -18,7 +18,7 @@
import { IActionHandler } from "../../../../framework/src/flux/action";
import { ViewSpecification } from "../models/uiModels";
-import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdatViewDescription } from "../actions/deviceActions";
+import { EnableValueSelector, SetSelectedValue, UpdateDeviceDescription, SetCollectingSelectionData, UpdatViewDescription, UpdatOutputData } from "../actions/deviceActions";
export interface IValueSelectorState {
collectingData: boolean;
@@ -62,7 +62,7 @@
onValueSelected: nc,
listData: [],
};
- } else if (action instanceof UpdateDeviceDescription || action instanceof UpdatViewDescription) {
+ } else if (action instanceof UpdateDeviceDescription || action instanceof UpdatViewDescription || action instanceof UpdatOutputData) {
state = {
...state,
collectingData: false,
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
index c1b3350..69710b9 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/handlers/viewDescriptionHandler.ts
@@ -18,31 +18,42 @@
import { IActionHandler } from "../../../../framework/src/flux/action";
-import { UpdatViewDescription } from "../actions/deviceActions";
+import { UpdatViewDescription, UpdatOutputData } from "../actions/deviceActions";
import { ViewSpecification } from "../models/uiModels";
+export enum DisplayModeType {
+ doNotDisplay = 0,
+ displayAsObject = 1,
+ displayAsList = 2,
+ displayAsRPC = 3
+};
+
+export type DisplaySpecification = {
+ displayMode: DisplayModeType.doNotDisplay;
+} | {
+ displayMode: DisplayModeType.displayAsObject | DisplayModeType.displayAsList ;
+ viewSpecification: ViewSpecification;
+ keyProperty: string | undefined;
+} | {
+ displayMode: DisplayModeType.displayAsRPC;
+ inputViewSpecification?: ViewSpecification;
+ outputViewSpecification?: ViewSpecification;
+}
+
export interface IViewDescriptionState {
vPath: string | null;
- keyProperty: string | undefined;
- displayAsList: boolean;
- viewSpecification: ViewSpecification;
- viewData: any
+ displaySpecification: DisplaySpecification;
+ viewData: any,
+ outputData?: any,
}
const viewDescriptionStateInit: IViewDescriptionState = {
vPath: null,
- keyProperty: undefined,
- displayAsList: false,
- viewSpecification: {
- id: "empty",
- canEdit: false,
- parentView: "",
- name: "emplty",
- language: "en-US",
- title: "empty",
- elements: {}
+ displaySpecification: {
+ displayMode: DisplayModeType.doNotDisplay,
},
- viewData: null
+ viewData: null,
+ outputData: undefined,
};
export const viewDescriptionHandler: IActionHandler<IViewDescriptionState> = (state = viewDescriptionStateInit, action) => {
@@ -50,11 +61,15 @@
state = {
...state,
vPath: action.vPath,
- keyProperty: action.key,
- displayAsList: action.displayAsList,
- viewSpecification: action.view,
viewData: action.viewData,
- }
+ outputData: undefined,
+ displaySpecification: action.displaySpecification,
+ };
+ } else if (action instanceof UpdatOutputData) {
+ state = {
+ ...state,
+ outputData: action.outputData,
+ };
}
return state;
};
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
index 7b41c38..f0391ee 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/models/uiModels.ts
@@ -109,12 +109,28 @@
"elements": ViewElement[];
}
+export type ViewElementChoiseCase = { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } };
+
export type ViewElementChoise = ViewElementBase & {
"uiType": "choise";
- "cases": { [name: string]: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } };
+ "cases": {
+ [name: string]: ViewElementChoiseCase;
+ }
+}
+
+// https://tools.ietf.org/html/rfc7950#section-7.14.1
+export type ViewElementRpc = ViewElementBase & {
+ "uiType": "rpc";
+ "inputViewId"?: string;
+ "outputViewId"?: string;
+}
+
+export type ViewElementEmpty = ViewElementBase & {
+ "uiType": "empty";
}
export type ViewElement =
+ | ViewElementEmpty
| ViewElementBits
| ViewElementBinary
| ViewElementString
@@ -125,7 +141,8 @@
| ViewElementSelection
| ViewElementReference
| ViewElementUnion
- | ViewElementChoise;
+ | ViewElementChoise
+ | ViewElementRpc;
export const isViewElementString = (viewElement: ViewElement): viewElement is ViewElementString => {
return viewElement && viewElement.uiType === "string";
@@ -167,16 +184,25 @@
return viewElement && viewElement.uiType === "choise";
}
+export const isViewElementRpc = (viewElement: ViewElement): viewElement is ViewElementRpc => {
+ return viewElement && viewElement.uiType === "rpc";
+}
+
+export const isViewElementEmpty = (viewElement: ViewElement): viewElement is ViewElementRpc => {
+ return viewElement && viewElement.uiType === "empty";
+}
+
+export const ResolveFunction = Symbol("IsResolved");
export type ViewSpecification = {
"id": string;
- "name": string;
+ "name"?: string;
"title"?: string;
"parentView"?: string;
"language": string;
"ifFeature"?: string;
"when"?: string;
- "uses"?: string[];
+ "uses"?: (string[]) & { [ResolveFunction]?: () => void };
"elements": { [name: string]: ViewElement };
readonly "canEdit": boolean;
}
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
index 0d28e66..b260f1f 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/services/restServices.ts
@@ -57,6 +57,18 @@
public setConfigData(path: string, data: any) {
return requestRestExt<{ [key: string]: any }>(path, { method: "PUT", body: JSON.stringify(data) });
}
+
+ public executeRpc(path: string, data: any) {
+ return requestRestExt<{ [key: string]: any }>(path, { method: "POST", body: JSON.stringify(data) });
+ }
+
+ /** Removes the element by restconf path.
+ * @param path The restconf path to identify the note to update.
+ * @returns The restconf result.
+ */
+ public removeConfigElement(path: string) {
+ return requestRestExt<{ [key: string]: any }>(path, { method: "DELETE" });
+ }
}
export const restService = new RestService();
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 06de39b..385f3b5 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -25,9 +25,11 @@
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from "../../../../framework/src/components/material-table";
import { Loader } from "../../../../framework/src/components/material-ui/loader";
+import { renderObject } from '../../../../framework/src/components/objectDump';
-import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator, updateViewActionAsyncCreator } from "../actions/deviceActions";
-import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion } from "../models/uiModels";
+import { DisplayModeType } from '../handlers/viewDescriptionHandler';
+import { SetSelectedValue, splitVPath, updateDataActionAsyncCreator, updateViewActionAsyncCreator, removeElementActionAsyncCreator, executeRpcActionAsyncCreator } from "../actions/deviceActions";
+import { ViewSpecification, isViewElementString, isViewElementNumber, isViewElementBoolean, isViewElementObjectOrList, isViewElementSelection, isViewElementChoise, ViewElement, ViewElementChoise, isViewElementUnion, isViewElementRpc, ViewElementRpc, isViewElementEmpty } from "../models/uiModels";
import Fab from '@material-ui/core/Fab';
import AddIcon from '@material-ui/icons/Add';
@@ -36,17 +38,14 @@
import SaveIcon from '@material-ui/icons/Save';
import EditIcon from '@material-ui/icons/Edit';
import Tooltip from "@material-ui/core/Tooltip";
-import TextField from "@material-ui/core/TextField";
import FormControl from "@material-ui/core/FormControl";
import IconButton from "@material-ui/core/IconButton";
-import InputAdornment from "@material-ui/core/InputAdornment";
import InputLabel from "@material-ui/core/InputLabel";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import Breadcrumbs from "@material-ui/core/Breadcrumbs";
import Link from "@material-ui/core/Link";
-import FormHelperText from '@material-ui/core/FormHelperText';
import { UIElementReference } from '../components/uiElementReference';
import { UiElementNumber } from '../components/uiElementNumber';
@@ -54,6 +53,7 @@
import { UiElementBoolean } from '../components/uiElementBoolean';
import { UiElementSelection } from '../components/uiElementSelection';
import { UIElementUnion } from '../components/uiElementUnion';
+import { Button } from '@material-ui/core';
const styles = (theme: Theme) => createStyles({
header: {
@@ -110,6 +110,9 @@
},
},
},
+ uiView: {
+ overflowY: "auto",
+ },
section: {
padding: "15px",
borderBottom: `2px solid ${theme.palette.divider}`,
@@ -130,15 +133,16 @@
vPath: state.configuration.viewDescription.vPath,
nodeId: state.configuration.deviceDescription.nodeId,
viewData: state.configuration.viewDescription.viewData,
- viewSpecification: state.configuration.viewDescription.viewSpecification,
- displayAsList: state.configuration.viewDescription.displayAsList,
- keyProperty: state.configuration.viewDescription.keyProperty,
+ outputData: state.configuration.viewDescription.outputData,
+ displaySpecification: state.configuration.viewDescription.displaySpecification,
});
const mapDispatch = (dispatcher: IDispatcher) => ({
onValueSelected: (value: any) => dispatcher.dispatch(new SetSelectedValue(value)),
onUpdateData: (vPath: string, data: any) => dispatcher.dispatch(updateDataActionAsyncCreator(vPath, data)),
reloadView: (vPath: string) => dispatcher.dispatch(updateViewActionAsyncCreator(vPath)),
+ removeElement: (vPath: string) => dispatcher.dispatch(removeElementActionAsyncCreator(vPath)),
+ executeRpc: (vPath: string, data: any) => dispatcher.dispatch(executeRpcActionAsyncCreator(vPath, data)),
});
const SelectElementTable = MaterialTable as MaterialTableCtorType<{ [key: string]: any }>;
@@ -171,49 +175,59 @@
}
}
+ private static getChoisesFromElements = (elements: { [name: string]: ViewElement }, viewData: any) => {
+ return Object.keys(elements).reduce((acc, cur) => {
+ const elm = elements[cur];
+ if (isViewElementChoise(elm)) {
+ const caseKeys = Object.keys(elm.cases);
+
+ // find the right case for this choise, use the first one with data, at least use index 0
+ const selectedCase = caseKeys.find(key => {
+ const caseElm = elm.cases[key];
+ return Object.keys(caseElm.elements).some(caseElmKey => {
+ const caseElmElm = caseElm.elements[caseElmKey];
+ return viewData[caseElmElm.label] !== undefined || viewData[caseElmElm.id] != undefined;
+ });
+ }) || caseKeys[0];
+
+ // extract all data of the active case
+ const caseElements = elm.cases[selectedCase].elements;
+ const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
+ const dataElm = caseElements[dataCur];
+ if (isViewElementEmpty(dataElm)) {
+ dataAcc[dataElm.label] = null;
+ } else if (viewData[dataElm.label] !== undefined) {
+ dataAcc[dataElm.label] = viewData[dataElm.label];
+ } else if (viewData[dataElm.id] !== undefined) {
+ dataAcc[dataElm.id] = viewData[dataElm.id];
+ }
+ return dataAcc;
+ }, {} as { [name: string]: any });
+
+ acc[elm.id] = {
+ selectedCase,
+ data,
+ };
+ }
+ return acc;
+ }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
+ }
+
static getDerivedStateFromProps(nextProps: ConfigurationApplicationComponentProps, prevState: ConfigurationApplicationComponentState & { [OldProps]: ConfigurationApplicationComponentProps }) {
if (!prevState || !prevState[OldProps] || (prevState[OldProps].viewData !== nextProps.viewData)) {
- const isNew: boolean = nextProps.vPath ?.endsWith("[]") || false;
+ const isNew: boolean = nextProps.vPath?.endsWith("[]") || false;
const state = {
...prevState,
isNew: isNew,
editMode: isNew,
viewData: nextProps.viewData || null,
[OldProps]: nextProps,
- choises: nextProps.viewSpecification && Object.keys(nextProps.viewSpecification.elements).reduce((acc, cur) => {
- const elm = nextProps.viewSpecification.elements[cur];
- if (isViewElementChoise(elm)) {
- const caseKeys = Object.keys(elm.cases);
-
- // find the right case for this choise, use the first one with data, at least use index 0
- const selectedCase = caseKeys.find(key => {
- const caseElm = elm.cases[key];
- return Object.keys(caseElm.elements).some(caseElmKey => {
- const caseElmElm = caseElm.elements[caseElmKey];
- return nextProps.viewData[caseElmElm.label] != null || nextProps.viewData[caseElmElm.id] != null;
- });
- }) || caseKeys[0];
-
- // extract all data of the active case
- const caseElements = elm.cases[selectedCase].elements;
- const data = Object.keys(caseElements).reduce((dataAcc, dataCur) => {
- const dataElm = caseElements[dataCur];
- if (nextProps.viewData[dataElm.label] !== undefined) {
- dataAcc[dataElm.label] = nextProps.viewData[dataElm.label];
- } else if (nextProps.viewData[dataElm.id] !== undefined) {
- dataAcc[dataElm.id] = nextProps.viewData[dataElm.id];
- }
- return dataAcc;
- }, {} as { [name: string]: any });
-
- acc[elm.id] = {
- selectedCase,
- data,
- };
- }
- return acc;
- }, {} as { [path: string]: { selectedCase: string, data: { [property: string]: any } } }) || {}
+ choises: nextProps.displaySpecification.displayMode === DisplayModeType.doNotDisplay
+ ? null
+ : nextProps.displaySpecification.displayMode === DisplayModeType.displayAsRPC
+ ? nextProps.displaySpecification.inputViewSpecification && ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.inputViewSpecification.elements, nextProps.viewData) || []
+ : ConfigurationApplicationComponent.getChoisesFromElements(nextProps.displaySpecification.viewSpecification.elements, nextProps.viewData)
}
return state;
}
@@ -233,10 +247,46 @@
});
}
+ private collectData = (elements: { [name: string]: ViewElement }) => {
+ // ensure only active choises will be contained
+ const viewData : { [key: string]: any }= { ...this.state.viewData };
+ const choiseKeys = Object.keys(elements).filter(elmKey => isViewElementChoise(elements[elmKey]));
+ const elementsToRemove = choiseKeys.reduce((acc, curChoiceKey) => {
+ const currentChoice = elements[curChoiceKey] as ViewElementChoise;
+ const selectedCase = this.state.choises[curChoiceKey].selectedCase;
+ Object.keys(currentChoice.cases).forEach(caseKey => {
+ const caseElements = currentChoice.cases[caseKey].elements;
+ if (caseKey === selectedCase) {
+ Object.keys(caseElements).forEach(caseElementKey => {
+ const elm = caseElements[caseElementKey];
+ if (isViewElementEmpty(elm)) {
+ // insert null for all empty elements
+ viewData[elm.id] = null;
+ }
+ });
+ return;
+ };
+ Object.keys(caseElements).forEach(caseElementKey => {
+ acc.push(caseElements[caseElementKey]);
+ });
+ });
+ return acc;
+ }, [] as ViewElement[]);
+
+ return viewData && Object.keys(viewData).reduce((acc, cur) => {
+ if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
+ acc[cur] = viewData[cur];
+ }
+ return acc;
+ }, {} as { [key: string]: any });
+ }
+
private renderUIElement = (uiElement: ViewElement, viewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) => {
const isKey = (uiElement.label === keyProperty);
const canEdit = editMode && (isNew || (uiElement.config && !isKey));
- if (isViewElementSelection(uiElement)) {
+ if (isViewElementEmpty(uiElement)) {
+ return null;
+ } else if (isViewElementSelection(uiElement)) {
return <UiElementSelection
key={uiElement.id}
@@ -283,8 +333,7 @@
readOnly={!canEdit}
disabled={editMode && !canEdit}
onChange={(e) => { this.changeValueFor(uiElement.id, e) }} />
- }
- else {
+ } else {
if (process.env.NODE_ENV !== "production") {
console.error(`Unknown element type - ${(uiElement as any).uiType} in ${(uiElement as any).id}.`)
}
@@ -391,16 +440,18 @@
acc.references.push(elm);
} else if (isViewElementChoise(elm)) {
acc.choises.push(elm);
+ } else if (isViewElementRpc(elm)) {
+ acc.rpcs.push(elm);
} else {
acc.elements.push(elm);
}
return acc;
- }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[] });
+ }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] });
sections.elements = sections.elements.sort(orderFunc);
return (
- <>
+ <div className={classes.uiView}>
<div className={classes.section} />
{sections.elements.length > 0
? (
@@ -425,7 +476,16 @@
</div>
) : null
}
- </>
+ {sections.rpcs.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.rpcs.map(element => (
+ <UIElementReference key={element.id} element={element} disabled={editMode} onOpenReference={(elm) => { this.navigate(`/${elm.id}`) }} />
+ ))}
+ </div>
+ ) : null
+ }
+ </div>
);
};
@@ -442,7 +502,7 @@
}
};
- const { classes } = this.props;
+ const { classes, removeElement } = this.props;
return (
<SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
@@ -457,11 +517,13 @@
}
return acc;
}, []).concat([{
- property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: (row => {
+ property: "Actions", disableFilter: true, disableSorting: true, type: ColumnType.custom, customControl: ( ({ rowData })=> {
return (
<Tooltip title={"Remove"} >
- <IconButton className={classes.button} onClick={event => {
-
+ <IconButton className={classes.button} onClick={(e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ removeElement(`${this.props.vPath}[${rowData[listKeyProperty]}]`)
}} >
<RemoveIcon />
</IconButton>
@@ -476,10 +538,73 @@
);
}
+ private renderUIViewRPC(inputViewSpecification: ViewSpecification | undefined, inputViewData: { [key: string]: any }, outputViewData: { [key: string]: any }, keyProperty: string | undefined, editMode: boolean, isNew: boolean) {
+ const { classes } = this.props;
+
+ const orderFunc = (vsA: ViewElement, vsB: ViewElement) => {
+ if (keyProperty) {
+ // if (vsA.label === vsB.label) return 0;
+ if (vsA.label === keyProperty) return -1;
+ if (vsB.label === keyProperty) return +1;
+ }
+
+ // if (vsA.uiType === vsB.uiType) return 0;
+ // if (vsA.uiType !== "object" && vsB.uiType !== "object") return 0;
+ // if (vsA.uiType === "object") return +1;
+ return -1;
+ };
+
+ const sections = inputViewSpecification && Object.keys(inputViewSpecification.elements).reduce((acc, cur) => {
+ const elm = inputViewSpecification.elements[cur];
+ if (isViewElementObjectOrList(elm)) {
+ console.error("Object should not appear in RPC view !");
+ } else if (isViewElementChoise(elm)) {
+ acc.choises.push(elm);
+ } else if (isViewElementRpc(elm)) {
+ console.error("RPC should not appear in RPC view !");
+ } else {
+ acc.elements.push(elm);
+ }
+ return acc;
+ }, { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] })
+ || { elements: [] as ViewElement[], references: [] as ViewElement[], choises: [] as ViewElementChoise[], rpcs: [] as ViewElementRpc[] };
+
+ sections.elements = sections.elements.sort(orderFunc);
+
+ return (
+ <>
+ <div className={classes.section} />
+ {sections.elements.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.elements.map(element => this.renderUIElement(element, inputViewData, keyProperty, editMode, isNew))}
+ </div>
+ ) : null
+ }
+ {sections.choises.length > 0
+ ? (
+ <div className={classes.section}>
+ {sections.choises.map(element => this.renderUIChoise(element, inputViewData, keyProperty, editMode, isNew))}
+ </div>
+ ) : null
+ }
+ <Button onClick={() => {
+ const resultingViewData = inputViewSpecification && this.collectData(inputViewSpecification.elements);
+ this.props.executeRpc(this.props.vPath!, resultingViewData);
+ }} >Exec</Button>
+ {outputViewData !== undefined
+ ? (
+ renderObject(outputViewData) )
+ : null
+ }
+ </>
+ );
+ };
+
private renderBreadCrumps() {
const { editMode } = this.state;
- const { viewSpecification, displayAsList } = this.props;
- const { vPath, match: { url, path }, nodeId } = this.props;
+ const { displaySpecification } = this.props;
+ const { vPath, nodeId } = this.props;
const pathParts = splitVPath(vPath!, /(?:([^\/\["]+)(?:\[([^\]]*)\])?)/g); // 1 = property / 2 = optional key
let lastPath = `/configuration`;
let basePath = `/configuration/${nodeId}`;
@@ -527,33 +652,11 @@
}} ><ArrowBack /></Fab>
) || null}
{ /* do not show edit if this is a list or it can't be edited */
- !displayAsList && viewSpecification.canEdit && (<div>
+ displaySpecification.displayMode === DisplayModeType.displayAsObject && displaySpecification.viewSpecification.canEdit && (<div>
<Fab color="secondary" aria-label="edit" className={this.props.classes.fab} onClick={() => {
if (this.state.editMode) {
-
// ensure only active choises will be contained
- const choiseKeys = Object.keys(viewSpecification.elements).filter(elmKey => isViewElementChoise(viewSpecification.elements[elmKey]));
- const elementsToRemove = choiseKeys.reduce((acc, cur) => {
- const choise = viewSpecification.elements[cur] as ViewElementChoise;
- const selectedCase = this.state.choises[cur].selectedCase;
- Object.keys(choise.cases).forEach(caseKey => {
- if (caseKey === selectedCase) return;
- const caseElements = choise.cases[caseKey].elements;
- Object.keys(caseElements).forEach(caseElementKey => {
- acc.push(caseElements[caseElementKey]);
- });
- });
- return acc;
- }, [] as ViewElement[]);
-
- const viewData = this.state.viewData;
- const resultingViewData = viewData && Object.keys(viewData).reduce((acc, cur) => {
- if (!elementsToRemove.some(elm => elm.label === cur || elm.id === cur)) {
- acc[cur] = viewData[cur];
- }
- return acc;
- }, {} as { [key: string]: any });
-
+ const resultingViewData = this.collectData(displaySpecification.viewSpecification.elements);
this.props.onUpdateData(this.props.vPath!, resultingViewData);
}
this.setState({ editMode: !editMode });
@@ -595,15 +698,19 @@
}
private renderValueEditor() {
- const { keyProperty, displayAsList, viewSpecification } = this.props;
+ const { displaySpecification: ds, outputData } = this.props;
const { viewData, editMode, isNew } = this.state;
return (
<div className={this.props.classes.container}>
{this.renderBreadCrumps()}
- {displayAsList && viewData instanceof Array
- ? this.renderUIViewList(viewSpecification, keyProperty!, viewData)
- : this.renderUIView(viewSpecification, viewData!, keyProperty, editMode, isNew)
+ {ds.displayMode === DisplayModeType.doNotDisplay
+ ? null
+ : ds.displayMode === DisplayModeType.displayAsList && viewData instanceof Array
+ ? this.renderUIViewList(ds.viewSpecification, ds.keyProperty!, viewData)
+ : ds.displayMode === DisplayModeType.displayAsRPC
+ ? this.renderUIViewRPC(ds.inputViewSpecification, viewData!, outputData, undefined, true, false)
+ : this.renderUIView(ds.viewSpecification, viewData!, ds.keyProperty, editMode, isNew)
}
</div >
);
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index 27859f7..b1c1e74 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -15,10 +15,12 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-
-
import { Token, Statement, Module, Identity } from "../models/yang";
-import { ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase, isViewElementReference, ViewElementChoise, ViewElementBinary, ViewElementString, isViewElementString, isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion } from "../models/uiModels";
+import {
+ ViewSpecification, ViewElement, isViewElementObjectOrList, ViewElementBase,
+ isViewElementReference, ViewElementChoise, ViewElementBinary, ViewElementString, isViewElementString,
+ isViewElementNumber, ViewElementNumber, Expression, YangRange, ViewElementUnion, ViewElementRpc, isViewElementRpc, ResolveFunction
+} from "../models/uiModels";
import { yangService } from "../services/yangService";
export const splitVPath = (vPath: string, vPathParser: RegExp): RegExpMatchArray[] => {
@@ -263,7 +265,8 @@
}
export class YangParser {
- private _groupingsToResolve: (() => void)[] = [];
+ private _groupingsToResolve: ViewSpecification[] = [];
+
private _identityToResolve: (() => void)[] = [];
private _unionsToResolve: (() => void)[] = [];
private _modulesToResolve: (() => void)[] = [];
@@ -410,11 +413,13 @@
this._modulesToResolve.push(() => {
Object.keys(module.elements).forEach(key => {
const viewElement = module.elements[key];
- if (!isViewElementObjectOrList(viewElement)) {
- throw new Error(`Module: [${module}]. Only List or Object allowed on root level.`);
+ if (!(isViewElementObjectOrList(viewElement) || isViewElementRpc(viewElement))) {
+ console.error(new Error(`Module: [${module}]. Only Object, List or RPC are allowed on root level.`));
}
- const viewIdIndex = Number(viewElement.viewId);
- module.views[key] = this._views[viewIdIndex];
+ if (isViewElementObjectOrList(viewElement)) {
+ const viewIdIndex = Number(viewElement.viewId);
+ module.views[key] = this._views[viewIdIndex];
+ }
this._views[0].elements[key] = module.elements[key];
});
});
@@ -431,8 +436,8 @@
});
// process all groupings
- this._groupingsToResolve.forEach(cb => {
- try { cb(); } catch (error) {
+ this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => {
+ try { vs.uses![ResolveFunction]!(); } catch (error) {
console.warn(`Error resolving: [${error.message}]`);
}
});
@@ -470,7 +475,6 @@
return result;
}
-
const baseIdentites: Identity[] = [];
Object.keys(this.modules).forEach(modKey => {
const module = this.modules[modKey];
@@ -478,7 +482,7 @@
const identity = module.identities[idKey];
if (identity.base != null) {
const base = this.resolveIdentity(identity.base, module);
- base.children ?.push(identity);
+ base.children?.push(identity);
} else {
baseIdentites.push(identity);
}
@@ -765,20 +769,60 @@
}, []));
}
- const rpcs = this.extractNodes(statement, "rpc");
- if (rpcs && rpcs.length > 0) {
- // todo:
+ const rpcStms = this.extractNodes(statement, "rpc");
+ if (rpcStms && rpcStms.length > 0) {
+ elements.push(...rpcStms.reduce<ViewElementRpc[]>((accRpc, curRpc) => {
+ if (!curRpc.arg) {
+ throw new Error(`Module: [${context.name}]${currentPath}. Found rpc without name.`);
+ }
+
+ const description = this.extractValue(curRpc, "description") || undefined;
+ const configValue = this.extractValue(curRpc, "config");
+ const config = configValue == null ? true : configValue.toLocaleLowerCase() !== "false";
+
+ let inputViewId: string | undefined = undefined;
+ let outputViewId: string | undefined = undefined;
+
+ const input = this.extractNodes(curRpc, "input") || undefined;
+ const output = this.extractNodes(curRpc, "output") || undefined;
+
+ if (input && input.length > 0) {
+ const [inputView, inputSubViews] = this.extractSubViews(input[0], parentId, context, `${currentPath}/${context.name}:${curRpc.arg}`);
+ subViews.push(inputView, ...inputSubViews);
+ inputViewId = inputView.id;
+ }
+
+ if (output && output.length > 0) {
+ const [outputView, outputSubViews] = this.extractSubViews(output[0], parentId, context, `${currentPath}/${context.name}:${curRpc.arg}`);
+ subViews.push(outputView, ...outputSubViews);
+ outputViewId = outputView.id;
+ }
+
+ const element: ViewElementRpc = {
+ uiType: "rpc",
+ id: parentId === 0 ? `${context.name}:${curRpc.arg}` : curRpc.arg,
+ label: curRpc.arg,
+ config: config,
+ description: description,
+ inputViewId: inputViewId,
+ outputViewId: outputViewId,
+ };
+
+ accRpc.push(element);
+
+ return accRpc;
+ }, []));
}
- if (!statement.arg) {
- throw new Error(`Module: [${context.name}]. Found statement without name.`);
- }
+ // if (!statement.arg) {
+ // throw new Error(`Module: [${context.name}]. Found statement without name.`);
+ // }
const viewSpec: ViewSpecification = {
id: String(currentId),
parentView: String(parentId),
- name: statement.arg,
- title: statement.arg,
+ name: statement.arg != null ? statement.arg : undefined,
+ title: statement.arg != null ? statement.arg : undefined,
language: "en-us",
canEdit: false,
ifFeature: ifFeature,
@@ -804,6 +848,8 @@
if (usesRefs && usesRefs.length > 0) {
viewSpec.uses = (viewSpec.uses || []);
+ const resolveFunctions : (()=>void)[] = [];
+
for (let i = 0; i < usesRefs.length; ++i) {
const groupingName = usesRefs[i].arg;
if (!groupingName) {
@@ -812,9 +858,14 @@
viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
- this._groupingsToResolve.push(() => {
+ resolveFunctions.push(() => {
const groupingViewSpec = this.resolveGrouping(groupingName, context);
if (groupingViewSpec) {
+
+ // resolve recursive
+ const resolveFunc = groupingViewSpec.uses && groupingViewSpec.uses[ResolveFunction];
+ resolveFunc && resolveFunc();
+
Object.keys(groupingViewSpec.elements).forEach(key => {
const elm = groupingViewSpec.elements[key];
viewSpec.elements[key] = {
@@ -826,6 +877,19 @@
}
});
}
+
+ viewSpec.uses[ResolveFunction] = () => {
+ resolveFunctions.forEach(res => {
+ try {
+ res();
+ } catch (error) {
+ console.error(error);
+ }
+ });
+ viewSpec?.uses![ResolveFunction] = undefined;
+ }
+
+ this._groupingsToResolve.push(viewSpec);
}
return [viewSpec, subViews];
@@ -1117,10 +1181,9 @@
/* 9.11. The empty Built-In Type
The empty built-in type represents a leaf that does not have any
value, it conveys information by its presence or absence. */
- console.warn(`found type: empty in [${module.name}][${currentPath}][${element.label}]`);
return {
...element,
- uiType: "string",
+ uiType: "empty",
};
} else if (type === "union") {
// todo: ❗ handle union ⚡
diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json
index 774daba..1efd282 100644
--- a/sdnr/wt/odlux/apps/connectApp/package.json
+++ b/sdnr/wt/odlux/apps/connectApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
index e3b6401..3b4cf3b 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -61,16 +61,19 @@
editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => {
const values = Object.keys(element);
+ console.log("edit element");
+ console.log(values);
//make sure properties are there in case they get renamed
const idProperty = propertyOf<UpdateNetworkElement>("id");
const isRequiredProperty = propertyOf<UpdateNetworkElement>("isRequired");
+
if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
// do not mount network element, if only isRequired is changed
await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
- } else {
+ } 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!)
await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
}
diff --git a/sdnr/wt/odlux/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json
index b585709..f30a922 100644
--- a/sdnr/wt/odlux/apps/demoApp/package.json
+++ b/sdnr/wt/odlux/apps/demoApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/eventLogApp/package.json b/sdnr/wt/odlux/apps/eventLogApp/package.json
index ce8b885..f182374 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/package.json
+++ b/sdnr/wt/odlux/apps/eventLogApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json
index b922df3..c42d289 100644
--- a/sdnr/wt/odlux/apps/faultApp/package.json
+++ b/sdnr/wt/odlux/apps/faultApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/helpApp/package.json b/sdnr/wt/odlux/apps/helpApp/package.json
index 2a331f6..1f516ce 100644
--- a/sdnr/wt/odlux/apps/helpApp/package.json
+++ b/sdnr/wt/odlux/apps/helpApp/package.json
@@ -29,8 +29,8 @@
"github-markdown-css": "2.10.0"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json
index 929ca0f..4b1f3f9 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/package.json
+++ b/sdnr/wt/odlux/apps/inventoryApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
new file mode 100644
index 0000000..c09b669
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts
@@ -0,0 +1,104 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+
+import { InventoryType, InventoryTreeNode, TreeDemoItem } from '../models/inventory';
+import { inventoryService } from '../services/inventoryService';
+import { AddErrorInfoAction } from '../../../../framework/src/actions/errorActions';
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+
+/**
+ * Represents the base action.
+ */
+export class BaseAction extends Action { }
+
+export class SetBusyAction extends BaseAction {
+ constructor(public busy: boolean = true) {
+ super();
+
+ }
+}
+
+export class SetSearchTextAction extends BaseAction {
+ constructor(public searchTerm: string = "") {
+ super();
+
+ }
+}
+
+export class UpdateInventoryTreeAction extends BaseAction {
+ constructor(public rootNode: InventoryTreeNode) {
+ super();
+
+ }
+}
+
+export class UpdateSelectedNodeAction extends BaseAction {
+ constructor(public selectedNode?: InventoryType) {
+ super();
+
+ }
+}
+
+export class UpdateExpandedNodesAction extends BaseAction {
+ constructor(public expandedNodes?: TreeDemoItem[]) {
+ super();
+
+ }
+}
+
+export const setSearchTermAction = (searchTerm: string) => (dispatch: Dispatch, getState: () => IApplicationStoreState) =>{
+ dispatch(new SetSearchTextAction(searchTerm));
+}
+
+
+export const updateInventoryTreeAsyncAction = (mountId: string, searchTerm?: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ dispatch(new SetBusyAction(true));
+ dispatch(new SetSearchTextAction(searchTerm));
+ try {
+ const result = await inventoryService.getInventoryTree(mountId, searchTerm);
+ if (!result) {
+ dispatch(new AddErrorInfoAction({ title: "Error", message: `Could not load inventory tree for [${mountId}]. Please check you connection to the server and try later.` }));
+ dispatch(new NavigateToApplication("inventory"));
+ } else {
+ dispatch(new UpdateInventoryTreeAction(result));
+ }
+ } catch (err) {
+ throw new Error("Could not load inventory tree from server.");
+ }
+ finally {
+ dispatch(new SetBusyAction(false));
+ }
+};
+
+export const selectInventoryNodeAsyncAction = (nodeId: string) => async (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+ dispatch(new SetBusyAction(true));
+ try {
+ const result = await inventoryService.getInventoryEntry(nodeId);
+ if (!result) throw new Error("Could not load inventory tree from server.");
+ dispatch(new UpdateSelectedNodeAction(result));
+ } catch (err) {
+ throw new Error("Could not load inventory tree from server.");
+ }
+ finally {
+ dispatch(new SetBusyAction(false));
+ }
+};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts b/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts
new file mode 100644
index 0000000..10fde8c
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts
@@ -0,0 +1,31 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { Action } from "../../../../framework/src/flux/action";
+import { PanelId } from "models/panelId";
+
+
+export class SetPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+ }
+
+export const setPanelAction = (panelId: PanelId) => {
+ return new SetPanelAction(panelId);
+ }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
index 692ea82..46827e8 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { InventoryTreeNode, InventoryType } from "models/inventory";
import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
@@ -30,31 +48,31 @@
const getTreeElements = (searchTerm: string | null, treeLevel: number = 0, parentUUID: string | null = null): [InventoryTreeNode, boolean] => {
const elements = (data.filter(e => e["tree-level"] === treeLevel && (!parentUUID || e["parent-uuid"] === parentUUID)) || [])
let elementMatch = false;
- const treeeNode = elements.reduce<InventoryTreeNode>((acc, cur) => {
- const [children, childMatch] = getTreeElements(searchTerm, treeLevel + 1, cur["node-id"]);
- const isMatch = searchTerm ? Object.keys(cur).some(k => String((cur as any)[k]).indexOf(searchTerm)) : false;
+ const treeNode = elements.reduce<InventoryTreeNode>((acc, cur) => {
+ const [children, childMatch] = getTreeElements(searchTerm, treeLevel + 1, cur["uuid"]);
+ const isMatch = searchTerm ? Object.keys(cur).some(k => String((cur as any)[k]).indexOf(searchTerm) > -1) : false;
elementMatch = elementMatch || isMatch || childMatch;
if (!searchTerm || isMatch || childMatch) {
- acc[cur["node-id"]] = {
- label: cur["node-id"],
+ acc[cur["uuid"]] = {
+ label: cur["uuid"],
children: children,
- isMatch: false,
+ isMatch: isMatch,
};
}
return acc;
}, {});
- return [treeeNode, elementMatch]
+ return [treeNode, elementMatch]
};
-export const getTree = async (searchTerm: string | null = null) : Promise<InventoryTreeNode> => {
+export const getTree = async (searchTerm: string | null = null): Promise<InventoryTreeNode> => {
await deleay(600);
const [node] = getTreeElements(searchTerm);
return node;
};
-export const getElement = async (id: string ): Promise<InventoryType | undefined> => {
+export const getElement = async (id: string): Promise<InventoryType | undefined> => {
await deleay(600);
- const res = data.find(e => e.id === id);
+ const res = data.find(e => e.uuid === id);
return res && convertPropertyNames(res, replaceHyphen) as unknown as InventoryType;
};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts
new file mode 100644
index 0000000..79c12d6
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts
@@ -0,0 +1,36 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import { createExternal, IExternalTableState } from '../../../../framework/src/components/material-table/utilities';
+import { createSearchDataHandler } from '../../../../framework/src/utilities/elasticSearch';
+
+import { NetworkElementConnection } from '../models/networkElementConnection';
+
+export interface IConnectedNetworkElementsState extends IExternalTableState<NetworkElementConnection> { }
+
+// create eleactic search material data fetch handler
+const connectedNetworkElementsSearchHandler = createSearchDataHandler<NetworkElementConnection>('network-element-connection', { status: "Connected" });
+
+export const {
+ actionHandler: connectedNetworkElementsActionHandler,
+ createActions: createConnectedNetworkElementsActions,
+ createProperties: createConnectedNetworkElementsProperties,
+ reloadAction: connectedNetworkElementsReloadAction,
+
+ // set value action, to change a value
+} = createExternal<NetworkElementConnection>(connectedNetworkElementsSearchHandler, appState => appState.inventory.connectedNetworkElements);
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
index 786f6d0..0e857ff 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts
@@ -22,14 +22,23 @@
// ** do not remove **
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { IActionHandler } from '../../../../framework/src/flux/action';
-import { IInventoryElementsState, inventoryElementsActionHandler } from './inventoryElementsHandler';
+import { IInvenroryTree, inventoryTreeHandler } from './inventoryTreeHandler';
+import { IConnectedNetworkElementsState, connectedNetworkElementsActionHandler } from './connectedNetworkElementsHandler';
+import { PanelId } from '../models/panelId';
+import { currentOpenPanelHandler } from './panelHandler';
+import { inventoryElementsActionHandler, IInventoryElementsState } from './inventoryElementsHandler';
export interface IInventoryAppStateState {
- inventoryElements: IInventoryElementsState
+ inventoryTree: IInvenroryTree;
+ connectedNetworkElements: IConnectedNetworkElementsState; // used for ne selection
+ currentOpenPanel: PanelId;
+ inventoryElements: IInventoryElementsState;
}
+
+
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
inventory: IInventoryAppStateState;
@@ -37,6 +46,9 @@
}
const actionHandlers = {
+ inventoryTree: inventoryTreeHandler,
+ connectedNetworkElements: connectedNetworkElementsActionHandler,
+ currentOpenPanel: currentOpenPanelHandler,
inventoryElements: inventoryElementsActionHandler
};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
similarity index 100%
rename from sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx
rename to sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
new file mode 100644
index 0000000..9029a67
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts
@@ -0,0 +1,68 @@
+/**
+ * ============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 { SetBusyAction, UpdateInventoryTreeAction, UpdateSelectedNodeAction, SetSearchTextAction, UpdateExpandedNodesAction } from "../actions/inventoryTreeActions";
+import { InventoryTreeNode, InventoryType, TreeDemoItem } from "../models/inventory";
+
+
+export interface IInvenroryTree {
+ isBusy: boolean;
+ rootNodes: TreeDemoItem[];
+ selectedNode?: InventoryType;
+ expandedItems: TreeDemoItem[];
+ searchTerm: string;
+}
+
+const initialState: IInvenroryTree = {
+ isBusy: false,
+ rootNodes: [],
+ searchTerm: "",
+ selectedNode: undefined,
+ expandedItems: [],
+}
+
+
+const getTreeDataFromInvetoryTreeNode = (node: InventoryTreeNode): TreeDemoItem[] => Object.keys(node).reduce<TreeDemoItem[]>((acc, key) => {
+ const cur = node[key];
+ acc.push({
+ isMatch: cur.isMatch,
+ content: cur.label || key,
+ value: key,
+ children: cur.children && getTreeDataFromInvetoryTreeNode(cur.children),
+ });
+ return acc;
+}, []);
+
+export const inventoryTreeHandler: IActionHandler<IInvenroryTree> = (state = initialState, action) => {
+ if (action instanceof SetBusyAction) {
+ state = { ...state, isBusy: action.busy };
+ } else if (action instanceof SetSearchTextAction) {
+ state = { ...state, searchTerm: action.searchTerm };
+ } else if (action instanceof UpdateInventoryTreeAction) {
+ const rootNodes = getTreeDataFromInvetoryTreeNode(action.rootNode);
+ state = { ...state, rootNodes: rootNodes, expandedItems: [], selectedNode: undefined };
+ } else if (action instanceof UpdateSelectedNodeAction) {
+ state = { ...state, selectedNode: action.selectedNode };
+ } else if (action instanceof UpdateExpandedNodesAction) {
+ state = { ...state, expandedItems: action.expandedNodes || []}
+ }
+
+ return state;
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
new file mode 100644
index 0000000..7612531
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts
@@ -0,0 +1,11 @@
+import { PanelId } from "../models/panelId";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetPanelAction } from "../actions/panelActions";
+
+
+export const currentOpenPanelHandler: IActionHandler<PanelId> = (state = null, action) => {
+ if (action instanceof SetPanelAction) {
+ state = action.panelId;
+ }
+ return state;
+ }
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/index.html b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
index 0cdb9e9..75531ec 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/index.html
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/index.html
@@ -15,8 +15,9 @@
<script type="text/javascript" src="./config.js"></script>
<script>
// run the application
- require(["app", "inventoryApp"], function (app, inventoryApp) {
+ require(["app", "inventoryApp", "connectApp"], function (app, inventoryApp, connectApp) {
inventoryApp.register();
+ connectApp.register();
app("./app.tsx").runApplication();
});
</script>
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
index c6b6c91..a6c9905 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -15,6 +15,9 @@
* the License.
* ============LICENSE_END==========================================================================
*/
+
+import { ExternalTreeItem } from '../../../../framework/src/components/material-ui/treeView';
+
export { HitEntry, Result } from '../../../../framework/src/models';
export type InventoryType = {
@@ -23,7 +26,7 @@
nodeId: string;
uuid: string;
containedHolder?: (string)[] | null;
- manufacturerName?: string ;
+ manufacturerName?: string;
manufacturerIdentifier: string;
serial: string;
date: string;
@@ -42,4 +45,6 @@
ownSeverity?: string;
childrenSeveritySummary?: string;
}
-}
\ No newline at end of file
+}
+
+export type TreeDemoItem = ExternalTreeItem<string>;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
new file mode 100644
index 0000000..88f7018
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type NetworkElementConnection = {
+ id?: string;
+ nodeId: string;
+ host: string;
+ port: number;
+ username?: string;
+ password?: string;
+ isRequired?: boolean;
+ status?: "connected" | "mounted" | "unmounted" | "connecting" | "disconnected" | "idle";
+ coreModelCapability?: string;
+ deviceType?: string;
+ nodeDetails?: {
+ availableCapabilities: string[];
+ unavailableCapabilities: {
+ failureReason: string;
+ capability: string;
+ }[];
+ }
+}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts
new file mode 100644
index 0000000..b05c1db
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts
@@ -0,0 +1,19 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+export type PanelId = null | "InventoryElementsTable" | "TreeviewTable";
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
index ad53285..665e085 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
@@ -22,43 +22,15 @@
import { faShoppingBag } from '@fortawesome/free-solid-svg-icons'; // select app icon
import applicationManager from '../../../framework/src/services/applicationManager';
-import connect, { Connect, IDispatcher } from '../../../framework/src/flux/connect';
-import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
+import { InventoryTreeView } from './views/treeview';
+import Dashboard from "./views/dashboard";
-import { Dashboard } from './views/dashboard';
import inventoryAppRootHandler from './handlers/inventoryAppRootHandler';
-import { createInventoryElementsProperties, createInventoryElementsActions, inventoryElementsReloadAction } from "./handlers/inventoryElementsHandler";
-
-let currentMountId: string | undefined = undefined;
-
-const mapProps = (state: IApplicationStoreState) => ({
- inventoryProperties: createInventoryElementsProperties(state),
-});
-
-const mapDisp = (dispatcher: IDispatcher) => ({
- inventoryActions: createInventoryElementsActions(dispatcher.dispatch, true)
-});
-
-const InventoryApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
- if (currentMountId !== props.match.params.mountId) {
- currentMountId = props.match.params.mountId || undefined;
- window.setTimeout(() => {
- if (currentMountId) {
- props.inventoryActions.onFilterChanged("nodeId", currentMountId);
- props.inventoryProperties.showFilter;
- props.inventoryActions.onRefresh();
- }
- });
- }
- return (
- <Dashboard />
- )
-});
-
const App = withRouter((props: RouteComponentProps) => (
<Switch>
- <Route path={`${props.match.path}/:mountId?`} component={InventoryApplicationRouteAdapter} />
+ <Route path={`${props.match.path}/:mountId`} component={InventoryTreeView} />
+ <Route path={`${props.match.path}`} component={Dashboard} />
<Redirect to={`${props.match.path}`} />
</Switch>
));
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
index 252d6d4..b6025d4 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
import { requestRest } from '../../../../framework/src/services/restService';
+import { convertPropertyNames, replaceHyphen } from '../../../../framework/src/utilities/yangHelper';
import { InventoryTreeNode, InventoryType } from '../models/inventory';
import { getTree, getElement } from '../fakeData';
@@ -24,12 +25,44 @@
* Represents a web api accessor service for all maintenence entries related actions.
*/
class InventoryService {
- public async getInventoryTree(searchTerm?: string): Promise<InventoryTreeNode> {
- return await getTree(searchTerm);
+ public async getInventoryTree(mountId: string, searchTerm: string = ""): Promise<InventoryTreeNode | null> {
+ //return await getTree(searchTerm);
+ const path = `/tree/read-inventoryequipment-tree/${mountId}`;
+ const body = {
+ "query": searchTerm
+ };
+ const inventoryTree = await requestRest<InventoryTreeNode>(path, { method: "POST" , body: JSON.stringify(body)});
+ return inventoryTree && convertPropertyNames(inventoryTree, replaceHyphen) || null;
}
- public async getInventoryEntry(id: string): Promise<InventoryType| undefined> {
- return await getElement(id);
+ public async getInventoryEntry(id: string): Promise<InventoryType | undefined> {
+ const path = `/restconf/operations/data-provider:read-inventory-list`;
+ const body = {
+ "input": {
+ "filter": [
+ { property: "id", filtervalue: id },
+ ],
+ "sortorder": [],
+ "pagination": {
+ "size": 1,
+ "page": 1
+ }
+ }
+ };
+ const inventoryTreeElement = await requestRest<{
+ output: {
+ "pagination": {
+ "size": number,
+ "page": number,
+ "total": number
+ },
+ "data": InventoryType[]
+ }
+ }>(path, { method: "POST", body: JSON.stringify(body) });
+
+ return inventoryTreeElement && inventoryTreeElement.output && inventoryTreeElement.output.pagination && inventoryTreeElement.output.pagination.total >= 1 &&
+ inventoryTreeElement.output.data && convertPropertyNames(inventoryTreeElement.output.data[0], replaceHyphen) || undefined;
+ // return await getElement(id);
}
}
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
index b63f628..14792df 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -15,88 +15,163 @@
* the License.
* ============LICENSE_END==========================================================================
*/
-import * as React from "react";
-import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
-import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
-import { TreeView, TreeItem, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
+import * as React from 'react';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+import { MaterialTable, MaterialTableCtorType, ColumnType } from "../../../../framework/src/components/material-table";
+import { AppBar, Tabs, Tab, MenuItem, Typography } from "@material-ui/core";
+import { PanelId } from "../models/panelId";
+import { setPanelAction } from "../actions/panelActions";
+
+
+import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "../handlers/connectedNetworkElementsHandler";
+
+import { NetworkElementConnection } from "../models/networkElementConnection";
import { InventoryType } from '../models/inventory';
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+
import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { updateInventoryTreeAsyncAction } from '../actions/inventoryTreeActions';
-const styles = (theme: Theme) => createStyles({
- root: {
- flex: "1 0 0%",
- display: "flex",
- flexDirection: "row",
- },
- tree: {
- flex: "1 0 0%",
- minWidth: "250px",
- padding: `0px ${theme.spacing(1)}px`
- },
- details: {
- flex: "5 0 0%",
- padding: `0px ${theme.spacing(1)}px`
- }
-});
-
-const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & {_id: string}>;
+const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & { _id: string }>;
const mapProps = (state: IApplicationStoreState) => ({
+ connectedNetworkElementsProperties: createConnectedNetworkElementsProperties(state),
+ panelId: state.inventory.currentOpenPanel,
inventoryElementsProperties: createInventoryElementsProperties(state),
inventoryElements: state.inventory.inventoryElements
});
const mapDispatch = (dispatcher: IDispatcher) => ({
- inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch)
+ connectedNetworkElementsActions: createConnectedNetworkElementsActions(dispatcher.dispatch),
+ switchActivePanel: (panelId: PanelId) => {
+ dispatcher.dispatch(setPanelAction(panelId));
+ },
+ inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch),
+ navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)),
+ updateInventoryTree: (mountId: string, seatchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, seatchTerm)),
});
-const SampleTree = TreeView as any as TreeViewCtorType<string>;
+let treeViewInitialSorted = false;
+let inventoryInitialSorted = false;
+const ConnectedElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
-type TreeDemoItem = TreeItem<string>;
+type DashboardComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
-const treeData: TreeDemoItem[] = [
- {
- content: "Erste Ebene", children: [
- {
- content: "Zweite Ebene", children: [
- { content: "Dritte Ebene" },
- ]
- },
- { content: "Zweite Ebene 2" },
- ]
- },
- { content: "Erste Ebene 3" },
-];
+class DashboardSelectorComponent extends React.Component<DashboardComponentProps> {
-class DashboardComponent extends React.Component<& WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>> {
+ private onHandleTabChange = (event: React.ChangeEvent<{}>, newValue: PanelId) => {
+ this.onTogglePanel(newValue);
+ }
+
+ private onTogglePanel = (panelId: PanelId) => {
+ const nextActivePanel = panelId;
+ this.props.switchActivePanel(nextActivePanel);
+
+ switch (nextActivePanel) {
+ case 'InventoryElementsTable':
+
+ if (!inventoryInitialSorted) {
+ this.props.inventoryElementsActions.onHandleExplicitRequestSort("nodeId", "asc");
+ inventoryInitialSorted = true;
+ } else {
+ this.props.inventoryElementsActions.onRefresh();
+
+ }
+ break;
+ case 'TreeviewTable':
+ if (!treeViewInitialSorted) {
+ this.props.connectedNetworkElementsActions.onHandleExplicitRequestSort("nodeId", "asc");
+ treeViewInitialSorted = true;
+ } else {
+ this.props.connectedNetworkElementsActions.onRefresh();
+ }
+ break;
+ case null:
+ // do nothing if all panels are closed
+ break;
+ default:
+ console.warn("Unknown nextActivePanel [" + nextActivePanel + "] in connectView");
+ break;
+ }
+
+ };
+
+ getContextMenu = (rowData: InventoryType) => {
+ return [
+ <MenuItem aria-label={"inventory-button"} onClick={event => { this.props.updateInventoryTree(rowData.nodeId, rowData.uuid); this.props.navigateToApplication("inventory", rowData.nodeId) }}><Typography>View in Treeview</Typography></MenuItem>,
+ ];
+
+ }
+
render() {
- return <InventoryTable stickyHeader title="Inventory" idProperty="_id" columns={[
- { property: "nodeId", title: "Node Name" },
- { property: "manufacturerIdentifier", title: "Manufacturer" },
- { property: "parentUuid", title: "Parent" },
- { property: "uuid", title: "Name" },
- { property: "serial", title: "Serial" },
- { property: "version", title: "Version" },
- { property: "date", title: "Date" },
- { property: "description", title: "Description" },
- { property: "partTypeId", title: "Part Type Id" },
- { property: "modelIdentifier", title: "Model Identifier" },
- { property: "typeName", title: "Type" },
- { property: "treeLevel", title: "Containment Level" },
- ]} {...this.props.inventoryElementsActions} {...this.props.inventoryElementsProperties} >
- </InventoryTable>
+
+ const { panelId: activePanelId } = this.props;
+ return (
+ <>
+ <AppBar position="static">
+ <Tabs value={activePanelId} onChange={this.onHandleTabChange} aria-label="simple tabs example">
+ <Tab label="Table View" value="InventoryElementsTable" />
+ <Tab label="Tree view" value="TreeviewTable" />
+ </Tabs>
+ </AppBar>
+
+ {
+
+ activePanelId === "InventoryElementsTable" &&
+
+ <InventoryTable stickyHeader title="Inventory" idProperty="_id" columns={[
+ { property: "nodeId", title: "Node Name" },
+ { property: "manufacturerIdentifier", title: "Manufacturer" },
+ { property: "parentUuid", title: "Parent" },
+ { property: "uuid", title: "Name" },
+ { property: "serial", title: "Serial" },
+ { property: "version", title: "Version" },
+ { property: "date", title: "Date" },
+ { property: "description", title: "Description" },
+ { property: "partTypeId", title: "Part Type Id" },
+ { property: "modelIdentifier", title: "Model Identifier" },
+ { property: "typeName", title: "Type" },
+ { property: "treeLevel", title: "Containment Level" },
+ ]} {...this.props.inventoryElementsActions} {...this.props.inventoryElementsProperties}
+ createContextMenu={rowData => {
+
+ return this.getContextMenu(rowData);
+ }} >
+ </InventoryTable>
+
+ }
+ {
+ activePanelId === "TreeviewTable" &&
+
+ <ConnectedElementTable stickyHeader onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
+ { property: "nodeId", title: "Name", type: ColumnType.text },
+ { property: "isRequired", title: "Required ?", type: ColumnType.boolean },
+ { property: "host", title: "Host", type: ColumnType.text },
+ { property: "port", title: "Port", type: ColumnType.numeric },
+ { property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
+ { property: "deviceType", title: "Type", type: ColumnType.text },
+ ]} idProperty="id" {...this.props.connectedNetworkElementsActions} {...this.props.connectedNetworkElementsProperties} asynchronus >
+ </ConnectedElementTable>
+ }
+ </>
+ );
}
componentDidMount() {
- this.props.inventoryElementsActions.onToggleFilter();
- this.props.inventoryElementsActions.onHandleRequestSort("node-id");
+
+ if (this.props.panelId === null) { //set default tab if none is set
+ this.onTogglePanel("InventoryElementsTable");
+ }
+
}
}
-export const Dashboard = connect(mapProps, mapDispatch)(withStyles(styles)(DashboardComponent));
-export default Dashboard;
\ No newline at end of file
+export const Dashboard = withRouter(connect(mapProps, mapDispatch)(DashboardSelectorComponent));
+export default Dashboard;
+
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx
new file mode 100644
index 0000000..5f2c610
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx
@@ -0,0 +1,132 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import * as React from "react";
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
+
+import { renderObject } from '../../../../framework/src/components/objectDump';
+import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
+import { TreeView, TreeViewCtorType, SearchMode } from '../../../../framework/src/components/material-ui/treeView';
+
+import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
+
+import { updateInventoryTreeAsyncAction, selectInventoryNodeAsyncAction, UpdateSelectedNodeAction, UpdateExpandedNodesAction, setSearchTermAction} from "../actions/inventoryTreeActions";
+import { TreeDemoItem } from "../models/inventory";
+
+import { RouteComponentProps } from "react-router-dom";
+
+const styles = (theme: Theme) => createStyles({
+ root: {
+ flex: "1 0 0%",
+ display: "flex",
+ flexDirection: "row",
+ },
+ tree: {
+ flex: "1 0 0%",
+ minWidth: "250px",
+ padding: `0px ${theme.spacing(1)}px`
+ },
+ details: {
+ flex: "5 0 0%",
+ padding: `0px ${theme.spacing(1)}px`
+ }
+});
+
+const mapProps = (state: IApplicationStoreState) => ({
+ isBusy: state.inventory.inventoryTree.isBusy,
+ rootNodes: state.inventory.inventoryTree.rootNodes,
+ searchTerm: state.inventory.inventoryTree.searchTerm,
+ selectedNode: state.inventory.inventoryTree.selectedNode,
+ expendedItems: state.inventory.inventoryTree.expandedItems,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ updateExpendedNodes: (expendedNodes: TreeDemoItem[]) => dispatcher.dispatch(new UpdateExpandedNodesAction(expendedNodes)),
+ updateInventoryTree: (mountId: string, seatchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, seatchTerm)),
+ selectTreeNode: (nodeId?: string) => nodeId ? dispatcher.dispatch(selectInventoryNodeAsyncAction(nodeId)) : dispatcher.dispatch(new UpdateSelectedNodeAction(undefined)),
+ setSearchTerm: (searchTerm: string) => dispatcher.dispatch(setSearchTermAction(searchTerm)),
+});
+
+const propsChache = Symbol("PropsCache");
+const InventoryTree = TreeView as any as TreeViewCtorType<string>;
+
+
+
+type TreeviewComponentProps = RouteComponentProps<{ mountId: string}> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>
+
+type TreeviewComponentState = {
+ [propsChache]: {
+ rootNodes?: TreeDemoItem[];
+ };
+ rootNodes: TreeDemoItem[];
+}
+
+
+class DashboardComponent extends React.Component<TreeviewComponentProps, TreeviewComponentState> {
+
+ constructor (props: TreeviewComponentProps) {
+ super(props);
+
+ this.state = {
+ [propsChache]: {},
+ rootNodes: [],
+ };
+ }
+
+ static getDerivedStateFromProps(props: TreeviewComponentProps, state: TreeviewComponentState) {
+ if (state[propsChache].rootNodes != props.rootNodes) {
+ state = { ...state, rootNodes: props.rootNodes}
+ }
+ return state;
+ }
+
+ render() {
+ const { classes, updateInventoryTree, updateExpendedNodes, expendedItems, selectedNode, selectTreeNode, searchTerm, match: { params: { mountId }} } = this.props;
+ return (
+ <div className={classes.root}>
+ <InventoryTree className={classes.tree} items={this.state.rootNodes} enableSearchBar initialSearchTerm={searchTerm} searchMode={SearchMode.OnEnter} searchTerm={searchTerm}
+ onSearch={(searchTerm) => updateInventoryTree(mountId, searchTerm)} expandedItems={expendedItems} onFolderClick={(item) => {
+ const indexOfItemToToggle = expendedItems.indexOf(item);
+ if (indexOfItemToToggle === -1) {
+ updateExpendedNodes([...expendedItems, item]);
+ } else {
+ updateExpendedNodes([
+ ...expendedItems.slice(0, indexOfItemToToggle),
+ ...expendedItems.slice(indexOfItemToToggle + 1),
+ ]);
+ }
+ }}
+ onItemClick={(elm) => selectTreeNode(elm.value)} />
+ <div className={classes.details}>{
+ selectedNode && renderObject(selectedNode) || null
+ }</div>
+ </div>
+ );
+ }
+
+ componentDidMount() {
+ const { updateInventoryTree, searchTerm, match: { params: { mountId } }} = this.props;
+ updateInventoryTree(mountId, searchTerm);
+ }
+
+ componentWillUnmount(){
+ this.props.setSearchTerm("");
+ }
+}
+
+export const InventoryTreeView = connect(mapProps, mapDispatch)(withStyles(styles)(DashboardComponent));
+export default InventoryTreeView;
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
index 889bb4d..d81797c 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
@@ -146,6 +146,10 @@
target: "http://localhost:48181",
secure: false
},
+ "/tree/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
"/websocket": {
target: "http://localhost:48181",
ws: true,
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/package.json b/sdnr/wt/odlux/apps/maintenanceApp/package.json
index edd5827..faaef75 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/package.json
+++ b/sdnr/wt/odlux/apps/maintenanceApp/package.json
@@ -25,8 +25,8 @@
"@odlux/connect-app": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json
index cfd4bd9..1f1b7d5 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/package.json
+++ b/sdnr/wt/odlux/apps/mediatorApp/package.json
@@ -25,8 +25,8 @@
},
"peerDependencies": {
"@fortawesome/free-solid-svg-icons": "5.6.3",
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/minimumApp/package.json b/sdnr/wt/odlux/apps/minimumApp/package.json
index 5a8352e..d2b8369 100644
--- a/sdnr/wt/odlux/apps/minimumApp/package.json
+++ b/sdnr/wt/odlux/apps/minimumApp/package.json
@@ -24,8 +24,8 @@
"@odlux/framework": "*"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
index e1ca801..1a6415f 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json
@@ -27,8 +27,8 @@
"chart.js": "2.8.0"
},
"peerDependencies": {
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
index 6014b22..88dc9fd 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
@@ -59,6 +59,9 @@
const children = React.Children.toArray(props.children);
+ //hide filter if visible + table
+ //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name
+
return (
<>
<div className={classes.toggleButtonContainer} >
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
index bbbc3e4..6579db3 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/webpack.config.js
@@ -126,15 +126,15 @@
},
proxy: {
"/oauth2/": {
- target: "http://localhost:48181",
+ target: "http://10.20.6.29:28181",
secure: false
},
"/restconf": {
- target: "http://localhost:48181",
+ target: "http://10.20.6.29:28181",
secure: false
},
"/database": {
- target: "http://localhost:48181",
+ target: "http://10.20.6.29:28181",
secure: false
}
}
diff --git a/sdnr/wt/odlux/core/features/pom.xml b/sdnr/wt/odlux/core/features/pom.xml
index d63f8d8..2aa72b7 100644
--- a/sdnr/wt/odlux/core/features/pom.xml
+++ b/sdnr/wt/odlux/core/features/pom.xml
@@ -46,17 +46,6 @@
</license>
</licenses>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>mdsal-artifacts</artifactId>
- <version>${odl.controller.mdsal.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
<dependencies>
<dependency>
diff --git a/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java b/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java
index 133b084..636c9db 100644
--- a/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java
+++ b/sdnr/wt/odlux/core/model/src/main/java/com/opensymphony/xwork2/util/ClassLoaderUtil.java
@@ -22,11 +22,11 @@
/**
- * This class is extremely useful for loading resources and classes in a fault tolerant manner
- * that works across different applications servers.
+ * This class is extremely useful for loading resources and classes in a fault tolerant manner that works across
+ * different applications servers.
*
- * It has come out of many months of frustrating use of multiple application servers at Atlassian,
- * please don't change things unless you're sure they're not going to break in one server or another!
+ * It has come out of many months of frustrating use of multiple application servers at Atlassian, please don't change
+ * things unless you're sure they're not going to break in one server or another!
*
* It was brought in from oscore trunk revision 147.
*
@@ -37,58 +37,59 @@
//~ Methods ////////////////////////////////////////////////////////////////
/**
- * Load all resources with a given name, potentially aggregating all results
- * from the searched classloaders. If no results are found, the resource name
- * is prepended by '/' and tried again.
+ * Load all resources with a given name, potentially aggregating all results from the searched classloaders. If no
+ * results are found, the resource name is prepended by '/' and tried again.
*
* This method will try to load the resources using the following methods (in order):
* <ul>
- * <li>From Thread.currentThread().getContextClassLoader()
- * <li>From ClassLoaderUtil.class.getClassLoader()
- * <li>callingClass.getClassLoader()
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
* </ul>
*
* @param resourceName The name of the resources to load
* @param callingClass The Class object of the calling object
*/
- public static Iterator<URL> getResources(String resourceName, Class<?> callingClass, boolean aggregate) throws IOException {
+ public static Iterator<URL> getResources(String resourceName, Class<?> callingClass, boolean aggregate)
+ throws IOException {
- AggregateIterator<URL> iterator = new AggregateIterator<>();
+ AggregateIterator<URL> iterator = new AggregateIterator<>();
- iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
+ iterator.addEnumeration(Thread.currentThread().getContextClassLoader().getResources(resourceName));
- if (!iterator.hasNext() || aggregate) {
- iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
- }
+ if (!iterator.hasNext() || aggregate) {
+ iterator.addEnumeration(ClassLoaderUtil.class.getClassLoader().getResources(resourceName));
+ }
- if (!iterator.hasNext() || aggregate) {
- ClassLoader cl = callingClass.getClassLoader();
+ if (!iterator.hasNext() || aggregate) {
+ ClassLoader cl = callingClass.getClassLoader();
- if (cl != null) {
- iterator.addEnumeration(cl.getResources(resourceName));
- }
- }
+ if (cl != null) {
+ iterator.addEnumeration(cl.getResources(resourceName));
+ }
+ }
- if (!iterator.hasNext() && resourceName != null && (resourceName.length() == 0 || resourceName.charAt(0) != '/')) {
- return getResources('/' + resourceName, callingClass, aggregate);
- }
+ if (!iterator.hasNext() && resourceName != null
+ && (resourceName.length() == 0 || resourceName.charAt(0) != '/')) {
+ return getResources('/' + resourceName, callingClass, aggregate);
+ }
- return iterator;
- }
+ return iterator;
+ }
/**
- * Load a given resource.
- *
- * This method will try to load the resource using the following methods (in order):
- * <ul>
- * <li>From Thread.currentThread().getContextClassLoader()
- * <li>From ClassLoaderUtil.class.getClassLoader()
- * <li>callingClass.getClassLoader()
- * </ul>
- *
- * @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
- * @param callingClass The Class object of the calling object
- */
+ * Load a given resource.
+ *
+ * This method will try to load the resource using the following methods (in order):
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param resourceName The name IllegalStateException("Unable to call ")of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
public static URL getResource(String resourceName, Class<?> callingClass) {
URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
@@ -112,13 +113,13 @@
}
/**
- * This is a convenience method to load a resource as a stream.
- *
- * The algorithm used to find the resource is given in getResource()
- *
- * @param resourceName The name of the resource to load
- * @param callingClass The Class object of the calling object
- */
+ * This is a convenience method to load a resource as a stream.
+ *
+ * The algorithm used to find the resource is given in getResource()
+ *
+ * @param resourceName The name of the resource to load
+ * @param callingClass The Class object of the calling object
+ */
public static InputStream getResourceAsStream(String resourceName, Class<?> callingClass) {
URL url = getResource(resourceName, callingClass);
@@ -130,20 +131,20 @@
}
/**
- * Load a class with a given name.
- *
- * It will try to load the class in the following order:
- * <ul>
- * <li>From Thread.currentThread().getContextClassLoader()
- * <li>Using the basic Class.forName()
- * <li>From ClassLoaderUtil.class.getClassLoader()
- * <li>From the callingClass.getClassLoader()
- * </ul>
- *
- * @param className The name of the class to load
- * @param callingClass The Class object of the calling object
- * @throws ClassNotFoundException If the class cannot be found anywhere.
- */
+ * Load a class with a given name.
+ *
+ * It will try to load the class in the following order:
+ * <ul>
+ * <li>From Thread.currentThread().getContextClassLoader()
+ * <li>Using the basic Class.forName()
+ * <li>From ClassLoaderUtil.class.getClassLoader()
+ * <li>From the callingClass.getClassLoader()
+ * </ul>
+ *
+ * @param className The name of the class to load
+ * @param callingClass The Class object of the calling object
+ * @throws ClassNotFoundException If the class cannot be found anywhere.
+ */
public static Class<?> loadClass(String className, Class<?> callingClass) throws ClassNotFoundException {
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
@@ -161,8 +162,8 @@
}
/**
- * Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one
- * ahead of the enumerator to protect against returning duplicates.
+ * Aggregates Enumeration instances into one iterator and filters out duplicates. Always keeps one ahead of the
+ * enumerator to protect against returning duplicates.
*/
static class AggregateIterator<E> implements Iterator<E> {
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java
index f6d0b55..a4a0e76 100644
--- a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/ClassLoaderUtilExt.java
@@ -37,7 +37,7 @@
try {
urls = getResources(resourceName, callingClass, true);
} catch (IOException e) {
- LOG.debug("No resource {}",resourceName);
+ LOG.debug("No resource {}", resourceName);
}
if (urls != null) {
while (urls.hasNext()) {
@@ -50,11 +50,9 @@
if (url == null) {
LOG.debug("res currently not found. try to find with bundle");
Bundle b = FrameworkUtil.getBundle(callingClass);
- if(b!=null)
- {
+ if (b != null) {
url = b.getEntry(resourceName);
- }
- else {
+ } else {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
url = loader.getResource(resourceName);
}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java
index e1e300a..ab69d63 100644
--- a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundle.java
@@ -25,8 +25,8 @@
import java.net.URL;
/**
- * At startup of each karaf bundle, each UI module creates an instance of this class via blueprint.
- * Initialize method gets called at loading of bundle.
+ * At startup of each karaf bundle, each UI module creates an instance of this class via blueprint. Initialize method
+ * gets called at loading of bundle.
*/
public class OdluxBundle {
@@ -103,12 +103,12 @@
public String getResourceFileContent(String filename) {
return this.loadFileContent(this.getResource(filename));
}
-
+
protected URL getResource(String filename) {
return ClassLoaderUtilExt.getResource(filename, this.getClass());
}
- protected String loadFileContent(final URL url ) {
+ protected String loadFileContent(final URL url) {
if (url == null)
return null;
LOG.debug("try to load res " + url.toString());
@@ -124,15 +124,14 @@
} catch (IOException e) {
LOG.warn("could not load resfile " + url.toString() + ": " + e.getMessage());
return null;
- }
- finally {
- if(in!=null) {
- try {
- in.close();
- } catch (IOException e) {
-
- }
- }
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+
+ }
+ }
}
return sb.toString();
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java
index 455c832..870011e 100644
--- a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleLoader.java
@@ -25,6 +25,6 @@
public int getNumberOfBundles();
- public String getResourceContent(String fn, OdluxBundleResourceAccess indexBundle);
+ public String getResourceContent(String fn, OdluxBundleResourceAccess indexBundle);
}
diff --git a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java
index f9a8425..1abed46 100644
--- a/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java
+++ b/sdnr/wt/odlux/core/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/model/bundles/OdluxBundleResourceAccess.java
@@ -22,7 +22,9 @@
public interface OdluxBundleResourceAccess {
boolean hasResource(String fn);
+
String getResourceFileContent(String fn, List<String> bundleNames);
+
String getBundleName();
}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java
index 75497e0..1ea27d7 100644
--- a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexOdluxBundle.java
@@ -46,15 +46,15 @@
super(null, BUNDLENAME_APP);
}
+
@Override
- protected String loadFileContent(URL url)
- {
+ protected String loadFileContent(URL url) {
return loadFileContent(url, OdluxBundleLoaderImpl.getInstance().getLoadedBundles(this.getBundleName()));
}
@Override
public String getResourceFileContent(String fn, List<String> bundleNames) {
- return loadFileContent(this.getResource(fn),bundleNames);
+ return loadFileContent(this.getResource(fn), bundleNames);
}
private static String loadFileContent(URL url, List<String> bundlesNamesList) {
@@ -64,7 +64,7 @@
LOG.debug("try to load res " + url.toString());
StringBuilder sb = new StringBuilder();
Matcher matcher;
- BufferedReader in=null;
+ BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(url.openStream()));
@@ -73,8 +73,8 @@
if (url.getFile().endsWith("index.html")) {
matcher = patternRequire.matcher(inputLine);
if (matcher.find()) {
- inputLine = inputLine.substring(0, matcher.start(1)) + "\"" + String.join("\",\"", bundlesNamesList)
- + "\"" + inputLine.substring(matcher.end(1));
+ inputLine = inputLine.substring(0, matcher.start(1)) + "\""
+ + String.join("\",\"", bundlesNamesList) + "\"" + inputLine.substring(matcher.end(1));
}
matcher = patternFunction.matcher(inputLine);
if (matcher.find()) {
@@ -89,26 +89,25 @@
hlp += bundle + ".register();" + LR;
}
}
- inputLine = inputLine.substring(0, matcher.start(1)) + hlp
- + inputLine.substring(matcher.start(1));
+ inputLine =
+ inputLine.substring(0, matcher.start(1)) + hlp + inputLine.substring(matcher.start(1));
}
}
sb.append(inputLine + LR);
}
-
+
} catch (IOException e) {
LOG.warn("could not load resfile {} : {}", url, e.getMessage());
return null;
- }
- finally {
- try {
- if (in != null) {
- in.close();
- }
- } catch (IOException e) {
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException e) {
- }
- }
+ }
+ }
return sb.toString();
}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java
index db709b1..a7cc2ac 100644
--- a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/IndexServlet.java
@@ -22,7 +22,6 @@
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.nio.file.Files;
-
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -32,40 +31,40 @@
public class IndexServlet extends HttpServlet {
- private static final long serialVersionUID = 3039669437157215355L;
- private static Logger LOG = LoggerFactory.getLogger(IndexServlet.class);
+ private static final long serialVersionUID = 3039669437157215355L;
+ private static Logger LOG = LoggerFactory.getLogger(IndexServlet.class);
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- if (req.getRequestURI() != null && req.getRequestURI().contains("favicon.ico")) {
- this.sendFile(resp, "etc/favicon.ico","image/x-icon");
- } else {
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ if (req.getRequestURI() != null && req.getRequestURI().contains("favicon.ico")) {
+ this.sendFile(resp, "etc/favicon.ico", "image/x-icon");
+ } else {
- LOG.debug("redirect to odlux/index.html");
- resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
- resp.setHeader("Location", "odlux/index.html");
- }
- }
+ LOG.debug("redirect to odlux/index.html");
+ resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ resp.setHeader("Location", "odlux/index.html");
+ }
+ }
- private void sendFile(HttpServletResponse response, String filename, String mimeType) {
- File f = new File(filename);
- if (f.exists()) {
- try {
- byte[] bytes = Files.readAllBytes(f.toPath());
- response.setContentType(mimeType);
- response.setContentLength(bytes.length);
- response.setStatus(HttpURLConnection.HTTP_OK);
- OutputStream os = response.getOutputStream();
- os.write(bytes);
- os.flush();
- os.close();
- } catch (IOException e) {
- LOG.debug("problem sending {}: {}", filename, e);
- }
- } else {
- LOG.debug("file not found: {}",filename);
- response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
- }
- }
+ private void sendFile(HttpServletResponse response, String filename, String mimeType) {
+ File f = new File(filename);
+ if (f.exists()) {
+ try {
+ byte[] bytes = Files.readAllBytes(f.toPath());
+ response.setContentType(mimeType);
+ response.setContentLength(bytes.length);
+ response.setStatus(HttpURLConnection.HTTP_OK);
+ OutputStream os = response.getOutputStream();
+ os.write(bytes);
+ os.flush();
+ os.close();
+ } catch (IOException e) {
+ LOG.debug("problem sending {}: {}", filename, e);
+ }
+ } else {
+ LOG.debug("file not found: {}", filename);
+ response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
+ }
}
diff --git a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
index 321924e..b480d89 100644
--- a/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
+++ b/sdnr/wt/odlux/core/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/odlux/ResFilesServlet.java
@@ -20,12 +20,10 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
-
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundleLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,34 +44,35 @@
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- final String fn = req.getRequestURI();
+ final String fn = req.getRequestURI();
LOG.debug("Get request with for URI: {}", fn);
OdluxBundleLoader odluxBundleLoader = OdluxBundleLoaderImpl.getInstance();
- if (odluxBundleLoader != null) {
- String fileContent = odluxBundleLoader.getResourceContent(fn, indexBundle);
- if (fileContent != null) {
- //Store header info
- String mimeType = getMimeType(fn);
- byte[] byteContent = fileContent.getBytes(java.nio.charset.StandardCharsets.UTF_8);
- int length = byteContent.length;
+ if (odluxBundleLoader != null) {
+ String fileContent = odluxBundleLoader.getResourceContent(fn, indexBundle);
+ if (fileContent != null) {
+ //Store header info
+ String mimeType = getMimeType(fn);
+ byte[] byteContent = fileContent.getBytes(java.nio.charset.StandardCharsets.UTF_8);
+ int length = byteContent.length;
- LOG.debug("Found file in resources. Name {} mimetype {} length {} and write to output stream", fn, mimeType, length);
- resp.setContentType(mimeType);
- resp.setContentLength(length);
- resp.setStatus(HttpURLConnection.HTTP_OK);
- OutputStream os = resp.getOutputStream();
- os.write(byteContent);
- os.flush();
- os.close();
- } else {
- LOG.debug("File {} not found in res.", fn);
- resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
- }
- } else {
- LOG.debug("BundleLoaderInstance to found.", fn);
- resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
- }
+ LOG.debug("Found file in resources. Name {} mimetype {} length {} and write to output stream", fn,
+ mimeType, length);
+ resp.setContentType(mimeType);
+ resp.setContentLength(length);
+ resp.setStatus(HttpURLConnection.HTTP_OK);
+ OutputStream os = resp.getOutputStream();
+ os.write(byteContent);
+ os.flush();
+ os.close();
+ } else {
+ LOG.debug("File {} not found in res.", fn);
+ resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
+ } else {
+ LOG.debug("BundleLoaderInstance to found.", fn);
+ resp.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
+ }
}
public String loadFileContent(String filename) {
@@ -82,7 +81,7 @@
//Provide own function that can be overloaded for test
public String getMimeType(String fileName) {
- return getServletContext().getMimeType(fileName);
+ return getServletContext().getMimeType(fileName);
}
}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java
index c973d53..3d817a2 100644
--- a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestBundleLoaderImpl.java
@@ -20,7 +20,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-
import org.junit.Test;
import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
import org.onap.ccsdk.features.sdnr.wt.odlux.model.bundles.OdluxBundle;
@@ -45,10 +44,10 @@
bundle2.initialize();
assertNotNull(bundle1.getResourceFileContent("index.html"));
assertNotNull(bundle2.getResourceFileContent("index2.html"));
- assertEquals(loaded+2, loader.getNumberOfBundles());
+ assertEquals(loaded + 2, loader.getNumberOfBundles());
loader.addBundle(bundle1);
loader.addBundle(bundle2);
- assertEquals(loaded+2, loader.getNumberOfBundles());
+ assertEquals(loaded + 2, loader.getNumberOfBundles());
loader.removeBundle(bundle1);
loader.removeBundle(bundle2);
assertEquals(loaded, loader.getNumberOfBundles());
@@ -56,10 +55,10 @@
assertTrue(bundle1.hasResource("index.html"));
assertTrue(bundle2.hasResource("index2.html"));
assertNotNull(bundle1.getLoader());
- assertEquals(0,bundle1.getIndex());
+ assertEquals(0, bundle1.getIndex());
bundle1.clean();
bundle2.clean();
- assertEquals(loaded,loader.getNumberOfBundles());
+ assertEquals(loaded, loader.getNumberOfBundles());
}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java
index d9cd920..bef3dba 100644
--- a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestLoadResources.java
@@ -16,11 +16,10 @@
* ============LICENSE_END==========================================================================
*/
package org.onap.ccsdk.features.sdnr.odlux.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-
import org.junit.Test;
import org.onap.ccsdk.features.sdnr.wt.odlux.ResFilesServlet;
@@ -29,15 +28,16 @@
@Test
public void test() {
ResFilesServlet servlet = new ResFilesServlet();
- String indexhtml=null;
- indexhtml=servlet.loadFileContent("odlux/index.html");
+ String indexhtml = null;
+ indexhtml = servlet.loadFileContent("odlux/index.html");
assertNotNull(indexhtml);
final String regex = "require\\(\\[.*\"run\".*\\]";
- final Pattern pattern = Pattern.compile(regex,Pattern.MULTILINE);
+ final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
System.out.println(indexhtml);
final Matcher matcher = pattern.matcher(indexhtml);
- assertTrue("Can not find patter '"+regex+"'",matcher.find());
+ assertTrue("Can not find patter '" + regex + "'", matcher.find());
}
+
@Test
public void test2() {
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java
index bbf5424..68bcae5 100644
--- a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestRedirect.java
@@ -18,40 +18,36 @@
package org.onap.ccsdk.features.sdnr.odlux.test;
import static org.junit.Assert.*;
-
+import static org.mockito.Mockito.*;
import org.junit.Test;
import org.onap.ccsdk.features.sdnr.wt.odlux.IndexServlet;
-
-import static org.mockito.Mockito.*;
-
import java.io.IOException;
-
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestRedirect {
- private static final int RESPONSECODE_REDIRECT = 301;
+ private static final int RESPONSECODE_REDIRECT = 301;
- @Test
- public void test() {
- PublicIndexServlet servlet =new PublicIndexServlet();
- HttpServletRequest req = mock(HttpServletRequest.class);
- HttpServletResponse resp = mock(HttpServletResponse.class);
- try {
- servlet.doGet(req,resp);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- verify(resp).setStatus(RESPONSECODE_REDIRECT);
- }
-
- private static class PublicIndexServlet extends IndexServlet{
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- super.doGet(req, resp);
- }
- }
+ @Test
+ public void test() {
+ PublicIndexServlet servlet = new PublicIndexServlet();
+ HttpServletRequest req = mock(HttpServletRequest.class);
+ HttpServletResponse resp = mock(HttpServletResponse.class);
+ try {
+ servlet.doGet(req, resp);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ verify(resp).setStatus(RESPONSECODE_REDIRECT);
+ }
+
+ private static class PublicIndexServlet extends IndexServlet {
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ super.doGet(req, resp);
+ }
+ }
}
diff --git a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java
index 0490c80..6d537e3 100644
--- a/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java
+++ b/sdnr/wt/odlux/core/provider/src/test/java/org/onap/ccsdk/features/sdnr/odlux/test/TestResFileServlet.java
@@ -18,18 +18,16 @@
package org.onap.ccsdk.features.sdnr.odlux.test;
import static org.junit.Assert.*;
-
+import static org.mockito.Mockito.*;
import java.io.IOException;
import java.io.StringWriter;
import java.net.HttpURLConnection;
-
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import static org.mockito.Mockito.*;
import org.junit.Test;
import org.onap.ccsdk.features.sdnr.wt.odlux.OdluxBundleLoaderImpl;
import org.onap.ccsdk.features.sdnr.wt.odlux.ResFilesServlet;
@@ -43,7 +41,7 @@
@Test
public void test() throws ServletException {
servlet = new PublicResFilesServlet();
- servlet.init();
+ servlet.init();
OdluxBundleLoader loader = OdluxBundleLoaderImpl.getInstance();
OdluxBundle b = new OdluxBundle();
@@ -96,9 +94,10 @@
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
+
@Override
public String getMimeType(String fileName) {
- return "mimetype";
+ return "mimetype";
}
}
}
diff --git a/sdnr/wt/odlux/framework/package.json b/sdnr/wt/odlux/framework/package.json
index c945688..511b977 100644
--- a/sdnr/wt/odlux/framework/package.json
+++ b/sdnr/wt/odlux/framework/package.json
@@ -24,7 +24,7 @@
"author": "Matthias Fischer",
"license": "Apache-2.0",
"peerDependencies": {
- "@types/node": "11.9.5",
+ "@types/node": "11.11.6",
"@types/react": "16.9.19",
"@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
@@ -44,6 +44,8 @@
"@types/jsonwebtoken": "7.2.8"
},
"dependencies": {
+ "@babel/polyfill": "^7.0.0",
+ "@types/x2js": "^3.1.0",
"http-server": "^0.11.1"
}
-}
\ No newline at end of file
+}
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
index b125a45..5bb7d6f 100644
--- a/sdnr/wt/odlux/framework/pom.xml
+++ b/sdnr/wt/odlux/framework/pom.xml
@@ -46,7 +46,7 @@
<properties>
<buildtime>${maven.build.timestamp}</buildtime>
<distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
- <buildno>52.3b24c2d(20/04/08)</buildno>
+ <buildno>56.139cd6d(20/07/08)</buildno>
<odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
</properties>
diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
index 1bb4936..adf0b8e 100644
--- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
@@ -77,15 +77,18 @@
itemHeight?: number;
depthOffset?: number;
searchMode?: SearchMode;
+
}
type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & {
+ initialSearchTerm? : string;
onItemClick?: (item: TreeItem<TData>) => void;
onFolderClick?: (item: TreeItem<TData>) => void;
}
type TreeViewComponentWithExternalSearchProps<TData = {}> = TreeViewComponentBaseProps<TData> & {
items: ExternalTreeItem<TData>[];
+ initialSearchTerm? : string;
searchTerm: string;
onSearch: (searchTerm: string) => void;
onItemClick?: (item: TreeItem<TData>) => void;
@@ -94,6 +97,7 @@
type TreeViewComponentWithExternalStateProps<TData = {}> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
items: ExternalTreeItem<TData>[];
+ initialSearchTerm? : string;
searchTerm: string;
onSearch: (searchTerm: string) => void;
onItemClick: (item: TreeItem<TData>) => void;
@@ -137,7 +141,7 @@
expandedItems: [],
activeItem: undefined,
searchTerm: undefined,
- searchTermValue: undefined
+ searchTermValue: props.initialSearchTerm
};
}
diff --git a/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx b/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx
new file mode 100644
index 0000000..d449f5c
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx
@@ -0,0 +1,173 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from "react";
+import { makeStyles } from '@material-ui/core/styles';
+
+export const getTypeName = (obj: any): string => {
+ if (obj == null) {
+ return obj === undefined ? "Undefined" : "Null";
+ }
+ return Object.prototype.toString.call(obj).slice(8, -1);
+};
+
+const isObjectLike = (obj: any) => {
+ return typeof obj === "object" && obj !== null;
+};
+
+const isBoolean = (obj: any) => {
+ return obj === true || obj === false ||
+ (isObjectLike(obj) && getTypeName(obj) === "Boolean");
+};
+
+const isNumber = (obj: any) => {
+ return typeof obj === "number" ||
+ (isObjectLike(obj) && getTypeName(obj) === "Number");
+};
+
+const isString = (obj: any) => {
+ return typeof obj === "string" ||
+ (isObjectLike(obj) && getTypeName(obj) === "String");
+};
+
+const isNull = (obj: any) => {
+ return obj === null;
+};
+
+const isDate = (obj: any): boolean => {
+ return isObjectLike(obj) && (obj instanceof Date);
+};
+
+const useSimpleTableStyles = makeStyles({
+ root: {
+ },
+ table: {
+ fontFamily: "verdana, arial, helvetica, sans-serif",
+ borderSpacing: "3px",
+ borderCollapse: "separate",
+ marginLeft: "30px"
+ },
+ label: {
+ cursor: "pointer",
+ },
+ th: {
+ textAlign: "left",
+ color: "white",
+ padding: "5px",
+ backgroundColor: "#cccccc",
+ },
+ td: {
+ verticalAlign: "top",
+ padding: "0.5rem 1rem",
+ borderBottom: "2px solid #DDD"
+ },
+ object: {
+ },
+ objectTh: {
+ backgroundColor: "#4444cc",
+ },
+ objectTd: {
+ padding: "0.5rem 1rem",
+ borderBottom: "2px solid #DDD"
+ },
+});
+
+
+type SimpleTableProps = {
+ classNameTh?: string;
+ label?: JSX.Element | string | null;
+ cols?: number;
+ expand?: boolean;
+}
+
+const SimpleTable: React.FC<SimpleTableProps> = (props) => {
+ const { label = '', cols = 2, expand = true, classNameTh, children } = props;
+ const [isExpanded, setIsExpanded] = React.useState(expand);
+
+ const classes = useSimpleTableStyles();
+
+ React.useEffect(() => {
+ setIsExpanded(expand);
+ }, [expand]);
+
+ const handleClick = () => {
+ setIsExpanded(!isExpanded);
+ };
+
+ return (
+ <table className={`${classes.root} ${classes.table}`}>
+ {label && (<thead>
+ <tr>
+ <th className={`${classes.th} ${classes.label} ${classNameTh ? classNameTh : ''}`} colSpan={cols} onClick={handleClick}>
+ {label}
+ </th>
+ </tr>
+ </thead>) || null
+ }
+ {isExpanded && <tbody >{children}</tbody> || null}
+ </table>
+ );
+};
+
+
+type ObjectRendererProps = {
+ className?: string;
+ label?: JSX.Element | string | null;
+ expand?: boolean;
+ object: { [key: string]: any };
+};
+
+const ObjectRenderer: React.FC<ObjectRendererProps> = (props) => {
+ const { object, className, label = 'Object', expand = true } = props;
+ const classes = useSimpleTableStyles();
+
+ return (
+ <SimpleTable classNameTh={classes.objectTh} label={getTypeName(object) || label} expand={expand}>
+ {
+ Object.keys(object).map(key => {
+ return (
+ <tr key={String(key)}>
+ <td className={`${classes.td} ${classes.objectTd}`}>{String(key)} </td>
+ <td className={`${classes.td}`}>{renderObject(object[key])}</td>
+ </tr>
+ );
+ })
+ }
+ </SimpleTable>
+ );
+};
+
+
+type ArrayRendererProps = {
+ label?: JSX.Element | string | null;
+ extraRenderer?: { [label: string]: React.ComponentType<{ label?: JSX.Element | string | null; object: any; }> };
+ description?: string;
+ object: any;
+};
+
+const ArrayRenderer: React.FC<ArrayRendererProps> = (props) => {
+
+ return null;
+};
+
+export const renderObject = (object: any): JSX.Element | string => {
+ if (isString(object) || isNumber(object) || isBoolean(object)) {
+ return String(object);
+ }
+ return <ObjectRenderer object={object} />;
+};
diff --git a/sdnr/wt/odlux/framework/src/index.html b/sdnr/wt/odlux/framework/src/index.html
index 1a37339..d51c448 100644
--- a/sdnr/wt/odlux/framework/src/index.html
+++ b/sdnr/wt/odlux/framework/src/index.html
@@ -13,11 +13,13 @@
<div id="app"></div>
<script type="text/javascript" src="./require.js"></script>
<script type="text/javascript" src="./config.js"></script>
- <script>
+<script>
// run the application
require(["run"], function (run) {
run.runApplication();
});
+
+ // don't change anything in here!!
</script>
</body>
diff --git a/sdnr/wt/odlux/framework/src/services/authenticationService.ts b/sdnr/wt/odlux/framework/src/services/authenticationService.ts
index d3d62c5..cd8a93a 100644
--- a/sdnr/wt/odlux/framework/src/services/authenticationService.ts
+++ b/sdnr/wt/odlux/framework/src/services/authenticationService.ts
@@ -26,7 +26,7 @@
class AuthenticationService {
- public async authenticateUser(email: string, password: string, scope: string): Promise<AuthToken | null> {
+ public async authenticateUserOAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
const result = await requestRest<string>(`oauth2/token`, {
method: "POST",
headers: {
@@ -47,6 +47,24 @@
expires: (new Date().valueOf()) + (resultObj.expires_in * 1000)
} || null;
}
+
+ public async authenticateUserBasicAuth(email: string, password: string, scope: string): Promise<AuthToken | null> {
+ const result = await requestRest<string>(`restconf/modules`, {
+ method: "GET",
+ headers: {
+ 'Authorization': "Basic " + btoa(email + ":" + password)
+ },
+ }, false);
+ if (result) {
+ return {
+ username: email,
+ access_token: btoa(email + ":" + password),
+ token_type: "Basic",
+ expires: (new Date()).valueOf() + 2678400000 // 31 days
+ }
+ }
+ return null;
+ }
}
export const authenticationService = new AuthenticationService();
diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx
index db04117..ca3953a 100644
--- a/sdnr/wt/odlux/framework/src/views/about.tsx
+++ b/sdnr/wt/odlux/framework/src/views/about.tsx
@@ -19,29 +19,51 @@
import * as marked from 'marked';
import * as hljs from 'highlight.js';
import { requestRestExt } from '../services/restService';
+import { Button, Typography } from '@material-ui/core';
const defaultRenderer = new marked.Renderer();
defaultRenderer.link = (href, title, text) => (
`<a target="_blank" rel="noopener noreferrer" href="${href}" title="${title}">${text}</a>`
);
interface AboutState {
content: string | null;
+ isCopiedSuccessfully: boolean;
+ isContentLoadedSucessfully: boolean;
}
class AboutComponent extends React.Component<any, AboutState> {
+ textarea: React.RefObject<HTMLTextAreaElement>;
constructor(props: any) {
super(props);
- this.state = { content: null }
+ this.state = { content: null, isCopiedSuccessfully:false, isContentLoadedSucessfully: false }
+ this.textarea = React.createRef();
this.loadAboutContent();
}
private loadAboutContent(): void {
requestRestExt<string>('/about').then((response) => {
- this.setState({ content: response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error" })
+ const content = response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error";
+ const loadedSucessfully = response.status == 200 ? true : false;
+ this.setState({ content: content, isContentLoadedSucessfully: loadedSucessfully });
}).catch((error) => {
this.setState({ content: error })
})
}
+
+ copyToClipboard = (e: React.MouseEvent<HTMLButtonElement>) =>{
+ e.preventDefault();
+
+ if(this.textarea.current!==null){
+ this.textarea.current.select();
+ document.execCommand('copy');
+ if(e.currentTarget != null){ // refocus on button, otherwhise the textarea would be focused
+ e.currentTarget.focus();
+ }
+ this.setState({isCopiedSuccessfully: true});
+ window.setTimeout(()=>{this.setState({isCopiedSuccessfully: false});},2000);
+ }
+ }
+
render() {
const markedOptions: marked.MarkedOptions = {
@@ -70,14 +92,33 @@
return (
<div style={containerStyle}>
+ { this.state.isContentLoadedSucessfully &&
+ <div style={{float: "right", marginRight: "10px"}}>
+ <Button variant="contained" onClick={e => this.copyToClipboard(e)}>
+ Copy to clipboard
+ </Button>
+ {
+ this.state.isCopiedSuccessfully &&
+ <Typography variant="body1" style={{color: "green"}} align="center">
+ copied successfully
+ </Typography>
+ }
+ </div>
+ }
+
<div
dangerouslySetInnerHTML={{ __html: html }}
className={className}
style={style}
/>
+ <form>
+ <textarea
+ style={{opacity: ".01"}}
+ ref={this.textarea}
+ value={this.state.content || ''}
+ />
+ </form>
</div>
-
-
);
}
};
diff --git a/sdnr/wt/odlux/framework/src/views/login.tsx b/sdnr/wt/odlux/framework/src/views/login.tsx
index fa01568..30b9c85 100644
--- a/sdnr/wt/odlux/framework/src/views/login.tsx
+++ b/sdnr/wt/odlux/framework/src/views/login.tsx
@@ -164,7 +164,8 @@
event.preventDefault();
this.setState({ busy: true });
- const token = await authenticationService.authenticateUser(this.state.username, this.state.password, this.state.scope);
+ // const token = await authenticationService.authenticateUserOAuth(this.state.username, this.state.password, this.state.scope);
+ const token = await authenticationService.authenticateUserBasicAuth(this.state.username, this.state.password, this.state.scope);
this.props.dispatch(new UpdateAuthentication(token));
this.setState({ busy: false });
diff --git a/sdnr/wt/odlux/framework/webpack.config.js b/sdnr/wt/odlux/framework/webpack.config.js
index e43539d..4887a75 100644
--- a/sdnr/wt/odlux/framework/webpack.config.js
+++ b/sdnr/wt/odlux/framework/webpack.config.js
@@ -45,6 +45,7 @@
app: [
"./app.tsx",
"./services",
+ "./components/objectDump",
"./components/material-table",
"./components/material-ui",
"./utilities/elasticSearch",
@@ -127,7 +128,10 @@
baseUrl: '',
pathUrl: '',
processOutput: function (assets) {
- return 'require.config(' + JSON.stringify(assets, null, 2) + ')';
+ let mainConfig = JSON.stringify(assets, null, 2);
+ mainConfig = mainConfig.slice(0,-1); // remove closing bracket from string
+ const entireConfig = mainConfig.concat(", waitSeconds: 30}"); // add waitSeconds to config
+ return 'require.config(' + entireConfig + ')';
}
}),
// new HtmlWebpackPlugin({
diff --git a/sdnr/wt/odlux/package.json b/sdnr/wt/odlux/package.json
index 12d18c1..9053e08 100644
--- a/sdnr/wt/odlux/package.json
+++ b/sdnr/wt/odlux/package.json
@@ -22,11 +22,10 @@
"@types/jquery": "3.3.10",
"@types/jsonwebtoken": "7.2.8",
"@types/node": "11.11.6",
- "@types/react": "16.9.11",
- "@types/react-dom": "16.9.4",
+ "@types/react": "16.9.19",
+ "@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
"@types/react-transition-group": "2.0.15",
- "@types/x2js": "3.1.0",
"classnames": "2.2.6",
"csstype": "2.6.8",
"jquery": "3.3.1",
diff --git a/sdnr/wt/odlux/yarn.lock b/sdnr/wt/odlux/yarn.lock
index 448d781..71488be 100644
--- a/sdnr/wt/odlux/yarn.lock
+++ b/sdnr/wt/odlux/yarn.lock
@@ -565,6 +565,14 @@
core-js "^2.5.7"
regenerator-runtime "^0.11.1"
+"@babel/polyfill@^7.0.0":
+ version "7.8.7"
+ resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.7.tgz#151ec24c7135481336168c3bd8b8bf0cf91c032f"
+ integrity sha512-LeSfP9bNZH2UOZgcGcZ0PIHUt1ZuHub1L3CVmEyqLxCeDLm4C5Gi8jRH8ZX2PNpDhQCo0z6y/+DIs2JlliXW8w==
+ dependencies:
+ core-js "^2.6.5"
+ regenerator-runtime "^0.13.4"
+
"@babel/preset-env@7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11"
@@ -1431,20 +1439,20 @@
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@octokit/auth-token@^2.4.0":
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f"
- integrity sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a"
+ integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==
dependencies:
- "@octokit/types" "^2.0.0"
+ "@octokit/types" "^5.0.0"
-"@octokit/endpoint@^5.5.0":
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.5.2.tgz#ed19d01fe85ac58bc2b774661658f9e5429b8164"
- integrity sha512-ICDcRA0C2vtTZZGud1nXRrBLXZqFayodXAKZfo3dkdcLNqcHsgaz3YSTupbURusYeucSVRjjG+RTcQhx6HPPcg==
+"@octokit/endpoint@^6.0.1":
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.3.tgz#dd09b599662d7e1b66374a177ab620d8cdf73487"
+ integrity sha512-Y900+r0gIz+cWp6ytnkibbD95ucEzDSKzlEnaWS52hbCDNcCJYO5mRmWW7HRAnDc7am+N/5Lnd8MppSaTYx1Yg==
dependencies:
- "@octokit/types" "^2.0.0"
+ "@octokit/types" "^5.0.0"
is-plain-object "^3.0.0"
- universal-user-agent "^4.0.0"
+ universal-user-agent "^5.0.0"
"@octokit/plugin-enterprise-rest@^2.1.1":
version "2.2.2"
@@ -1471,7 +1479,7 @@
"@octokit/types" "^2.0.1"
deprecation "^2.3.1"
-"@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2":
+"@octokit/request-error@^1.0.2":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801"
integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==
@@ -1480,19 +1488,28 @@
deprecation "^2.0.0"
once "^1.4.0"
-"@octokit/request@^5.2.0":
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.3.1.tgz#3a1ace45e6f88b1be4749c5da963b3a3b4a2f120"
- integrity sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg==
+"@octokit/request-error@^2.0.0":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0"
+ integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==
dependencies:
- "@octokit/endpoint" "^5.5.0"
- "@octokit/request-error" "^1.0.1"
- "@octokit/types" "^2.0.0"
+ "@octokit/types" "^5.0.1"
+ deprecation "^2.0.0"
+ once "^1.4.0"
+
+"@octokit/request@^5.2.0":
+ version "5.4.5"
+ resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.5.tgz#8df65bd812047521f7e9db6ff118c06ba84ac10b"
+ integrity sha512-atAs5GAGbZedvJXXdjtKljin+e2SltEs48B3naJjqWupYl2IUBbB/CJisyjbNHcKpHzb3E+OYEZ46G8eakXgQg==
+ dependencies:
+ "@octokit/endpoint" "^6.0.1"
+ "@octokit/request-error" "^2.0.0"
+ "@octokit/types" "^5.0.0"
deprecation "^2.0.0"
is-plain-object "^3.0.0"
node-fetch "^2.3.0"
once "^1.4.0"
- universal-user-agent "^4.0.0"
+ universal-user-agent "^5.0.0"
"@octokit/rest@^16.16.0":
version "16.43.1"
@@ -1517,9 +1534,16 @@
universal-user-agent "^4.0.0"
"@octokit/types@^2.0.0", "@octokit/types@^2.0.1":
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.1.1.tgz#77e80d1b663c5f1f829e5377b728fa3c4fe5a97d"
- integrity sha512-89LOYH+d/vsbDX785NOfLxTW88GjNd0lWRz1DVPVsZgg9Yett5O+3MOvwo7iHgvUwbFz0mf/yPIjBkUbs4kxoQ==
+ version "2.16.2"
+ resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2"
+ integrity sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==
+ dependencies:
+ "@types/node" ">= 8"
+
+"@octokit/types@^5.0.0", "@octokit/types@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.0.1.tgz#5459e9a5e9df8565dcc62c17a34491904d71971e"
+ integrity sha512-GorvORVwp244fGKEt3cgt/P+M0MGy4xEDbckw+K5ojEezxyMDgCaYPKVct+/eWQfZXOT7uq0xRpmrl/+hliabA==
dependencies:
"@types/node" ">= 8"
@@ -1573,6 +1597,11 @@
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.6.0.tgz#e4ac316144a84afda5c2474488d7b9fef3ab9995"
integrity sha512-TxwhgR9VsIfRDJ3WwFokG8Xu+ea0nYGDRHdI783WJ983uffatz0ytIeUEIBOwPvRy241KRSNVyywQltuTqDh0w==
+"@types/minimist@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6"
+ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=
+
"@types/node@*":
version "12.12.7"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
@@ -1584,19 +1613,24 @@
integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==
"@types/node@>= 8":
- version "13.7.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.0.tgz#b417deda18cf8400f278733499ad5547ed1abec4"
- integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==
+ version "14.0.13"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.13.tgz#ee1128e881b874c371374c1f72201893616417c9"
+ integrity sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==
+
+"@types/normalize-package-data@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
+ integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
-"@types/react-dom@16.9.4":
- version "16.9.4"
- resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.4.tgz#0b58df09a60961dcb77f62d4f1832427513420df"
- integrity sha512-fya9xteU/n90tda0s+FtN5Ym4tbgxpq/hb/Af24dvs6uYnYn+fspaxw5USlw0R8apDNwxsqumdRoCoKitckQqw==
+"@types/react-dom@16.9.5":
+ version "16.9.5"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7"
+ integrity sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg==
dependencies:
"@types/react" "*"
@@ -1631,7 +1665,7 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@16.9.11":
+"@types/react@*":
version "16.9.11"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.11.tgz#70e0b7ad79058a7842f25ccf2999807076ada120"
integrity sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==
@@ -1639,7 +1673,15 @@
"@types/prop-types" "*"
csstype "^2.2.0"
-"@types/x2js@3.1.0":
+"@types/react@16.9.19":
+ version "16.9.19"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40"
+ integrity sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^2.2.0"
+
+"@types/x2js@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@types/x2js/-/x2js-3.1.0.tgz#d809ef1ace1a8b55b3e8cb6a1a0b282af66475be"
integrity sha1-2AnvGs4ai1Wz6MtqGgsoKvZkdb4=
@@ -2072,6 +2114,11 @@
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+arrify@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
+ integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
+
asap@^2.0.0, asap@~2.0.3:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
@@ -2703,7 +2750,28 @@
unique-filename "^1.1.1"
y18n "^4.0.0"
-cacache@^12.0.0, cacache@^12.0.2:
+cacache@^12.0.0:
+ version "12.0.4"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
+ integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==
+ dependencies:
+ bluebird "^3.5.5"
+ chownr "^1.1.1"
+ figgy-pudding "^3.5.1"
+ glob "^7.1.4"
+ graceful-fs "^4.1.15"
+ infer-owner "^1.0.3"
+ lru-cache "^5.1.1"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ promise-inflight "^1.0.1"
+ rimraf "^2.6.3"
+ ssri "^6.0.1"
+ unique-filename "^1.1.1"
+ y18n "^4.0.0"
+
+cacache@^12.0.2:
version "12.0.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390"
integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==
@@ -2788,6 +2856,15 @@
map-obj "^2.0.0"
quick-lru "^1.0.0"
+camelcase-keys@^6.2.2:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0"
+ integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==
+ dependencies:
+ camelcase "^5.3.1"
+ map-obj "^4.0.0"
+ quick-lru "^4.0.1"
+
camelcase@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
@@ -2803,11 +2880,16 @@
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
-camelcase@^5.0.0:
+camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+camelcase@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e"
+ integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==
+
caniuse-lite@^1.0.30000884, caniuse-lite@^1.0.30001004:
version "1.0.30001010"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001010.tgz#397a14034d384260453cc81994f494626d34b938"
@@ -2892,11 +2974,16 @@
optionalDependencies:
fsevents "^1.2.7"
-chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
+chownr@^1.0.1, chownr@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==
+chownr@^1.1.2:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
+ integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
+
chrome-trace-event@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4"
@@ -2947,9 +3034,9 @@
restore-cursor "^2.0.0"
cli-width@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
- integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
+ version "2.2.1"
+ 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"
@@ -3088,9 +3175,9 @@
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
compare-func@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648"
- integrity sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg=
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.4.tgz#6b07c4c5e8341119baf44578085bda0f4a823516"
+ integrity sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==
dependencies:
array-ify "^1.0.0"
dot-prop "^3.0.0"
@@ -3186,9 +3273,9 @@
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
conventional-changelog-angular@^5.0.3:
- version "5.0.6"
- resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059"
- integrity sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA==
+ version "5.0.10"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.10.tgz#5cf7b00dd315b6a6a558223c80d5ef24ddb34205"
+ integrity sha512-k7RPPRs0vp8+BtPsM9uDxRl6KcgqtCJmzRD1wRtgqmhQ96g8ifBGo9O/TZBG23jqlXS/rg8BKRDELxfnQQGiaA==
dependencies:
compare-func "^1.3.1"
q "^1.5.1"
@@ -3213,43 +3300,43 @@
through2 "^3.0.0"
conventional-changelog-preset-loader@^2.1.1:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz#580fa8ab02cef22c24294d25e52d7ccd247a9a6a"
- integrity sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ==
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c"
+ integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==
conventional-changelog-writer@^4.0.6:
- version "4.0.11"
- resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz#9f56d2122d20c96eb48baae0bf1deffaed1edba4"
- integrity sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw==
+ version "4.0.16"
+ resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.16.tgz#ca10f2691a8ea6d3c2eb74bd35bcf40aa052dda5"
+ integrity sha512-jmU1sDJDZpm/dkuFxBeRXvyNcJQeKhGtVcFFkwTphUAzyYWcwz2j36Wcv+Mv2hU3tpvLMkysOPXJTLO55AUrYQ==
dependencies:
compare-func "^1.3.1"
- conventional-commits-filter "^2.0.2"
+ conventional-commits-filter "^2.0.6"
dateformat "^3.0.0"
- handlebars "^4.4.0"
+ handlebars "^4.7.6"
json-stringify-safe "^5.0.1"
lodash "^4.17.15"
- meow "^5.0.0"
+ meow "^7.0.0"
semver "^6.0.0"
split "^1.0.0"
through2 "^3.0.0"
-conventional-commits-filter@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1"
- integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ==
+conventional-commits-filter@^2.0.2, conventional-commits-filter@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz#0935e1240c5ca7698329affee1b6a46d33324c4c"
+ integrity sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==
dependencies:
lodash.ismatch "^4.4.0"
modify-values "^1.0.0"
conventional-commits-parser@^3.0.2, conventional-commits-parser@^3.0.3:
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz#23310a9bda6c93c874224375e72b09fb275fe710"
- integrity sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ==
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz#10140673d5e7ef5572633791456c5d03b69e8be4"
+ integrity sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==
dependencies:
JSONStream "^1.0.4"
is-text-path "^1.0.1"
lodash "^4.17.15"
- meow "^5.0.0"
+ meow "^7.0.0"
split2 "^2.0.0"
through2 "^3.0.0"
trim-off-newlines "^1.0.0"
@@ -3326,6 +3413,11 @@
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f"
integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==
+core-js@^2.6.5:
+ version "2.6.11"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
+ integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
+
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -3563,7 +3655,7 @@
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
-decamelize-keys@^1.0.0:
+decamelize-keys@^1.0.0, decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
@@ -4392,7 +4484,12 @@
dependencies:
bser "^2.0.0"
-figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
+figgy-pudding@^3.4.1:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
+ integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
+
+figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
@@ -4499,6 +4596,14 @@
dependencies:
locate-path "^3.0.0"
+find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
findup-sync@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
@@ -4901,11 +5006,16 @@
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.4.tgz#ef089d2880f033b011823ce5c8fae798da775dbd"
integrity sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=
-graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2:
version "4.2.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
+graceful-fs@^4.1.6:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
+ integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
+
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -4927,14 +5037,15 @@
optionalDependencies:
uglify-js "^3.1.4"
-handlebars@^4.4.0:
- version "4.7.3"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.3.tgz#8ece2797826886cf8082d1726ff21d2a022550ee"
- integrity sha512-SRGwSYuNfx8DwHD/6InAPzD6RgeruWLT+B8e8a7gGs8FWgHzlExpTFMEq2IA6QpAfOClpKHy6+8IqTjeBCu6Kg==
+handlebars@^4.7.6:
+ version "4.7.6"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
+ integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
dependencies:
+ minimist "^1.2.5"
neo-async "^2.6.0"
- optimist "^0.6.1"
source-map "^0.6.1"
+ wordwrap "^1.0.0"
optionalDependencies:
uglify-js "^3.1.4"
@@ -4959,6 +5070,11 @@
ajv "^6.5.5"
har-schema "^2.0.0"
+hard-rejection@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
+ integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
+
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
@@ -5098,11 +5214,16 @@
dependencies:
parse-passwd "^1.0.0"
-hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
+hosted-git-info@^2.1.4:
version "2.8.5"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==
+hosted-git-info@^2.7.1:
+ version "2.8.8"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
+ integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+
hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
@@ -5405,6 +5526,11 @@
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
infer-owner@^1.0.3, infer-owner@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@@ -5772,11 +5898,6 @@
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-is-promise@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
- integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
-
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
@@ -6540,6 +6661,11 @@
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
+kind-of@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
kleur@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
@@ -6655,6 +6781,11 @@
resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300"
integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ==
+lines-and-columns@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
+ integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -6726,6 +6857,13 @@
p-locate "^3.0.0"
path-exists "^3.0.0"
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -6964,6 +7102,11 @@
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9"
integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk=
+map-obj@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5"
+ integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==
+
map-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
@@ -7051,20 +7194,24 @@
redent "^2.0.0"
trim-newlines "^2.0.0"
-meow@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
- integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==
+meow@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc"
+ integrity sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==
dependencies:
- camelcase-keys "^4.0.0"
- decamelize-keys "^1.0.0"
- loud-rejection "^1.0.0"
- minimist-options "^3.0.1"
- normalize-package-data "^2.3.4"
- read-pkg-up "^3.0.0"
- redent "^2.0.0"
- trim-newlines "^2.0.0"
- yargs-parser "^10.0.0"
+ "@types/minimist" "^1.2.0"
+ arrify "^2.0.1"
+ camelcase "^6.0.0"
+ camelcase-keys "^6.2.2"
+ decamelize-keys "^1.1.0"
+ hard-rejection "^2.1.0"
+ minimist-options "^4.0.2"
+ normalize-package-data "^2.5.0"
+ read-pkg-up "^7.0.1"
+ redent "^3.0.0"
+ trim-newlines "^3.0.0"
+ type-fest "^0.13.1"
+ yargs-parser "^18.1.3"
merge-descriptors@1.0.1:
version "1.0.1"
@@ -7079,9 +7226,9 @@
readable-stream "^2.0.1"
merge2@^1.2.3:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81"
- integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
merge@^1.2.0:
version "1.2.1"
@@ -7171,6 +7318,11 @@
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@@ -7196,6 +7348,15 @@
arrify "^1.0.1"
is-plain-obj "^1.1.0"
+minimist-options@^4.0.2:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
+ integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
+ dependencies:
+ arrify "^1.0.1"
+ is-plain-obj "^1.1.0"
+ kind-of "^6.0.3"
+
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -7206,6 +7367,11 @@
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+minimist@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
+ integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+
minimist@~0.0.1:
version "0.0.10"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
@@ -7410,9 +7576,9 @@
lower-case "^1.1.1"
node-fetch-npm@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
- integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4"
+ integrity sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==
dependencies:
encoding "^0.1.11"
json-parse-better-errors "^1.0.0"
@@ -7571,7 +7737,7 @@
abbrev "1"
osenv "^0.1.4"
-normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0:
+normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
@@ -7691,9 +7857,9 @@
npm-package-arg "^6.1.0"
npm-registry-fetch@^4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz#2b1434f93ccbe6b6385f8e45f45db93e16921d7a"
- integrity sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-4.0.4.tgz#2da1ecf3f43d419d96abf313664291a4623d3ea5"
+ integrity sha512-6jb34hX/iYNQebqWUHtU8YF6Cjb1H6ouTFPClYsyiW6lpFkljTpdeftm53rRojtja1rKAvKNIIiTS5Sjpw4wsA==
dependencies:
JSONStream "^1.3.4"
bluebird "^3.5.1"
@@ -7972,6 +8138,13 @@
dependencies:
p-try "^2.0.0"
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -7986,6 +8159,13 @@
dependencies:
p-limit "^2.0.0"
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
p-map-series@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca"
@@ -8124,6 +8304,16 @@
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
+parse-json@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f"
+ integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+ lines-and-columns "^1.1.6"
+
parse-passwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
@@ -8184,6 +8374,11 @@
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -8602,6 +8797,11 @@
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
+quick-lru@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f"
+ integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==
+
randomatic@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
@@ -8767,6 +8967,15 @@
find-up "^2.0.0"
read-pkg "^3.0.0"
+read-pkg-up@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
+ integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
+ dependencies:
+ find-up "^4.1.0"
+ read-pkg "^5.2.0"
+ type-fest "^0.8.1"
+
read-pkg@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
@@ -8785,6 +8994,16 @@
normalize-package-data "^2.3.2"
path-type "^3.0.0"
+read-pkg@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
+ integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
+ dependencies:
+ "@types/normalize-package-data" "^2.4.0"
+ normalize-package-data "^2.5.0"
+ parse-json "^5.0.0"
+ type-fest "^0.6.0"
+
read@1, read@~1.0.1:
version "1.0.7"
resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
@@ -8806,9 +9025,9 @@
util-deprecate "~1.0.1"
"readable-stream@2 || 3", readable-stream@^3.0.2:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.5.0.tgz#465d70e6d1087f6162d079cd0b5db7fbebfd1606"
- integrity sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
@@ -8865,6 +9084,14 @@
indent-string "^3.0.0"
strip-indent "^2.0.0"
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
reflect-metadata@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
@@ -8892,6 +9119,11 @@
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
+regenerator-runtime@^0.13.4:
+ version "0.13.5"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
+ integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
+
regenerator-transform@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb"
@@ -9192,11 +9424,9 @@
integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
run-async@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
- integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
- dependencies:
- is-promise "^2.1.0"
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
+ integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
@@ -9206,9 +9436,9 @@
aproba "^1.1.1"
rxjs@^6.4.0:
- version "6.5.4"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c"
- integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==
+ version "6.5.5"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
+ integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
dependencies:
tslib "^1.9.0"
@@ -9217,11 +9447,16 @@
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0:
+safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
+safe-buffer@^5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
safe-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
@@ -9875,6 +10110,13 @@
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
@@ -10184,6 +10426,11 @@
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20"
integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=
+trim-newlines@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30"
+ integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==
+
trim-off-newlines@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
@@ -10373,6 +10620,21 @@
dependencies:
prelude-ls "~1.1.2"
+type-fest@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
+ integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
+
+type-fest@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+ integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type-fest@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
@@ -10481,9 +10743,16 @@
imurmurhash "^0.1.4"
universal-user-agent@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.0.tgz#27da2ec87e32769619f68a14996465ea1cb9df16"
- integrity sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA==
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
+ integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==
+ dependencies:
+ os-name "^3.1.0"
+
+universal-user-agent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9"
+ integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==
dependencies:
os-name "^3.1.0"
@@ -10892,9 +11161,9 @@
string-width "^1.0.2 || 2"
windows-release@^3.1.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f"
- integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace"
+ integrity sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==
dependencies:
execa "^1.0.0"
@@ -10903,6 +11172,11 @@
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+wordwrap@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
+
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@@ -11018,7 +11292,7 @@
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-yargs-parser@10.x, yargs-parser@^10.0.0, yargs-parser@^10.1.0:
+yargs-parser@10.x, yargs-parser@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
@@ -11033,6 +11307,14 @@
camelcase "^5.0.0"
decamelize "^1.2.0"
+yargs-parser@^18.1.3:
+ version "18.1.3"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
+ integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
yargs-parser@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"