Feature/table ui download data (#52)
* Created header for common functionalities in Table Widget * Client side searching added in Table Widget. Action created for server side searching also. * Columns visibility feature initial commit * Column visibility list added in Table Widget * Changed pagination designs in accordance with new layout. This enable user to jump page as well. * Using colors values from constants * Table widget pagination, numeric input page number clamped between 1 and total pages * Adding tool tip to truncated values in table widget. Added AutoToolTipComponent that adds tooltip when text is truncated. * Table data download changes. Added downlaod icon and button to table widget. * Table data download changes * Download table data as CSV implemented * table data download, unused code removed * Code review changes * code review changes Co-authored-by: Arpit Mohan <me@arpitmohan.com>
This commit is contained in:
parent
eabe496fbd
commit
4f47a8ad3f
5
app/client/src/assets/icons/control/download-table.svg
Executable file
5
app/client/src/assets/icons/control/download-table.svg
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path d="M16.125 8.36658C15.5583 5.49158 13.0333 3.33325 10 3.33325C7.59167 3.33325 5.5 4.69992 4.45833 6.69992C1.95 6.96658 0 9.09158 0 11.6666C0 14.4249 2.24167 16.6666 5 16.6666H15.8333C18.1333 16.6666 20 14.7999 20 12.4999C20 10.2999 18.2917 8.51658 16.125 8.36658ZM14.1667 10.8333L10 14.9999L5.83333 10.8333H8.33333V7.49992H11.6667V10.8333H14.1667Z" fill="#2E3D49"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 484 B |
|
|
@ -3,7 +3,25 @@ import { ColumnAction } from "components/propertyControls/ColumnActionSelectorCo
|
|||
import Table from "./Table";
|
||||
import { RenderMode, RenderModes } from "constants/WidgetConstants";
|
||||
import { debounce } from "lodash";
|
||||
import { getMenuOptions, renderActions, renderCell } from "./TableUtilities";
|
||||
import {
|
||||
getMenuOptions,
|
||||
getAllTableColumnKeys,
|
||||
} from "components/designSystems/appsmith/TableUtilities";
|
||||
|
||||
export enum ColumnTypes {
|
||||
CURRENCY = "currency",
|
||||
TIME = "time",
|
||||
DATE = "date",
|
||||
VIDEO = "video",
|
||||
IMAGE = "image",
|
||||
TEXT = "text",
|
||||
}
|
||||
|
||||
export interface TableColumnMetaProps {
|
||||
isHidden: boolean;
|
||||
format?: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface ReactTableColumnProps {
|
||||
Header: string;
|
||||
|
|
@ -12,6 +30,7 @@ export interface ReactTableColumnProps {
|
|||
minWidth: number;
|
||||
draggable: boolean;
|
||||
isHidden?: boolean;
|
||||
metaProperties?: TableColumnMetaProps;
|
||||
Cell: (props: any) => JSX.Element;
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +55,7 @@ export interface ColumnMenuSubOptionProps {
|
|||
|
||||
interface ReactTableComponentProps {
|
||||
widgetId: string;
|
||||
widgetName: string;
|
||||
searchKey: string;
|
||||
isDisabled?: boolean;
|
||||
isVisible?: boolean;
|
||||
|
|
@ -72,140 +92,12 @@ interface ReactTableComponentProps {
|
|||
handleResizeColumn: Function;
|
||||
handleReorderColumn: Function;
|
||||
searchTableData: (searchKey: any) => void;
|
||||
columns: ReactTableColumnProps[];
|
||||
}
|
||||
|
||||
const ReactTableComponent = (props: ReactTableComponentProps) => {
|
||||
let dragged = -1;
|
||||
const getAllTableColumnKeys = () => {
|
||||
const tableData: object[] = props.tableData;
|
||||
const columnKeys: string[] = [];
|
||||
for (let i = 0, tableRowCount = tableData.length; i < tableRowCount; i++) {
|
||||
const row = tableData[i];
|
||||
for (const key in row) {
|
||||
if (!columnKeys.includes(key)) {
|
||||
columnKeys.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return columnKeys;
|
||||
};
|
||||
|
||||
const reorderColumns = (columns: ReactTableColumnProps[]) => {
|
||||
const columnOrder = props.columnOrder || [];
|
||||
const reorderedColumns = [];
|
||||
const reorderedFlagMap: { [key: string]: boolean } = {};
|
||||
for (let index = 0; index < columns.length; index++) {
|
||||
const accessor = columnOrder[index];
|
||||
if (accessor) {
|
||||
const column = columns.filter((col: ReactTableColumnProps) => {
|
||||
return col.accessor === accessor;
|
||||
});
|
||||
if (column.length && !reorderedFlagMap[column[0].accessor]) {
|
||||
reorderedColumns.push(column[0]);
|
||||
reorderedFlagMap[column[0].accessor] = true;
|
||||
} else if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
} else if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
}
|
||||
if (reorderedColumns.length < columns.length) {
|
||||
for (let index = 0; index < columns.length; index++) {
|
||||
if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return reorderedColumns;
|
||||
};
|
||||
const getTableColumns = () => {
|
||||
const tableData: object[] = props.tableData;
|
||||
let columns: ReactTableColumnProps[] = [];
|
||||
const hiddenColumns: ReactTableColumnProps[] = [];
|
||||
if (tableData.length) {
|
||||
const columnKeys: string[] = getAllTableColumnKeys();
|
||||
for (let index = 0; index < columnKeys.length; index++) {
|
||||
const i = columnKeys[index];
|
||||
const columnName: string =
|
||||
props.columnNameMap && props.columnNameMap[i]
|
||||
? props.columnNameMap[i]
|
||||
: i;
|
||||
const columnType: { type: string; format?: string } =
|
||||
props.columnTypeMap && props.columnTypeMap[i]
|
||||
? props.columnTypeMap[i]
|
||||
: { type: "text" };
|
||||
const columnSize: number =
|
||||
props.columnSizeMap && props.columnSizeMap[i]
|
||||
? props.columnSizeMap[i]
|
||||
: 150;
|
||||
const isHidden =
|
||||
!!props.hiddenColumns && props.hiddenColumns.includes(i);
|
||||
const columnData = {
|
||||
Header: columnName,
|
||||
accessor: i,
|
||||
width: columnSize,
|
||||
minWidth: 60,
|
||||
draggable: true,
|
||||
isHidden: false,
|
||||
Cell: (props: any) => {
|
||||
return renderCell(
|
||||
props.cell.value,
|
||||
props.cell.row.index,
|
||||
columnType.type,
|
||||
isHidden,
|
||||
props.widgetId,
|
||||
columnType.format,
|
||||
);
|
||||
},
|
||||
};
|
||||
if (isHidden) {
|
||||
columnData.isHidden = true;
|
||||
hiddenColumns.push(columnData);
|
||||
} else {
|
||||
columns.push(columnData);
|
||||
}
|
||||
}
|
||||
columns = reorderColumns(columns);
|
||||
if (props.columnActions?.length) {
|
||||
columns.push({
|
||||
Header:
|
||||
props.columnNameMap && props.columnNameMap["actions"]
|
||||
? props.columnNameMap["actions"]
|
||||
: "Actions",
|
||||
accessor: "actions",
|
||||
width: 150,
|
||||
minWidth: 60,
|
||||
draggable: true,
|
||||
Cell: () => {
|
||||
return renderActions({
|
||||
columnActions: props.columnActions,
|
||||
onCommandClick: props.onCommandClick,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
if (hiddenColumns.length && props.renderMode === RenderModes.CANVAS) {
|
||||
columns = columns.concat(hiddenColumns);
|
||||
}
|
||||
}
|
||||
return columns;
|
||||
};
|
||||
|
||||
const tableColumns = React.useMemo(getTableColumns, [
|
||||
JSON.stringify({
|
||||
data: props.tableData,
|
||||
columnNameMap: props.columnNameMap,
|
||||
columnActions: props.columnActions,
|
||||
hiddenColumns: props.hiddenColumns,
|
||||
columnSizeMap: props.columnSizeMap,
|
||||
columnTypeMap: props.columnTypeMap,
|
||||
columnOrder: props.columnOrder,
|
||||
}),
|
||||
]);
|
||||
useEffect(() => {
|
||||
const headers = Array.prototype.slice.call(
|
||||
document.querySelectorAll(`#table${props.widgetId} .draggable-header`),
|
||||
|
|
@ -267,9 +159,9 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
e.preventDefault();
|
||||
let columnOrder = props.columnOrder;
|
||||
if (columnOrder === undefined) {
|
||||
columnOrder = getAllTableColumnKeys();
|
||||
columnOrder = props.columns.map(item => item.accessor);
|
||||
}
|
||||
const draggedColumn = tableColumns[dragged].accessor;
|
||||
const draggedColumn = props.columns[dragged].accessor;
|
||||
columnOrder.splice(dragged, 1);
|
||||
columnOrder.splice(i, 0, draggedColumn);
|
||||
props.handleReorderColumn(columnOrder);
|
||||
|
|
@ -281,7 +173,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
});
|
||||
|
||||
const getColumnMenu = (columnIndex: number) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnId = column.accessor;
|
||||
const columnType =
|
||||
props.columnTypeMap && props.columnTypeMap[columnId]
|
||||
|
|
@ -308,7 +200,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
};
|
||||
|
||||
const hideColumn = (columnIndex: number, isColumnHidden: boolean) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
let hiddenColumns = props.hiddenColumns || [];
|
||||
if (!isColumnHidden) {
|
||||
hiddenColumns.push(column.accessor);
|
||||
|
|
@ -326,7 +218,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
};
|
||||
|
||||
const updateColumnType = (columnIndex: number, columnType: string) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnTypeMap = props.columnTypeMap || {};
|
||||
columnTypeMap[column.accessor] = {
|
||||
type: columnType,
|
||||
|
|
@ -336,7 +228,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
};
|
||||
|
||||
const handleColumnNameUpdate = (columnIndex: number, columnName: string) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnNameMap = props.columnNameMap || {};
|
||||
columnNameMap[column.accessor] = columnName;
|
||||
props.updateColumnName(columnNameMap);
|
||||
|
|
@ -346,7 +238,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
columnIndex: number,
|
||||
currencySymbol: string,
|
||||
) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnTypeMap = props.columnTypeMap || {};
|
||||
columnTypeMap[column.accessor] = {
|
||||
type: "currency",
|
||||
|
|
@ -356,7 +248,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
};
|
||||
|
||||
const handleDateFormatUpdate = (columnIndex: number, dateFormat: string) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnTypeMap = props.columnTypeMap || {};
|
||||
columnTypeMap[column.accessor] = {
|
||||
type: "date",
|
||||
|
|
@ -366,7 +258,7 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
};
|
||||
|
||||
const handleResizeColumn = (columnIndex: number, columnWidth: string) => {
|
||||
const column = tableColumns[columnIndex];
|
||||
const column = props.columns[columnIndex];
|
||||
const columnSizeMap = props.columnSizeMap || {};
|
||||
const width = Number(columnWidth.split("px")[0]);
|
||||
columnSizeMap[column.accessor] = width;
|
||||
|
|
@ -391,8 +283,9 @@ const ReactTableComponent = (props: ReactTableComponentProps) => {
|
|||
height={props.height}
|
||||
pageSize={props.pageSize || 1}
|
||||
widgetId={props.widgetId}
|
||||
widgetName={props.widgetName}
|
||||
searchKey={props.searchKey}
|
||||
columns={tableColumns}
|
||||
columns={props.columns}
|
||||
hiddenColumns={props.hiddenColumns}
|
||||
updateHiddenColumns={props.updateHiddenColumns}
|
||||
data={props.tableData}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ interface TableProps {
|
|||
height: number;
|
||||
pageSize: number;
|
||||
widgetId: string;
|
||||
widgetName: string;
|
||||
searchKey: string;
|
||||
isLoading: boolean;
|
||||
columns: ReactTableColumnProps[];
|
||||
|
|
@ -64,6 +65,9 @@ export const Table = (props: TableProps) => {
|
|||
const pageCount = Math.ceil(props.data.length / props.pageSize);
|
||||
const currentPageIndex = props.pageNo < pageCount ? props.pageNo : 0;
|
||||
const data = React.useMemo(() => props.data, [JSON.stringify(props.data)]);
|
||||
const columns = React.useMemo(() => props.columns, [
|
||||
JSON.stringify(props.columns),
|
||||
]);
|
||||
const {
|
||||
getTableProps,
|
||||
getTableBodyProps,
|
||||
|
|
@ -73,7 +77,7 @@ export const Table = (props: TableProps) => {
|
|||
pageOptions,
|
||||
} = useTable(
|
||||
{
|
||||
columns: props.columns,
|
||||
columns: columns,
|
||||
data,
|
||||
defaultColumn,
|
||||
initialState: {
|
||||
|
|
@ -103,6 +107,8 @@ export const Table = (props: TableProps) => {
|
|||
id={`table${props.widgetId}`}
|
||||
>
|
||||
<TableHeader
|
||||
tableData={props.data}
|
||||
tableColumns={props.columns}
|
||||
searchTableData={props.searchTableData}
|
||||
searchKey={props.searchKey}
|
||||
updatePageNo={props.updatePageNo}
|
||||
|
|
@ -112,6 +118,7 @@ export const Table = (props: TableProps) => {
|
|||
pageCount={pageCount}
|
||||
currentPageIndex={currentPageIndex}
|
||||
pageOptions={pageOptions}
|
||||
widgetName={props.widgetName}
|
||||
serverSidePaginationEnabled={props.serverSidePaginationEnabled}
|
||||
columns={props.columns.filter((column: ReactTableColumnProps) => {
|
||||
return column.accessor !== "actions";
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
PopoverInteractionKind,
|
||||
Position,
|
||||
Icon,
|
||||
Tooltip,
|
||||
} from "@blueprintjs/core";
|
||||
import { IconWrapper } from "constants/IconConstants";
|
||||
import styled from "styled-components";
|
||||
|
|
@ -12,19 +13,7 @@ import { Colors } from "constants/Colors";
|
|||
import { ReactComponent as VisibleIcon } from "assets/icons/control/columns-visibility.svg";
|
||||
import { ReactTableColumnProps } from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import Button from "components/editorComponents/Button";
|
||||
|
||||
const TableIconWrapper = styled.div<{ selected?: boolean; disabled?: boolean }>`
|
||||
background: ${props => (props.selected ? Colors.ATHENS_GRAY : "transparent")};
|
||||
box-shadow: ${props =>
|
||||
props.selected ? `inset 0px 4px 0px ${Colors.GREEN}` : "none"};
|
||||
width: 48px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: ${props => (props.disabled ? 0.6 : 1)};
|
||||
cursor: ${props => !props.disabled && "pointer"};
|
||||
`;
|
||||
import { TableIconWrapper } from "components/designSystems/appsmith/TableStyledWrappers";
|
||||
|
||||
const DropDownWrapper = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -117,13 +106,20 @@ const TableColumnsVisibility = (props: TableColumnsVisibilityProps) => {
|
|||
selectMenu(true);
|
||||
}}
|
||||
>
|
||||
<IconWrapper
|
||||
width={20}
|
||||
height={20}
|
||||
color={selected ? Colors.OXFORD_BLUE : Colors.CADET_BLUE}
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
hoverOpenDelay={1000}
|
||||
content="Hidden Fields"
|
||||
position="top"
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconWrapper>
|
||||
<IconWrapper
|
||||
width={20}
|
||||
height={20}
|
||||
color={selected ? Colors.OXFORD_BLUE : Colors.CADET_BLUE}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
</TableIconWrapper>
|
||||
<DropDownWrapper>
|
||||
{columns.map((option: ReactTableColumnProps, index: number) => (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
import React from "react";
|
||||
import { IconWrapper } from "constants/IconConstants";
|
||||
import { Tooltip } from "@blueprintjs/core";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { ReactComponent as DownloadIcon } from "assets/icons/control/download-table.svg";
|
||||
import { ReactTableColumnProps } from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import { TableIconWrapper } from "components/designSystems/appsmith/TableStyledWrappers";
|
||||
|
||||
interface TableDataDownloadProps {
|
||||
data: object[];
|
||||
columns: ReactTableColumnProps[];
|
||||
widgetName: string;
|
||||
}
|
||||
|
||||
const TableDataDownload = (props: TableDataDownloadProps) => {
|
||||
const [selected, toggleButtonClick] = React.useState(false);
|
||||
const downloadTableData = () => {
|
||||
toggleButtonClick(true);
|
||||
const csvData = [];
|
||||
csvData.push(
|
||||
props.columns
|
||||
.map((column: ReactTableColumnProps) => {
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
return column.Header;
|
||||
}
|
||||
})
|
||||
.filter(i => !!i),
|
||||
);
|
||||
for (let row = 0; row < props.data.length; row++) {
|
||||
const data: { [key: string]: any } = props.data[row];
|
||||
const csvDataRow = [];
|
||||
for (let colIndex = 0; colIndex < props.columns.length; colIndex++) {
|
||||
const column = props.columns[colIndex];
|
||||
const value = data[column.accessor];
|
||||
if (column.metaProperties && !column.metaProperties.isHidden) {
|
||||
csvDataRow.push(value);
|
||||
}
|
||||
}
|
||||
csvData.push(csvDataRow);
|
||||
}
|
||||
let csvContent = "";
|
||||
csvData.forEach(function(infoArray, index) {
|
||||
const dataString = infoArray.join(",");
|
||||
csvContent += index < csvData.length ? dataString + "\n" : dataString;
|
||||
});
|
||||
const fileName = `${props.widgetName}.csv`;
|
||||
const anchor = document.createElement("a");
|
||||
const mimeType = "application/octet-stream";
|
||||
if (navigator.msSaveBlob) {
|
||||
navigator.msSaveBlob(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
fileName,
|
||||
);
|
||||
} else if (URL && "download" in anchor) {
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([csvContent], {
|
||||
type: mimeType,
|
||||
}),
|
||||
);
|
||||
anchor.setAttribute("download", fileName);
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
toggleButtonClick(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<TableIconWrapper
|
||||
onClick={() => {
|
||||
downloadTableData();
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
hoverOpenDelay={1000}
|
||||
content="Download"
|
||||
position="top"
|
||||
>
|
||||
<IconWrapper
|
||||
width={20}
|
||||
height={20}
|
||||
color={selected ? Colors.OXFORD_BLUE : Colors.CADET_BLUE}
|
||||
>
|
||||
<DownloadIcon />
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
</TableIconWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableDataDownload;
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { Icon, NumericInput } from "@blueprintjs/core";
|
||||
import SearchComponent from "components/designSystems/appsmith/SearchComponent";
|
||||
import TableColumnsVisibility from "components/designSystems/appsmith/TableColumnsVisibility";
|
||||
import { ReactTableColumnProps } from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import {
|
||||
RowWrapper,
|
||||
PaginationWrapper,
|
||||
|
|
@ -11,6 +8,10 @@ import {
|
|||
PaginationItemWrapper,
|
||||
CommonFunctionsMenuWrapper,
|
||||
} from "./TableStyledWrappers";
|
||||
import SearchComponent from "components/designSystems/appsmith/SearchComponent";
|
||||
import TableColumnsVisibility from "components/designSystems/appsmith/TableColumnsVisibility";
|
||||
import { ReactTableColumnProps } from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import TableDataDownload from "components/designSystems/appsmith/TableDataDownload";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
const PageNumberInputWrapper = styled(NumericInput)`
|
||||
|
|
@ -58,12 +59,15 @@ interface TableHeaderProps {
|
|||
nextPageClick: () => void;
|
||||
prevPageClick: () => void;
|
||||
pageNo: number;
|
||||
tableData: object[];
|
||||
tableColumns: ReactTableColumnProps[];
|
||||
pageCount: number;
|
||||
currentPageIndex: number;
|
||||
pageOptions: number[];
|
||||
columns: ReactTableColumnProps[];
|
||||
hiddenColumns?: string[];
|
||||
updateHiddenColumns: (hiddenColumns?: string[]) => void;
|
||||
widgetName: string;
|
||||
searchKey: string;
|
||||
searchTableData: (searchKey: any) => void;
|
||||
serverSidePaginationEnabled: boolean;
|
||||
|
|
@ -79,6 +83,11 @@ const TableHeader = (props: TableHeaderProps) => {
|
|||
onSearch={props.searchTableData}
|
||||
/>
|
||||
<CommonFunctionsMenuWrapper>
|
||||
<TableDataDownload
|
||||
data={props.tableData}
|
||||
columns={props.tableColumns}
|
||||
widgetName={props.widgetName}
|
||||
/>
|
||||
{props.displayColumnActions && (
|
||||
<TableColumnsVisibility
|
||||
columns={props.columns}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { Colors } from "constants/Colors";
|
|||
import { TABLE_SIZES } from "components/designSystems/appsmith/Table";
|
||||
|
||||
export const TableWrapper = styled.div<{ width: number; height: number }>`
|
||||
width: ${props => props.width - 5}px;
|
||||
height: ${props => props.height - 5}px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
border: 1px solid ${Colors.GEYSER_LIGHT};
|
||||
box-sizing: border-box;
|
||||
|
|
@ -21,26 +21,14 @@ export const TableWrapper = styled.div<{ width: number; height: number }>`
|
|||
border-spacing: 0;
|
||||
color: ${Colors.BLUE_BAYOUX};
|
||||
position: relative;
|
||||
.thead {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
overflow-y: auto;
|
||||
height: ${props => props.height - TABLE_SIZES.TABLE_HEADER_HEIGHT}px;
|
||||
.thead,
|
||||
.tbody {
|
||||
overflow: scroll;
|
||||
/*
|
||||
Here 5px is subtracted to compensate padding from widget resizers and
|
||||
113px to compensate table column header and table header heights
|
||||
*/
|
||||
height: ${props =>
|
||||
props.height -
|
||||
5 -
|
||||
TABLE_SIZES.TABLE_HEADER_HEIGHT -
|
||||
TABLE_SIZES.COLUMN_HEADER_HEIGHT}px;
|
||||
&.no-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
overflow: hidden;
|
||||
}
|
||||
.tr {
|
||||
overflow: hidden;
|
||||
:nth-child(even) {
|
||||
background: ${Colors.ATHENS_GRAY_DARKER};
|
||||
}
|
||||
|
|
@ -285,3 +273,22 @@ export const RowWrapper = styled.div`
|
|||
margin: 0 4px;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
export const TableIconWrapper = styled.div<{
|
||||
selected?: boolean;
|
||||
disabled?: boolean;
|
||||
}>`
|
||||
background: ${props => (props.selected ? Colors.ATHENS_GRAY : "transparent")};
|
||||
box-shadow: ${props =>
|
||||
props.selected ? `inset 0px 4px 0px ${Colors.GREEN}` : "none"};
|
||||
width: 48px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: ${props => (props.disabled ? 0.6 : 1)};
|
||||
cursor: ${props => !props.disabled && "pointer"};
|
||||
&:hover {
|
||||
background: ${Colors.ATHENS_GRAY};
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
import React, { useState } from "react";
|
||||
import { Icon, InputGroup } from "@blueprintjs/core";
|
||||
import moment from "moment-timezone";
|
||||
import {
|
||||
MenuColumnWrapper,
|
||||
CellWrapper,
|
||||
ActionWrapper,
|
||||
} from "./TableStyledWrappers";
|
||||
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
||||
import { ColumnMenuOptionProps } from "./ReactTableComponent";
|
||||
import { isString } from "lodash";
|
||||
import {
|
||||
ColumnMenuOptionProps,
|
||||
ReactTableColumnProps,
|
||||
ColumnTypes,
|
||||
} from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import { isString, isNumber } from "lodash";
|
||||
import VideoComponent from "components/designSystems/appsmith/VideoComponent";
|
||||
import Button from "components/editorComponents/Button";
|
||||
import AutoToolTipComponent from "components/designSystems/appsmith/AutoToolTipComponent";
|
||||
import TableColumnMenuPopup from "./TableColumnMenu";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
interface MenuOptionProps {
|
||||
columnAccessor?: string;
|
||||
|
|
@ -57,86 +61,106 @@ export const getMenuOptions = (props: MenuOptionProps) => {
|
|||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "image"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.IMAGE}>
|
||||
<Icon
|
||||
icon="media"
|
||||
iconSize={12}
|
||||
color={props.columnType === "image" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.IMAGE
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Image</div>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
closeOnClick: true,
|
||||
isSelected: props.columnType === "image",
|
||||
isSelected: props.columnType === ColumnTypes.IMAGE,
|
||||
onClick: (columnIndex: number, isSelected: boolean) => {
|
||||
if (isSelected) {
|
||||
props.updateColumnType(columnIndex, "");
|
||||
} else {
|
||||
props.updateColumnType(columnIndex, "image");
|
||||
props.updateColumnType(columnIndex, ColumnTypes.IMAGE);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "video"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.VIDEO}>
|
||||
<Icon
|
||||
icon="video"
|
||||
iconSize={12}
|
||||
color={props.columnType === "video" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.VIDEO
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Video</div>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
isSelected: props.columnType === "video",
|
||||
isSelected: props.columnType === ColumnTypes.VIDEO,
|
||||
closeOnClick: true,
|
||||
onClick: (columnIndex: number, isSelected: boolean) => {
|
||||
if (isSelected) {
|
||||
props.updateColumnType(columnIndex, "");
|
||||
} else {
|
||||
props.updateColumnType(columnIndex, "video");
|
||||
props.updateColumnType(columnIndex, ColumnTypes.VIDEO);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "text"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.TEXT}>
|
||||
<Icon
|
||||
icon="label"
|
||||
iconSize={12}
|
||||
color={props.columnType === "text" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.TEXT
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Text</div>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
closeOnClick: true,
|
||||
isSelected: props.columnType === "text",
|
||||
isSelected: props.columnType === ColumnTypes.TEXT,
|
||||
onClick: (columnIndex: number, isSelected: boolean) => {
|
||||
if (isSelected) {
|
||||
props.updateColumnType(columnIndex, "");
|
||||
} else {
|
||||
props.updateColumnType(columnIndex, "text");
|
||||
props.updateColumnType(columnIndex, ColumnTypes.TEXT);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "currency"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.CURRENCY}>
|
||||
<Icon
|
||||
icon="dollar"
|
||||
iconSize={12}
|
||||
color={props.columnType === "currency" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.CURRENCY
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Currency</div>
|
||||
<Icon
|
||||
className="sub-menu"
|
||||
icon="chevron-right"
|
||||
iconSize={16}
|
||||
color={props.columnType === "currency" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.CURRENCY
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
closeOnClick: false,
|
||||
isSelected: props.columnType === "currency",
|
||||
isSelected: props.columnType === ColumnTypes.CURRENCY,
|
||||
options: [
|
||||
{
|
||||
content: "USD - $",
|
||||
|
|
@ -198,23 +222,31 @@ export const getMenuOptions = (props: MenuOptionProps) => {
|
|||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "date"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.DATE}>
|
||||
<Icon
|
||||
icon="calendar"
|
||||
iconSize={12}
|
||||
color={props.columnType === "date" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.DATE
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Date</div>
|
||||
<Icon
|
||||
className="sub-menu"
|
||||
icon="chevron-right"
|
||||
iconSize={16}
|
||||
color={props.columnType === "date" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.DATE
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
closeOnClick: false,
|
||||
isSelected: props.columnType === "date",
|
||||
isSelected: props.columnType === ColumnTypes.DATE,
|
||||
options: [
|
||||
{
|
||||
content: "MM-DD-YY",
|
||||
|
|
@ -252,22 +284,26 @@ export const getMenuOptions = (props: MenuOptionProps) => {
|
|||
},
|
||||
{
|
||||
content: (
|
||||
<MenuColumnWrapper selected={props.columnType === "time"}>
|
||||
<MenuColumnWrapper selected={props.columnType === ColumnTypes.TIME}>
|
||||
<Icon
|
||||
icon="time"
|
||||
iconSize={12}
|
||||
color={props.columnType === "time" ? "#ffffff" : "#2E3D49"}
|
||||
color={
|
||||
props.columnType === ColumnTypes.TIME
|
||||
? Colors.WHITE
|
||||
: Colors.OXFORD_BLUE
|
||||
}
|
||||
/>
|
||||
<div className="title">Time</div>
|
||||
</MenuColumnWrapper>
|
||||
),
|
||||
closeOnClick: true,
|
||||
isSelected: props.columnType === "time",
|
||||
isSelected: props.columnType === ColumnTypes.TIME,
|
||||
onClick: (columnIndex: number, isSelected: boolean) => {
|
||||
if (isSelected) {
|
||||
props.updateColumnType(columnIndex, "");
|
||||
} else {
|
||||
props.updateColumnType(columnIndex, "time");
|
||||
props.updateColumnType(columnIndex, ColumnTypes.TIME);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -277,17 +313,11 @@ export const getMenuOptions = (props: MenuOptionProps) => {
|
|||
|
||||
export const renderCell = (
|
||||
value: any,
|
||||
rowIndex: number,
|
||||
columnType: string,
|
||||
isHidden: boolean,
|
||||
widgetId: string,
|
||||
format?: string,
|
||||
) => {
|
||||
if (!value) {
|
||||
return <div></div>;
|
||||
}
|
||||
switch (columnType) {
|
||||
case "image":
|
||||
case ColumnTypes.IMAGE:
|
||||
if (!isString(value)) {
|
||||
return (
|
||||
<CellWrapper isHidden={isHidden}>
|
||||
|
|
@ -316,7 +346,7 @@ export const renderCell = (
|
|||
})}
|
||||
</CellWrapper>
|
||||
);
|
||||
case "video":
|
||||
case ColumnTypes.VIDEO:
|
||||
const youtubeRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
|
||||
if (isString(value) && youtubeRegex.test(value)) {
|
||||
return (
|
||||
|
|
@ -329,65 +359,11 @@ export const renderCell = (
|
|||
<CellWrapper isHidden={isHidden}>Invalid Video Link</CellWrapper>
|
||||
);
|
||||
}
|
||||
case "currency":
|
||||
if (!isNaN(value)) {
|
||||
return (
|
||||
<AutoToolTipComponent
|
||||
title={`${format}${value}`}
|
||||
isHidden={isHidden}
|
||||
>{`${format}${value}`}</AutoToolTipComponent>
|
||||
);
|
||||
} else {
|
||||
return <CellWrapper isHidden={isHidden}>Invalid Value</CellWrapper>;
|
||||
}
|
||||
case "date":
|
||||
let isValidDate = true;
|
||||
if (isNaN(value)) {
|
||||
const dateTime = Date.parse(value);
|
||||
if (isNaN(dateTime)) {
|
||||
isValidDate = false;
|
||||
}
|
||||
}
|
||||
if (isValidDate) {
|
||||
return (
|
||||
<AutoToolTipComponent
|
||||
title={moment(value).format(format)}
|
||||
isHidden={isHidden}
|
||||
>
|
||||
{moment(value).format(format)}
|
||||
</AutoToolTipComponent>
|
||||
);
|
||||
} else {
|
||||
return <CellWrapper isHidden={isHidden}>Invalid Date</CellWrapper>;
|
||||
}
|
||||
case "time":
|
||||
let isValidTime = true;
|
||||
if (isNaN(value)) {
|
||||
const time = Date.parse(value);
|
||||
if (isNaN(time)) {
|
||||
isValidTime = false;
|
||||
}
|
||||
}
|
||||
if (isValidTime) {
|
||||
return (
|
||||
<CellWrapper isHidden={isHidden}>
|
||||
{moment(value).format("HH:mm")}
|
||||
</CellWrapper>
|
||||
);
|
||||
} else {
|
||||
return <CellWrapper isHidden={isHidden}>Invalid Time</CellWrapper>;
|
||||
}
|
||||
case "text":
|
||||
const text = isString(value) ? value : JSON.stringify(value);
|
||||
return (
|
||||
<AutoToolTipComponent title={text} isHidden={isHidden}>
|
||||
{text}
|
||||
</AutoToolTipComponent>
|
||||
);
|
||||
default:
|
||||
const data = isString(value) ? value : JSON.stringify(value);
|
||||
const data =
|
||||
isString(value) || isNumber(value) ? value : JSON.stringify(value);
|
||||
return (
|
||||
<AutoToolTipComponent title={data} isHidden={isHidden}>
|
||||
<AutoToolTipComponent title={data.toString()} isHidden={isHidden}>
|
||||
{data}
|
||||
</AutoToolTipComponent>
|
||||
);
|
||||
|
|
@ -586,3 +562,51 @@ export const TableHeaderCell = (props: {
|
|||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getAllTableColumnKeys = (tableData: object[]) => {
|
||||
const columnKeys: string[] = [];
|
||||
for (let i = 0, tableRowCount = tableData.length; i < tableRowCount; i++) {
|
||||
const row = tableData[i];
|
||||
for (const key in row) {
|
||||
if (!columnKeys.includes(key)) {
|
||||
columnKeys.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return columnKeys;
|
||||
};
|
||||
|
||||
export const reorderColumns = (
|
||||
columns: ReactTableColumnProps[],
|
||||
columnOrder: string[],
|
||||
) => {
|
||||
const reorderedColumns = [];
|
||||
const reorderedFlagMap: { [key: string]: boolean } = {};
|
||||
for (let index = 0; index < columns.length; index++) {
|
||||
const accessor = columnOrder[index];
|
||||
if (accessor) {
|
||||
const column = columns.filter((col: ReactTableColumnProps) => {
|
||||
return col.accessor === accessor;
|
||||
});
|
||||
if (column.length && !reorderedFlagMap[column[0].accessor]) {
|
||||
reorderedColumns.push(column[0]);
|
||||
reorderedFlagMap[column[0].accessor] = true;
|
||||
} else if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
} else if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
}
|
||||
if (reorderedColumns.length < columns.length) {
|
||||
for (let index = 0; index < columns.length; index++) {
|
||||
if (!reorderedFlagMap[columns[index].accessor]) {
|
||||
reorderedColumns.push(columns[index]);
|
||||
reorderedFlagMap[columns[index].accessor] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return reorderedColumns;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,9 +2,19 @@ import React, { Suspense } from "react";
|
|||
import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import ReactTableComponent from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import ReactTableComponent, {
|
||||
ReactTableColumnProps,
|
||||
ColumnTypes,
|
||||
} from "components/designSystems/appsmith/ReactTableComponent";
|
||||
import {
|
||||
getAllTableColumnKeys,
|
||||
renderCell,
|
||||
renderActions,
|
||||
reorderColumns,
|
||||
} from "components/designSystems/appsmith/TableUtilities";
|
||||
import { TABLE_SIZES } from "components/designSystems/appsmith/Table";
|
||||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import { RenderMode, RenderModes } from "constants/WidgetConstants";
|
||||
import {
|
||||
WidgetPropertyValidationType,
|
||||
BASE_WIDGET_VALIDATION,
|
||||
|
|
@ -12,6 +22,7 @@ import {
|
|||
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
||||
import { TriggerPropertiesMap } from "utils/WidgetFactory";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
import moment from "moment";
|
||||
|
||||
class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
||||
static getPropertyValidationMap(): WidgetPropertyValidationType {
|
||||
|
|
@ -51,6 +62,141 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
};
|
||||
}
|
||||
|
||||
getTableColumns = (tableData: object[]) => {
|
||||
let columns: ReactTableColumnProps[] = [];
|
||||
const hiddenColumns: ReactTableColumnProps[] = [];
|
||||
const {
|
||||
columnNameMap,
|
||||
columnSizeMap,
|
||||
columnTypeMap,
|
||||
widgetId,
|
||||
columnActions,
|
||||
} = this.props;
|
||||
if (tableData.length) {
|
||||
const columnKeys: string[] = getAllTableColumnKeys(tableData);
|
||||
for (let index = 0; index < columnKeys.length; index++) {
|
||||
const i = columnKeys[index];
|
||||
const columnName: string =
|
||||
columnNameMap && columnNameMap[i] ? columnNameMap[i] : i;
|
||||
const columnType: { type: string; format?: string } =
|
||||
columnTypeMap && columnTypeMap[i]
|
||||
? columnTypeMap[i]
|
||||
: { type: ColumnTypes.TEXT };
|
||||
const columnSize: number =
|
||||
columnSizeMap && columnSizeMap[i] ? columnSizeMap[i] : 150;
|
||||
const isHidden =
|
||||
!!this.props.hiddenColumns && this.props.hiddenColumns.includes(i);
|
||||
const columnData = {
|
||||
Header: columnName,
|
||||
accessor: i,
|
||||
width: columnSize,
|
||||
minWidth: 60,
|
||||
draggable: true,
|
||||
isHidden: false,
|
||||
metaProperties: {
|
||||
isHidden: isHidden,
|
||||
type: columnType.type,
|
||||
format: columnType.format,
|
||||
},
|
||||
Cell: (props: any) => {
|
||||
return renderCell(props.cell.value, columnType.type, isHidden);
|
||||
},
|
||||
};
|
||||
if (isHidden) {
|
||||
columnData.isHidden = true;
|
||||
hiddenColumns.push(columnData);
|
||||
} else {
|
||||
columns.push(columnData);
|
||||
}
|
||||
}
|
||||
columns = reorderColumns(columns, this.props.columnOrder || []);
|
||||
if (columnActions?.length) {
|
||||
columns.push({
|
||||
Header:
|
||||
columnNameMap && columnNameMap["actions"]
|
||||
? columnNameMap["actions"]
|
||||
: "Actions",
|
||||
accessor: "actions",
|
||||
width: 150,
|
||||
minWidth: 60,
|
||||
draggable: true,
|
||||
Cell: () => {
|
||||
return renderActions({
|
||||
columnActions: columnActions,
|
||||
onCommandClick: this.onCommandClick,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
if (
|
||||
hiddenColumns.length &&
|
||||
this.props.renderMode === RenderModes.CANVAS
|
||||
) {
|
||||
columns = columns.concat(hiddenColumns);
|
||||
}
|
||||
}
|
||||
return columns;
|
||||
};
|
||||
|
||||
transformData = (tableData: object[], columns: ReactTableColumnProps[]) => {
|
||||
const updatedTableData = [];
|
||||
for (let row = 0; row < tableData.length; row++) {
|
||||
const data: { [key: string]: any } = tableData[row];
|
||||
const tableRow: { [key: string]: any } = {};
|
||||
for (let colIndex = 0; colIndex < columns.length; colIndex++) {
|
||||
const column = columns[colIndex];
|
||||
const { accessor } = column;
|
||||
const value = data[accessor];
|
||||
if (column.metaProperties) {
|
||||
const type = column.metaProperties.type;
|
||||
const format = column.metaProperties.format;
|
||||
switch (type) {
|
||||
case ColumnTypes.CURRENCY:
|
||||
if (!isNaN(value)) {
|
||||
tableRow[accessor] = `${format}${value ? value : ""}`;
|
||||
} else {
|
||||
tableRow[accessor] = "Invalid Value";
|
||||
}
|
||||
break;
|
||||
case ColumnTypes.DATE:
|
||||
let isValidDate = true;
|
||||
if (isNaN(value)) {
|
||||
const dateTime = Date.parse(value);
|
||||
if (isNaN(dateTime)) {
|
||||
isValidDate = false;
|
||||
}
|
||||
}
|
||||
if (isValidDate) {
|
||||
tableRow[accessor] = moment(value).format(format);
|
||||
} else {
|
||||
tableRow[accessor] = "Invalid Value";
|
||||
}
|
||||
break;
|
||||
case ColumnTypes.TIME:
|
||||
let isValidTime = true;
|
||||
if (isNaN(value)) {
|
||||
const time = Date.parse(value);
|
||||
if (isNaN(time)) {
|
||||
isValidTime = false;
|
||||
}
|
||||
}
|
||||
if (isValidTime) {
|
||||
tableRow[accessor] = moment(value).format("HH:mm");
|
||||
} else {
|
||||
tableRow[accessor] = "Invalid Value";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tableRow[accessor] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
updatedTableData.push(tableRow);
|
||||
}
|
||||
return updatedTableData;
|
||||
};
|
||||
|
||||
searchTableData = (tableData: object[]) => {
|
||||
const searchKey =
|
||||
this.props.searchKey !== undefined
|
||||
|
|
@ -66,8 +212,9 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
|
||||
getPageView() {
|
||||
const { tableData, hiddenColumns } = this.props;
|
||||
const tableColumns = this.getTableColumns(tableData);
|
||||
const filteredTableData = this.searchTableData(tableData);
|
||||
|
||||
const transformedData = this.transformData(filteredTableData, tableColumns);
|
||||
const serverSidePaginationEnabled = (this.props
|
||||
.serverSidePaginationEnabled &&
|
||||
this.props.serverSidePaginationEnabled) as boolean;
|
||||
|
|
@ -94,9 +241,11 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
<ReactTableComponent
|
||||
height={componentHeight}
|
||||
width={componentWidth}
|
||||
tableData={filteredTableData}
|
||||
tableData={transformedData}
|
||||
columns={tableColumns}
|
||||
isLoading={this.props.isLoading}
|
||||
widgetId={this.props.widgetId}
|
||||
widgetName={this.props.widgetName}
|
||||
searchKey={this.props.searchKey}
|
||||
renderMode={this.props.renderMode}
|
||||
hiddenColumns={hiddenColumns}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user