aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/framework/src/components
diff options
context:
space:
mode:
authorMichael Dürre <michael.duerre@highstreet-technologies.com>2022-09-08 09:45:06 +0200
committerMichael Dürre <michael.duerre@highstreet-technologies.com>2022-09-08 09:46:47 +0200
commita2b6dd34d73bf432846dc59c6f57dd59a03aff9b (patch)
tree35658e382769bc7575f87d0e9580d6ee98230eb2 /sdnr/wt/odlux/framework/src/components
parent6f9c3d2cea04a2af7a73d8df1de87d584b277552 (diff)
update odlux sources
update basic odlux functionality for kohn Issue-ID: CCSDK-3765 Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com> Change-Id: I3723c9c2f35b9012ba537920b294a54bb556cbc6 Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
Diffstat (limited to 'sdnr/wt/odlux/framework/src/components')
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts1
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/index.tsx51
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx188
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx7
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx14
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx36
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/utilities.ts40
-rw-r--r--sdnr/wt/odlux/framework/src/components/navigationMenu.tsx11
-rw-r--r--sdnr/wt/odlux/framework/src/components/titleBar.tsx8
9 files changed, 330 insertions, 26 deletions
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 ce5b2cd1e..3ed313497 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
+++ b/sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
@@ -37,6 +37,7 @@ export type ColumnModel<TData> = {
disablePadding?: boolean;
width?: string | number ;
className?: string;
+ hide?: boolean;
style?: React.CSSProperties;
align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
disableSorting?: boolean;
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 aac2a1252..8541cfe56 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
@@ -36,7 +36,7 @@ import { EnhancedTableHead } from './tableHead';
import { EnhancedTableFilter } from './tableFilter';
import { ColumnModel, ColumnType } from './columnModel';
-import { Menu } from '@mui/material';
+import { Menu, Typography } from '@mui/material';
import { DistributiveOmit } from '@mui/types';
import makeStyles from '@mui/styles/makeStyles';
@@ -151,19 +151,23 @@ export type MaterialTableComponentState<TData = {}> = {
rowsPerPage: number;
loading: boolean;
showFilter: boolean;
+ hiddenColumns: string[];
filter: { [property: string]: string };
};
export type TableApi = { forceRefresh?: () => Promise<void> };
-type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
+type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
className?: string;
columns: ColumnModel<TData>[];
idProperty: keyof TData | ((data: TData) => React.Key);
- tableId?: string;
+
+ //Note: used to save settings as well. Must be unique across apps. Null tableIds will not get saved to the settings
+ tableId: string | null;
isPopup?: boolean;
title?: string;
stickyHeader?: boolean;
+ allowHtmlHeader?: boolean;
defaultSortOrder?: 'asc' | 'desc';
defaultSortColumn?: keyof TData;
enableSelection?: boolean;
@@ -182,6 +186,8 @@ type MaterialTableComponentPropsWithExternalState<TData = {}> = MaterialTableCom
onHandleChangePage: (page: number) => void;
onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
onHandleRequestSort: (property: string) => void;
+ onHideColumns : (columnNames: string[]) => void
+ onShowColumns: (columnNames: string[]) => void
};
type MaterialTableComponentProps<TData = {}> =
@@ -203,13 +209,18 @@ function isMaterialTableComponentPropsWithRowsAndRequestData(props: MaterialTabl
propsWithExternalState.onHandleChangePage instanceof Function ||
propsWithExternalState.onHandleChangeRowsPerPage instanceof Function ||
propsWithExternalState.onToggleFilter instanceof Function ||
+ propsWithExternalState.onHideColumns instanceof Function ||
propsWithExternalState.onHandleRequestSort instanceof Function
}
+// get settings in here!
+
+
class MaterialTableComponent<TData extends {} = {}> extends React.Component<MaterialTableComponentProps, MaterialTableComponentState & { contextMenuInfo: { index: number; mouseX?: number; mouseY?: number }; }> {
constructor(props: MaterialTableComponentProps) {
super(props);
+
const page = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.page : 0;
const rowsPerPage = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.rowsPerPage || 10 : 10;
@@ -224,6 +235,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
selected: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.selected : null,
rows: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) || [],
total: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.length || 0,
+ hiddenColumns: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) && this.props.hiddenColumns || [],
page,
rowsPerPage,
};
@@ -237,18 +249,27 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
}
}
render(): JSX.Element {
- const { classes, columns } = this.props;
+ const { classes, columns, allowHtmlHeader } = this.props;
const { rows, total: rowCount, order, orderBy, selected, rowsPerPage, page, showFilter, filter } = this.state;
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rowCount - page * rowsPerPage);
const getId = typeof this.props.idProperty !== "function" ? (data: TData) => ((data as { [key: string]: any })[this.props.idProperty as any as string] as string | number) : this.props.idProperty;
const toggleFilter = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onToggleFilter : () => { !this.props.disableFilter && this.setState({ showFilter: !showFilter }, this.update) }
+
+ const hideColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onHideColumns : (data: string[]) => { const newArray = [...new Set([...this.state.hiddenColumns, ...data])]; this.setState({hiddenColumns:newArray}); }
+ const showColumns = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onShowColumns : (data: string[]) => { const newArray = this.state.hiddenColumns.filter(el=> !data.includes(el)); this.setState({hiddenColumns:newArray}); }
+
+ const allColumnsHidden = this.props.columns.length === this.state.hiddenColumns.length;
return (
<Paper className={this.props.className ? `${classes.root} ${this.props.className}` : classes.root}>
<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} />
+ onToggleFilter={toggleFilter}
+ columns={columns}
+ onHideColumns={hideColumns}
+ onShowColumns={showColumns} />
<Table padding="normal" aria-label={this.props.tableId ? this.props.tableId : 'tableTitle'} stickyHeader={this.props.stickyHeader || false} >
<EnhancedTableHead
+ allowHtmlHeader={allowHtmlHeader || false}
columns={columns}
numSelected={selected && selected.length}
order={order}
@@ -257,10 +278,14 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
onRequestSort={this.onHandleRequestSort}
rowCount={rows.length}
enableSelection={this.props.enableSelection}
+ hiddenColumns={this.state.hiddenColumns}
/>
<TableBody>
- {showFilter && <EnhancedTableFilter columns={columns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
- {rows // may need ordering here
+ {showFilter && <EnhancedTableFilter columns={columns} hiddenColumns={this.state.hiddenColumns} filter={filter} onFilterChanged={this.onFilterChanged} enableSelection={this.props.enableSelection} /> || null}
+
+ {allColumnsHidden ? <Typography variant="body1" textAlign="center">All columns of this table are hidden.</Typography> :
+
+ rows // may need ordering here
.map((entry: TData & { [RowDisabled]?: boolean, [kex: string]: any }, index) => {
const entryId = getId(entry);
const contextMenu = (this.props.createContextMenu && this.state.contextMenuInfo.index === index && this.props.createContextMenu(entry)) || null;
@@ -295,15 +320,17 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
>
{this.props.enableSelection
? <TableCell padding="checkbox" style={{ width: "50px", color: entry[RowDisabled] || false ? "inherit" : undefined } }>
- <Checkbox checked={isSelected} />
+ <Checkbox color='secondary' checked={isSelected} />
</TableCell>
: null
}
{
+
this.props.columns.map(
col => {
const style = col.width ? { width: col.width } : {};
- return (
+ const tableCell = (
+
<TableCell style={ entry[RowDisabled] || false ? { ...style, color: "inherit" } : style } aria-label={col.title? toAriaLabel(col.title) : toAriaLabel(col.property)} key={col.property} align={col.type === ColumnType.numeric && !col.align ? "right" : col.align} >
{col.type === ColumnType.custom && col.customControl
? <col.customControl className={col.className} style={col.style} rowData={entry} />
@@ -313,6 +340,10 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
}
</TableCell>
);
+
+ //show column if...
+ const showColumn = !this.state.hiddenColumns.includes(col.property);
+ return showColumn && tableCell
}
)
}
@@ -352,6 +383,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
}
static getDerivedStateFromProps(props: MaterialTableComponentProps, state: MaterialTableComponentState & { _rawRows: {}[] }): MaterialTableComponentState & { _rawRows: {}[] } {
+
if (isMaterialTableComponentPropsWithRowsAndRequestData(props)) {
return {
...state,
@@ -363,6 +395,7 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
loading: props.loading,
showFilter: props.showFilter,
page: props.page,
+ hiddenColumns: props.hiddenColumns,
rowsPerPage: props.rowsPerPage
}
} else if (isMaterialTableComponentPropsWithRows(props) && props.asynchronus && state._rawRows !== props.rows) {
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx b/sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx
new file mode 100644
index 000000000..f8ae6ea97
--- /dev/null
+++ b/sdnr/wt/odlux/framework/src/components/material-table/showColumnDialog.tsx
@@ -0,0 +1,188 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2022 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 { Button, Checkbox, FormControlLabel, MenuItem, Popover, Switch, Typography } from '@mui/material';
+import connect, { Connect, IDispatcher } from '../../flux/connect';
+import * as React from 'react';
+
+import { ColumnModel } from './columnModel';
+import { IApplicationStoreState } from '../../store/applicationStore';
+import { TableSettingsColumn } from '../../models/settings';
+import { updateTableSettings } from '../../actions/settingsAction';
+
+const mapStateToProps = (state: IApplicationStoreState) => ({
+ settings: state.framework.applicationState.settings,
+ settingsDoneLoading: state.framework.applicationState.settings.isInitialLoadDone
+});
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+ saveToSettings: (tableName: string, columns: TableSettingsColumn[]) => dispatcher.dispatch(updateTableSettings(tableName, columns))
+})
+
+type DialogProps = {
+ columns: ColumnModel<{}>[],
+ settingsName: string | null,
+ anchorEl: HTMLElement | null;
+ hideColumns: (columnNames: string[]) => void
+ showColumns: (columnNames: string[]) => void
+ onClose(): void
+
+} & Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
+ //TODO: figure out why everything gets triggered twice...
+
+const ShowColumnsDialog: React.FunctionComponent<DialogProps> = (props) => {
+
+ const savedSettings = props.settingsName && props.settings.tables[props.settingsName];
+
+ const [checkedColumns, setCheckedColumns] = React.useState<{ property: string, display: boolean, title: string | undefined }[]>([]);
+
+ const open = Boolean(props.anchorEl);
+ const allColumnNames = props.columns.map(e => e.property);
+
+ React.useEffect(() => {
+
+ createHideShowSelection();
+
+ }, []);
+
+ React.useEffect(() => {
+
+ createHideShowSelection();
+
+ }, [props.settings.isInitialLoadDone]);
+
+
+ const createHideShowSelection = () => {
+ let columns = props.columns.map(e => { return { property: e.property, display: !Boolean(e.hide), title: e.title } });
+
+
+ if (savedSettings) {
+
+ if (columns.length !== savedSettings.columns.length) {
+ console.error("saved column length does not match current column length. Maybe a settings entry got wrongly overridden?")
+ }
+
+ //overwrite column data with settings
+ savedSettings?.columns.forEach(el => {
+ let foundIndex = columns.findIndex(e => e.property == el.property);
+ if (columns[foundIndex] !== undefined)
+ columns[foundIndex].display = el.displayed;
+ });
+
+ } else {
+ console.warn("No settingsName set, changes will not be saved.")
+ }
+
+ setCheckedColumns(columns);
+
+ const hideColumns = columns.filter(el => !el.display).map(e => e.property);
+ props.hideColumns(hideColumns);
+ }
+
+
+ const handleChange = (propertyName: string, checked: boolean) => {
+ if (!checked) {
+ props.hideColumns([propertyName]);
+ } else {
+ props.showColumns([propertyName])
+
+ }
+
+ let updatedList = checkedColumns.map(item => {
+ if (item.property == propertyName) {
+ return { ...item, display: checked };
+ }
+ return item;
+ });
+
+ setCheckedColumns(updatedList);
+ };
+
+ const onHideAll = () => {
+
+ switchCheckedColumns(false);
+ props.hideColumns(allColumnNames);
+ }
+
+ const onShowAll = () => {
+
+ switchCheckedColumns(true);
+ props.showColumns(allColumnNames);
+ }
+
+ const onClose = () => {
+
+ const tableColumns: TableSettingsColumn[] = checkedColumns.map(el => {
+ return {
+ property: el.property,
+ displayed: el.display
+ }
+ });
+
+ if (props.settingsName) {
+ props.saveToSettings(props.settingsName, tableColumns);
+ }
+ props.onClose();
+
+ }
+
+ const switchCheckedColumns = (changeToValue: boolean) => {
+ let updatedList = checkedColumns.map(item => {
+ return { ...item, display: changeToValue };
+ });
+
+ setCheckedColumns(updatedList);
+
+ }
+
+ return (<Popover open={open} onClose={onClose}
+ anchorEl={props.anchorEl}
+ anchorOrigin={{
+ vertical: 'top',
+ horizontal: 'left',
+ }} >
+ <div>
+ <Typography fontWeight={600} style={{ margin: 10 }} >Hide / Show Columns</Typography>
+ </div>
+ <div style={{ display: "flex", flexDirection: "column", margin: 10 }}>
+ {
+ checkedColumns?.map((el, i) => {
+
+ return <>
+
+ <FormControlLabel
+ value="end"
+ key={"hide-show-column-"+i}
+ aria-label={"hide-or-show-column-button"}
+ control={<Switch color="secondary" checked={el.display} onChange={e => handleChange(el.property, e.target.checked)} />}
+ label={el.title || el.property}
+ labelPlacement="end"
+ />
+ </>
+ })
+ }
+ <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between" }}>
+ <Button color="secondary" aria-label="hide-all-columns-button" onClick={(e) => onHideAll()}>Hide all</Button>
+ <Button color="secondary" aria-label="show-all-columns-button" onClick={(e) => onShowAll()}>Show all</Button>
+ </div>
+ </div>
+ </Popover>)
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ShowColumnsDialog);
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 a46dd18d8..1b9136844 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -50,6 +50,7 @@ interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
onFilterChanged: (property: string, filterTerm: string) => void;
filter: { [property: string]: string };
columns: ColumnModel<{}>[];
+ hiddenColumns: string[];
enableSelection?: boolean;
}
@@ -73,7 +74,7 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
}
{columns.map((col, ind) => {
const style = col.width ? { width: col.width } : {};
- return (
+ const tableCell = (
<TableCell
className={col.type === ColumnType.numeric ? classes.numberInput : ''}
key={col.property}
@@ -99,6 +100,10 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
onChange={this.createInputFilterHandler(col.property)} />}
</TableCell>
);
+
+ const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+ return showColumn && tableCell;
}, this)}
</TableRow>
);
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 c500f44ce..d6f7b7def 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableHead.tsx
@@ -50,7 +50,9 @@ interface IEnhancedTableHeadComponentProps extends styles_header {
orderBy: string | null;
rowCount: number;
columns: ColumnModel<{}>[];
+ hiddenColumns: string[];
enableSelection?: boolean;
+ allowHtmlHeader?: boolean;
}
class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadComponentProps> {
@@ -77,7 +79,7 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo
}
{ columns.map(col => {
const style = col.width ? { width: col.width } : {};
- return (
+ const tableCell = (
<TableCell className= {classes.header}
key={ col.property }
align={ col.type === ColumnType.numeric ? 'right' : 'left' }
@@ -102,11 +104,19 @@ class EnhancedTableHeadComponent extends React.Component<IEnhancedTableHeadCompo
direction={ order || undefined }
onClick={ this.createSortHandler(col.property) }
>
- { col.title || col.property }
+ {
+ this.props.allowHtmlHeader ? <div className="content" dangerouslySetInnerHTML={{__html: col.title || col.property}}></div>
+ : (col.title || col.property )
+ }
</TableSortLabel>
</Tooltip> }
</TableCell>
);
+
+ //show column if...
+ const showColumn = !this.props.hiddenColumns.includes(col.property);
+
+ return showColumn && tableCell;
}, this) }
</TableRow>
</TableHead>
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 426436d44..143b802a4 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx
@@ -33,6 +33,8 @@ import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import { SvgIconProps } from '@mui/material/SvgIcon';
import { Button } from '@mui/material';
+import { ColumnModel } from './columnModel';
+import ShowColumnsDialog from './showColumnDialog'
const styles = (theme: Theme) => createStyles({
root: {
@@ -69,18 +71,24 @@ const styles = (theme: Theme) => createStyles({
interface ITableToolbarComponentProps extends WithStyles<typeof styles> {
numSelected: number | null;
title?: string;
- tableId?: string;
+ tableId: string | null;
customActionButtons?: { icon: React.ComponentType<SvgIconProps>, tooltip?: string, ariaLabel: string, onClick: () => void, disabled?: boolean }[];
+ columns: ColumnModel<{}>[];
+ onHideColumns: (columnNames: string[]) => void
+ onShowColumns: (columnNames: string[]) => void
onToggleFilter: () => void;
onExportToCsv: () => void;
}
-class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null }> {
+class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, { anchorEl: EventTarget & HTMLElement | null, anchorElDialog: HTMLElement | null }> {
+
+
constructor(props: ITableToolbarComponentProps) {
super(props);
this.state = {
- anchorEl: null
+ anchorEl: null,
+ anchorElDialog: null
};
}
@@ -91,11 +99,22 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps,
private handleClose = () => {
this.setState({ anchorEl: null });
};
+
+ private showColumnsDialog = (event: React.MouseEvent<HTMLElement>) =>{
+ this.setState({ anchorElDialog: this.state.anchorEl });
+ }
+
+ private onCloseDialog = () =>{
+ this.setState({ anchorElDialog: null });
+
+ }
+
render() {
const { numSelected, classes } = this.props;
const open = !!this.state.anchorEl;
- const buttonPrefix = this.props.tableId !== undefined ? this.props.tableId : 'table';
+ const buttonPrefix = this.props.tableId !== null ? this.props.tableId : 'table';
return (
+ <>
<Toolbar className={`${classes.root} ${numSelected && numSelected > 0 ? classes.highlight : ''} `} >
<div className={classes.title}>
{numSelected && numSelected > 0 ? (
@@ -153,9 +172,18 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps,
<Menu id="menu-appbar" anchorEl={this.state.anchorEl} anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }} open={open} onClose={this.handleClose} >
<MenuItem aria-label="export-table-as-csv" onClick={(e) =>{ this.props.onExportToCsv(); this.handleClose()}}>Export as CSV</MenuItem>
+ <MenuItem aria-label="hide-show-table-columns" onClick={(e) =>{ this.showColumnsDialog(e); this.handleClose()}}>Hide/show columns</MenuItem>
</Menu>
</div>
</Toolbar>
+ <ShowColumnsDialog
+ anchorEl={this.state.anchorElDialog}
+ onClose={this.onCloseDialog}
+ settingsName={this.props.tableId}
+ columns={this.props.columns}
+ hideColumns={this.props.onHideColumns}
+ showColumns={this.props.onShowColumns} />
+ </>
);
}
}
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
index 544e14e01..f9015493f 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
+++ b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
@@ -28,6 +28,7 @@ export interface IExternalTableState<TData> {
order: 'asc' | 'desc';
orderBy: string | null;
selected: any[] | null;
+ hiddenColumns: string[]
rows: (TData & { [RowDisabled]?: boolean })[];
total: number;
page: number;
@@ -48,7 +49,9 @@ export type ExternalMethodes<TData> = {
onFilterChanged: (property: string, filterTerm: string) => void;
onHandleChangePage: (page: number) => void;
onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
- };
+ onHideColumns: (columnName: string[]) => void;
+ onShowColumns: (columnName: string[]) => void;
+ },
createPreActions: (dispatch: Dispatch, skipRefresh?: boolean) => {
onPreFilterChanged: (preFilter: {
[key: string]: string;
@@ -128,6 +131,18 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
}
}
+ class HideColumnsAction extends TableAction{
+ constructor(public property: string[]){
+ super();
+ }
+ }
+
+ class ShowColumnsAction extends TableAction{
+ constructor(public property: string[]){
+ super();
+ }
+ }
+
// #endregion
//#region Action Handler
@@ -135,6 +150,7 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
order: 'asc',
orderBy: null,
selected: null,
+ hiddenColumns:[],
rows: [],
total: 0,
page: 0,
@@ -208,6 +224,18 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
rowsPerPage: action.rowsPerPage
}
}
+ else if (action instanceof HideColumnsAction){
+
+ //merge arrays, remove duplicates
+ const newArray = [...new Set([...state.hiddenColumns, ...action.property])]
+ state = {...state, hiddenColumns: newArray};
+ }
+ else if(action instanceof ShowColumnsAction){
+
+ const newArray = state.hiddenColumns.filter(el=> !action.property.includes(el));
+ state = {...state, hiddenColumns: newArray};
+ }
+
return state;
}
@@ -290,6 +318,16 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
dispatch(new SetRowsPerPageAction(rowsPerPage || 10));
(!skipRefresh) && dispatch(reloadAction);
});
+ },
+ onHideColumns: (columnName: string[]) =>{
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new HideColumnsAction(columnName));
+ })
+ },
+ onShowColumns: (columnName: string[]) =>{
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new ShowColumnsAction(columnName));
+ })
}
// selected:
};
diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
index 1134e230b..195706d28 100644
--- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
+++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
@@ -64,9 +64,9 @@ const styles = (theme: Theme) => createStyles({
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
- width: theme.spacing(7) + 1,
+ width: theme.spacing(7),
[theme.breakpoints.up('sm')]: {
- width: theme.spacing(9) + 1,
+ width: theme.spacing(9),
},
},
drawer: {
@@ -101,7 +101,7 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
//collapse menu on mount if necessary
React.useEffect(()=>{
- if(isOpen && window.innerWidth < tabletWidthBreakpoint){
+ if(isOpen && window.innerWidth <= tabletWidthBreakpoint){
setResponsive(true);
dispatch(new MenuAction(false));
@@ -116,14 +116,12 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
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));
}
@@ -145,13 +143,14 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
let menuItems = state.framework.applicationRegistraion && Object.keys(state.framework.applicationRegistraion).map(key => {
const reg = state.framework.applicationRegistraion[key];
+ const icon = !reg.icon ? null :( typeof reg.icon === 'string' ? <img height={22} src={reg.icon} /> : <FontAwesomeIcon icon={reg.icon} /> )
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} />
+ icon={icon} />
) || null;
}) || null;
diff --git a/sdnr/wt/odlux/framework/src/components/titleBar.tsx b/sdnr/wt/odlux/framework/src/components/titleBar.tsx
index 7872e51da..19d3bdf74 100644
--- a/sdnr/wt/odlux/framework/src/components/titleBar.tsx
+++ b/sdnr/wt/odlux/framework/src/components/titleBar.tsx
@@ -131,6 +131,10 @@ class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLE
}
}
+ const stateIcon = state.framework.applicationState.icon;
+ const icon = !stateIcon ? null :( typeof stateIcon === 'string' ? <img className={classes.icon} height={22} src={stateIcon} /> : <FontAwesomeIcon className={classes.icon} icon={stateIcon} /> )
+
+
return (
<AppBar enableColorOnDark position="absolute" className={classes.appBar}>
<Toolbar>
@@ -144,9 +148,7 @@ class TitleBarComponent extends React.Component<TitleBarProps, { anchorEl: HTMLE
</IconButton>
<Logo />
<Typography variant="h6" color="inherit" >
- {state.framework.applicationState.icon
- ? (<FontAwesomeIcon className={classes.icon} icon={state.framework.applicationState.icon} />)
- : null}
+ {icon}
{state.framework.applicationState.title}
</Typography>
<div className={classes.grow}></div>