Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Refactor WDSTableWidget with basic features #33286

Merged
merged 16 commits into from
May 13, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class LightModeTheme implements ColorModeTheme {
bgNegative: this.bgNegative.to("sRGB").toString(),
bgNegativeHover: this.bgNegativeHover.to("sRGB").toString(),
bgNegativeActive: this.bgNegativeActive.to("sRGB").toString(),
bgNegativeSubtle: this.bgNegativeActive.to("sRGB").toString(),
bgNegativeSubtle: this.bgNegativeSubtle.to("sRGB").toString(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a typo in the LightModeTheme. bgNegativeSubtle was using the function of bgNegativeActive

bgNegativeSubtleHover: this.bgNegativeSubtleHover.to("sRGB").toString(),
bgNegativeSubtleActive: this.bgNegativeSubtleActive.to("sRGB").toString(),
bgWarning: this.bgWarning.to("sRGB").toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ describe("bgNegativeSubtle color", () => {
const { bgNegativeSubtle } = new LightModeTheme(
"oklch(0.55 0.22 27)",
).getColors();
expect(bgNegativeSubtle).toEqual("rgb(80.074% 0% 19.209%)");
expect(bgNegativeSubtle).toEqual("rgb(100% 89.936% 89.52%)");
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./src";
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";

import { Text } from "../../Text";
import type { LinkProps } from "./types";
import styles from "./styles.module.css";

export function Link(props: LinkProps) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to use Link from react-aria-components. Also we need to make story here.

const { children, href, rel, target, ...rest } = props;

return (
<Text {...rest}>
<a className={styles.link} href={href} rel={rel} target={target}>
{children}
</a>
</Text>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Link";
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.link {
text-decoration: underline;
text-decoration-color: currentColor;
text-underline-offset: 2px;

&:hover {
color: currentColor;
text-decoration-color: currentColor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { ComponentProps } from "react";

import type { TextProps } from "../../Text";

export interface LinkProps extends TextProps {
href?: string;
target?: ComponentProps<"a">["target"];
rel?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const _Text = (props: TextProps, ref: Ref<HTMLParagraphElement>) => {
isItalic = false,
lineClamp,
style,
textAlign = "left",
textAlign = "start",
title,
variant = "body",
...rest
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { Text } from "./Text";
export type { TextProps } from "./types";
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface TextProps {
/** Sets the horizontal alignment of the inline-level content inside a block element or table-cell box. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align).
* @default left
*/
textAlign?: "left" | "center" | "right";
textAlign?: "start" | "center" | "end" | "left" | "right";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need left and right here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove it. Let me remove them.

/** Allows limiting of the contents of a block to the specified number of lines. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp). */
lineClamp?: number;
/** Sets the CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. Only use as a **last resort**. Use style props instead. */
Expand Down
1 change: 1 addition & 0 deletions app/client/packages/design-system/widgets/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export * from "./components/ActionGroup";
export * from "./components/ButtonGroup";
export * from "./components/Select";
export * from "./components/ContextualHelp";
export * from "./components/Link";

export * from "./utils";
export * from "./styles";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,22 +201,24 @@ class PrimaryColumnsControlV2 extends BaseControl<ControlProps, State> {
const isFocused =
!_.isNull(this.state.focusedIndex) &&
_.includes(this.state.duplicateColumnIds, column?.id);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern for this should be that TableWidget module exports the control, which is then registered by Appsmith. This way, this control can be as specific as necessary to the TableWidget.

@jsartisan What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree. We have to make a system where widgets can also register custom controls in the control registry.

return (
<>
<div className="flex pt-2 pb-2 justify-between">
<div>{Object.values(reorderedColumns).length} columns</div>
{this.isEditableColumnPresent() && (
<EdtiableCheckboxWrapper
className="flex t--uber-editable-checkbox"
rightPadding={this.state.hasScrollableList}
>
<span className="mr-2">Editable</span>
<Checkbox
isSelected={this.isAllColumnsEditable()}
onChange={this.toggleAllColumnsEditability}
/>
</EdtiableCheckboxWrapper>
)}
{this.props.widgetProperties.type !== "WDS_TABLE_WIDGET" &&
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hiding the editable checkbox for WDSTableWidget

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Contributor Author

@jsartisan jsartisan May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't want to show the editable icon for wds table widget. This control is being used in TableWidgetV2 as well. So had to add a check. Another way is to create the whole control and use it in table widget.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another way is to create the whole control and use it table widget.

This is the preferred approach, and we have to promote a complete separation from the legacy.

this.isEditableColumnPresent() && (
<EdtiableCheckboxWrapper
className="flex t--uber-editable-checkbox"
rightPadding={this.state.hasScrollableList}
>
<span className="mr-2">Editable</span>
<Checkbox
isSelected={this.isAllColumnsEditable()}
onChange={this.toggleAllColumnsEditability}
/>
</EdtiableCheckboxWrapper>
)}
</div>
<div className="flex flex-col w-full gap-1">
<EvaluatedValuePopupWrapper {...this.props} isFocused={isFocused}>
Expand All @@ -233,26 +235,34 @@ class PrimaryColumnsControlV2 extends BaseControl<ControlProps, State> {
renderComponent={(props: any) =>
DraggableListCard({
...props,
showCheckbox: true,
showCheckbox:
this.props.widgetProperties.type !== "WDS_TABLE_WIDGET" &&
true,
placeholder: "Column title",
})
}
toggleCheckbox={this.toggleCheckbox}
toggleVisibility={this.toggleVisibility}
toggleVisibility={
this.props.widgetProperties.type !== "WDS_TABLE_WIDGET"
? this.toggleVisibility
: undefined
}
updateFocus={this.updateFocus}
updateItems={this.updateItems}
updateOption={this.updateOption}
/>
</EvaluatedValuePopupWrapper>
<Button
className="self-end t--add-column-btn"
kind="tertiary"
onClick={this.addNewColumn}
size="sm"
startIcon="plus"
>
Add new column
</Button>
{this.props.widgetProperties.type !== "WDS_TABLE_WIDGET" && (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hiding the Add the new column button for WDSTableWidget

<Button
className="self-end t--add-column-btn"
kind="tertiary"
onClick={this.addNewColumn}
size="sm"
startIcon="plus"
>
Add new column
</Button>
)}
</div>
</>
);
Expand Down
80 changes: 11 additions & 69 deletions app/client/src/widgets/wds/WDSTableWidget/component/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import type {
import type { ColumnTypes } from "../constants";
import type { TimePrecision } from "widgets/DatePickerWidget2/constants";
import { generateReactKey } from "widgets/WidgetUtils";
import type { PlainTextCellProps } from "./cellComponents/PlainTextCell";
import type { ButtonCellProps } from "./cellComponents/ButtonCell";

export interface TableSizes {
COLUMN_HEADER_HEIGHT: number;
Expand Down Expand Up @@ -112,8 +114,8 @@ export interface TableStyles {
export type CompactMode = keyof typeof CompactModeTypes;
export type Condition = keyof typeof ConditionFunctions | "";
export type Operator = keyof typeof OperatorTypes;
export type CellAlignment = keyof typeof CellAlignmentTypes;
export type VerticalAlignment = keyof typeof VerticalAlignmentTypes;
export type CellAlignment = "start" | "center" | "end";
export type VerticalAlignment = "start" | "center" | "end";
export type ImageSize = keyof typeof ImageSizes;

export interface ReactTableFilter {
Expand Down Expand Up @@ -153,7 +155,7 @@ export interface CellWrappingProperties {
}

export interface ButtonCellProperties {
buttonVariant: ButtonVariant;
buttonVariant: ButtonCellProps["buttonVariant"];
buttonColor?: string;
buttonLabel?: string;
isCompact?: boolean;
Expand Down Expand Up @@ -212,24 +214,17 @@ export interface BaseCellProperties {
cellBackground?: string;
isVisible?: boolean;
isDisabled?: boolean;
borderRadius: string;
boxShadow: string;
isCellVisible: boolean;
isCellDisabled?: boolean;
}

export interface CellLayoutProperties
extends EditActionCellProperties,
InlineEditingCellProperties,
CellWrappingProperties,
extends CellWrappingProperties,
ButtonCellProperties,
URLCellProperties,
MenuButtonCellProperties,
SelectCellProperties,
ImageCellProperties,
DateCellProperties,
CurrencyCellProperties,
BaseCellProperties {}
BaseCellProperties {
cellColor?: "default" | PlainTextCellProps["cellColor"];
}

export interface TableColumnMetaProps {
isHidden: boolean;
Expand Down Expand Up @@ -280,7 +275,6 @@ export interface ColumnBaseProperties {
enableFilter?: boolean;
enableSort?: boolean;
isDerived: boolean;
computedValue: string;
isCellVisible?: boolean;
isAscOrder?: boolean;
alias: string;
Expand Down Expand Up @@ -353,38 +347,26 @@ export interface CurrencyColumnProperties {
export interface ColumnProperties
extends ColumnBaseProperties,
ColumnStyleProperties,
DateColumnProperties,
ColumnEditabilityProperties,
CurrencyColumnProperties,
EditActionColumnProperties {
ColumnEditabilityProperties {
allowSameOptionsInNewRow?: boolean;
newRowSelectOptions?: DropdownOption[];
buttonLabel?: string;
menuButtonLabel?: string;
buttonColor?: string;
onClick?: string;
dropdownOptions?: string;
onOptionChange?: string;
displayText?: string;
buttonVariant?: ButtonVariant;
isCompact?: boolean;
menuItems?: MenuItems;
menuVariant?: ButtonVariant;
menuColor?: string;
borderRadius?: ButtonBorderRadius;
boxShadow?: string;
boxShadowColor?: string;
iconName?: IconName;
menuButtoniconName?: IconName;
iconAlign?: Alignment;
onItemClicked?: (onClick: string | undefined) => void;
iconButtonStyle?: ButtonStyleType;
imageSize?: ImageSize;
sticky?: StickyType;
getVisibleItems?: () => Array<MenuItem>;
menuItemsSource?: MenuItemsSource;
configureMenuItems?: ConfigureMenuItems;
sourceData?: Array<Record<string, unknown>>;
cellColor?: PlainTextCellProps["cellColor"];
}

export const ConditionFunctions: {
Expand Down Expand Up @@ -494,16 +476,13 @@ export enum IMAGE_VERTICAL_ALIGN {
}

export interface BaseCellComponentProps {
compactMode: string;
isHidden: boolean;
allowCellWrapping?: boolean;
horizontalAlignment?: CellAlignment;
verticalAlignment?: VerticalAlignment;
cellBackground?: string;
isCellVisible: boolean;
fontStyle?: string;
textColor?: string;
textSize?: string;
isCellDisabled?: boolean;
}

Expand All @@ -513,50 +492,13 @@ export enum CheckboxState {
PARTIAL = 2,
}

export const scrollbarOnHoverCSS = `
.track-horizontal {
height: 6px;
bottom: 1px;
width: 100%;
opacity: 0;
transition: opacity 0.15s ease-in;
&:active {
opacity: 1;
}
}
&:hover {
.track-horizontal {
opacity: 1;
}
}
.thumb-horizontal {
&:hover, &:active {
height: 6px !important;
}
}
`;

export const MULTISELECT_CHECKBOX_WIDTH = 40;

export enum AddNewRowActions {
SAVE = "SAVE",
DISCARD = "DISCARD",
}

export const EDITABLE_CELL_PADDING_OFFSET = 8;

export const TABLE_SCROLLBAR_WIDTH = 10;
export const TABLE_SCROLLBAR_HEIGHT = 8;

export const POPOVER_ITEMS_TEXT_MAP = {
SORT_ASC: "Sort column ascending",
SORT_DSC: "Sort column descending",
FREEZE_LEFT: "Freeze column left",
FREEZE_RIGHT: "Freeze column right",
};

export const HEADER_MENU_PORTAL_CLASS = ".header-menu-portal";
export const MENU_CONTENT_CLASS = ".menu-content";
export const DEFAULT_FILTER = {
id: generateReactKey(),
column: "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
import type { ReactElementType } from "react-window";
import "simplebar-react/dist/simplebar.min.css";
import type { ReactTableColumnProps, TableSizes } from "./Constants";
import { MULTISELECT_CHECKBOX_WIDTH, TABLE_SCROLLBAR_WIDTH } from "./Constants";
import { MULTISELECT_CHECKBOX_WIDTH } from "./Constants";
import type { TableColumnHeaderProps } from "./TableHeader/TableColumnHeader";
import TableColumnHeader from "./TableHeader/TableColumnHeader";
import { TableBody } from "./TableBody";
Expand Down Expand Up @@ -86,7 +86,7 @@ const StaticTable = (props: StaticTableProps) => {
selectedRowIndex={props.selectedRowIndex}
selectedRowIndices={props.selectedRowIndices}
useVirtual={props.useVirtual}
width={props.width - TABLE_SCROLLBAR_WIDTH / 2}
width={props.width}
/>
</>
);
Expand Down