aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/inventoryApp
diff options
context:
space:
mode:
authorMichael Dürre <michael.duerre@highstreet-technologies.com>2020-07-16 05:55:07 +0200
committerMichael Dürre <michael.duerre@highstreet-technologies.com>2020-07-16 05:55:21 +0200
commit7dbe38ba0522b346a0fcd9851e797f0fd71ecd5e (patch)
treecc19db7e0637c8e392d40cdf3a53bb5e5f3e0d30 /sdnr/wt/odlux/apps/inventoryApp
parent25b3759a0907d06e0d8e391f751c6fcf067087f5 (diff)
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
Diffstat (limited to 'sdnr/wt/odlux/apps/inventoryApp')
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/package.json4
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/actions/inventoryTreeActions.ts104
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/actions/panelActions.ts31
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts38
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/connectedNetworkElementsHandler.ts36
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryAppRootHandler.ts16
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.ts (renamed from sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx)0
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryTreeHandler.ts68
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/handlers/panelHandler.ts11
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/index.html3
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts9
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/models/networkElementConnection.ts37
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/models/panelId.ts19
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx36
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts41
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx195
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/views/treeview.tsx132
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/webpack.config.js4
18 files changed, 671 insertions, 113 deletions
diff --git a/sdnr/wt/odlux/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json
index 929ca0fb4..4b1f3f9f9 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 000000000..c09b669a1
--- /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 000000000..10fde8c1d
--- /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 692ea82c7..46827e842 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 deleay = (time: number) => () => new Promise<number>(resolve => setTimeout
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 000000000..79c12d619
--- /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 786f6d0c5..0e857ffe9 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 @@ import { combineActionHandler } from '../../../../framework/src/flux/middleware'
// ** do not remove **
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { IActionHandler } from '../../../../framework/src/flux/action';
-import { IInventoryElementsState, inventoryElementsActionHandler } from './inventoryElementsHandler';
+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 @@ declare module '../../../../framework/src/store/applicationStore' {
}
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
index a65319efa..a65319efa 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/handlers/inventoryElementsHandler.tsx
+++ b/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 000000000..9029a6719
--- /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 000000000..761253112
--- /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 0cdb9e93b..75531ec1b 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 c6b6c91cb..a6c990529 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 @@ export type InventoryType = {
nodeId: string;
uuid: string;
containedHolder?: (string)[] | null;
- manufacturerName?: string ;
+ manufacturerName?: string;
manufacturerIdentifier: string;
serial: string;
date: string;
@@ -42,4 +45,6 @@ export type InventoryTreeNode = {
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 000000000..88f70181c
--- /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 000000000..b05c1db64
--- /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 ad53285cb..665e085e6 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/pluginInventory.tsx
@@ -22,43 +22,15 @@ import { withRouter, RouteComponentProps, Route, Switch, Redirect } from 'react-
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 252d6d425..b6025d4da 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 @@ import { getTree, getElement } from '../fakeData';
* 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 b63f628a3..14792df5b 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 { InventoryType } from '../models/inventory';
+import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
+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";
-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}>;
+import { createConnectedNetworkElementsProperties, createConnectedNetworkElementsActions } from "../handlers/connectedNetworkElementsHandler";
+
+import { NetworkElementConnection } from "../models/networkElementConnection";
+
+import { InventoryType } from '../models/inventory';
+
+import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
+import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
+import { updateInventoryTreeAsyncAction } from '../actions/inventoryTreeActions';
+
+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> {
+
+ 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>,
+ ];
+
+ }
-class DashboardComponent extends React.Component<& WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>> {
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 000000000..5f2c61080
--- /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 889bb4d8e..d81797c1e 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
@@ -146,6 +146,10 @@ module.exports = (env) => {
target: "http://localhost:48181",
secure: false
},
+ "/tree/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
"/websocket": {
target: "http://localhost:48181",
ws: true,