aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/framework/src
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/framework/src
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/framework/src')
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx6
-rw-r--r--sdnr/wt/odlux/framework/src/components/objectDump/index.tsx173
-rw-r--r--sdnr/wt/odlux/framework/src/index.html4
-rw-r--r--sdnr/wt/odlux/framework/src/services/authenticationService.ts20
-rw-r--r--sdnr/wt/odlux/framework/src/views/about.tsx49
-rw-r--r--sdnr/wt/odlux/framework/src/views/login.tsx3
6 files changed, 247 insertions, 8 deletions
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 1bb49367c..adf0b8e5a 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 @@ type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styl
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 TreeViewComponentWithExternalSearchProps<TData = {}> = TreeViewComponentBas
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 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
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 000000000..d449f5cd3
--- /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 1a373392d..d51c448a9 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 d3d62c566..cd8a93a53 100644
--- a/sdnr/wt/odlux/framework/src/services/authenticationService.ts
+++ b/sdnr/wt/odlux/framework/src/services/authenticationService.ts
@@ -26,7 +26,7 @@ type AuthTokenResponse = {
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 @@ class AuthenticationService {
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 db0411793..ca3953af1 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 React from 'react';
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 @@ class AboutComponent extends React.Component<any, AboutState> {
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 fa01568ea..30b9c85a2 100644
--- a/sdnr/wt/odlux/framework/src/views/login.tsx
+++ b/sdnr/wt/odlux/framework/src/views/login.tsx
@@ -164,7 +164,8 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
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 });