Update ODLUX
[ccsdk/features.git] / sdnr / wt / odlux / framework / src / views / about.tsx
index d47e09c..1b6135e 100644 (file)
  * the License.
  * ============LICENSE_END==========================================================================
  */
-import * as React from 'react';\r
-\r
-const AboutComponent = () => {\r
-\r
-  return (\r
-    <div>\r
-      <h2>About</h2>\r
-      <div style={{ margin: "0 auto" }}>##odlux.version##</div>\r
-    </div>\r
-  );\r
-};\r
-\r
-export const About = AboutComponent;\r
+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 '@mui/material';
+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;
+}
+
+type odluxVersion= {version:string,build:string, framework: string, 
+  applications:{
+    configurationApp: string,
+    connectApp: string,
+    eventLogApp: string,
+    faultApp: string,
+    helpApp: string,
+    inventoryApp: string,
+    linkCalculationApp: string,
+    maintenanceApp: string,
+    mediatorApp: string,
+    networkMapApp: string,
+    permanceHistoryApp: string
+  }};
+
+type topologyVersion = {version: string, buildTimestamp: string};
+
+class AboutComponent extends React.Component<any, AboutState> {
+  textarea: React.RefObject<HTMLTextAreaElement>;
+
+
+  constructor(props: any) {
+    super(props);
+    this.state = { content: null, isCopiedSuccessfully:false, isContentLoadedSucessfully: false }
+    this.textarea = React.createRef();
+    this.loadAboutContent();
+  }
+
+  private getMarkOdluxVersionMarkdownTable(data:odluxVersion|null|undefined):string{
+    if(!data) {
+      return "";
+    }else{
+      let applicationVersions= '';
+      if(data.applications){
+
+        applicationVersions = `| Framework | ${data.framework}|\n `+
+        `| ConnectApp | ${data.applications.connectApp}|\n `+
+        `| FaultApp | ${data.applications.faultApp}|\n `+
+        `| MaintenanceApp | ${data.applications.maintenanceApp}|\n `+
+        `| ConfigurationApp | ${data.applications.configurationApp}|\n `+
+        `| PerformanceHistoryApp | ${data.applications.permanceHistoryApp}|\n `+
+        `| InventoryApp | ${data.applications.inventoryApp}|\n `+
+        `| EventLogApp | ${data.applications.eventLogApp}|\n `+
+        `| MediatorApp | ${data.applications.mediatorApp}|\n `+
+        `| NetworkMapApp | ${data.applications.networkMapApp}|\n `+
+        `| LinkCalculatorApp | ${data.applications.linkCalculationApp}|\n `+
+        `| HelpApp | ${data.applications.helpApp}|\n `;
+      }
+    
+    return `| | |\n| --- | --- |\n| Version | ${data.version} |\n| Build timestamp | ${data.build}|\n`+
+    applicationVersions;
+    }
+  }
+
+  private getTopologyVersionMarkdownTable(data: topologyVersion|null|undefined){ 
+    if(!data){
+      return "No version";
+    }
+    else
+    {
+      const topologyInfo = `| | |\n| --- | --- |\n| Version | ${data.version} |\n` +
+                           `| Build timestamp | ${data.buildTimestamp} |\n`;
+      return topologyInfo;
+    }
+  }
+
+  private loadAboutContent(): void {
+    const baseUri = window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/")+1);
+    const init = {
+      'method': 'GET',
+      headers: {
+        'Content-Type': 'application/json',
+        'Accept': 'text/markdown',
+      }
+    };
+    const p1 = requestRestExt<string>('/about',init);
+    const p2 = requestRestExt<odluxVersion>(`${baseUri}version.json`);
+    const p3 = requestRestExt<any>(`/topology/info/version`);
+
+    Promise.all([p1,p2, p3]).then((responses) => {
+      const response = responses[0];
+      const response2 = responses[1]; 
+      const response3 = responses[2];   
+      const content = response.status == 200 ? response.data : `${response.status} ${response.message}` || "Server error";
+      const content2 = `\n## ODLUX Version Info\n`+(response2.status == 200 ? this.getMarkOdluxVersionMarkdownTable(response2.data) : `${response2.message}` || "ODLUX Server error");
+      const content3 =  `\n## Topology API Version Info\n`+(response3.status == 200 ? this.getTopologyVersionMarkdownTable(response3.data): `Topology API not available`);
+      const loadedSucessfully = response.status == 200 ? true : false;
+      this.setState({ content: (content + content2 + content3 ) || null, 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 = {
+      gfm: true,
+      breaks: false,
+      pedantic: false,
+      sanitize: true,
+      smartLists: true,
+      smartypants: false,
+      langPrefix: 'hljs ',
+      ...({}),
+      highlight: (code, lang) => {
+        if (!!(lang && hljs.getLanguage(lang))) {
+          return hljs.highlight(lang, code).value;
+        }
+        return code;
+      }
+    };
+
+
+    const className = "about-table"
+    const style: React.CSSProperties = {};
+    const containerStyle = { overflow: "auto", paddingRight: "20px" }
+
+    const html = (marked(this.state.content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
+
+    return (
+      <div style={containerStyle}>
+        { this.state.isContentLoadedSucessfully &&
+        <div style={{float: "right", marginRight: "10px"}}>
+        <Button color="inherit" 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>
+    );
+  }
+};
+
+export const About = AboutComponent;
 export default About;
\ No newline at end of file