2021-02-16 10:29:08 +00:00
|
|
|
import React, { useState } from "react";
|
2021-10-06 12:57:05 +00:00
|
|
|
import {
|
|
|
|
|
MenuItem,
|
|
|
|
|
Classes,
|
|
|
|
|
Button as BButton,
|
|
|
|
|
Alignment,
|
|
|
|
|
} from "@blueprintjs/core";
|
2021-02-16 10:29:08 +00:00
|
|
|
import {
|
|
|
|
|
CellWrapper,
|
2021-07-07 05:52:10 +00:00
|
|
|
CellCheckboxWrapper,
|
|
|
|
|
CellCheckbox,
|
2021-02-16 10:29:08 +00:00
|
|
|
ActionWrapper,
|
|
|
|
|
SortIconWrapper,
|
2021-04-09 10:34:01 +00:00
|
|
|
DraggableHeaderWrapper,
|
2021-02-16 10:29:08 +00:00
|
|
|
} from "./TableStyledWrappers";
|
|
|
|
|
import { ColumnAction } from "components/propertyControls/ColumnActionSelectorControl";
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
ColumnTypes,
|
|
|
|
|
CellAlignmentTypes,
|
|
|
|
|
VerticalAlignmentTypes,
|
|
|
|
|
ColumnProperties,
|
|
|
|
|
CellLayoutProperties,
|
|
|
|
|
TableStyles,
|
2021-10-06 12:57:05 +00:00
|
|
|
MenuItems,
|
2021-09-09 15:10:22 +00:00
|
|
|
} from "./Constants";
|
2021-04-07 01:03:30 +00:00
|
|
|
import { isString, isEmpty, findIndex } from "lodash";
|
2021-09-09 15:10:22 +00:00
|
|
|
import PopoverVideo from "widgets/VideoWidget/component/PopoverVideo";
|
2021-02-16 10:29:08 +00:00
|
|
|
import Button from "components/editorComponents/Button";
|
2021-09-09 15:10:22 +00:00
|
|
|
import AutoToolTipComponent from "widgets/TableWidget/component/AutoToolTipComponent";
|
2021-02-16 10:29:08 +00:00
|
|
|
import { ControlIcons } from "icons/ControlIcons";
|
|
|
|
|
import { AnyStyledComponent } from "styled-components";
|
|
|
|
|
import styled from "constants/DefaultTheme";
|
|
|
|
|
import { Colors } from "constants/Colors";
|
2021-09-09 15:10:22 +00:00
|
|
|
import { DropdownOption } from "widgets/DropdownWidget/constants";
|
2021-09-01 09:50:23 +00:00
|
|
|
import { IconName, IconNames } from "@blueprintjs/icons";
|
2021-02-16 10:29:08 +00:00
|
|
|
import { Select, IItemRendererProps } from "@blueprintjs/select";
|
2021-04-01 08:30:33 +00:00
|
|
|
import { FontStyleTypes, TextSizes } from "constants/WidgetConstants";
|
2021-07-09 12:21:51 +00:00
|
|
|
import { noop } from "utils/AppsmithUtils";
|
2021-09-09 15:10:22 +00:00
|
|
|
|
2021-10-26 08:31:27 +00:00
|
|
|
import { ReactComponent as CheckBoxLineIcon } from "assets/icons/widget/table/checkbox-line.svg";
|
|
|
|
|
import { ReactComponent as CheckBoxCheckIcon } from "assets/icons/widget/table/checkbox-check.svg";
|
|
|
|
|
|
2021-09-01 09:50:23 +00:00
|
|
|
import {
|
|
|
|
|
ButtonVariant,
|
2021-09-09 15:10:22 +00:00
|
|
|
ButtonBoxShadow,
|
|
|
|
|
ButtonBorderRadius,
|
|
|
|
|
} from "components/constants";
|
|
|
|
|
|
|
|
|
|
//TODO(abstraction leak)
|
|
|
|
|
import { StyledButton } from "widgets/IconButtonWidget/component";
|
2021-10-06 12:57:05 +00:00
|
|
|
import MenuButtonTableComponent from "./components/menuButtonTableComponent";
|
2021-09-23 11:46:47 +00:00
|
|
|
import { stopClickEventPropagation } from "utils/helpers";
|
2021-02-16 10:29:08 +00:00
|
|
|
|
|
|
|
|
export const renderCell = (
|
|
|
|
|
value: any,
|
|
|
|
|
columnType: string,
|
|
|
|
|
isHidden: boolean,
|
|
|
|
|
cellProperties: CellLayoutProperties,
|
|
|
|
|
tableWidth: number,
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible: boolean,
|
2021-07-09 12:21:51 +00:00
|
|
|
onClick: () => void = noop,
|
|
|
|
|
isSelected?: boolean,
|
2021-02-16 10:29:08 +00:00
|
|
|
) => {
|
|
|
|
|
switch (columnType) {
|
|
|
|
|
case ColumnTypes.IMAGE:
|
|
|
|
|
if (!value) {
|
|
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
/>
|
2021-02-16 10:29:08 +00:00
|
|
|
);
|
|
|
|
|
} else if (!isString(value)) {
|
|
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
2021-02-16 10:29:08 +00:00
|
|
|
<div>Invalid Image </div>
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-07-06 13:13:26 +00:00
|
|
|
// better regex: /(?<!base64),/g ; can't use due to safari incompatibility
|
|
|
|
|
const imageSplitRegex = /[^(base64)],/g;
|
2021-03-05 19:37:49 +00:00
|
|
|
const imageUrlRegex = /(http(s?):)([/|.|\w|\s|-])*\.(?:jpeg|jpg|gif|png)??(?:&?[^=&]*=[^=&]*)*/;
|
|
|
|
|
const base64ImageRegex = /^data:image\/.*;base64/;
|
2021-02-16 10:29:08 +00:00
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
2021-02-16 10:29:08 +00:00
|
|
|
{value
|
|
|
|
|
.toString()
|
2021-07-06 13:13:26 +00:00
|
|
|
// imageSplitRegex matched "," and char before it, so add space before ","
|
|
|
|
|
.replace(imageSplitRegex, (match) =>
|
|
|
|
|
match.length > 1 ? `${match.charAt(0)} ,` : " ,",
|
|
|
|
|
)
|
2021-03-05 19:37:49 +00:00
|
|
|
.split(imageSplitRegex)
|
2021-02-16 10:29:08 +00:00
|
|
|
.map((item: string, index: number) => {
|
2021-03-05 19:37:49 +00:00
|
|
|
if (imageUrlRegex.test(item) || base64ImageRegex.test(item)) {
|
2021-02-16 10:29:08 +00:00
|
|
|
return (
|
2021-07-09 12:21:51 +00:00
|
|
|
<div
|
2021-02-16 10:29:08 +00:00
|
|
|
className="image-cell-wrapper"
|
|
|
|
|
key={index}
|
2021-07-09 12:21:51 +00:00
|
|
|
onClick={(e) => {
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
onClick();
|
|
|
|
|
}}
|
2021-02-16 10:29:08 +00:00
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
className="image-cell"
|
|
|
|
|
style={{ backgroundImage: `url("${item}")` }}
|
|
|
|
|
/>
|
2021-07-09 12:21:51 +00:00
|
|
|
</div>
|
2021-02-16 10:29:08 +00:00
|
|
|
);
|
|
|
|
|
} else {
|
2021-06-29 13:29:19 +00:00
|
|
|
return <div key={index}>Invalid Image</div>;
|
2021-02-16 10:29:08 +00:00
|
|
|
}
|
|
|
|
|
})}
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
case ColumnTypes.VIDEO:
|
|
|
|
|
const youtubeRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=|\?v=)([^#&?]*).*/;
|
|
|
|
|
if (!value) {
|
|
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
/>
|
2021-02-16 10:29:08 +00:00
|
|
|
);
|
|
|
|
|
} else if (isString(value) && youtubeRegex.test(value)) {
|
|
|
|
|
return (
|
|
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
className="video-cell"
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible={isCellVisible}
|
2021-04-28 10:28:39 +00:00
|
|
|
isHidden={isHidden}
|
2021-02-16 10:29:08 +00:00
|
|
|
>
|
|
|
|
|
<PopoverVideo url={value} />
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
2021-02-16 10:29:08 +00:00
|
|
|
Invalid Video Link
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return (
|
|
|
|
|
<AutoToolTipComponent
|
|
|
|
|
cellProperties={cellProperties}
|
2021-03-24 11:24:10 +00:00
|
|
|
columnType={columnType}
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible={isCellVisible}
|
2021-04-28 10:28:39 +00:00
|
|
|
isHidden={isHidden}
|
|
|
|
|
tableWidth={tableWidth}
|
2021-08-18 07:14:56 +00:00
|
|
|
title={!!value ? value.toString() : ""}
|
2021-02-16 10:29:08 +00:00
|
|
|
>
|
2021-05-05 09:26:57 +00:00
|
|
|
{value && columnType === ColumnTypes.URL && cellProperties.displayText
|
|
|
|
|
? cellProperties.displayText
|
2021-08-18 07:14:56 +00:00
|
|
|
: !!value
|
|
|
|
|
? value.toString()
|
|
|
|
|
: ""}
|
2021-02-16 10:29:08 +00:00
|
|
|
</AutoToolTipComponent>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2021-09-01 09:50:23 +00:00
|
|
|
interface RenderIconButtonProps {
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
columnActions?: ColumnAction[];
|
|
|
|
|
iconName?: IconName;
|
|
|
|
|
buttonVariant: ButtonVariant;
|
2021-09-23 15:14:24 +00:00
|
|
|
buttonColor: string;
|
2021-09-01 09:50:23 +00:00
|
|
|
borderRadius: ButtonBorderRadius;
|
|
|
|
|
boxShadow: ButtonBoxShadow;
|
|
|
|
|
boxShadowColor: string;
|
|
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
|
|
|
|
|
isCellVisible: boolean;
|
|
|
|
|
}
|
|
|
|
|
export const renderIconButton = (
|
|
|
|
|
props: RenderIconButtonProps,
|
|
|
|
|
isHidden: boolean,
|
|
|
|
|
cellProperties: CellLayoutProperties,
|
|
|
|
|
) => {
|
|
|
|
|
if (!props.columnActions)
|
|
|
|
|
return <CellWrapper cellProperties={cellProperties} isHidden={isHidden} />;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={props.isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
|
|
|
|
{props.columnActions.map((action: ColumnAction, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<IconButton
|
|
|
|
|
action={action}
|
|
|
|
|
borderRadius={props.borderRadius}
|
|
|
|
|
boxShadow={props.boxShadow}
|
|
|
|
|
boxShadowColor={props.boxShadowColor}
|
2021-09-23 15:14:24 +00:00
|
|
|
buttonColor={props.buttonColor}
|
2021-09-01 09:50:23 +00:00
|
|
|
buttonVariant={props.buttonVariant}
|
|
|
|
|
iconName={props.iconName}
|
|
|
|
|
isSelected={props.isSelected}
|
|
|
|
|
key={index}
|
|
|
|
|
onCommandClick={props.onCommandClick}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
function IconButton(props: {
|
|
|
|
|
iconName?: IconName;
|
|
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
action: ColumnAction;
|
2021-09-23 15:14:24 +00:00
|
|
|
buttonColor: string;
|
2021-09-01 09:50:23 +00:00
|
|
|
buttonVariant: ButtonVariant;
|
|
|
|
|
borderRadius: ButtonBorderRadius;
|
|
|
|
|
boxShadow: ButtonBoxShadow;
|
|
|
|
|
boxShadowColor: string;
|
|
|
|
|
}): JSX.Element {
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const onComplete = () => {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
const handlePropagation = (
|
|
|
|
|
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
|
|
|
|
) => {
|
|
|
|
|
if (props.isSelected) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const handleClick = () => {
|
|
|
|
|
if (props.action.dynamicTrigger) {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
props.onCommandClick(props.action.dynamicTrigger, onComplete);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
return (
|
|
|
|
|
<div onClick={handlePropagation}>
|
|
|
|
|
<StyledButton
|
|
|
|
|
borderRadius={props.borderRadius}
|
|
|
|
|
boxShadow={props.boxShadow}
|
|
|
|
|
boxShadowColor={props.boxShadowColor}
|
2021-09-23 15:14:24 +00:00
|
|
|
buttonColor={props.buttonColor}
|
2021-09-01 09:50:23 +00:00
|
|
|
buttonVariant={props.buttonVariant}
|
|
|
|
|
icon={props.iconName}
|
|
|
|
|
loading={loading}
|
|
|
|
|
onClick={handleClick}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-16 10:29:08 +00:00
|
|
|
interface RenderActionProps {
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
columnActions?: ColumnAction[];
|
|
|
|
|
backgroundColor: string;
|
|
|
|
|
buttonLabelColor: string;
|
2021-08-17 12:54:43 +00:00
|
|
|
isDisabled: boolean;
|
|
|
|
|
isCellVisible: boolean;
|
2021-02-16 10:29:08 +00:00
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
|
|
|
|
|
}
|
2021-10-06 12:57:05 +00:00
|
|
|
export interface RenderMenuButtonProps {
|
|
|
|
|
isSelected: boolean;
|
|
|
|
|
// columnActions?: ColumnAction[];
|
|
|
|
|
label: string;
|
|
|
|
|
isDisabled: boolean;
|
|
|
|
|
isCellVisible: boolean;
|
|
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete?: () => void) => void;
|
|
|
|
|
isCompact?: boolean;
|
|
|
|
|
menuItems: MenuItems;
|
|
|
|
|
menuVariant?: ButtonVariant;
|
|
|
|
|
menuColor?: string;
|
|
|
|
|
borderRadius?: ButtonBorderRadius;
|
|
|
|
|
boxShadow?: ButtonBoxShadow;
|
|
|
|
|
boxShadowColor?: string;
|
|
|
|
|
iconName?: IconName;
|
|
|
|
|
iconAlign?: Alignment;
|
|
|
|
|
}
|
2021-02-16 10:29:08 +00:00
|
|
|
|
|
|
|
|
export const renderActions = (
|
|
|
|
|
props: RenderActionProps,
|
|
|
|
|
isHidden: boolean,
|
|
|
|
|
cellProperties: CellLayoutProperties,
|
|
|
|
|
) => {
|
|
|
|
|
if (!props.columnActions)
|
2021-08-17 12:54:43 +00:00
|
|
|
return (
|
|
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={props.isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2021-02-16 10:29:08 +00:00
|
|
|
|
|
|
|
|
return (
|
2021-08-17 12:54:43 +00:00
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={props.isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
2021-02-16 10:29:08 +00:00
|
|
|
{props.columnActions.map((action: ColumnAction, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<TableAction
|
|
|
|
|
action={action}
|
|
|
|
|
backgroundColor={props.backgroundColor}
|
|
|
|
|
buttonLabelColor={props.buttonLabelColor}
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible={props.isCellVisible}
|
|
|
|
|
isDisabled={props.isDisabled}
|
2021-04-28 10:28:39 +00:00
|
|
|
isSelected={props.isSelected}
|
|
|
|
|
key={index}
|
2021-02-16 10:29:08 +00:00
|
|
|
onCommandClick={props.onCommandClick}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-10-06 12:57:05 +00:00
|
|
|
export const renderMenuButton = (
|
|
|
|
|
props: RenderMenuButtonProps,
|
|
|
|
|
isHidden: boolean,
|
|
|
|
|
cellProperties: CellLayoutProperties,
|
|
|
|
|
) => {
|
|
|
|
|
return (
|
|
|
|
|
<CellWrapper
|
|
|
|
|
cellProperties={cellProperties}
|
|
|
|
|
isCellVisible={props.isCellVisible}
|
|
|
|
|
isHidden={isHidden}
|
|
|
|
|
>
|
|
|
|
|
<MenuButton {...props} />
|
|
|
|
|
</CellWrapper>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
interface MenuButtonProps extends Omit<RenderMenuButtonProps, "columnActions"> {
|
|
|
|
|
action?: ColumnAction;
|
|
|
|
|
}
|
|
|
|
|
function MenuButton({
|
|
|
|
|
borderRadius,
|
|
|
|
|
boxShadow,
|
|
|
|
|
boxShadowColor,
|
|
|
|
|
iconAlign,
|
|
|
|
|
iconName,
|
|
|
|
|
isCompact,
|
|
|
|
|
isDisabled,
|
|
|
|
|
isSelected,
|
|
|
|
|
label,
|
|
|
|
|
menuColor,
|
|
|
|
|
menuItems,
|
|
|
|
|
menuVariant,
|
|
|
|
|
onCommandClick,
|
|
|
|
|
}: MenuButtonProps): JSX.Element {
|
|
|
|
|
const handlePropagation = (
|
|
|
|
|
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
|
|
|
|
|
) => {
|
|
|
|
|
if (isSelected) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const onItemClicked = (onClick?: string) => {
|
|
|
|
|
if (onClick) {
|
|
|
|
|
onCommandClick(onClick);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div onClick={handlePropagation}>
|
|
|
|
|
<MenuButtonTableComponent
|
|
|
|
|
borderRadius={borderRadius}
|
|
|
|
|
boxShadow={boxShadow}
|
|
|
|
|
boxShadowColor={boxShadowColor}
|
|
|
|
|
iconAlign={iconAlign}
|
|
|
|
|
iconName={iconName}
|
|
|
|
|
isCompact={isCompact}
|
|
|
|
|
isDisabled={isDisabled}
|
|
|
|
|
label={label}
|
|
|
|
|
menuColor={menuColor}
|
|
|
|
|
menuItems={{ ...menuItems }}
|
|
|
|
|
menuVariant={menuVariant}
|
|
|
|
|
onItemClicked={onItemClicked}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
function TableAction(props: {
|
2021-02-16 10:29:08 +00:00
|
|
|
isSelected: boolean;
|
|
|
|
|
action: ColumnAction;
|
|
|
|
|
backgroundColor: string;
|
|
|
|
|
buttonLabelColor: string;
|
2021-08-17 12:54:43 +00:00
|
|
|
isDisabled: boolean;
|
|
|
|
|
isCellVisible: boolean;
|
2021-02-16 10:29:08 +00:00
|
|
|
onCommandClick: (dynamicTrigger: string, onComplete: () => void) => void;
|
2021-04-28 10:28:39 +00:00
|
|
|
}) {
|
2021-02-16 10:29:08 +00:00
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const onComplete = () => {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ActionWrapper
|
|
|
|
|
background={props.backgroundColor}
|
|
|
|
|
buttonLabelColor={props.buttonLabelColor}
|
2021-09-28 10:57:44 +00:00
|
|
|
onClick={(e) => {
|
|
|
|
|
if (props.isSelected) {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}
|
|
|
|
|
}}
|
2021-02-16 10:29:08 +00:00
|
|
|
>
|
2021-08-17 12:54:43 +00:00
|
|
|
{props.isCellVisible ? (
|
|
|
|
|
<Button
|
|
|
|
|
disabled={props.isDisabled}
|
|
|
|
|
filled
|
|
|
|
|
intent="PRIMARY_BUTTON"
|
|
|
|
|
loading={loading}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
props.onCommandClick(props.action.dynamicTrigger, onComplete);
|
|
|
|
|
}}
|
|
|
|
|
size="small"
|
|
|
|
|
text={props.action.label}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
2021-02-16 10:29:08 +00:00
|
|
|
</ActionWrapper>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2021-02-16 10:29:08 +00:00
|
|
|
|
2021-07-07 05:52:10 +00:00
|
|
|
export const renderCheckBoxCell = (isChecked: boolean) => (
|
|
|
|
|
<CellCheckboxWrapper
|
|
|
|
|
className="td t--table-multiselect"
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible
|
2021-07-07 05:52:10 +00:00
|
|
|
isChecked={isChecked}
|
|
|
|
|
>
|
2021-10-26 08:31:27 +00:00
|
|
|
<CellCheckbox>
|
|
|
|
|
{isChecked && <CheckBoxCheckIcon className="th-svg" />}
|
|
|
|
|
</CellCheckbox>
|
2021-07-07 05:52:10 +00:00
|
|
|
</CellCheckboxWrapper>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const renderCheckBoxHeaderCell = (
|
|
|
|
|
onClick: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void,
|
|
|
|
|
checkState: number | null,
|
|
|
|
|
) => (
|
|
|
|
|
<CellCheckboxWrapper
|
|
|
|
|
className="th header-reorder t--table-multiselect-header"
|
|
|
|
|
isChecked={!!checkState}
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
role="columnheader"
|
|
|
|
|
style={{ padding: "0px", justifyContent: "center" }}
|
|
|
|
|
>
|
|
|
|
|
<CellCheckbox>
|
2021-10-26 08:31:27 +00:00
|
|
|
{checkState === 1 && <CheckBoxCheckIcon className="th-svg" />}
|
|
|
|
|
{checkState === 2 && (
|
|
|
|
|
<CheckBoxLineIcon className="th-svg t--table-multiselect-header-half-check-svg" />
|
|
|
|
|
)}
|
2021-07-07 05:52:10 +00:00
|
|
|
</CellCheckbox>
|
|
|
|
|
</CellCheckboxWrapper>
|
|
|
|
|
);
|
|
|
|
|
|
2021-02-16 10:29:08 +00:00
|
|
|
export const renderEmptyRows = (
|
|
|
|
|
rowCount: number,
|
|
|
|
|
columns: any,
|
|
|
|
|
tableWidth: number,
|
|
|
|
|
page: any,
|
|
|
|
|
prepareRow: any,
|
2021-07-07 05:52:10 +00:00
|
|
|
multiRowSelection = false,
|
2021-02-16 10:29:08 +00:00
|
|
|
) => {
|
|
|
|
|
const rows: string[] = new Array(rowCount).fill("");
|
|
|
|
|
if (page.length) {
|
|
|
|
|
const row = page[0];
|
|
|
|
|
return rows.map((item: string, index: number) => {
|
|
|
|
|
prepareRow(row);
|
2021-07-07 05:52:10 +00:00
|
|
|
const rowProps = {
|
|
|
|
|
...row.getRowProps(),
|
|
|
|
|
style: { display: "flex" },
|
|
|
|
|
};
|
2021-02-16 10:29:08 +00:00
|
|
|
return (
|
2021-07-07 05:52:10 +00:00
|
|
|
<div {...rowProps} className="tr" key={index}>
|
|
|
|
|
{multiRowSelection && renderCheckBoxCell(false)}
|
2021-02-16 10:29:08 +00:00
|
|
|
{row.cells.map((cell: any, cellIndex: number) => {
|
2021-08-30 07:48:10 +00:00
|
|
|
const cellProps = cell.getCellProps();
|
|
|
|
|
if (columns[0]?.columnProperties?.cellBackground) {
|
|
|
|
|
cellProps.style.background =
|
|
|
|
|
columns[0].columnProperties.cellBackground;
|
|
|
|
|
}
|
|
|
|
|
return <div {...cellProps} className="td" key={cellIndex} />;
|
2021-02-16 10:29:08 +00:00
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
});
|
2021-07-27 05:03:13 +00:00
|
|
|
} else {
|
|
|
|
|
const tableColumns = columns.length
|
|
|
|
|
? columns
|
|
|
|
|
: new Array(3).fill({ width: tableWidth / 3, isHidden: false });
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{rows.map((row: string, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="tr"
|
|
|
|
|
key={index}
|
|
|
|
|
style={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
flex: "1 0 auto",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{multiRowSelection && renderCheckBoxCell(false)}
|
|
|
|
|
{tableColumns.map((column: any, colIndex: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className="td"
|
|
|
|
|
key={colIndex}
|
|
|
|
|
style={{
|
|
|
|
|
width: column.width + "px",
|
|
|
|
|
boxSizing: "border-box",
|
|
|
|
|
flex: `${column.width} 0 auto`,
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</>
|
|
|
|
|
);
|
2021-02-16 10:29:08 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AscendingIcon = styled(ControlIcons.SORT_CONTROL as AnyStyledComponent)`
|
|
|
|
|
padding: 0;
|
|
|
|
|
position: relative;
|
2021-03-13 06:36:02 +00:00
|
|
|
top: 12px;
|
2021-02-16 10:29:08 +00:00
|
|
|
cursor: pointer;
|
|
|
|
|
transform: rotate(180deg);
|
2021-04-03 19:40:12 +00:00
|
|
|
&& svg {
|
2021-02-16 10:29:08 +00:00
|
|
|
path {
|
|
|
|
|
fill: ${(props) => props.theme.colors.secondary};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const DescendingIcon = styled(ControlIcons.SORT_CONTROL as AnyStyledComponent)`
|
|
|
|
|
padding: 0;
|
|
|
|
|
position: relative;
|
|
|
|
|
top: 3px;
|
|
|
|
|
cursor: pointer;
|
2021-04-03 19:40:12 +00:00
|
|
|
&& svg {
|
2021-02-16 10:29:08 +00:00
|
|
|
path {
|
|
|
|
|
fill: ${(props) => props.theme.colors.secondary};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
2021-04-28 10:28:39 +00:00
|
|
|
export function TableHeaderCell(props: {
|
2021-02-16 10:29:08 +00:00
|
|
|
columnName: string;
|
|
|
|
|
columnIndex: number;
|
|
|
|
|
isHidden: boolean;
|
|
|
|
|
isAscOrder?: boolean;
|
|
|
|
|
sortTableColumn: (columnIndex: number, asc: boolean) => void;
|
|
|
|
|
isResizingColumn: boolean;
|
|
|
|
|
column: any;
|
2021-04-28 10:28:39 +00:00
|
|
|
}) {
|
2021-02-16 10:29:08 +00:00
|
|
|
const { column } = props;
|
|
|
|
|
const handleSortColumn = () => {
|
|
|
|
|
if (props.isResizingColumn) return;
|
|
|
|
|
let columnIndex = props.columnIndex;
|
|
|
|
|
if (props.isAscOrder === true) {
|
|
|
|
|
columnIndex = -1;
|
|
|
|
|
}
|
|
|
|
|
const sortOrder =
|
|
|
|
|
props.isAscOrder === undefined ? false : !props.isAscOrder;
|
|
|
|
|
props.sortTableColumn(columnIndex, sortOrder);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
{...column.getHeaderProps()}
|
|
|
|
|
className="th header-reorder"
|
|
|
|
|
onClick={handleSortColumn}
|
|
|
|
|
>
|
|
|
|
|
{props.isAscOrder !== undefined ? (
|
|
|
|
|
<SortIconWrapper>
|
|
|
|
|
{props.isAscOrder ? (
|
|
|
|
|
<AscendingIcon height={16} width={16} />
|
|
|
|
|
) : (
|
|
|
|
|
<DescendingIcon height={16} width={16} />
|
|
|
|
|
)}
|
|
|
|
|
</SortIconWrapper>
|
|
|
|
|
) : null}
|
2021-04-09 10:34:01 +00:00
|
|
|
<DraggableHeaderWrapper
|
2021-02-16 10:29:08 +00:00
|
|
|
className={
|
|
|
|
|
!props.isHidden
|
|
|
|
|
? `draggable-header ${
|
|
|
|
|
props.isAscOrder !== undefined ? "sorted" : ""
|
|
|
|
|
}`
|
|
|
|
|
: "hidden-header"
|
|
|
|
|
}
|
2021-04-28 10:28:39 +00:00
|
|
|
horizontalAlignment={column.columnProperties.horizontalAlignment}
|
2021-02-16 10:29:08 +00:00
|
|
|
>
|
2021-04-03 19:40:12 +00:00
|
|
|
{props.columnName}
|
2021-04-09 10:34:01 +00:00
|
|
|
</DraggableHeaderWrapper>
|
2021-02-16 10:29:08 +00:00
|
|
|
<div
|
|
|
|
|
{...column.getResizerProps()}
|
|
|
|
|
className={`resizer ${column.isResizing ? "isResizing" : ""}`}
|
|
|
|
|
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2021-04-28 10:28:39 +00:00
|
|
|
}
|
2021-02-16 10:29:08 +00:00
|
|
|
|
|
|
|
|
export function getDefaultColumnProperties(
|
|
|
|
|
accessor: string,
|
|
|
|
|
index: number,
|
|
|
|
|
widgetName: string,
|
|
|
|
|
isDerived?: boolean,
|
|
|
|
|
): ColumnProperties {
|
|
|
|
|
const columnProps = {
|
|
|
|
|
index: index,
|
|
|
|
|
width: 150,
|
|
|
|
|
id: accessor,
|
|
|
|
|
horizontalAlignment: CellAlignmentTypes.LEFT,
|
|
|
|
|
verticalAlignment: VerticalAlignmentTypes.CENTER,
|
|
|
|
|
columnType: ColumnTypes.TEXT,
|
|
|
|
|
textColor: Colors.THUNDER,
|
|
|
|
|
textSize: TextSizes.PARAGRAPH,
|
|
|
|
|
fontStyle: FontStyleTypes.REGULAR,
|
|
|
|
|
enableFilter: true,
|
|
|
|
|
enableSort: true,
|
|
|
|
|
isVisible: true,
|
2021-08-17 12:54:43 +00:00
|
|
|
isDisabled: false,
|
|
|
|
|
isCellVisible: true,
|
2021-02-16 10:29:08 +00:00
|
|
|
isDerived: !!isDerived,
|
|
|
|
|
label: accessor,
|
|
|
|
|
computedValue: isDerived
|
|
|
|
|
? ""
|
2021-07-22 08:43:58 +00:00
|
|
|
: `{{${widgetName}.sanitizedTableData.map((currentRow) => ( currentRow.${accessor}))}}`,
|
2021-02-16 10:29:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return columnProps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getTableStyles(props: TableStyles) {
|
|
|
|
|
return {
|
|
|
|
|
textColor: props.textColor,
|
|
|
|
|
textSize: props.textSize,
|
|
|
|
|
fontStyle: props.fontStyle,
|
|
|
|
|
cellBackground: props.cellBackground,
|
|
|
|
|
verticalAlignment: props.verticalAlignment,
|
|
|
|
|
horizontalAlignment: props.horizontalAlignment,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SingleDropDown = Select.ofType<DropdownOption>();
|
|
|
|
|
|
|
|
|
|
const StyledSingleDropDown = styled(SingleDropDown)`
|
|
|
|
|
div {
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
span {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
position: relative;
|
|
|
|
|
}
|
|
|
|
|
.${Classes.BUTTON} {
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
background: transparent;
|
|
|
|
|
min-height: 32px;
|
|
|
|
|
}
|
|
|
|
|
.${Classes.BUTTON_TEXT} {
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
text-align: left;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
display: -webkit-box;
|
|
|
|
|
-webkit-line-clamp: 1;
|
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
|
}
|
|
|
|
|
&& {
|
|
|
|
|
.${Classes.ICON} {
|
|
|
|
|
width: fit-content;
|
|
|
|
|
color: ${Colors.SLATE_GRAY};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
export const renderDropdown = (props: {
|
|
|
|
|
options: DropdownOption[];
|
2021-08-17 12:54:43 +00:00
|
|
|
isCellVisible: boolean;
|
2021-02-16 10:29:08 +00:00
|
|
|
onItemSelect: (onOptionChange: string, item: DropdownOption) => void;
|
|
|
|
|
onOptionChange: string;
|
|
|
|
|
selectedIndex?: number;
|
|
|
|
|
}) => {
|
|
|
|
|
const isOptionSelected = (selectedOption: DropdownOption) => {
|
|
|
|
|
const optionIndex = findIndex(props.options, (option) => {
|
|
|
|
|
return option.value === selectedOption.value;
|
|
|
|
|
});
|
|
|
|
|
return optionIndex === props.selectedIndex;
|
|
|
|
|
};
|
|
|
|
|
const renderSingleSelectItem = (
|
|
|
|
|
option: DropdownOption,
|
|
|
|
|
itemProps: IItemRendererProps,
|
|
|
|
|
) => {
|
|
|
|
|
if (!itemProps.modifiers.matchesPredicate) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2021-08-17 12:54:43 +00:00
|
|
|
if (!props.isCellVisible) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2021-02-16 10:29:08 +00:00
|
|
|
const isSelected: boolean = isOptionSelected(option);
|
|
|
|
|
return (
|
|
|
|
|
<MenuItem
|
|
|
|
|
active={isSelected}
|
2021-04-28 10:28:39 +00:00
|
|
|
className="single-select"
|
2021-02-16 10:29:08 +00:00
|
|
|
key={option.value}
|
|
|
|
|
onClick={itemProps.handleClick}
|
|
|
|
|
text={option.label}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
return (
|
2021-09-23 11:46:47 +00:00
|
|
|
<div onClick={stopClickEventPropagation} style={{ height: "100%" }}>
|
2021-02-16 10:29:08 +00:00
|
|
|
<StyledSingleDropDown
|
2021-04-28 10:28:39 +00:00
|
|
|
filterable={false}
|
2021-02-16 10:29:08 +00:00
|
|
|
itemRenderer={renderSingleSelectItem}
|
2021-04-28 10:28:39 +00:00
|
|
|
items={props.options}
|
2021-02-16 10:29:08 +00:00
|
|
|
onItemSelect={(item: DropdownOption) => {
|
|
|
|
|
props.onItemSelect(props.onOptionChange, item);
|
|
|
|
|
}}
|
|
|
|
|
popoverProps={{
|
|
|
|
|
minimal: true,
|
|
|
|
|
usePortal: true,
|
|
|
|
|
popoverClassName: "select-popover-wrapper",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<BButton
|
|
|
|
|
rightIcon={IconNames.CHEVRON_DOWN}
|
|
|
|
|
text={
|
|
|
|
|
!isEmpty(props.options) &&
|
|
|
|
|
props.selectedIndex !== undefined &&
|
|
|
|
|
props.selectedIndex > -1
|
|
|
|
|
? props.options[props.selectedIndex].label
|
|
|
|
|
: "-- Select --"
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
</StyledSingleDropDown>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|