diff options
author | Michael Dürre <michael.duerre@highstreet-technologies.com> | 2020-07-16 05:55:07 +0200 |
---|---|---|
committer | Michael Dürre <michael.duerre@highstreet-technologies.com> | 2020-07-16 05:55:21 +0200 |
commit | 7dbe38ba0522b346a0fcd9851e797f0fd71ecd5e (patch) | |
tree | cc19db7e0637c8e392d40cdf3a53bb5e5f3e0d30 /sdnr/wt/odlux/framework | |
parent | 25b3759a0907d06e0d8e391f751c6fcf067087f5 (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')
-rw-r--r-- | sdnr/wt/odlux/framework/package.json | 6 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/pom.xml | 2 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx | 6 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/components/objectDump/index.tsx | 173 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/index.html | 4 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/services/authenticationService.ts | 20 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/views/about.tsx | 49 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/src/views/login.tsx | 3 | ||||
-rw-r--r-- | sdnr/wt/odlux/framework/webpack.config.js | 6 |
9 files changed, 257 insertions, 12 deletions
diff --git a/sdnr/wt/odlux/framework/package.json b/sdnr/wt/odlux/framework/package.json index c94568857..511b97778 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 b125a4537..5bb7d6f6a 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 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 }); diff --git a/sdnr/wt/odlux/framework/webpack.config.js b/sdnr/wt/odlux/framework/webpack.config.js index e43539dc7..4887a757e 100644 --- a/sdnr/wt/odlux/framework/webpack.config.js +++ b/sdnr/wt/odlux/framework/webpack.config.js @@ -45,6 +45,7 @@ module.exports = (env) => { app: [
"./app.tsx",
"./services",
+ "./components/objectDump",
"./components/material-table",
"./components/material-ui",
"./utilities/elasticSearch",
@@ -127,7 +128,10 @@ module.exports = (env) => { 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({
|