diff options
author | Aijana Schumann <aijana.schumann@highstreet-technologies.com> | 2022-02-01 13:18:42 +0100 |
---|---|---|
committer | Aijana Schumann <aijana.schumann@highstreet-technologies.com> | 2022-02-01 13:18:42 +0100 |
commit | 1a868116614dd9996c78e69941b537e9da19460b (patch) | |
tree | 352e8e4226f6ce798610d75ceef08ad9056df6d9 /sdnr/wt/odlux/framework/src | |
parent | 9912e1626d93afeb4f7148dd5d826ae1caa1ef8a (diff) |
Update ODLUX
Updated to Material-ui 5, updated dashboard view, removed NetworkMap, LinkCalculator and LineOfSightApp, small bugfixes
Issue-ID: CCSDK-3580
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: Id0fc148673e23a755cafc2be1c489248c38ff47c
Diffstat (limited to 'sdnr/wt/odlux/framework/src')
31 files changed, 1502 insertions, 1718 deletions
diff --git a/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts b/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts index 32e2b2626..ad4d60609 100644 --- a/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts +++ b/sdnr/wt/odlux/framework/src/actions/snackbarActions.ts @@ -17,11 +17,11 @@ */ import { Action } from '../flux/action'; import { SnackbarItem } from '../models/snackbarItem'; -import { Omit } from '@material-ui/core'; +import { DistributiveOmit } from '@mui/types'; export class AddSnackbarNotification extends Action { - constructor(notification: Omit<SnackbarItem, 'key' >) { + constructor(notification: DistributiveOmit<SnackbarItem, 'key' >) { super(); this.notification = { ...notification, key: (new Date().getTime() + Math.random()) } diff --git a/sdnr/wt/odlux/framework/src/app.tsx b/sdnr/wt/odlux/framework/src/app.tsx index a73b7529b..9b03a216d 100644 --- a/sdnr/wt/odlux/framework/src/app.tsx +++ b/sdnr/wt/odlux/framework/src/app.tsx @@ -1,111 +1,119 @@ -/**
- * ============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 * as ReactDOM from 'react-dom';
-
-import { MuiThemeProvider } from '@material-ui/core/styles';
-
-import { Frame } from './views/frame';
-
-import { User } from './models/authentication';
-
-import { AddErrorInfoAction } from './actions/errorActions';
-import { loginUserAction } from './actions/authentication';
-
-import { applicationStoreCreator } from './store/applicationStore';
-import { ApplicationStoreProvider } from './flux/connect';
-
-import { startHistoryListener } from './middleware/navigation';
-import { startRestService } from './services/restService';
-
-import { startUserSessionService } from './services/userSessionService';
-import { startNotificationService } from './services/notificationService';
-
-import theme from './design/default';
-import '!style-loader!css-loader!./app.css';
-import { startBroadcastChannel } from './services/broadcastService';
-
-declare module '@material-ui/core/styles/createMuiTheme' {
-
- interface IDesign {
- id: string,
- name: string,
- url: string, // image url of a company logo, which will be presented in the ui header
- height: number, // image height [px] as delivered by the url
- width: number, // image width [px] as delivered by the url
- logoHeight: number // height in [px] of the logo (see url) within the ui header
- }
-
- interface Theme {
- design?: IDesign
- }
- interface ThemeOptions {
- design?: IDesign
- }
-}
-
-export { configureApplication } from "./handlers/applicationStateHandler";
-
-export const transportPCEUrl = "transportPCEUrl";
-
-export const runApplication = () => {
-
- const initialToken = localStorage.getItem("userToken");
- const applicationStore = applicationStoreCreator();
-
- startBroadcastChannel(applicationStore);
- startUserSessionService(applicationStore);
-
- if (initialToken) {
- applicationStore.dispatch(loginUserAction(User.fromString(initialToken) || undefined));
- }
-
- window.onerror = function (msg: string, url: string, line: number, col: number, error: Error) {
- // Note that col & error are new to the HTML 5 spec and may not be
- // supported in every browser. It worked for me in Chrome.
- var extra = !col ? '' : '\ncolumn: ' + col;
- extra += !error ? '' : '\nerror: ' + error;
-
- // You can view the information in an alert to see things working like this:
- applicationStore.dispatch(new AddErrorInfoAction({ error, message: msg, url, line, col, info: { extra } }));
-
- var suppressErrorAlert = true;
- // If you return true, then error alerts (like in older versions of
- // Internet Explorer) will be suppressed.
- return suppressErrorAlert;
- };
-
-
- startRestService(applicationStore);
- startHistoryListener(applicationStore);
- startNotificationService(applicationStore);
-
- const App = (): JSX.Element => (
- <ApplicationStoreProvider applicationStore={applicationStore} >
- <MuiThemeProvider theme={theme}>
- <Frame />
- </MuiThemeProvider>
- </ApplicationStoreProvider>
- );
-
- ReactDOM.render(<App />, document.getElementById('app'));
-
-
-
-};
+/** + * ============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 * as ReactDOM from 'react-dom'; + +import { ThemeProvider, Theme, StyledEngineProvider } from '@mui/material/styles'; + +import { Frame } from './views/frame'; + +import { User } from './models/authentication'; + +import { AddErrorInfoAction } from './actions/errorActions'; +import { loginUserAction } from './actions/authentication'; + +import { applicationStoreCreator } from './store/applicationStore'; +import { ApplicationStoreProvider } from './flux/connect'; + +import { startHistoryListener } from './middleware/navigation'; +import { startRestService } from './services/restService'; + +import { startUserSessionService } from './services/userSessionService'; +import { startNotificationService } from './services/notificationService'; + +import theme from './design/default'; +import '!style-loader!css-loader!./app.css'; +import { startBroadcastChannel } from './services/broadcastService'; + +declare module '@mui/material/styles' { + + interface IDesign { + id: string, + name: string, + url: string, // image url of a company logo, which will be presented in the ui header + height: number, // image height [px] as delivered by the url + width: number, // image width [px] as delivered by the url + logoHeight: number // height in [px] of the logo (see url) within the ui header + } + + interface Theme { + design?: IDesign + } + interface DeprecatedThemeOptions { + design?: IDesign + } +} + + +declare module '@mui/styles/defaultTheme' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface (remove this line if you don't have the rule enabled) + interface DefaultTheme extends Theme {} +} + +export { configureApplication } from "./handlers/applicationStateHandler"; + +export const transportPCEUrl = "transportPCEUrl"; + +export const runApplication = () => { + + const initialToken = localStorage.getItem("userToken"); + const applicationStore = applicationStoreCreator(); + + startBroadcastChannel(applicationStore); + startUserSessionService(applicationStore); + + if (initialToken) { + applicationStore.dispatch(loginUserAction(User.fromString(initialToken) || undefined)); + } + + window.onerror = function (msg: string, url: string, line: number, col: number, error: Error) { + // Note that col & error are new to the HTML 5 spec and may not be + // supported in every browser. It worked for me in Chrome. + var extra = !col ? '' : '\ncolumn: ' + col; + extra += !error ? '' : '\nerror: ' + error; + + // You can view the information in an alert to see things working like this: + applicationStore.dispatch(new AddErrorInfoAction({ error, message: msg, url, line, col, info: { extra } })); + + var suppressErrorAlert = true; + // If you return true, then error alerts (like in older versions of + // Internet Explorer) will be suppressed. + return suppressErrorAlert; + }; + + + startRestService(applicationStore); + startHistoryListener(applicationStore); + startNotificationService(applicationStore); + + const App = (): JSX.Element => ( + <ApplicationStoreProvider applicationStore={applicationStore} > + <StyledEngineProvider injectFirst> + <ThemeProvider theme={theme}> + <Frame /> + </ThemeProvider> + </StyledEngineProvider> + </ApplicationStoreProvider> + ); + + ReactDOM.render(<App />, document.getElementById('app')); + + + +}; diff --git a/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx b/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx index b2a1f1f20..a04ab16af 100644 --- a/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx +++ b/sdnr/wt/odlux/framework/src/components/errorDisplay.tsx @@ -16,14 +16,18 @@ * ============LICENSE_END========================================================================== */ import * as React from 'react'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import Modal from '@material-ui/core/Modal'; -import Button from '@material-ui/core/Button'; -import Card from '@material-ui/core/Card'; -import CardActions from '@material-ui/core/CardActions'; -import CardContent from '@material-ui/core/CardContent'; -import Typography from '@material-ui/core/Typography'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import Modal from '@mui/material/Modal'; +import Button from '@mui/material/Button'; +import Card from '@mui/material/Card'; +import CardActions from '@mui/material/CardActions'; +import CardContent from '@mui/material/CardContent'; +import Typography from '@mui/material/Typography'; import { ClearErrorInfoAction, RemoveErrorInfoAction } from '../actions/errorActions'; @@ -113,7 +117,7 @@ class ErrorDisplayComponent extends React.Component<ErrorDisplayProps> { </Typography> </CardContent> <CardActions> - <Button size="small" onClick={() => this.props.dispatch(new RemoveErrorInfoAction(errorInfo))} >Close</Button> + <Button color="inherit" size="small" onClick={() => this.props.dispatch(new RemoveErrorInfoAction(errorInfo))} >Close</Button> </CardActions> </Card> </div> || <div></div> diff --git a/sdnr/wt/odlux/framework/src/components/logo.tsx b/sdnr/wt/odlux/framework/src/components/logo.tsx index 470eb9620..b10cc8ce1 100644 --- a/sdnr/wt/odlux/framework/src/components/logo.tsx +++ b/sdnr/wt/odlux/framework/src/components/logo.tsx @@ -34,7 +34,12 @@ import * as React from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; // infra for styling +import { Theme } from '@mui/material/styles'; // infra for styling + + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; import defaultLogo from '../assets/images/defaultLogo.svg'; diff --git a/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts b/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts index 8124e450d..ce5b2cd1e 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts +++ b/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts @@ -1,55 +1,55 @@ -/**
- * ============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';
-
-export enum ColumnType {
- text,
- numeric,
- boolean,
- date,
- custom
-}
-
-type CustomControl<TData> = {
- className?: string;
- style?: React.CSSProperties;
- rowData: TData;
-}
-
-export type ColumnModel<TData> = {
- title?: string;
- disablePadding?: boolean;
- width?: string | number ;
- className?: string;
- style?: React.CSSProperties;
- align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
- disableSorting?: boolean;
- disableFilter?: boolean;
-} & ({
- property: string;
- type: ColumnType.custom;
- customControl: React.ComponentType<CustomControl<TData>>;
-} | {
- property: keyof TData;
- type: ColumnType.boolean;
- labels?: { "true": string, "false": string };
-} | {
- property: keyof TData;
- type?: ColumnType.numeric | ColumnType.text | ColumnType.date;
+/** + * ============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'; + +export enum ColumnType { + text, + numeric, + boolean, + date, + custom +} + +type CustomControl<TData> = { + className?: string; + style?: React.CSSProperties; + rowData: TData; +} + +export type ColumnModel<TData> = { + title?: string; + disablePadding?: boolean; + width?: string | number ; + className?: string; + style?: React.CSSProperties; + align?: 'inherit' | 'left' | 'center' | 'right' | 'justify'; + disableSorting?: boolean; + disableFilter?: boolean; +} & ({ + property: string; + type: ColumnType.custom; + customControl: React.ComponentType<CustomControl<TData>>; +} | { + property: keyof TData; + type: ColumnType.boolean; + labels?: { "true": string, "false": string }; +} | { + property: keyof TData; + type?: ColumnType.numeric | ColumnType.text | ColumnType.date; });
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx index cb675218f..aac2a1252 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx @@ -16,29 +16,36 @@ * ============LICENSE_END========================================================================== */ import * as React from 'react'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import Table from '@material-ui/core/Table'; -import TableBody from '@material-ui/core/TableBody'; -import TableCell from '@material-ui/core/TableCell'; -import TableContainer from '@material-ui/core/TableContainer'; -import TablePagination from '@material-ui/core/TablePagination'; -import TableRow from '@material-ui/core/TableRow'; -import Paper from '@material-ui/core/Paper'; -import Checkbox from '@material-ui/core/Checkbox'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import TableCell from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TablePagination from '@mui/material/TablePagination'; +import TableRow from '@mui/material/TableRow'; +import Paper from '@mui/material/Paper'; +import Checkbox from '@mui/material/Checkbox'; import { TableToolbar } from './tableToolbar'; import { EnhancedTableHead } from './tableHead'; import { EnhancedTableFilter } from './tableFilter'; import { ColumnModel, ColumnType } from './columnModel'; -import { Omit, Menu, makeStyles } from '@material-ui/core'; +import { Menu } from '@mui/material'; +import { DistributiveOmit } from '@mui/types'; + +import makeStyles from '@mui/styles/makeStyles'; -import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon'; +import { SvgIconProps } from '@mui/material/SvgIcon'; -import { DividerTypeMap } from '@material-ui/core/Divider'; -import { MenuItemProps } from '@material-ui/core/MenuItem'; -import { flexbox } from '@material-ui/system'; +import { DividerTypeMap } from '@mui/material/Divider'; +import { MenuItemProps } from '@mui/material/MenuItem'; +import { flexbox } from '@mui/system'; import { RowDisabled } from './utilities'; import { toAriaLabel } from '../../utilities/yangHelper'; export { ColumnModel, ColumnType } from './columnModel'; @@ -51,7 +58,7 @@ export type DataCallback<TData = dataType> = (page?: number, rowsPerPage?: numbe function regExpEscape(s: string) { return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'); -}; +} function wildcardCheck(input: string, pattern: string) { if (!pattern) return true; @@ -61,7 +68,7 @@ function wildcardCheck(input: string, pattern: string) { (!pattern.endsWith('*') ? '$' : '') ); return input.match(regex) !== null && input.match(regex)!.length >= 1; -}; +} function desc(a: dataType, b: dataType, orderBy: string) { if ((b[orderBy] || "") < (a[orderBy] || "")) { @@ -240,7 +247,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate <TableContainer className={classes.container}> <TableToolbar tableId={this.props.tableId} numSelected={selected && selected.length} title={this.props.title} customActionButtons={this.props.customActionButtons} onExportToCsv={this.exportToCsv} onToggleFilter={toggleFilter} /> - <Table aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'} stickyHeader={this.props.stickyHeader || false} > + <Table padding="normal" aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'} stickyHeader={this.props.stickyHeader || false} > <EnhancedTableHead columns={columns} numSelected={selected && selected.length} @@ -330,15 +337,15 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate count={rowCount} rowsPerPage={rowsPerPage} page={page} - aria-label={"table-pagination-footer" } + aria-label={this.props.isPopup ? "popup-table-pagination-footer" : "table-pagination-footer" } backIconButtonProps={{ 'aria-label': this.props.isPopup ? 'popup-previous-page' : 'previous-page', }} nextIconButtonProps={{ 'aria-label': this.props.isPopup ? 'popup-next-page': 'next-page', }} - onChangePage={this.onHandleChangePage} - onChangeRowsPerPage={this.onHandleChangeRowsPerPage} + onPageChange={this.onHandleChangePage} + onRowsPerPageChange={this.onHandleChangeRowsPerPage} /> </Paper> ); @@ -371,7 +378,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate private static updateRows(props: MaterialTableComponentPropsWithRows, state: MaterialTableComponentState): { rows: {}[], total: number, page: number } { - let data = [...props.rows as dataType[] || []]; + let data = [...(props.rows as dataType[] || [])]; const columns = props.columns; const { page, rowsPerPage, order, orderBy, filter } = state; @@ -661,7 +668,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate } } -export type MaterialTableCtorType<TData extends {} = {}> = new () => React.Component<Omit<MaterialTableComponentProps<TData>, 'classes'>>; +export type MaterialTableCtorType<TData extends {} = {}> = new () => React.Component<DistributiveOmit<MaterialTableComponentProps<TData>, 'classes'>>; export const MaterialTable = withStyles(styles)(MaterialTableComponent); export default MaterialTable;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx index e4cc5ab7c..a46dd18d8 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx @@ -18,13 +18,18 @@ import * as React from 'react'; import { ColumnModel, ColumnType } from './columnModel'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import TableCell from '@material-ui/core/TableCell'; -import TableRow from '@material-ui/core/TableRow'; -import Input from '@material-ui/core/Input'; -import { Select, FormControl, InputLabel, MenuItem } from '@material-ui/core'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + + +import TableCell from '@mui/material/TableCell'; +import TableRow from '@mui/material/TableRow'; +import Input from '@mui/material/Input'; +import { Select, FormControl, InputLabel, MenuItem, SelectChangeEvent } from '@mui/material'; import { toAriaLabel } from '../../utilities/yangHelper'; @@ -49,9 +54,13 @@ interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> { } class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterComponentProps> { - createFilterHandler = (property: string) => (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => { - this.props.onFilterChanged && this.props.onFilterChanged(property, event.target.value); + createSelectFilterHandler = (property: string) => (event: SelectChangeEvent<HTMLSelectElement | string>) => { + this.props.onFilterChanged && this.props.onFilterChanged(property, event.target.value as string); }; + createInputFilterHandler = (property: string) => (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => { + this.props.onFilterChanged && this.props.onFilterChanged(property, event.currentTarget.value); + }; + render() { const { columns, filter, classes } = this.props; @@ -68,20 +77,26 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC <TableCell className={col.type === ColumnType.numeric ? classes.numberInput : ''} key={col.property} - padding={col.disablePadding ? 'none' : 'default'} + padding={col.disablePadding ? 'none' : 'normal'} style={style} > {col.disableFilter || (col.type === ColumnType.custom) ? null : (col.type === ColumnType.boolean) - ? <Select className={classes.input} aria-label={col.title ? toAriaLabel(col.title as string) + '-filter' : `${ind + 1}-filter`} value={filter[col.property] !== undefined ? filter[col.property] : ''} onChange={this.createFilterHandler(col.property)} inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} > + ? <Select variant="standard" className={classes.input} aria-label={col.title ? toAriaLabel(col.title as string) + '-filter' : `${ind + 1}-filter`} + value={filter[col.property] !== undefined ? filter[col.property] : ''} + onChange={this.createSelectFilterHandler(col.property)} + inputProps={{ name: `${col.property}-bool`, id: `${col.property}-bool` }} > <MenuItem value={undefined} aria-label="none-value" > <em>None</em> </MenuItem> <MenuItem aria-label="true-value" value={true as any as string}>{col.labels ? col.labels["true"] : "true"}</MenuItem> <MenuItem aria-label="false-value" value={false as any as string}>{col.labels ? col.labels["false"] : "false"}</MenuItem> </Select> - : <Input className={classes.input} inputProps={{ 'aria-label': col.title ? toAriaLabel(col.title as string)+ '-filter' : `${ind + 1}-filter` }} value={filter[col.property] || ''} onChange={this.createFilterHandler(col.property)} />} + : <Input className={classes.input} + inputProps={{ 'aria-label': col.title ? toAriaLabel(col.title as string) + '-filter' : `${ind + 1}-filter` }} + value={filter[col.property] || ''} + onChange={this.createInputFilterHandler(col.property)} />} </TableCell> ); }, this)} diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx index 428f4cf3f..c500f44ce 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx @@ -18,16 +18,31 @@ import * as React from 'react'; import { ColumnModel, ColumnType } from './columnModel'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import TableSortLabel from '@material-ui/core/TableSortLabel'; -import TableCell from '@material-ui/core/TableCell'; -import TableHead from '@material-ui/core/TableHead'; -import TableRow from '@material-ui/core/TableRow'; -import Checkbox from '@material-ui/core/Checkbox'; -import Tooltip from '@material-ui/core/Tooltip'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; -interface IEnhancedTableHeadComponentProps { +import TableSortLabel from '@mui/material/TableSortLabel'; +import TableCell from '@mui/material/TableCell'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import Checkbox from '@mui/material/Checkbox'; +import Tooltip from '@mui/material/Tooltip'; + +const styles = (theme: Theme) => createStyles({ + header: { + backgroundColor: "#fafafa", + position: "sticky", + top: 0 + } +}); + + +type styles_header = WithStyles<typeof styles>; + +interface IEnhancedTableHeadComponentProps extends styles_header { numSelected: number | null; onRequestSort: (event: React.SyntheticEvent, property: string) => void; onSelectAllClick: () => void; @@ -45,12 +60,13 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo render() { const { onSelectAllClick, order, orderBy, numSelected, rowCount, columns } = this.props; + const {classes} = this.props; return ( <TableHead> <TableRow> { this.props.enableSelection - ? <TableCell padding="checkbox" style={ { width: "50px" } }> + ? <TableCell padding="checkbox" style={ { width: "50px" } } className= {classes.header} > <Checkbox indeterminate={ numSelected && numSelected > 0 && numSelected < rowCount || undefined } checked={ numSelected === rowCount } @@ -62,10 +78,10 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo { columns.map(col => { const style = col.width ? { width: col.width } : {}; return ( - <TableCell + <TableCell className= {classes.header} key={ col.property } align={ col.type === ColumnType.numeric ? 'right' : 'left' } - padding={ col.disablePadding ? 'none' : 'default' } + padding={ col.disablePadding ? 'none' : 'normal' } sortDirection={ orderBy === (col.property) ? order : false } style={ style } > @@ -76,7 +92,7 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo > { col.title || col.property } </TableSortLabel> - : <Tooltip + : <Tooltip disableInteractive title="Sort" placement={ col.type === ColumnType.numeric ? 'bottom-end' : 'bottom-start' } enterDelay={ 300 } @@ -98,4 +114,4 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo } } -export const EnhancedTableHead = EnhancedTableHeadComponent;
\ No newline at end of file +export const EnhancedTableHead = withStyles(styles)(EnhancedTableHeadComponent);
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx index 4ad6422dc..426436d44 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx @@ -16,27 +16,30 @@ * ============LICENSE_END========================================================================== */ import * as React from 'react'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme, lighten } from '@mui/material/styles'; -import IconButton from '@material-ui/core/IconButton'; -import Tooltip from '@material-ui/core/Tooltip'; -import Toolbar from '@material-ui/core/Toolbar'; -import Typography from '@material-ui/core/Typography'; -import DeleteIcon from '@material-ui/icons/Delete'; -import MoreIcon from '@material-ui/icons/MoreVert'; -import FilterListIcon from '@material-ui/icons/FilterList'; -import MenuItem from '@material-ui/core/MenuItem'; -import Menu from '@material-ui/core/Menu'; -import { lighten } from '@material-ui/core/styles/colorManipulator'; -import { SvgIconProps } from '@material-ui/core/SvgIcon/SvgIcon'; -import { Button } from '@material-ui/core'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import IconButton from '@mui/material/IconButton'; +import Tooltip from '@mui/material/Tooltip'; +import Toolbar from '@mui/material/Toolbar'; +import Typography from '@mui/material/Typography'; +import DeleteIcon from '@mui/icons-material/Delete'; +import MoreIcon from '@mui/icons-material/MoreVert'; +import FilterListIcon from '@mui/icons-material/FilterList'; +import MenuItem from '@mui/material/MenuItem'; +import Menu from '@mui/material/Menu'; +import { SvgIconProps } from '@mui/material/SvgIcon'; +import { Button } from '@mui/material'; const styles = (theme: Theme) => createStyles({ root: { paddingRight: theme.spacing(1), }, highlight: - theme.palette.type === 'light' + theme.palette.mode === 'light' ? { color: theme.palette.secondary.main, backgroundColor: lighten(theme.palette.secondary.light, 0.85), @@ -109,32 +112,41 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, <div className={classes.actions}> {this.props.customActionButtons ? this.props.customActionButtons.map((action, ind) => ( - <Tooltip key={`custom-action-${ind}`} title={action.tooltip || ''}> - <IconButton disabled={action.disabled} aria-label={`${buttonPrefix}-${action.ariaLabel}-button`} onClick={() => action.onClick()}> + <Tooltip disableInteractive key={`custom-action-${ind}`} title={action.tooltip || ''}> + <IconButton + disabled={action.disabled} + aria-label={`${buttonPrefix}-${action.ariaLabel}-button`} + onClick={() => action.onClick()} + size="large"> <action.icon /> </IconButton> </Tooltip> )) : null} {numSelected && numSelected > 0 ? ( - <Tooltip title="Delete"> - <IconButton aria-label={`${buttonPrefix}-delete-button`}> + <Tooltip disableInteractive title="Delete"> + <IconButton aria-label={`${buttonPrefix}-delete-button`} size="large"> <DeleteIcon /> </IconButton> </Tooltip> ) : ( - <Tooltip title="Filter list"> - <IconButton aria-label={`${buttonPrefix}-filter-list-button`} onClick={() => { this.props.onToggleFilter && this.props.onToggleFilter() }}> + <Tooltip disableInteractive title="Filter list"> + <IconButton + aria-label={`${buttonPrefix}-filter-list-button`} + onClick={() => { this.props.onToggleFilter && this.props.onToggleFilter() }} + size="large"> <FilterListIcon /> </IconButton> </Tooltip> )} - <Tooltip title="Actions"> - <IconButton color="inherit" - aria-label={`${buttonPrefix}-additional-actions-button`} + <Tooltip disableInteractive title="Actions"> + <IconButton + color="inherit" + aria-label={`${buttonPrefix}-additional-actions-button`} aria-owns={open ? 'menu-appbar' : undefined} aria-haspopup="true" - onClick={this.handleMenu} > + onClick={this.handleMenu} + size="large"> <MoreIcon /> </IconButton> </Tooltip> @@ -146,6 +158,6 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, </Toolbar> ); } -}; +} export const TableToolbar = withStyles(styles)(TableToolbarComponent);
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx index 49e7be514..744cb0d24 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/listItemLink.tsx @@ -1,72 +1,75 @@ -/**
- * ============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 { NavLink, Link, Route } from 'react-router-dom';
-
-import ListItem from '@material-ui/core/ListItem';
-import ListItemIcon from '@material-ui/core/ListItemIcon';
-import ListItemText from '@material-ui/core/ListItemText';
-
-import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
-import { toAriaLabel } from '../../utilities/yangHelper';
-
-const styles = (theme: Theme) => createStyles({
- active: {
- backgroundColor: theme.palette.action.selected
- }
-});
-
-export interface IListItemLinkProps extends WithStyles<typeof styles> {
- icon: JSX.Element | null;
- primary: string | React.ComponentType;
- secondary?: React.ComponentType;
- to: string;
- exact?: boolean;
- external?: boolean;
-}
-
-export const ListItemLink = withStyles(styles)((props: IListItemLinkProps) => {
- const { icon, primary: Primary, secondary: Secondary, classes, to, exact = false, external=false } = props;
- const renderLink = (itemProps: any): JSX.Element => (
- props.external ? <a target="_blank" href={to} { ...itemProps }></a> :
- <NavLink exact={ exact } to={ to } activeClassName={ classes.active } { ...itemProps } />);
-
- const ariaLabel = typeof Primary === 'string' ? toAriaLabel("link-to-"+Primary) : toAriaLabel("link-to-"+Primary.displayName);
- return (
- <>
- <ListItem button component={ renderLink } aria-label={ariaLabel}>
- { icon
- ? <ListItemIcon>{ icon }</ListItemIcon>
- : null
- }
- { typeof Primary === 'string'
- ? <ListItemText primary={ Primary } style={{ padding: 0 }} />
- : <Primary />
- }
- </ListItem>
- { Secondary
- ? <Route exact={ exact } path={ to } component={ Secondary } />
- : null
- }
- </>
- );
- }
-);
-
-export default ListItemLink;
-
+/** + * ============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 { NavLink, Link, Route } from 'react-router-dom'; + +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; + +import { Theme } from '@mui/material/styles'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; +import { toAriaLabel } from '../../utilities/yangHelper'; + +const styles = (theme: Theme) => createStyles({ + active: { + backgroundColor: theme.palette.action.selected + } +}); + +export interface IListItemLinkProps extends WithStyles<typeof styles> { + icon: JSX.Element | null; + primary: string | React.ComponentType; + secondary?: React.ComponentType; + to: string; + exact?: boolean; + external?: boolean; +} + +export const ListItemLink = withStyles(styles)((props: IListItemLinkProps) => { + const { icon, primary: Primary, secondary: Secondary, classes, to, exact = false, external=false } = props; + const renderLink = (itemProps: any): JSX.Element => ( + props.external ? <a target="_blank" href={to} { ...itemProps }></a> : + <NavLink exact={ exact } to={ to } activeClassName={ classes.active } { ...itemProps } />); + + const ariaLabel = typeof Primary === 'string' ? toAriaLabel("link-to-"+Primary) : toAriaLabel("link-to-"+Primary.displayName); + return ( + <> + <ListItem button component={ renderLink } aria-label={ariaLabel}> + { icon + ? <ListItemIcon>{ icon }</ListItemIcon> + : null + } + { typeof Primary === 'string' + ? <ListItemText primary={ Primary } style={{ padding: 0 }} /> + : <Primary /> + } + </ListItem> + { Secondary + ? <Route exact={ exact } path={ to } component={ Secondary } /> + : null + } + </> + ); + } +); + +export default ListItemLink; + diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx index 5ab2fd415..bd523e1f4 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/loader.tsx @@ -19,7 +19,11 @@ import * as React from "react"; -import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; const styles = (theme: Theme) => createStyles({ "@keyframes spin": { diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx index 378d48592..6d192d2f0 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/panel.tsx @@ -1,73 +1,76 @@ -/**
- * ============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, Theme, WithStyles, createStyles } from '@material-ui/core/styles';
-
-import { ExpansionPanel, ExpansionPanelSummary, ExpansionPanelDetails, Typography, ExpansionPanelActions } from '@material-ui/core';
-
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
-import { SvgIconProps } from '@material-ui/core/SvgIcon';
-
-const styles = (theme: Theme) => createStyles({
- accordion: {
- // background: theme.palette.secondary.dark,
- // color: theme.palette.primary.contrastText
- },
- detail: {
- // background: theme.palette.background.paper,
- // color: theme.palette.text.primary,
- position: "relative",
- display: 'flex',
- flexDirection: 'column'
- },
- text: {
- // color: theme.palette.common.white,
- // fontSize: "1rem"
- },
-});
-
-type PanalProps = WithStyles<typeof styles> & {
- activePanel: string | null,
- panelId: string,
- title: string,
- customActionButtons?: JSX.Element[];
- onToggle: (panelId: string | null) => void;
-}
-
-const PanelComponent: React.SFC<PanalProps> = (props) => {
- const { classes, activePanel, onToggle } = props;
- return (
- <ExpansionPanel className={classes.accordion} expanded={activePanel === props.panelId} onChange={() => onToggle(props.panelId)} >
- <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
- <Typography className={classes.text} >{props.title}</Typography>
- </ExpansionPanelSummary>
- <ExpansionPanelDetails className={classes.detail}>
- {props.children}
- </ExpansionPanelDetails>
- {props.customActionButtons
- ? <ExpansionPanelActions>
- {props.customActionButtons}
- </ExpansionPanelActions>
- : null}
- </ExpansionPanel>
- );
-};
-
-export const Panel = withStyles(styles)(PanelComponent);
+/** + * ============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 { Theme } from '@mui/material/styles'; + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import { Accordion, AccordionSummary, AccordionDetails, Typography, AccordionActions } from '@mui/material'; + +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import { SvgIconProps } from '@mui/material/SvgIcon'; + +const styles = (theme: Theme) => createStyles({ + accordion: { + // background: theme.palette.secondary.dark, + // color: theme.palette.primary.contrastText + }, + detail: { + // background: theme.palette.background.paper, + // color: theme.palette.text.primary, + position: "relative", + flexDirection: 'column' + }, + text: { + // color: theme.palette.common.white, + // fontSize: "1rem" + }, +}); + +type PanalProps = WithStyles<typeof styles> & { + activePanel: string | null, + panelId: string, + title: string, + customActionButtons?: JSX.Element[]; + onToggle: (panelId: string | null) => void; +} + +const PanelComponent: React.SFC<PanalProps> = (props) => { + const { classes, activePanel, onToggle } = props; + return ( + <Accordion className={classes.accordion} expanded={activePanel === props.panelId} onChange={() => onToggle(props.panelId)} > + <AccordionSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.text} >{props.title}</Typography> + </AccordionSummary> + <AccordionDetails className={classes.detail}> + {props.children} + </AccordionDetails> + {props.customActionButtons + ? <AccordionActions> + {props.customActionButtons} + </AccordionActions> + : null} + </Accordion> + ); +}; + +export const Panel = withStyles(styles)(PanelComponent); export default Panel;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx index 1a29d6970..54f14a7e0 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButton.tsx @@ -1,179 +1,181 @@ -/**
- * ============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 classNames from 'classnames';
-import { withStyles, WithStyles, Theme, createStyles } from '@material-ui/core/styles';
-import { fade } from '@material-ui/core/styles/colorManipulator';
-import ButtonBase from '@material-ui/core/ButtonBase';
-
-
-export const styles = (theme: Theme) => createStyles({
- /* Styles applied to the root element. */
- root: {
- ...theme.typography.button,
- height: 32,
- minWidth: 48,
- margin: 0,
- padding: `${theme.spacing(1 - 4)}px ${theme.spacing(1.5)}px`,
- borderRadius: 2,
- willChange: 'opacity',
- color: fade(theme.palette.action.active, 0.38),
- '&:hover': {
- textDecoration: 'none',
- // Reset on mouse devices
- backgroundColor: fade(theme.palette.text.primary, 0.12),
- '@media (hover: none)': {
- backgroundColor: 'transparent',
- },
- '&$disabled': {
- backgroundColor: 'transparent',
- },
- },
- '&:not(:first-child)': {
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- },
- '&:not(:last-child)': {
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- },
- },
- /* Styles applied to the root element if `disabled={true}`. */
- disabled: {
- color: fade(theme.palette.action.disabled, 0.12),
- },
- /* Styles applied to the root element if `selected={true}`. */
- selected: {
- color: theme.palette.action.active,
- '&:after': {
- content: '""',
- display: 'block',
- position: 'absolute',
- overflow: 'hidden',
- borderRadius: 'inherit',
- width: '100%',
- height: '100%',
- left: 0,
- top: 0,
- pointerEvents: 'none',
- zIndex: 0,
- backgroundColor: 'currentColor',
- opacity: 0.38,
- },
- '& + &:before': {
- content: '""',
- display: 'block',
- position: 'absolute',
- overflow: 'hidden',
- width: 1,
- height: '100%',
- left: 0,
- top: 0,
- pointerEvents: 'none',
- zIndex: 0,
- backgroundColor: 'currentColor',
- opacity: 0.12,
- },
- },
- /* Styles applied to the `label` wrapper element. */
- label: {
- width: '100%',
- display: 'inherit',
- alignItems: 'inherit',
- justifyContent: 'inherit',
- },
-});
-
-export type ToggleButtonClassKey = 'disabled' | 'root' | 'label' | 'selected';
-
-interface IToggleButtonProps extends WithStyles<typeof styles> {
- className?: string;
- component?: React.ReactType<IToggleButtonProps>;
- disabled?: boolean;
- disableFocusRipple?: boolean;
- disableRipple?: boolean;
- selected?: boolean;
- type?: string;
- value?: any;
- onClick?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
- onChange?: (event: React.FormEvent<HTMLElement>, value?: any) => void;
-}
-
-class ToggleButtonComponent extends React.Component<IToggleButtonProps> {
- handleChange = (event: React.FormEvent<HTMLElement>) => {
- const { onChange, onClick, value } = this.props;
-
- event.stopPropagation();
- if (onClick) {
- onClick(event, value);
- if (event.isDefaultPrevented()) {
- return;
- }
- }
-
- if (onChange) {
- onChange(event, value);
- }
- event.preventDefault();
- };
-
- render() {
- const {
- children,
- className: classNameProp,
- classes,
- disableFocusRipple,
- disabled,
- selected,
- ...other
- } = this.props;
-
- const className = classNames(
- classes.root,
- {
- [classes.disabled]: disabled,
- [classes.selected]: selected,
- },
- classNameProp,
- );
-
- return (
- <ButtonBase
- className={className}
- disabled={disabled}
- focusRipple={!disableFocusRipple}
- onClick={this.handleChange}
- href="#"
- {...other}
- >
- <span className={classes.label}>{children}</span>
- </ButtonBase>
- );
- }
- public static defaultProps = {
- disabled: false,
- disableFocusRipple: false,
- disableRipple: false,
- };
-
- public static muiName = 'ToggleButton';
-}
-
-export const ToggleButton = withStyles(styles, { name: 'MuiToggleButton' })(ToggleButtonComponent);
+/** + * ============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 classNames from 'classnames'; +import { Theme, alpha } from '@mui/material/styles'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; +import ButtonBase from '@mui/material/ButtonBase'; + + +export const styles = (theme: Theme) => createStyles({ + /* Styles applied to the root element. */ + root: { + ...theme.typography.button, + height: 32, + minWidth: 48, + margin: 0, + padding: `${theme.spacing(1 - 4)} ${theme.spacing(1.5)}`, + borderRadius: 2, + willChange: 'opacity', + color: alpha(theme.palette.action.active, 0.38), + '&:hover': { + textDecoration: 'none', + // Reset on mouse devices + backgroundColor: alpha(theme.palette.text.primary, 0.12), + '@media (hover: none)': { + backgroundColor: 'transparent', + }, + '&.Mui-disabled': { + backgroundColor: 'transparent', + }, + }, + '&:not(:first-child)': { + borderTopLeftRadius: 0, + borderBottomLeftRadius: 0, + }, + '&:not(:last-child)': { + borderTopRightRadius: 0, + borderBottomRightRadius: 0, + }, + }, + /* Styles applied to the root element if `disabled={true}`. */ + disabled: { + color: alpha(theme.palette.action.disabled, 0.12), + }, + /* Styles applied to the root element if `selected={true}`. */ + selected: { + color: theme.palette.action.active, + '&:after': { + content: '""', + display: 'block', + position: 'absolute', + overflow: 'hidden', + borderRadius: 'inherit', + width: '100%', + height: '100%', + left: 0, + top: 0, + pointerEvents: 'none', + zIndex: 0, + backgroundColor: 'currentColor', + opacity: 0.38, + }, + '& + &:before': { + content: '""', + display: 'block', + position: 'absolute', + overflow: 'hidden', + width: 1, + height: '100%', + left: 0, + top: 0, + pointerEvents: 'none', + zIndex: 0, + backgroundColor: 'currentColor', + opacity: 0.12, + }, + }, + /* Styles applied to the `label` wrapper element. */ + label: { + width: '100%', + display: 'inherit', + alignItems: 'inherit', + justifyContent: 'inherit', + }, +}); + +export type ToggleButtonClassKey = 'disabled' | 'root' | 'label' | 'selected'; + +interface IToggleButtonProps extends WithStyles<typeof styles> { + className?: string; + component?: React.ReactType<IToggleButtonProps>; + disabled?: boolean; + disableFocusRipple?: boolean; + disableRipple?: boolean; + selected?: boolean; + type?: string; + value?: any; + onClick?: (event: React.FormEvent<HTMLElement>, value?: any) => void; + onChange?: (event: React.FormEvent<HTMLElement>, value?: any) => void; +} + +class ToggleButtonComponent extends React.Component<IToggleButtonProps> { + handleChange = (event: React.FormEvent<HTMLElement>) => { + const { onChange, onClick, value } = this.props; + + event.stopPropagation(); + if (onClick) { + onClick(event, value); + if (event.isDefaultPrevented()) { + return; + } + } + + if (onChange) { + onChange(event, value); + } + event.preventDefault(); + }; + + render() { + const { + children, + className: classNameProp, + classes, + disableFocusRipple, + disabled, + selected, + ...other + } = this.props; + + const className = classNames( + classes.root, + { + [classes.disabled]: disabled, + [classes.selected]: selected, + }, + classNameProp, + ); + + return ( + <ButtonBase + className={className} + disabled={disabled} + focusRipple={!disableFocusRipple} + onClick={this.handleChange} + href="#" + {...other} + > + <span className={classes.label}>{children}</span> + </ButtonBase> + ); + } + public static defaultProps = { + disabled: false, + disableFocusRipple: false, + disableRipple: false, + }; + + public static muiName = 'ToggleButton'; +} + +export const ToggleButton = withStyles(styles, { name: 'MuiToggleButton' })(ToggleButtonComponent); export default ToggleButton;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx index 6460e8a3f..bdabe0d56 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/toggleButtonGroup.tsx @@ -17,7 +17,11 @@ */ import * as React from 'react'; import classNames from 'classnames'; -import { withStyles, WithStyles, Theme, createStyles } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; export const styles = (theme: Theme) => createStyles({ /* Styles applied to the root element. */ 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 e62b42472..5c23909c4 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx @@ -16,15 +16,27 @@ * ============LICENSE_END========================================================================== */ import * as React from 'react'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import { List, ListItem, TextField, ListItemText, ListItemIcon, WithTheme, withTheme, Omit, Typography } from '@material-ui/core'; +import { makeStyles, WithStyles, WithTheme } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; -import { SvgIconProps } from '@material-ui/core/SvgIcon'; -import FileIcon from '@material-ui/icons/InsertDriveFile'; -import CloseIcon from '@material-ui/icons/ExpandLess'; -import OpenIcon from '@material-ui/icons/ExpandMore'; -import FolderIcon from '@material-ui/icons/Folder'; +import { List, ListItem, TextField, ListItemText, ListItemIcon, Typography } from '@mui/material'; +import { DistributiveOmit } from '@mui/types'; + +import withTheme from '@mui/styles/withTheme'; + +import { SvgIconProps } from '@mui/material/SvgIcon'; +import FileIcon from '@mui/icons-material/InsertDriveFile'; +import CloseIcon from '@mui/icons-material/ExpandLess'; +import OpenIcon from '@mui/icons-material/ExpandMore'; +import FolderIcon from '@mui/icons-material/Folder'; + +declare module '@mui/styles/defaultTheme' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface (remove this line if you don't have the rule enabled) + interface DefaultTheme extends Theme {} +} const styles = (theme: Theme) => createStyles({ root: { @@ -33,7 +45,7 @@ const styles = (theme: Theme) => createStyles({ paddingTop: 8, }, search: { - padding: `0px ${theme.spacing(1)}px` + padding: `0px ${theme.spacing(1)}` } }); @@ -153,7 +165,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr return ( <div className={this.props.className ? `${this.props.classes.root} ${this.props.className}` : this.props.classes.root} style={this.props.style}> {children} - {enableSearchBar && <TextField label={"Search"} inputProps={{'aria-label': 'treeview-searchfield'}} fullWidth={true} className={this.props.classes.search} value={searchTermValue} onKeyDown={this.onSearchKeyDown} onChange={this.onChangeSearchText} /> || null} + {enableSearchBar && <TextField variant="standard" label={"Search"} inputProps={{'aria-label': 'treeview-searchfield'}} fullWidth={true} className={this.props.classes.search} value={searchTermValue} onKeyDown={this.onSearchKeyDown} onChange={this.onChangeSearchText} /> || null} {enableSearchBar && (searchTerm === undefined || searchTerm.length===0 )&& <Typography style={{marginTop:'10px'}}>Please search for an inventory identifier or use *.</Typography>} <List> {this.renderItems(items, searchTerm && searchTerm.toLowerCase())} @@ -187,10 +199,10 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr }, [] as JSX.Element[]); } - private renderItem = (item: ExternalTreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean, forceRender: boolean): JSX.Element | null => { + private renderItem = (item: ExternalTreeItem<TData> , searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean, forceRender: boolean): JSX.Element | null => { const styles = { item: { - paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)), + paddingLeft: (((this.props.depthOffset || 0) + depth) * Number(this.props.theme.spacing(3).replace("px", ''))), backgroundColor: this.state.activeItem === item ? this.props.theme.palette.action.selected : undefined, height: this.props.itemHeight || undefined, cursor: item.disabled ? 'not-allowed' : 'pointer', @@ -201,8 +213,17 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr }; const text = item.content || ''; // need to keep track of search - const matchIndex = searchTerm ? text.toLowerCase().indexOf(searchTerm) : -1; - const searchTermLength = searchTerm && searchTerm.length || 0; + const search_array = searchTerm?.split("*"); + const index = search_array?.findIndex(function (_str: String) { + return _str.length > 0; + }) || 0; + const firstSearchSubString = search_array ? search_array[index] : ""; + const matchIndex = firstSearchSubString ? text.toLowerCase().indexOf(firstSearchSubString) : -1; + + const hasStarInSearch = search_array ? search_array.length > 1 : false; + const isSearchStringWithStar = hasStarInSearch && firstSearchSubString?.length > 0 || false; + + const searchTermLength = firstSearchSubString && firstSearchSubString.length || 0; const handleClickCreator = (isIcon: boolean) => (event: React.SyntheticEvent) => { if (item.disabled) return; @@ -225,9 +246,8 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr { // highlight search result - matchIndex > -1 - ? <ListItemText className={item.contentClass} primary={(<span> - {text.substring(0, matchIndex)} + isSearchStringWithStar && matchIndex > -1 + ? <ListItemText className={item.contentClass} primary={( <span style={{ display: 'inline-block', @@ -235,18 +255,29 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr padding: '3px', }} > - {text.substring(matchIndex, matchIndex + searchTermLength)} - </span> - {text.substring(matchIndex + searchTermLength)} - </span>)} /> - : <ListItemText className={item.contentClass} primary={( - <span style={item.isMatch ? { - display: 'inline-block', - backgroundColor: 'rgba(255,235,59,0.5)', - padding: '3px', - } : undefined}> - {text} </span> - )} /> + {text} + </span>)} /> + : matchIndex > -1 + ? <ListItemText className={item.contentClass} primary={(<span> + {text.substring(0, matchIndex)} + <span + style={{ + display: 'inline-block', + backgroundColor: 'rgba(255,235,59,0.5)', + padding: '3px', + }} + > + {text.substring(matchIndex, matchIndex + searchTermLength)} + </span> + {text.substring(matchIndex + searchTermLength)} + </span>)} /> + : <ListItemText className={item.contentClass} primary={( + <span style={item.isMatch ? { + display: 'inline-block', + padding: '3px', + } : undefined}> + {text} </span> + )} /> } { // display the right icon, depending on the state @@ -343,7 +374,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr } } -export type TreeViewCtorType<TData = { }> = new () => React.Component<Omit<TreeViewComponentProps<TData>, 'theme'|'classes'>>; +export type TreeViewCtorType<TData = { }> = new () => React.Component<DistributiveOmit<TreeViewComponentProps<TData>, 'theme'|'classes'>>; export const TreeView = withTheme(withStyles(styles)(TreeViewComponent)); export default TreeView;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx index b50d68081..1134e230b 100644 --- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx +++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx @@ -1,214 +1,218 @@ -/**
- * ============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 { faHome, faAddressBook } from '@fortawesome/free-solid-svg-icons';
-
-import Drawer from '@material-ui/core/Drawer';
-import List from '@material-ui/core/List';
-
-import Divider from '@material-ui/core/Divider';
-
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
-
-import ListItemLink from '../components/material-ui/listItemLink';
-
-import connect, { Connect } from '../flux/connect';
-import { MenuAction } from '../actions/menuAction';
-import * as classNames from 'classnames';
-import { transportPCEUrl } from '../app';
-
-
-const drawerWidth = 240;
-
-const extraLinks = (window as any)._odluxExtraLinks as [string, string][];
-
-const styles = (theme: Theme) => createStyles({
- drawerPaper: {
- position: 'relative',
- width: drawerWidth,
- },
- toolbar: theme.mixins.toolbar as any,
-
- drawerOpen: {
- width: drawerWidth,
- transition: theme.transitions.create('width', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.enteringScreen,
- }),
- },
- drawerClose: {
- transition: theme.transitions.create('width', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen,
- }),
- overflowX: 'hidden',
- width: theme.spacing(7) + 1,
- [theme.breakpoints.up('sm')]: {
- width: theme.spacing(9) + 1,
- },
- },
- drawer: {
-
- },
- menu: {
- flex: "1 0 0%",
- },
- optLinks: {
- borderTop: "2px solid #cfcfcf",
- display: "flex",
- flexDirection: "row",
- flexWrap: "wrap",
- justifyContent: "space-around"
- },
- link: {
- margin: theme.spacing(1)+1,
- fontSize: theme.typography.fontSize-2,
- },
-});
-
-const tabletWidthBreakpoint = 768;
-
-export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, dispatch }: WithStyles<typeof styles> & Connect & Connect) => {
- const { user } = state.framework.authenticationState;
- const isOpen = state.framework.applicationState.isMenuOpen;
- const closedByUser = state.framework.applicationState.isMenuClosedByUser;
- const transportUrl = state.framework.applicationState.transportpceUrl;
-
- const [responsive, setResponsive] = React.useState(false);
-
- //collapse menu on mount if necessary
- React.useEffect(()=>{
-
- if(isOpen && window.innerWidth < tabletWidthBreakpoint){
-
- setResponsive(true);
- dispatch(new MenuAction(false));
- }
-
- },[]);
-
- React.useEffect(() => {
-
- function handleResize() {
- if (user && user.isValid) {
- if (window.innerWidth < tabletWidthBreakpoint && !responsive) {
- setResponsive(true);
- if (!closedByUser) {
- console.log("responsive menu collapsed")
- dispatch(new MenuAction(false));
- }
-
- } else if (window.innerWidth > tabletWidthBreakpoint && responsive) {
- setResponsive(false);
- if (!closedByUser) {
- console.log("responsive menu restored")
- dispatch(new MenuAction(true));
- }
-
- }
- }
- }
- window.addEventListener("resize", handleResize);
-
-
- return () => {
- window.removeEventListener("resize", handleResize);
- }
- })
-
- React.useEffect(()=>{
- // trigger a resize if menu changed in case elements have to re-arrange
- window.dispatchEvent(new Event('menu-resized'));
- }, [isOpen])
-
- let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
- const reg = state.framework.applicationRegistraion[key];
- return reg && (
- <ListItemLink
- key={reg.name}
- to={reg.path || `/${reg.name}`}
- primary={reg.menuEntry || reg.name}
- secondary={reg.subMenuEntry}
- icon={reg.icon && <FontAwesomeIcon icon={reg.icon} /> || null} />
- ) || null;
- }) || null;
-
- if(transportUrl.length>0){
-
- const transportPCELink = <ListItemLink
- key={"transportPCE"}
- to={transportUrl}
- primary={"TransportPCE"}
- icon={<FontAwesomeIcon icon={faProjectDiagram} />}
- external />;
-
- const linkFound = menuItems.find(obj => obj.key === "linkCalculation");
-
- if (linkFound) {
- const index = menuItems.indexOf(linkFound);
- menuItems.splice(index + 1, 0, transportPCELink);
- } else {
- menuItems.push(transportPCELink);
- }
- }
-
-
- return (
- <Drawer
- variant="permanent"
- className={
- classNames(classes.drawer, {
- [classes.drawerOpen]: isOpen,
- [classes.drawerClose]: !isOpen
- })
- }
- classes={{
- paper: classes.drawerPaper,
- }}
- >
- {user && user.isValid && <>
- <div className={classes.toolbar} />
- { /* https://fiffty.github.io/react-treeview-mui/ */}
- <List className={classes.menu} component="nav">
- <ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} />
- <Divider />
- {
- menuItems
- }
- <Divider />
- <ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} />
- {(false && process.env.NODE_ENV === "development")
- ? <>
- <Divider />
- <ListItemLink to="/test" primary="Test" icon={<FontAwesomeIcon icon={faHome} />} />
- </>
- : null
- }
- </List>
- {isOpen && extraLinks && <div className={classes.optLinks}>
- {extraLinks.map(linkInfo => (<a className={classes.link} href={linkInfo[1]}>{linkInfo[0]}</a>))}
- </div> || null}
- </> || null
- }
- </Drawer>)
-}));
-
+/** + * ============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 { Theme } from '@mui/material/styles'; + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import { faHome, faAddressBook } from '@fortawesome/free-solid-svg-icons'; + +import Drawer from '@mui/material/Drawer'; +import List from '@mui/material/List'; + +import Divider from '@mui/material/Divider'; + +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; + +import ListItemLink from '../components/material-ui/listItemLink'; + +import connect, { Connect } from '../flux/connect'; +import { MenuAction } from '../actions/menuAction'; +import * as classNames from 'classnames'; +import { transportPCEUrl } from '../app'; + + +const drawerWidth = 240; + +const extraLinks = (window as any)._odluxExtraLinks as [string, string][]; + +const styles = (theme: Theme) => createStyles({ + drawerPaper: { + position: 'relative', + width: drawerWidth, + }, + toolbar: theme.mixins.toolbar as any, + + drawerOpen: { + width: drawerWidth, + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.enteringScreen, + }), + }, + drawerClose: { + transition: theme.transitions.create('width', { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + overflowX: 'hidden', + width: theme.spacing(7) + 1, + [theme.breakpoints.up('sm')]: { + width: theme.spacing(9) + 1, + }, + }, + drawer: { + + }, + menu: { + flex: "1 0 0%", + }, + optLinks: { + borderTop: "2px solid #cfcfcf", + display: "flex", + flexDirection: "row", + flexWrap: "wrap", + justifyContent: "space-around" + }, + link: { + margin: theme.spacing(1)+1, + fontSize: theme.typography.fontSize-2, + }, +}); + +const tabletWidthBreakpoint = 768; + +export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, dispatch }: WithStyles<typeof styles> & Connect & Connect) => { + const { user } = state.framework.authenticationState; + const isOpen = state.framework.applicationState.isMenuOpen; + const closedByUser = state.framework.applicationState.isMenuClosedByUser; + const transportUrl = state.framework.applicationState.transportpceUrl; + + const [responsive, setResponsive] = React.useState(false); + + //collapse menu on mount if necessary + React.useEffect(()=>{ + + if(isOpen && window.innerWidth < tabletWidthBreakpoint){ + + setResponsive(true); + dispatch(new MenuAction(false)); + } + + },[]); + + React.useEffect(() => { + + function handleResize() { + if (user && user.isValid) { + if (window.innerWidth < tabletWidthBreakpoint && !responsive) { + setResponsive(true); + if (!closedByUser) { + console.log("responsive menu collapsed") + dispatch(new MenuAction(false)); + } + + } else if (window.innerWidth > tabletWidthBreakpoint && responsive) { + setResponsive(false); + if (!closedByUser) { + console.log("responsive menu restored") + dispatch(new MenuAction(true)); + } + + } + } + } + window.addEventListener("resize", handleResize); + + + return () => { + window.removeEventListener("resize", handleResize); + } + }) + + React.useEffect(()=>{ + // trigger a resize if menu changed in case elements have to re-arrange + window.dispatchEvent(new Event('menu-resized')); + }, [isOpen]) + + let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => { + const reg = state.framework.applicationRegistraion[key]; + return reg && ( + <ListItemLink + key={reg.name} + to={reg.path || `/${reg.name}`} + primary={reg.menuEntry || reg.name} + secondary={reg.subMenuEntry} + icon={reg.icon && <FontAwesomeIcon icon={reg.icon} /> || null} /> + ) || null; + }) || null; + + if(transportUrl.length>0){ + + const transportPCELink = <ListItemLink + key={"transportPCE"} + to={transportUrl} + primary={"TransportPCE"} + icon={<FontAwesomeIcon icon={faProjectDiagram} />} + external />; + + const linkFound = menuItems.find(obj => obj.key === "linkCalculation"); + + if (linkFound) { + const index = menuItems.indexOf(linkFound); + menuItems.splice(index + 1, 0, transportPCELink); + } else { + menuItems.push(transportPCELink); + } + } + + + return ( + <Drawer + variant="permanent" + className={ + classNames(classes.drawer, { + [classes.drawerOpen]: isOpen, + [classes.drawerClose]: !isOpen + }) + } + classes={{ + paper: classes.drawerPaper, + }} + > + {user && user.isValid && <> + <div className={classes.toolbar} /> + { /* https://fiffty.github.io/react-treeview-mui/ */} + <List className={classes.menu} component="nav"> + <ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} /> + <Divider /> + { + menuItems + } + <Divider /> + <ListItemLink to="/about" primary="About" icon={<FontAwesomeIcon icon={faAddressBook} />} /> + {(false && process.env.NODE_ENV === "development") + ? <> + <Divider /> + <ListItemLink to="/test" primary="Test" icon={<FontAwesomeIcon icon={faHome} />} /> + </> + : null + } + </List> + {isOpen && extraLinks && <div className={classes.optLinks}> + {extraLinks.map(linkInfo => (<a className={classes.link} href={linkInfo[1]}>{linkInfo[0]}</a>))} + </div> || null} + </> || null + } + </Drawer>) +})); + export default NavigationMenu;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx b/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx index d2de7cc02..10a0547be 100644 --- a/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx +++ b/sdnr/wt/odlux/framework/src/components/objectDump/index.tsx @@ -17,7 +17,7 @@ */ import * as React from "react"; -import { makeStyles } from '@material-ui/core/styles'; +import makeStyles from '@mui/styles/makeStyles'; export const getTypeName = (obj: any): string => { if (obj == null) { diff --git a/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx b/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx index d212257c8..d055b8a87 100644 --- a/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx +++ b/sdnr/wt/odlux/framework/src/components/routing/appFrame.tsx @@ -1,55 +1,55 @@ -/**
- * ============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 connect, { Connect } from '../../flux/connect';
-
-import { SetTitleAction } from '../../actions/titleActions';
-import { AddErrorInfoAction } from '../../actions/errorActions';
-
-import { IconType } from '../../models/iconDefinition';
-
-export interface IAppFrameProps {
- title: string;
- icon?: IconType;
- appId?: string
-}
-
-/**
- * Represents a component to wich will embed each single app providing the
- * functionality to update the title and implement an exeprion border.
- */
-export class AppFrame extends React.Component<IAppFrameProps & Connect> {
-
- public render(): JSX.Element {
- return (
- <div style={{ flex: "1", overflow: "hidden", display: "flex", flexDirection: "column" }}>
- { this.props.children }
- </div>
- )
- }
-
- public componentDidMount() {
- this.props.dispatch(new SetTitleAction(this.props.title, this.props.icon, this.props.appId));
- }
- public componentDidCatch(error: Error | null, info: object) {
- this.props.dispatch(new AddErrorInfoAction({ error, info }));
- }
-}
-
+/** + * ============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 connect, { Connect } from '../../flux/connect'; + +import { SetTitleAction } from '../../actions/titleActions'; +import { AddErrorInfoAction } from '../../actions/errorActions'; + +import { IconType } from '../../models/iconDefinition'; + +export interface IAppFrameProps { + title: string; + icon?: IconType; + appId?: string +} + +/** + * Represents a component to wich will embed each single app providing the + * functionality to update the title and implement an exeprion border. + */ +export class AppFrame extends React.Component<IAppFrameProps & Connect> { + + public render(): JSX.Element { + return ( + <div style={{ flex: "1", overflow: "hidden", display: "flex", flexDirection: "column" }}> + { this.props.children } + </div> + ) + } + + public componentDidMount() { + this.props.dispatch(new SetTitleAction(this.props.title, this.props.icon, this.props.appId)); + } + public componentDidCatch(error: Error | null, info: object) { + this.props.dispatch(new AddErrorInfoAction({ error, info })); + } +} + export default connect()(AppFrame);
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/settings/general.tsx b/sdnr/wt/odlux/framework/src/components/settings/general.tsx index ca1849049..90f15c1d2 100644 --- a/sdnr/wt/odlux/framework/src/components/settings/general.tsx +++ b/sdnr/wt/odlux/framework/src/components/settings/general.tsx @@ -16,7 +16,8 @@ * ============LICENSE_END========================================================================== */ -import { Button, FormControlLabel, makeStyles, Switch, Typography } from '@material-ui/core'; +import { Button, FormControlLabel, Switch, Typography } from '@mui/material'; +import makeStyles from '@mui/styles/makeStyles'; import { SettingsComponentProps } from '../../models/settings'; import * as React from 'react'; import connect, { Connect, IDispatcher } from '../../flux/connect'; @@ -94,13 +95,13 @@ const onCancel = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) =>{ </Typography> <FormControlLabel style={{ padding:5}} value="end" - control={<Switch color="secondary" checked={areWebsocketsEnabled} onChange={onWebsocketsChange} />} + control={<Switch color="secondary" aria-label="enable-notifications-button" aria-checked={areWebsocketsEnabled} checked={areWebsocketsEnabled} onChange={onWebsocketsChange} />} label="Enable Notifications" labelPlacement="end" /> <div className={classes.buttonPosition}> - <Button className={classes.elementMargin} variant="contained" color="primary" onClick={onCancel}>Cancel</Button> - <Button className={classes.elementMargin} variant="contained" color="secondary" onClick={onSave}>Save</Button> + <Button aria-label="cancel-button" className={classes.elementMargin} variant="contained" color="primary" onClick={onCancel}>Cancel</Button> + <Button aria-label="save-button" className={classes.elementMargin} variant="contained" color="secondary" onClick={onSave}>Save</Button> </div> </div> } diff --git a/sdnr/wt/odlux/framework/src/components/titleBar.tsx b/sdnr/wt/odlux/framework/src/components/titleBar.tsx index 5d916e8c8..7872e51da 100644 --- a/sdnr/wt/odlux/framework/src/components/titleBar.tsx +++ b/sdnr/wt/odlux/framework/src/components/titleBar.tsx @@ -1,218 +1,226 @@ -/**
- * ============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 { withRouter, RouteComponentProps } from 'react-router-dom';
-
-import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
-import AppBar from '@material-ui/core/AppBar';
-import Toolbar from '@material-ui/core/Toolbar';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import IconButton from '@material-ui/core/IconButton';
-import Block from '@material-ui/icons/Block';
-import Adjust from '@material-ui/icons/Adjust';
-import MenuIcon from '@material-ui/icons/Menu';
-import AccountCircle from '@material-ui/icons/AccountCircle';
-import MenuItem from '@material-ui/core/MenuItem';
-import Menu from '@material-ui/core/Menu';
-
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faBan } from '@fortawesome/free-solid-svg-icons';
-import { faDotCircle } from '@fortawesome/free-solid-svg-icons';
-
-import { logoutUser } from '../actions/authentication';
-import { PushAction, ReplaceAction } from '../actions/navigationActions';
-
-import connect, { Connect, IDispatcher } from '../flux/connect';
-import Logo from './logo';
-import { MenuAction, MenuClosedByUser } from '../actions/menuAction';
-
-const styles = (theme: Theme) => createStyles({
- appBar: {
- zIndex: theme.zIndex.drawer + 1,
- },
- grow: {
- flexGrow: 1,
- },
- menuButton: {
- marginLeft: -12,
- marginRight: 20,
- },
- icon: {
- marginLeft: 16,
- marginRight: 8
- },
- connected: {
- color: "green"
- },
- notConnected: {
- color: "red"
- },
- notificationInfo: {
- marginLeft: 5
- }
-});
-
-const mapDispatch = (dispatcher: IDispatcher) => {
- return {
- logout: () => {
- dispatcher.dispatch(logoutUser());
- dispatcher.dispatch(new ReplaceAction("/login"));
- },
- openSettings : () =>{
- dispatcher.dispatch(new PushAction("/settings"));
- },
- toggleMainMenu: (value: boolean, value2: boolean) => {
- dispatcher.dispatch(new MenuAction(value));
- dispatcher.dispatch(new MenuClosedByUser(value2))
- }
- }
-};
-
-type TitleBarProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<undefined, typeof mapDispatch>
-
-class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLElement | null }> {
-
- constructor(props: TitleBarProps) {
- super(props);
- this.state = {
- anchorEl: null
- }
-
- }
- render(): JSX.Element {
- const { classes, state, history, location } = this.props;
- const open = !!this.state.anchorEl;
- let toolbarElements: Array<JSX.Element>;
- toolbarElements = [];
-
- // create notificationInfo element
- const notificationInfo = state.framework.applicationState.isWebsocketAvailable != undefined ?
- (state.framework.applicationState.isWebsocketAvailable ?
- <Typography aria-label="notifications-are-active" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.connected} icon={faDotCircle} /> |</Typography> : <Typography aria-label="notifications-are-inactive" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.notConnected} icon={faBan} /> |</Typography>)
- : <Typography variant="body1" aria-label="notifications-are-not-available" className={classes.notificationInfo}>Notifications N/A |</Typography>;
-
-
- // add notificationInfo element before help
- if (state.framework.applicationRegistraion) {
- let isNotificationInfoAdded = false;
- Object.keys(state.framework.applicationRegistraion).map(key => {
- const reg = state.framework.applicationRegistraion[key];
- if (reg && reg.statusBarElement) {
- if (key === "help") {
- isNotificationInfoAdded = true;
- toolbarElements.push(notificationInfo);
- }
- toolbarElements.push(<reg.statusBarElement key={key} />);
- }
- });
-
- // add notificationInfo in case help wasn't found
- if (!isNotificationInfoAdded) {
- toolbarElements.push(notificationInfo);
- }
- }
-
- return (
- <AppBar position="absolute" className={classes.appBar}>
- <Toolbar>
- <IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleMainMenu}>
- <MenuIcon />
- </IconButton>
- <Logo />
- <Typography variant="h6" color="inherit" >
- {state.framework.applicationState.icon
- ? (<FontAwesomeIcon className={classes.icon} icon={state.framework.applicationState.icon} />)
- : null}
- {state.framework.applicationState.title}
- </Typography>
- <div className={classes.grow}></div>
- {
- // render toolbar
- toolbarElements.map((item) => {
- return item
- })
- }
-
- {state.framework.authenticationState.user
- ? (<div>
- <Button aria-label="current user menu button"
- aria-owns={open ? 'menu-appbar' : undefined}
- aria-haspopup="true"
- onClick={this.openMenu}
- color="inherit"
- >
- <AccountCircle />
- {state.framework.authenticationState.user.user}
- </Button>
- <Menu
- id="menu-appbar"
- anchorEl={this.state.anchorEl}
- anchorOrigin={{
- vertical: 'top',
- horizontal: 'right',
- }}
- transformOrigin={{
- vertical: 'top',
- horizontal: 'right',
- }}
- open={open}
- onClose={this.closeMenu}
- >
- {/* <MenuItem onClick={ this.closeMenu }>Profile</MenuItem> */}
- <MenuItem
- aria-label="settings-button"
- onClick={ () =>{
- this.props.openSettings();
- this.closeMenu(); }}>Settings</MenuItem>
- <MenuItem
- aria-label="logout-button"
- onClick={() => {
- this.props.logout();
- this.closeMenu();
- }}>Logout</MenuItem>
- </Menu>
- </div>)
- : (<Button onClick={() => { history.push('/login') }} color="inherit" disabled={location.pathname == "/login"}>Login</Button>)}
- </Toolbar>
- </AppBar>
- );
- };
-
- private toggleMainMenu = (event: React.MouseEvent<HTMLElement>) => {
- console.log(this.props);
- if (this.props.state.framework.authenticationState.user && this.props.state.framework.authenticationState.user.isValid) {
- const isMainMenuOpen = this.props.state.framework.applicationState.isMenuOpen
- const isClosedByUser = this.props.state.framework.applicationState.isMenuClosedByUser
- this.props.toggleMainMenu(!isMainMenuOpen, !isClosedByUser);
- }
- }
-
- private openMenu = (event: React.MouseEvent<HTMLElement>) => {
- this.setState({ anchorEl: event.currentTarget });
- };
-
- private closeMenu = () => {
- this.setState({ anchorEl: null });
- };
-}
-
-//todo: ggf. https://github.com/acdlite/recompose verwenden zur Vereinfachung
-
-export const TitleBar = withStyles(styles)(withRouter(connect(undefined, mapDispatch)(TitleBarComponent)));
+/** + * ============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 { withRouter, RouteComponentProps } from 'react-router-dom'; + +import { Theme } from '@mui/material/styles'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; +import Typography from '@mui/material/Typography'; +import Button from '@mui/material/Button'; +import IconButton from '@mui/material/IconButton'; +import Block from '@mui/icons-material/Block'; +import Adjust from '@mui/icons-material/Adjust'; +import MenuIcon from '@mui/icons-material/Menu'; +import AccountCircle from '@mui/icons-material/AccountCircle'; +import MenuItem from '@mui/material/MenuItem'; +import Menu from '@mui/material/Menu'; + +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faBan } from '@fortawesome/free-solid-svg-icons'; +import { faDotCircle } from '@fortawesome/free-solid-svg-icons'; + +import { logoutUser } from '../actions/authentication'; +import { PushAction, ReplaceAction } from '../actions/navigationActions'; + +import connect, { Connect, IDispatcher } from '../flux/connect'; +import Logo from './logo'; +import { MenuAction, MenuClosedByUser } from '../actions/menuAction'; + +const styles = (theme: Theme) => createStyles({ + appBar: { + zIndex: theme.zIndex.drawer + 1, + }, + grow: { + flexGrow: 1, + }, + menuButton: { + marginLeft: -12, + marginRight: 20, + }, + icon: { + marginLeft: 16, + marginRight: 8 + }, + connected: { + color: "green" + }, + notConnected: { + color: "red" + }, + notificationInfo: { + marginLeft: 5 + } +}); + +const mapDispatch = (dispatcher: IDispatcher) => { + return { + logout: () => { + dispatcher.dispatch(logoutUser()); + dispatcher.dispatch(new ReplaceAction("/login")); + }, + openSettings : () =>{ + dispatcher.dispatch(new PushAction("/settings")); + }, + toggleMainMenu: (value: boolean, value2: boolean) => { + dispatcher.dispatch(new MenuAction(value)); + dispatcher.dispatch(new MenuClosedByUser(value2)) + } + } +}; + +type TitleBarProps = RouteComponentProps<{}> & WithStyles<typeof styles> & Connect<undefined, typeof mapDispatch> + +class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLElement | null }> { + + constructor(props: TitleBarProps) { + super(props); + this.state = { + anchorEl: null + } + + } + render(): JSX.Element { + const { classes, state, history, location } = this.props; + const open = !!this.state.anchorEl; + let toolbarElements: Array<JSX.Element>; + toolbarElements = []; + + // create notificationInfo element + const notificationInfo = state.framework.applicationState.isWebsocketAvailable != undefined ? + (state.framework.applicationState.isWebsocketAvailable ? + <Typography aria-label="notifications-are-active" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.connected} icon={faDotCircle} /> |</Typography> : <Typography aria-label="notifications-are-inactive" variant="body1" className={classes.notificationInfo}>Notifications <FontAwesomeIcon className={classes.notConnected} icon={faBan} /> |</Typography>) + : <Typography variant="body1" aria-label="notifications-are-not-available" className={classes.notificationInfo}>Notifications N/A |</Typography>; + + + // add notificationInfo element before help + if (state.framework.applicationRegistraion) { + let isNotificationInfoAdded = false; + Object.keys(state.framework.applicationRegistraion).map(key => { + const reg = state.framework.applicationRegistraion[key]; + if (reg && reg.statusBarElement) { + if (key === "help") { + isNotificationInfoAdded = true; + toolbarElements.push(notificationInfo); + } + toolbarElements.push(<reg.statusBarElement key={key} />); + } + }); + + // add notificationInfo in case help wasn't found + if (!isNotificationInfoAdded) { + toolbarElements.push(notificationInfo); + } + } + + return ( + <AppBar enableColorOnDark position="absolute" className={classes.appBar}> + <Toolbar> + <IconButton + className={classes.menuButton} + color="inherit" + aria-label="Menu" + onClick={this.toggleMainMenu} + size="large"> + <MenuIcon /> + </IconButton> + <Logo /> + <Typography variant="h6" color="inherit" > + {state.framework.applicationState.icon + ? (<FontAwesomeIcon className={classes.icon} icon={state.framework.applicationState.icon} />) + : null} + {state.framework.applicationState.title} + </Typography> + <div className={classes.grow}></div> + { + // render toolbar + toolbarElements.map((item) => { + return item + }) + } + + {state.framework.authenticationState.user + ? (<div> + <Button aria-label="current user menu button" + aria-owns={open ? 'menu-appbar' : undefined} + aria-haspopup="true" + onClick={this.openMenu} + color="inherit" + > + <AccountCircle /> + {state.framework.authenticationState.user.user} + </Button> + <Menu + id="menu-appbar" + anchorEl={this.state.anchorEl} + anchorOrigin={{ + vertical: 'top', + horizontal: 'right', + }} + transformOrigin={{ + vertical: 'top', + horizontal: 'right', + }} + open={open} + onClose={this.closeMenu} + > + {/* <MenuItem onClick={ this.closeMenu }>Profile</MenuItem> */} + <MenuItem + aria-label="settings-button" + onClick={ () =>{ + this.props.openSettings(); + this.closeMenu(); }}>Settings</MenuItem> + <MenuItem + aria-label="logout-button" + onClick={() => { + this.props.logout(); + this.closeMenu(); + }}>Logout</MenuItem> + </Menu> + </div>) + : (<Button onClick={() => { history.push('/login') }} color="inherit" disabled={location.pathname == "/login"}>Login</Button>)} + </Toolbar> + </AppBar> + ); + }; + + private toggleMainMenu = (event: React.MouseEvent<HTMLElement>) => { + console.log(this.props); + if (this.props.state.framework.authenticationState.user && this.props.state.framework.authenticationState.user.isValid) { + const isMainMenuOpen = this.props.state.framework.applicationState.isMenuOpen + const isClosedByUser = this.props.state.framework.applicationState.isMenuClosedByUser + this.props.toggleMainMenu(!isMainMenuOpen, !isClosedByUser); + } + } + + private openMenu = (event: React.MouseEvent<HTMLElement>) => { + this.setState({ anchorEl: event.currentTarget }); + }; + + private closeMenu = () => { + this.setState({ anchorEl: null }); + }; +} + +//todo: ggf. https://github.com/acdlite/recompose verwenden zur Vereinfachung + +export const TitleBar = withStyles(styles)(withRouter(connect(undefined, mapDispatch)(TitleBarComponent))); export default TitleBar;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/design/default.ts b/sdnr/wt/odlux/framework/src/design/default.ts index 59b8c20ef..c4a8118c2 100644 --- a/sdnr/wt/odlux/framework/src/design/default.ts +++ b/sdnr/wt/odlux/framework/src/design/default.ts @@ -31,10 +31,10 @@ * limitations under the License. *****************************************************************************/ -import { createMuiTheme } from '@material-ui/core/styles'; +import { createTheme, adaptV4Theme } from '@mui/material/styles'; import onapLogo from '../assets/images/onapLogo.gif' -const theme = createMuiTheme({ +const theme = createTheme(adaptV4Theme({ design: { id: "onap", name: "Open Networking Automation Plattform (ONAP)", @@ -60,7 +60,7 @@ const theme = createMuiTheme({ overrides: { //temp fix for labels turning white after material new version (palette primary color) MuiFormLabel: { root: { - "&$focused": { + "&.Mui-focused": { color: "rgba(143,143,143,1)" } }, @@ -76,6 +76,6 @@ const theme = createMuiTheme({ } } }, -}); +})); export default theme;
\ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/middleware/navigation.ts b/sdnr/wt/odlux/framework/src/middleware/navigation.ts index 94350ab5d..5f3eed55d 100644 --- a/sdnr/wt/odlux/framework/src/middleware/navigation.ts +++ b/sdnr/wt/odlux/framework/src/middleware/navigation.ts @@ -60,11 +60,11 @@ const routerMiddlewareCreator = (history: History) => () => (next: Dispatch): Di if (tokenStr && token) { // @ts-ignore const user = new User({ username: token["name"], access_token: tokenStr, token_type: "Bearer", expires: token['exp'], issued: token['iat'] }) || undefined; - return next(loginUserAction(user)) as any; + applicationStore?.dispatch(loginUserAction(user)); } } if (!action.pathname.startsWith("/login") && applicationStore && (!applicationStore.state.framework.authenticationState.user || !applicationStore.state.framework.authenticationState.user.isValid)) { history.replace(`/login?returnTo=${action.pathname}`); - return next(logoutUser()) as any; + applicationStore.dispatch(logoutUser()); }else if (action.pathname.startsWith("/login") && applicationStore && (applicationStore.state.framework.authenticationState.user && applicationStore.state.framework.authenticationState.user.isValid)) { history.replace(`/`); diff --git a/sdnr/wt/odlux/framework/src/models/elasticSearch.ts b/sdnr/wt/odlux/framework/src/models/elasticSearch.ts index b5f25097c..41d29fb0f 100644 --- a/sdnr/wt/odlux/framework/src/models/elasticSearch.ts +++ b/sdnr/wt/odlux/framework/src/models/elasticSearch.ts @@ -1,61 +1,61 @@ -/**
- * ============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 Result<TSource extends {}> = {
- "data-provider:output": {
- pagination?: {
- size: number;
- page: number;
- total: number;
- },
- data: TSource[];
- }
-}
-
-export type SingeResult<TSource extends {}> = {
- "data-provider:output": TSource;
-}
-
-
-export type HitEntry<TSource extends {}> = {
- _index: string;
- _type: string;
- _id: string;
- _score: number;
- _source: TSource;
-}
-
-type ActionResponse ={
- _index: string;
- _type: string;
- _id: string;
- _shards: {
- total: number,
- successful: number,
- failed: number
- },
-
-}
-
-export type PostResponse = ActionResponse & {
- created: boolean
-}
-
-export type DeleteResponse = ActionResponse & {
- found: boolean
-}
-
+/** + * ============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 Result<TSource extends {}> = { + "data-provider:output": { + pagination?: { + size: number; + page: number; + total: number; + }, + data: TSource[]; + } +} + +export type SingeResult<TSource extends {}> = { + "data-provider:output": TSource; +} + + +export type HitEntry<TSource extends {}> = { + _index: string; + _type: string; + _id: string; + _score: number; + _source: TSource; +} + +type ActionResponse ={ + _index: string; + _type: string; + _id: string; + _shards: { + total: number, + successful: number, + failed: number + }, + +} + +export type PostResponse = ActionResponse & { + created: boolean +} + +export type DeleteResponse = ActionResponse & { + found: boolean +} + diff --git a/sdnr/wt/odlux/framework/src/services/restAccessorService.ts b/sdnr/wt/odlux/framework/src/services/restAccessorService.ts index ca95ebc1a..5ed4d7b6e 100644 --- a/sdnr/wt/odlux/framework/src/services/restAccessorService.ts +++ b/sdnr/wt/odlux/framework/src/services/restAccessorService.ts @@ -55,7 +55,7 @@ export const createRestApiAccessor = <TResult extends PlainObject>(urlOrPath: st $.ajax({ url: uri, method: (action.settings && action.settings.method) || "GET", - headers: { ...authHeader, ...action.settings && action.settings.headers ? action.settings.headers : { } }, + headers: { ...authHeader, ...(action.settings && action.settings.headers ? action.settings.headers : { }) }, }).then((data: TResult) => { next(new RestResponseAction(data)); }).catch((err: any) => { diff --git a/sdnr/wt/odlux/framework/src/styles/att.ts b/sdnr/wt/odlux/framework/src/styles/att.ts index cfd743d11..2d54590c9 100644 --- a/sdnr/wt/odlux/framework/src/styles/att.ts +++ b/sdnr/wt/odlux/framework/src/styles/att.ts @@ -16,9 +16,9 @@ * ============LICENSE_END========================================================================== */ -import { createMuiTheme } from '@material-ui/core/styles'; +import { createTheme, adaptV4Theme } from '@mui/material/styles'; -const theme = createMuiTheme({ +const theme = createTheme(adaptV4Theme({ design: { id: "att", name: "AT&T", @@ -41,6 +41,6 @@ const theme = createMuiTheme({ contrastText: "#0094d3" } }, -}); +})); export default theme; diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx index 400ee35bb..1b6135e5f 100644 --- a/sdnr/wt/odlux/framework/src/views/about.tsx +++ b/sdnr/wt/odlux/framework/src/views/about.tsx @@ -19,8 +19,7 @@ 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'; -import createBreakpoints from '@material-ui/core/styles/createBreakpoints'; +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>` @@ -168,7 +167,7 @@ class AboutComponent extends React.Component<any, AboutState> { <div style={containerStyle}> { this.state.isContentLoadedSucessfully && <div style={{float: "right", marginRight: "10px"}}> - <Button variant="contained" onClick={e => this.copyToClipboard(e)}> + <Button color="inherit" variant="contained" onClick={e => this.copyToClipboard(e)}> Copy to clipboard </Button> { diff --git a/sdnr/wt/odlux/framework/src/views/frame.tsx b/sdnr/wt/odlux/framework/src/views/frame.tsx index 1c78dd297..278fbe1db 100644 --- a/sdnr/wt/odlux/framework/src/views/frame.tsx +++ b/sdnr/wt/odlux/framework/src/views/frame.tsx @@ -1,130 +1,133 @@ -/**
- * ============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 { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
-
-import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
-import { faHome, faAddressBook, faSignInAlt, faCog } from '@fortawesome/free-solid-svg-icons';
-
-import { SnackbarProvider } from 'notistack';
-import { ConfirmProvider } from 'material-ui-confirm';
-
-import AppFrame from '../components/routing/appFrame';
-import TitleBar from '../components/titleBar';
-import Menu from '../components/navigationMenu';
-import ErrorDisplay from '../components/errorDisplay';
-import SnackDisplay from '../components/material-ui/snackDisplay';
-
-import Home from '../views/home';
-import Login from '../views/login';
-import About from '../views/about';
-import Test from '../views/test';
-import UserSettings from '../views/settings';
-
-import applicationService from '../services/applicationManager';
-
-
-const styles = (theme: Theme) => createStyles({
- root: {
- flexGrow: 1,
- height: '100%',
- zIndex: 1,
- overflow: 'hidden',
- position: 'relative',
- display: 'flex',
- },
- content: {
- flexGrow: 1,
- display: "flex",
- flexDirection: "column",
- backgroundColor: theme.palette.background.default,
- padding: theme.spacing(3),
- minWidth: 0, // So the Typography noWrap works
- },
- toolbar: theme.mixins.toolbar as any
-});
-
-
-
-type FrameProps = WithStyles<typeof styles>;
-
-class FrameComponent extends React.Component<FrameProps>{
-
- render() {
- const registrations = applicationService.applications;
- const { classes } = this.props;
- return (
- <ConfirmProvider>
- <SnackbarProvider maxSnack={3}>
- <Router>
- <div className={classes.root}>
- <SnackDisplay />
- <ErrorDisplay />
- <TitleBar />
- <Menu />
- <main className={classes.content}>
- {
- <div className={classes.toolbar} /> //needed for margins, don't remove!
- }
- <Switch>
- <Route exact path="/" component={() => (
- <AppFrame title={"Home"} icon={faHome} >
- <Home />
- </AppFrame>
- )} />
- <Route path="/about" component={() => (
- <AppFrame title={"About"} icon={faAddressBook} >
- <About />
- </AppFrame>
- )} />
- <Route path="/settings" component={() => (
- <AppFrame title={"Settings"} icon={faCog} >
- <UserSettings />
- </AppFrame>
- )} />
- {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => (
- <AppFrame title={"Test"} icon={faAddressBook} >
- <Test />
- </AppFrame>
- )} /> : null}
- <Route path="/login" component={() => (
- <AppFrame title={"Login"} icon={faSignInAlt} >
- <Login />
- </AppFrame>
- )} />
- { Object.keys(registrations).map(p => {
- const application = registrations[p];
- return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => (
- <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} >
- <application.rootComponent />
- </AppFrame>
- )} />)
- })}
- <Redirect to="/" />
- </Switch>
- </main>
- </div>
- </Router>
- </SnackbarProvider>
- </ConfirmProvider>
- );
- }
-}
-
-export const Frame = withStyles(styles)(FrameComponent);
-export default Frame;
+/** + * ============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 { HashRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; + +import { Theme } from '@mui/material/styles'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; +import { faHome, faAddressBook, faSignInAlt, faCog } from '@fortawesome/free-solid-svg-icons'; + +import { SnackbarProvider } from 'notistack'; +import { ConfirmProvider } from 'material-ui-confirm'; + +import AppFrame from '../components/routing/appFrame'; +import TitleBar from '../components/titleBar'; +import Menu from '../components/navigationMenu'; +import ErrorDisplay from '../components/errorDisplay'; +import SnackDisplay from '../components/material-ui/snackDisplay'; + +import Home from '../views/home'; +import Login from '../views/login'; +import About from '../views/about'; +import Test from '../views/test'; +import UserSettings from '../views/settings'; + +import applicationService from '../services/applicationManager'; + + +const styles = (theme: Theme) => createStyles({ + root: { + flexGrow: 1, + height: '100%', + zIndex: 1, + overflow: 'hidden', + position: 'relative', + display: 'flex', + }, + content: { + flexGrow: 1, + display: "flex", + flexDirection: "column", + backgroundColor: '#fafafa', + padding: theme.spacing(3), + minWidth: 0, // So the Typography noWrap works + }, + toolbar: theme.mixins.toolbar as any +}); + + + +type FrameProps = WithStyles<typeof styles>; + +class FrameComponent extends React.Component<FrameProps>{ + + render() { + const registrations = applicationService.applications; + const { classes } = this.props; + return ( + <ConfirmProvider> + <SnackbarProvider maxSnack={3}> + <Router> + <div className={classes.root}> + <SnackDisplay /> + <ErrorDisplay /> + <TitleBar /> + <Menu /> + <main className={classes.content}> + { + <div className={classes.toolbar} /> //needed for margins, don't remove! + } + <Switch> + <Route exact path="/" component={() => ( + <AppFrame title={"Home"} icon={faHome} > + <Home /> + </AppFrame> + )} /> + <Route path="/about" component={() => ( + <AppFrame title={"About"} icon={faAddressBook} > + <About /> + </AppFrame> + )} /> + <Route path="/settings" component={() => ( + <AppFrame title={"Settings"} icon={faCog} > + <UserSettings /> + </AppFrame> + )} /> + {process.env.NODE_ENV === "development" ? <Route path="/test" component={() => ( + <AppFrame title={"Test"} icon={faAddressBook} > + <Test /> + </AppFrame> + )} /> : null} + <Route path="/login" component={() => ( + <AppFrame title={"Login"} icon={faSignInAlt} > + <Login /> + </AppFrame> + )} /> + { Object.keys(registrations).map(p => { + const application = registrations[p]; + return (<Route key={application.name} path={application.path || `/${application.name}`} component={() => ( + <AppFrame title={application.title || (typeof application.menuEntry === 'string' && application.menuEntry) || application.name} icon={application.icon} appId={application.name} > + <application.rootComponent /> + </AppFrame> + )} />) + })} + <Redirect to="/" /> + </Switch> + </main> + </div> + </Router> + </SnackbarProvider> + </ConfirmProvider> + ); + } +} + +export const Frame = withStyles(styles)(FrameComponent); +export default Frame; diff --git a/sdnr/wt/odlux/framework/src/views/home.tsx b/sdnr/wt/odlux/framework/src/views/home.tsx index 176de02ab..92fd0b262 100644 --- a/sdnr/wt/odlux/framework/src/views/home.tsx +++ b/sdnr/wt/odlux/framework/src/views/home.tsx @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================================== * ONAP : ccsdk feature sdnr wt odlux * ================================================================================================= - * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * Copyright (C) 2021 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 @@ -15,409 +15,56 @@ * the License. * ============LICENSE_END========================================================================== */ -import * as React from 'react'; - -import { withRouter, RouteComponentProps } from 'react-router-dom'; -import connect, { Connect, IDispatcher } from '..//flux/connect'; -import { IApplicationState } from '../handlers/applicationStateHandler'; -import { IApplicationStoreState } from '../store/applicationStore'; -import { WithStyles, withStyles, createStyles, Theme } from '@material-ui/core/styles'; -import { Doughnut } from 'react-chartjs-2'; -import { NavigateToApplication } from '../actions/navigationActions'; -const styles = (theme: Theme) => createStyles({ - pageWidthSettings: { - width: '50%', - float: 'left' - }, -}) +import * as React from 'react'; +import { IApplicationStoreState } from "../store/applicationStore"; +import connect, { Connect, IDispatcher } from "../flux/connect"; +import applicationService from '../services/applicationManager'; -const scrollbar = { overflow: "auto", paddingRight: "20px" } +type props = Connect<typeof mapProps, typeof mapDispatch>; -let connectionStatusinitialLoad = true; -let connectionStatusinitialStateChanged = false; -let connectionStatusDataLoad: number[] = [0, 0, 0, 0]; -let connectionTotalCount = 0; +type SettingsEntry = { name: string, element: JSX.Element } -let alarmStatusinitialLoad = true; -let alarmStatusinitialStateChanged = false; -let alarmStatusDataLoad: number[] = [0, 0, 0, 0]; -let alarmTotalCount = 0; const mapProps = (state: IApplicationStoreState) => ({ - connectionStatusCount: state.connect.connectionStatusCount, - alarmStatus: state.fault.faultStatus }); const mapDispatch = (dispatcher: IDispatcher) => ({ - navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path)), }); -type HomeComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>; - -class Home extends React.Component<HomeComponentProps> { - constructor(props: HomeComponentProps) { - super(props); - this.state = { - } - } - - render(): JSX.Element { - const { classes } = this.props; - - if (!this.props.connectionStatusCount.isLoadingConnectionStatusChart) { - connectionStatusDataLoad = [ - this.props.connectionStatusCount.Connected, - this.props.connectionStatusCount.Connecting, - this.props.connectionStatusCount.Disconnected, - this.props.connectionStatusCount.UnableToConnect - ]; - connectionTotalCount = this.props.connectionStatusCount.Connected + this.props.connectionStatusCount.Connecting - + this.props.connectionStatusCount.Disconnected + this.props.connectionStatusCount.UnableToConnect; +const DashboardView: React.FunctionComponent<props> = (props) => { - } - - if (!this.props.alarmStatus.isLoadingAlarmStatusChart) { - alarmStatusDataLoad = [ - this.props.alarmStatus.critical, - this.props.alarmStatus.major, - this.props.alarmStatus.minor, - this.props.alarmStatus.warning - ]; - alarmTotalCount = this.props.alarmStatus.critical + this.props.alarmStatus.major - + this.props.alarmStatus.minor + this.props.alarmStatus.warning; - } + const registrations = applicationService.applications; - /** Available Network Connection Status chart data */ - const connectionStatusData = { - labels: ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect'], - datasets: [{ - data: connectionStatusDataLoad, - backgroundColor: [ - 'rgb(0, 153, 51)', - 'rgb(255, 102, 0)', - 'rgb(191, 191, 191)', - 'rgb(191, 191, 191)' - ] - }] - }; + const [selectedIndex] = React.useState(0); + let settingsArray: SettingsEntry[] = []; - /** No Devices available */ - const connectionStatusUnavailableData = { - labels: ['No Devices available'], - datasets: [{ - data: [1], - backgroundColor: [ - 'rgb(255, 255, 255)' - ] - }] - }; - - /** Loading Connection Status chart */ - const connectionStatusisLoading = { - labels: ['Loading chart...'], - datasets: [{ - data: [1], - backgroundColor: [ - 'rgb(255, 255, 255)' - ] - }] - }; - - /** Loading Alarm Status chart */ - const alarmStatusisLoading = { - labels: ['Loading chart...'], - datasets: [{ - data: [1], - backgroundColor: [ - 'rgb(255, 255, 255)' - ] - }] - }; - - /** Connection status options */ - let labels: String[] = ['Connected', 'Connecting', 'Disconnected', 'UnableToConnect']; - const connectionStatusOptions = { - responsive: true, - maintainAspectRatio: false, - animation: { - duration: 0 - }, - plugins: { - legend: { - display: true, - position: 'top' - } - }, - onClick: (event: MouseEvent, item: any) => { - if (item[0]) { - let connectionStatus = labels[item[0].index] + ''; - this.props.navigateToApplication("connect", '/connectionStatus/' + connectionStatus); - } - } - } - - /** Connection status unavailable options */ - const connectionStatusUnavailableOptions = { - responsive: true, - maintainAspectRatio: false, - animation: { - duration: 0 - }, - plugins: { - legend: { - display: true, - position: 'top' - }, - tooltip: { - enabled: false - } - } - } + let settingsElements: (SettingsEntry)[] = Object.keys(registrations).map(p => { + const application = registrations[p]; - /** Add text inside the doughnut chart for Connection Status */ - const connectionStatusPlugins = [{ - beforeDraw: function (chart: any) { - var width = chart.width, - height = chart.height, - ctx = chart.ctx; - ctx.restore(); - var fontSize = (height / 480).toFixed(2); - ctx.font = fontSize + "em sans-serif"; - ctx.textBaseline = "top"; - var text = "Network Connection Status", - textX = Math.round((width - ctx.measureText(text).width) / 2), - textY = height / 2; - ctx.fillText(text, textX, textY); - ctx.save(); - } - }] + if (application.dashbaordElement) { + const value: SettingsEntry = { name: application.menuEntry?.toString()!, element: <application.dashbaordElement /> }; + return value; - /** Alarm status Data */ - const alarmStatusData = { - labels: [ - 'Critical', - 'Major', - 'Minor', - 'Warning' - ], - datasets: [{ - data: alarmStatusDataLoad, - backgroundColor: [ - 'rgb(240, 25, 10)', - 'rgb(240, 133, 10)', - 'rgb(240, 240, 10)', - 'rgb(46, 115, 176)' - ], - }] - } - - /** No Alarm status available */ - const alarmStatusUnavailableData = { - labels: ['No Alarms available'], - datasets: [{ - data: [1], - backgroundColor: [ - 'rgb(0, 153, 51)' - ] - }] - }; - - /** Alarm status Options */ - let alarmLabels: String[] = ['Critical', 'Major', 'Minor', 'Warning']; - const alarmStatusOptions = { - responsive: true, - maintainAspectRatio: false, - animation: { - duration: 0 - }, - plugins: { - legend: { - display: true, - position: 'top' - } - }, - onClick: (event: MouseEvent, item: any) => { - if (item[0]) { - let severity = alarmLabels[item[0].index] + ''; - this.props.navigateToApplication("fault", '/alarmStatus/' + severity); - } - }, - }; - - /** Alarm status unavailable options */ - const alarmStatusUnavailableOptions = { - responsive: true, - maintainAspectRatio: false, - animation: { - duration: 0 - }, - plugins: { - legend: { - display: true, - position: 'top' - }, - tooltip: { - enabled: false - } - } - } - /** Add text inside the doughnut chart for Alarm Status */ - const alarmStatusPlugins = [{ - beforeDraw: function (chart: any) { - var width = chart.width, - height = chart.height, - ctx = chart.ctx; - ctx.restore(); - var fontSize = (height / 480).toFixed(2); - ctx.font = fontSize + "em sans-serif"; - ctx.textBaseline = "top"; - var text = "Network Alarm Status", - textX = Math.round((width - ctx.measureText(text).width) / 2), - textY = height / 2; - ctx.fillText(text, textX, textY); - ctx.save(); - } - }] - - return ( - <> - <div style={scrollbar} > - <h1>Welcome to ODLUX</h1> - <div className={classes.pageWidthSettings}> - {this.checkElementsAreLoaded() ? - this.checkConnectionStatus() && connectionTotalCount != 0 ? - <Doughnut - data={connectionStatusData} - type={Doughnut} - width={500} - height={500} - options={connectionStatusOptions} - plugins={connectionStatusPlugins} - /> - : <Doughnut - data={connectionStatusUnavailableData} - type={Doughnut} - width={500} - height={500} - options={connectionStatusUnavailableOptions} - plugins={connectionStatusPlugins} /> - : <Doughnut - data={connectionStatusisLoading} - type={Doughnut} - width={500} - height={500} - options={connectionStatusUnavailableOptions} - plugins={connectionStatusPlugins} - /> - } - </div> - <div className={classes.pageWidthSettings}> - {this.checkAlarmsAreLoaded() ? - this.checkAlarmStatus() && alarmTotalCount != 0 ? - <Doughnut - data={alarmStatusData} - type={Doughnut} - width={500} - height={500} - options={alarmStatusOptions} - plugins={alarmStatusPlugins} - /> - : <Doughnut - data={alarmStatusUnavailableData} - type={Doughnut} - width={500} - height={500} - options={alarmStatusUnavailableOptions} - plugins={alarmStatusPlugins} - /> - : <Doughnut - data={alarmStatusisLoading} - type={Doughnut} - width={500} - height={500} - options={alarmStatusUnavailableOptions} - plugins={alarmStatusPlugins} - /> - } - </div> - </div> - </> - ) - } - - /** Check if connection status data available */ - public checkConnectionStatus = () => { - let statusCount = this.props.connectionStatusCount; - if (statusCount.isLoadingConnectionStatusChart) { - return true; - } - if (statusCount.Connected == 0 && statusCount.Connecting == 0 && statusCount.Disconnected == 0 - && statusCount.UnableToConnect == 0) { - return false; } else { - return true; + return null; } - } + }).filter((x): x is SettingsEntry => x !== null); - /** Check if connection status chart data is loaded */ - public checkElementsAreLoaded = () => { - let isLoadingCheck = this.props.connectionStatusCount; - if (connectionStatusinitialLoad && !isLoadingCheck.isLoadingConnectionStatusChart) { - if (this.checkConnectionStatus()) { - connectionStatusinitialLoad = false; - return true; - } - return false; - } else if (connectionStatusinitialLoad && isLoadingCheck.isLoadingConnectionStatusChart) { - connectionStatusinitialLoad = false; - connectionStatusinitialStateChanged = true; - return !isLoadingCheck.isLoadingConnectionStatusChart; - } else if (connectionStatusinitialStateChanged) { - if (!isLoadingCheck.isLoadingConnectionStatusChart) { - connectionStatusinitialStateChanged = false; - } - return !isLoadingCheck.isLoadingConnectionStatusChart; - } - return true; - } - /** Check if alarms data available */ - public checkAlarmStatus = () => { - let alarmCount = this.props.alarmStatus; - if (alarmCount.isLoadingAlarmStatusChart) { - return true; - } - if (alarmCount.critical == 0 && alarmCount.major == 0 && alarmCount.minor == 0 && alarmCount.warning == 0) { - return false; - } - else { - return true; - } - } + settingsArray.push(...settingsElements); - /** Check if alarm status chart data is loaded */ - public checkAlarmsAreLoaded = () => { - let isLoadingCheck = this.props.alarmStatus; - if (alarmStatusinitialLoad && !isLoadingCheck.isLoadingAlarmStatusChart) { - if (this.checkAlarmStatus()) { - alarmStatusinitialLoad = false; - return true; - } - return false; - } else if (alarmStatusinitialLoad && isLoadingCheck.isLoadingAlarmStatusChart) { - alarmStatusinitialLoad = false; - alarmStatusinitialStateChanged = true; - return !isLoadingCheck.isLoadingAlarmStatusChart; - } else if (alarmStatusinitialStateChanged) { - if (!isLoadingCheck.isLoadingAlarmStatusChart) { - alarmStatusinitialStateChanged = false; - } - return !isLoadingCheck.isLoadingAlarmStatusChart; - } - return true; - } + return <div> + <div> + <div> + { + settingsArray[selectedIndex]?.element + } + </div> + </div> + </div> } -export default withStyles(styles)(withRouter(connect(mapProps, mapDispatch)(Home)));
\ No newline at end of file + +export default connect(mapProps, mapDispatch)(DashboardView); diff --git a/sdnr/wt/odlux/framework/src/views/login.tsx b/sdnr/wt/odlux/framework/src/views/login.tsx index 53219facd..8eb7a6c0f 100644 --- a/sdnr/wt/odlux/framework/src/views/login.tsx +++ b/sdnr/wt/odlux/framework/src/views/login.tsx @@ -18,19 +18,23 @@ import * as React from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; -import Alert from '@material-ui/lab/Alert'; -import Avatar from '@material-ui/core/Avatar'; -import Button from '@material-ui/core/Button'; -import CssBaseline from '@material-ui/core/CssBaseline'; -import FormControl from '@material-ui/core/FormControl'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import Checkbox from '@material-ui/core/Checkbox'; -import Input from '@material-ui/core/Input'; -import InputLabel from '@material-ui/core/InputLabel'; -import LockIcon from '@material-ui/icons/LockOutlined'; -import Paper from '@material-ui/core/Paper'; -import Typography from '@material-ui/core/Typography'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import Alert from '@mui/material/Alert'; +import Avatar from '@mui/material/Avatar'; +import Button from '@mui/material/Button'; +import CssBaseline from '@mui/material/CssBaseline'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Checkbox from '@mui/material/Checkbox'; +import Input from '@mui/material/Input'; +import InputLabel from '@mui/material/InputLabel'; +import LockIcon from '@mui/icons-material/LockOutlined'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; +import { Theme } from '@mui/material/styles'; + +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; import connect, { Connect, IDispatcher } from '../flux/connect'; import authenticationService from '../services/authenticationService'; @@ -40,8 +44,8 @@ import { loginUserAction, UpdatePolicies } from '../actions/authentication'; import { IApplicationStoreState } from '../store/applicationStore'; import { AuthPolicy, AuthToken, User } from '../models/authentication'; -import Menu from '@material-ui/core/Menu'; -import { MenuItem } from '@material-ui/core'; +import Menu from '@mui/material/Menu'; +import { MenuItem } from '@mui/material'; const styles = (theme: Theme) => createStyles({ layout: { @@ -49,7 +53,7 @@ const styles = (theme: Theme) => createStyles({ display: 'block', // Fix IE11 issue. marginLeft: theme.spacing(3), marginRight: theme.spacing(3), - [theme.breakpoints.up(400 + theme.spacing(3) * 2)]: { + [theme.breakpoints.up(400 + Number(theme.spacing(3).replace('px','')) * 2)]: { width: 400, marginLeft: 'auto', marginRight: 'auto', @@ -60,7 +64,7 @@ const styles = (theme: Theme) => createStyles({ display: 'flex', flexDirection: 'column', alignItems: 'center', - padding: `${theme.spacing(2)}px ${theme.spacing(3)}px ${theme.spacing(3)}px`, + padding: `${theme.spacing(2)} ${theme.spacing(3)} ${theme.spacing(3)}`, }, avatar: { margin: theme.spacing(1), @@ -175,7 +179,7 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> { aria-haspopup="true" fullWidth variant="contained" - color="primary" + color="inherit" className={classes.submit} onClick={() => { window.location = provider.loginUrl as any; }}> {provider.title} </Button>)) @@ -189,14 +193,14 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> { </> } - <FormControl margin="normal" required fullWidth> + <FormControl variant="standard" margin="normal" required fullWidth> <InputLabel htmlFor="username">Username</InputLabel> <Input id="username" name="username" autoComplete="username" autoFocus disabled={this.state.busy} value={this.state.username} onChange={event => { this.setState({ username: event.target.value }) }} /> </FormControl> - <FormControl margin="normal" required fullWidth> + <FormControl variant="standard" margin="normal" required fullWidth> <InputLabel htmlFor="password">Password</InputLabel> <Input name="password" @@ -208,7 +212,7 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> { onChange={event => { this.setState({ password: event.target.value }) }} /> </FormControl> - <FormControl margin="normal" required fullWidth> + <FormControl variant="standard" margin="normal" required fullWidth> <InputLabel htmlFor="password">Domain</InputLabel> <Input name="scope" @@ -224,7 +228,7 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> { type="submit" fullWidth variant="contained" - color="primary" + color="inherit" disabled={this.state.busy} className={classes.submit} onClick={this.onSignIn} diff --git a/sdnr/wt/odlux/framework/src/views/settings.tsx b/sdnr/wt/odlux/framework/src/views/settings.tsx index f1a8ab35a..a6b940bfa 100644 --- a/sdnr/wt/odlux/framework/src/views/settings.tsx +++ b/sdnr/wt/odlux/framework/src/views/settings.tsx @@ -21,8 +21,8 @@ import { IApplicationStoreState } from "../store/applicationStore"; import connect, { Connect, IDispatcher } from "../flux/connect"; import applicationService from '../services/applicationManager'; -import { makeStyles } from '@material-ui/styles'; -import { Divider, List, ListItem, ListItemText, Paper } from '@material-ui/core'; +import { makeStyles } from '@mui/styles'; +import { Divider, List, ListItem, ListItemText, Paper } from '@mui/material'; import { GeneralUserSettings } from '../components/settings/general' import { GoBackAction } from '../actions/navigationActions'; diff --git a/sdnr/wt/odlux/framework/src/views/test.tsx b/sdnr/wt/odlux/framework/src/views/test.tsx index 763b79a1f..84c4094c3 100644 --- a/sdnr/wt/odlux/framework/src/views/test.tsx +++ b/sdnr/wt/odlux/framework/src/views/test.tsx @@ -18,17 +18,21 @@ import * as React from 'react'; import { withComponents, WithComponents } from '../utilities/withComponents'; -import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; +import { Theme } from '@mui/material/styles'; -import ExpansionPanel from '@material-ui/core/ExpansionPanel'; -import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'; -import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails'; -import Typography from '@material-ui/core/Typography'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { WithStyles } from '@mui/styles'; +import withStyles from '@mui/styles/withStyles'; +import createStyles from '@mui/styles/createStyles'; + +import Accordion from '@mui/material/Accordion'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import Typography from '@mui/material/Typography'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { MaterialTable, MaterialTableCtorType, ColumnType } from '../components/material-table'; import { TreeView, TreeItem, TreeViewCtorType } from '../components/material-ui/treeView'; -import { SvgIconProps } from '@material-ui/core/SvgIcon'; +import { SvgIconProps } from '@mui/material/SvgIcon'; const styles = (theme: Theme) => createStyles({ root: { @@ -839,11 +843,11 @@ const TestComponent = (props: WithComponents<typeof components> & WithStyles<typ return ( <div> <h2>About</h2> - <ExpansionPanel> - <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Accordion> + <AccordionSummary expandIcon={<ExpandMoreIcon />}> <Typography className={props.classes.heading}>Client Side Table Demo</Typography> - </ExpansionPanelSummary> - <ExpansionPanelDetails> + </AccordionSummary> + <AccordionDetails> <SampleDataMaterialTable rows={tableData} columns={ [ { property: "index", type: ColumnType.text, title: "Index", width: "80px", disableFilter: true, disableSorting: true }, @@ -855,16 +859,16 @@ const TestComponent = (props: WithComponents<typeof components> & WithStyles<typ ] } idProperty={"_id"} title={"Customers 2018"} > </SampleDataMaterialTable> - </ExpansionPanelDetails> - </ExpansionPanel> - <ExpansionPanel> - <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + </AccordionDetails> + </Accordion> + <Accordion> + <AccordionSummary expandIcon={<ExpandMoreIcon />}> <Typography className={props.classes.heading}>Tree Demo</Typography> - </ExpansionPanelSummary> - <ExpansionPanelDetails> + </AccordionSummary> + <AccordionDetails> <SampleTree items={treeData} useFolderIcons enableSearchBar /> - </ExpansionPanelDetails> - </ExpansionPanel> + </AccordionDetails> + </Accordion> </div> ); }; |