From 7dbe38ba0522b346a0fcd9851e797f0fd71ecd5e Mon Sep 17 00:00:00 2001 From: Michael Dürre Date: Thu, 16 Jul 2020 05:55:07 +0200 Subject: switch to rfc8040 restconf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit change rest interface and some small code cleanups Issue-ID: CCSDK-2572 Signed-off-by: Michael Dürre Change-Id: I3475bd2574b32950c4bf84fbd1c2a9dac9af208a --- .../src/components/material-ui/treeView.tsx | 6 +- .../framework/src/components/objectDump/index.tsx | 173 +++++++++++++++++++++ sdnr/wt/odlux/framework/src/index.html | 4 +- .../src/services/authenticationService.ts | 20 ++- sdnr/wt/odlux/framework/src/views/about.tsx | 49 +++++- sdnr/wt/odlux/framework/src/views/login.tsx | 3 +- 6 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 sdnr/wt/odlux/framework/src/components/objectDump/index.tsx (limited to 'sdnr/wt/odlux/framework/src') 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 = WithTheme & WithStyles = TreeViewComponentBaseProps & { + initialSearchTerm? : string; onItemClick?: (item: TreeItem) => void; onFolderClick?: (item: TreeItem) => void; } type TreeViewComponentWithExternalSearchProps = TreeViewComponentBaseProps & { items: ExternalTreeItem[]; + initialSearchTerm? : string; searchTerm: string; onSearch: (searchTerm: string) => void; onItemClick?: (item: TreeItem) => void; @@ -94,6 +97,7 @@ type TreeViewComponentWithExternalSearchProps = TreeViewComponentBas type TreeViewComponentWithExternalStateProps = TreeViewComponentBaseProps & TreeViewComponentState & { items: ExternalTreeItem[]; + initialSearchTerm? : string; searchTerm: string; onSearch: (searchTerm: string) => void; onItemClick: (item: TreeItem) => void; @@ -137,7 +141,7 @@ class TreeViewComponent extends React.Component { + 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 = (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 ( + + {label && ( + + + + ) || null + } + {isExpanded && {children} || null} +
+ {label} +
+ ); +}; + + +type ObjectRendererProps = { + className?: string; + label?: JSX.Element | string | null; + expand?: boolean; + object: { [key: string]: any }; +}; + +const ObjectRenderer: React.FC = (props) => { + const { object, className, label = 'Object', expand = true } = props; + const classes = useSimpleTableStyles(); + + return ( + + { + Object.keys(object).map(key => { + return ( + + {String(key)} + {renderObject(object[key])} + + ); + }) + } + + ); +}; + + +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 = (props) => { + + return null; +}; + +export const renderObject = (object: any): JSX.Element | string => { + if (isString(object) || isNumber(object) || isBoolean(object)) { + return String(object); + } + return ; +}; 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 @@
- 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 { + public async authenticateUserOAuth(email: string, password: string, scope: string): Promise { const result = await requestRest(`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 { + const result = await requestRest(`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) => ( `${text}` ); interface AboutState { content: string | null; + isCopiedSuccessfully: boolean; + isContentLoadedSucessfully: boolean; } class AboutComponent extends React.Component { + textarea: React.RefObject; 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('/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) =>{ + 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 { return (
+ { this.state.isContentLoadedSucessfully && +
+ + { + this.state.isCopiedSuccessfully && + + copied successfully + + } +
+ } +
+
+