@gpa-gemstone/react-table
Version:
Table for GPA web applications
206 lines (205 loc) • 12.2 kB
JavaScript
"use strict";
// ******************************************************************************************************
// ConfigurableTable.tsx - Gbtc
//
// Copyright © 2021, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
// file except in compliance with the License. You may obtain a copy of the License at:
//
// http://opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 09/15/2021 - Christoph Lackner
// Generated original version of source code.
// ******************************************************************************************************
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ConfigurableTable;
const React = require("react");
const Table_1 = require("../Table/Table");
const gpa_symbols_1 = require("@gpa-gemstone/gpa-symbols");
const react_interactive_1 = require("@gpa-gemstone/react-interactive");
const react_portal_1 = require("react-portal");
const helper_functions_1 = require("@gpa-gemstone/helper-functions");
const react_forms_1 = require("@gpa-gemstone/react-forms");
const _ = require("lodash");
const ConfigurableColumn_1 = require("./ConfigurableColumn");
/**
* Table with modal to show and hide columns
*/
function ConfigurableTable(props) {
const getKeyMappings = () => {
var _a, _b, _c;
const updated = new Map();
const localKeys = (_c = (_b = localStorage.getItem((_a = props.LocalStorageKey) !== null && _a !== void 0 ? _a : '')) === null || _b === void 0 ? void 0 : _b.split(',')) !== null && _c !== void 0 ? _c : [];
if (localKeys[0] == '')
localKeys.pop(); // if localstorage is empty, set the array to an empty array. [''] by default
React.Children.forEach(props.children, (element) => {
var _a, _b;
if (!React.isValidElement(element))
return;
if (element.type === ConfigurableColumn_1.default) {
const key = element.props.Key;
const baseCol = {
Key: key,
Label: (_a = element.props.Label) !== null && _a !== void 0 ? _a : key,
Default: (_b = element.props.Default) !== null && _b !== void 0 ? _b : false,
Enabled: false,
}; // use local if it has anything
baseCol.Enabled = localKeys.length > 0 ? localKeys.includes(key) : isEnabled(baseCol);
updated.set(key, baseCol);
}
});
return updated;
};
const [showSettings, setShowSettings] = React.useState(false);
const [columns, setColumns] = React.useState(() => getKeyMappings());
const [hover, setHover] = React.useState(false);
const [guid] = React.useState((0, helper_functions_1.CreateGuid)());
const [widthDisabledAdd, setWidthDisabledAdd] = React.useState(false);
const handleReduceWidthCallback = React.useCallback((hiddenKeys) => {
if (hiddenKeys.length !== 0) {
setWidthDisabledAdd(true);
}
else {
setWidthDisabledAdd(false);
}
}, []);
React.useEffect(() => {
setColumns(() => getKeyMappings());
}, [props.children]);
React.useEffect(() => {
if (props.OnSettingsChange !== undefined)
props.OnSettingsChange(showSettings);
}, [showSettings]);
React.useEffect(() => {
saveLocal();
}, [columns]);
function saveLocal() {
if (props.LocalStorageKey === undefined)
return;
const currentState = localStorage.getItem(props.LocalStorageKey);
const allKeys = Array.from(columns.keys());
let currentKeys = [];
if (currentState !== null)
currentKeys = currentState.split(',');
currentKeys = currentKeys.filter((k) => !allKeys.includes(k));
const enabled = allKeys.filter((k) => { var _a; return (_a = columns.get(k)) === null || _a === void 0 ? void 0 : _a.Enabled; });
currentKeys.push(...enabled);
localStorage.setItem(props.LocalStorageKey, currentKeys.join(','));
}
function changeColumns(key) {
setColumns((d) => {
var _a, _b;
const u = _.cloneDeep(d);
const mapRef = u.get(key);
if (mapRef == null) {
console.error("Could not find reference for column " + key);
}
else
mapRef.Enabled = !((_b = (_a = u.get(key)) === null || _a === void 0 ? void 0 : _a.Enabled) !== null && _b !== void 0 ? _b : false);
return u;
});
}
function checkLocal(key) {
if (props.LocalStorageKey === undefined)
return false;
const keys = localStorage.getItem(props.LocalStorageKey);
if (keys === null)
return false;
const activeKeys = keys.split(',');
return activeKeys.includes(key !== null && key !== void 0 ? key : '');
}
/**
* Returns true if a column is enabled by default, required as sortKey, or was saved in the users preferences
* @param c Column to check
* @param useLocal If true, will not consider if key is in localstorage
*/
function isEnabled(c, useLocal = true) {
if (c == undefined)
return false;
const isDefault = c.Default === true;
const isSortKey = props.SortKey === c.Key;
const isInLocal = useLocal && checkLocal(c.Key);
return isSortKey || isInLocal || isDefault;
}
return (React.createElement(React.Fragment, null,
React.createElement(Table_1.Table, Object.assign({}, props, { LastColumn: React.createElement("div", { style: { marginLeft: -5, marginBottom: 12, cursor: 'pointer' }, onMouseEnter: () => setHover(true), onMouseLeave: () => setHover(false), id: guid + '-tooltip', onClick: () => setShowSettings(true) },
React.createElement(gpa_symbols_1.ReactIcons.Settings, null)), ReduceWidthCallback: handleReduceWidthCallback }), React.Children.map(props.children, (element) => {
var _a, _b;
if (!React.isValidElement(element))
return null;
if (element.type === ConfigurableColumn_1.default)
return ((_b = (_a = columns.get(element.props.Key)) === null || _a === void 0 ? void 0 : _a.Enabled) !== null && _b !== void 0 ? _b : false) ? element.props.children : null;
return element;
})),
React.createElement(react_forms_1.ToolTip, { Show: hover, Position: 'bottom', Target: guid + '-tooltip', Zindex: 99999 },
React.createElement("p", null, "Change Columns")),
props.SettingsPortal === undefined ? (React.createElement(react_interactive_1.Modal, { Title: 'Table Columns', Show: showSettings, ShowX: true, ShowCancel: false, ZIndex: props.ModalZIndex, CallBack: (conf) => {
setShowSettings(false);
if (conf)
setColumns((d) => {
const u = _.cloneDeep(d);
Array.from(d.keys()).forEach((k) => {
var _a;
const ref = u.get(k);
if (ref != null)
ref.Enabled = (_a = isEnabled(u.get(k), false)) !== null && _a !== void 0 ? _a : true;
});
return u;
});
}, ConfirmText: 'Reset Defaults', ConfirmBtnClass: 'btn-warning float-left' },
React.createElement(ColumnSelection, { columns: Array.from(columns.values()), onChange: changeColumns, sortKey: props.SortKey, disableAdd: widthDisabledAdd }))) : showSettings ? (React.createElement(react_portal_1.Portal, { node: document === null || document === void 0 ? void 0 : document.getElementById(props.SettingsPortal) },
React.createElement("div", { className: "card" },
React.createElement("div", { className: "card-header" },
React.createElement("h4", { className: "modal-title" }, "Table Columns"),
React.createElement("button", { type: "button", className: "close", onClick: () => setShowSettings(false) }, "\u00D7")),
React.createElement("div", { className: "card-body", style: { maxHeight: 'calc(100% - 210px)', overflowY: 'auto' } },
React.createElement(ColumnSelection, { columns: Array.from(columns.values()), onChange: changeColumns, sortKey: props.SortKey, disableAdd: widthDisabledAdd })),
React.createElement("div", { className: "card-footer" },
React.createElement("button", { type: "button", className: 'btn btn-primary float-left', onClick: () => {
setShowSettings(false);
setColumns((d) => {
const u = _.cloneDeep(d);
Array.from(d.keys()).forEach((k) => {
var _a;
const ref = u.get(k);
if (ref != null)
ref.Enabled = (_a = isEnabled(u.get(k), true)) !== null && _a !== void 0 ? _a : true;
});
return u;
});
} }, "Reset Defaults"))))) : null));
}
function ColumnSelection(props) {
const enabledCols = props.columns.filter((column) => column.Enabled);
const isOnlyOneEnabled = enabledCols.length === 1;
const helpMessage = (col) => {
if (col.Key === props.sortKey)
return 'The Table is currently sorted by this column, so it cannot be hidden.';
if (isOnlyOneEnabled && col.Enabled)
return 'The Table must have one column visible at all times, so it cannot be hidden.';
return undefined;
};
return (React.createElement(React.Fragment, null,
React.createElement("div", { className: "row" },
React.createElement("div", { className: "col-4" }, props.columns.map((c, i) => i % 3 == 0 ? (React.createElement(react_forms_1.CheckBox, { Label: c.Label, Field: 'Enabled', Record: c, Setter: () => props.onChange(c.Key), key: c.Key, Disabled: c.Key === props.sortKey ||
(props.disableAdd && !c.Enabled) ||
(isOnlyOneEnabled && c.Enabled), Help: helpMessage(c) })) : null)),
React.createElement("div", { className: "col-4" }, props.columns.map((c, i) => i % 3 == 1 ? (React.createElement(react_forms_1.CheckBox, { Label: c.Label, Field: 'Enabled', Record: c, Setter: () => props.onChange(c.Key), key: c.Key, Disabled: c.Key === props.sortKey ||
(props.disableAdd && !c.Enabled) ||
(isOnlyOneEnabled && c.Enabled), Help: helpMessage(c) })) : null)),
React.createElement("div", { className: "col-4" }, props.columns.map((c, i) => i % 3 == 2 ? (React.createElement(react_forms_1.CheckBox, { Label: c.Label, Field: 'Enabled', Record: c, Setter: () => props.onChange(c.Key), key: c.Key, Disabled: c.Key === props.sortKey ||
(props.disableAdd && !c.Enabled) ||
(isOnlyOneEnabled && c.Enabled), Help: helpMessage(c) })) : null))),
props.disableAdd ?
React.createElement(react_interactive_1.Alert, { Class: 'alert-primary', Style: { marginBottom: 0, marginTop: '0.5em' } }, "Additional columns disabled due to table size.")
: null));
}