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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ADS Entity List Tree #38493

Merged
merged 62 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
ce99143
chore: Setup for Entity Item
hetunandu Jan 1, 2025
c28f6a2
chore: Editable State and stories
hetunandu Jan 1, 2025
962253f
chore: Fix list item changes
hetunandu Jan 2, 2025
019dccf
chore: Create new Editable submodule for shared usage
hetunandu Jan 2, 2025
f72e009
chore: Reuse ads editable in tabs
hetunandu Jan 2, 2025
98a50b4
Update tests
hetunandu Jan 2, 2025
b83ae34
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
ankitakinger Jan 2, 2025
8ba6531
Merge branch 'feat/ads/entity-item' of https://github.com/appsmithorg…
ankitakinger Jan 2, 2025
87ac4d8
fix: No permission to edit
hetunandu Jan 2, 2025
fd6c715
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
ankitakinger Jan 2, 2025
c03b0e1
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
ankitakinger Jan 2, 2025
cb6b0ad
updating spacings in list item component
ankitakinger Jan 2, 2025
2c3b12f
Merge branch 'feat/ads/entity-item' of https://github.com/appsmithorg…
ankitakinger Jan 2, 2025
e0c258a
minor change
ankitakinger Jan 2, 2025
9a9db48
css updates
ankitakinger Jan 2, 2025
c38364f
chore: First Draft
hetunandu Jan 3, 2025
58d5329
Merge branch 'feat/ads/entity-item' into feat/ads/entity-tree
hetunandu Jan 3, 2025
09a902e
chore: Fixed padding and styles
hetunandu Jan 3, 2025
0ac9545
chore: Add loading state
hetunandu Jan 3, 2025
4afc917
fix: missing dependency
hetunandu Jan 3, 2025
3679b9f
fix: Test case changes
hetunandu Jan 4, 2025
0bb665e
Merge branch 'release' into feat/ads/entity-item
hetunandu Jan 4, 2025
0978b1c
Merge branch 'release' into feat/ads/entity-item
hetunandu Jan 6, 2025
fa29de4
Merge branch 'feat/ads/entity-item' into feat/ads/entity-tree
hetunandu Jan 6, 2025
699c018
chore: ListItem hook and event improvements
hetunandu Jan 6, 2025
cfd157a
chore: Entity Tree improvements
hetunandu Jan 6, 2025
353e7c4
chore: Entity Tree story improvements
hetunandu Jan 6, 2025
a23a3c9
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 6, 2025
74fe83e
chore: Update types and event handling
hetunandu Jan 6, 2025
d53a243
chore: Use feature flag to show new Entity Item tree
hetunandu Jan 6, 2025
fe2ab7b
chore: Update flag name
hetunandu Jan 6, 2025
ecd2ae3
fix: Update flag name
hetunandu Jan 6, 2025
7fab390
fix: jest test event mocking
hetunandu Jan 7, 2025
001e7a6
fix: Padding with depth is 0
hetunandu Jan 7, 2025
2b41c8a
chore: Rename and correct style application
hetunandu Jan 7, 2025
e161648
fix: Typo
hetunandu Jan 7, 2025
5f34be1
chore: Add more identifiers
hetunandu Jan 7, 2025
74ac8e0
chore: Move Widget Tree inside IDE / UI
hetunandu Jan 8, 2025
3b64e70
chore: Move Widget Tree inside IDE / UI
hetunandu Jan 8, 2025
40a1ae1
Merge remote-tracking branch 'origin/feat/ads/entity-tree' into feat/…
hetunandu Jan 8, 2025
3f68ddf
chore: Housekeeping of List Item and Entity Item
hetunandu Jan 8, 2025
5e37259
Merge branch 'chore/ads-listitem-updates' into feat/ads/entity-tree
hetunandu Jan 8, 2025
027fac7
chore: Some refactors
hetunandu Jan 8, 2025
c5e5b7b
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 8, 2025
064ad76
refactor: Separate UIEntityListTree component logic into hooks and ut…
devin-ai-integration[bot] Jan 8, 2025
e835fc1
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 8, 2025
a25c03e
Revert "refactor: Separate UIEntityListTree component logic into hook…
hetunandu Jan 9, 2025
38705a5
fix: Improve separations
hetunandu Jan 9, 2025
ccaf13e
fix: Null checks
hetunandu Jan 10, 2025
b744321
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 10, 2025
9a8d80f
fix: implement design feedback
hetunandu Jan 10, 2025
034271e
revert type
hetunandu Jan 10, 2025
d566221
fix: Update paths to reduce cycles
hetunandu Jan 10, 2025
b971035
chore: Coderabbit suggestions
hetunandu Jan 10, 2025
5115bb4
add tests
hetunandu Jan 10, 2025
6bafb5e
fix: parent not expanded when children selected
hetunandu Jan 10, 2025
4f80a9a
chore: Padding left design update
hetunandu Jan 10, 2025
560ff97
chore: Test fix
hetunandu Jan 10, 2025
3bc67d9
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 10, 2025
0662ff6
Merge branch 'release' into feat/ads/entity-tree
hetunandu Jan 13, 2025
818289e
Update OldWidgetEntityList.tsx
hetunandu Jan 13, 2025
31e9ae6
Update EntityListTree.styles.ts
hetunandu Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
chore: Setup for Entity Item
  • Loading branch information
hetunandu committed Jan 1, 2025
commit ce9914350b2d545e94e6198d06bde77d536032bd
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const ContentTextWrapper = styled.div`
overflow: hidden;
flex: 1;
min-width: 0;
flex-shrink: 0;

& .${ListItemTextOverflowClassName} {
overflow: hidden;
Expand Down Expand Up @@ -115,7 +116,6 @@ export const StyledListItem = styled.div<{
padding-left: var(--ads-v2-spaces-3);

${({ size }) => Sizes[size]}

&[data-isblockdescription="true"] {
height: 54px;
}
Expand All @@ -128,6 +128,7 @@ export const StyledListItem = styled.div<{
${RightControlWrapper} {
display: none;
}

&:hover ${RightControlWrapper} {
display: block;
}
Expand All @@ -138,6 +139,7 @@ export const StyledListItem = styled.div<{
}

/* disabled style */

&[data-disabled="true"] {
cursor: not-allowed;
opacity: var(--ads-v2-opacity-disabled);
Expand All @@ -153,6 +155,7 @@ export const StyledListItem = styled.div<{
}

/* Focus styles */

&:focus-visible {
outline: var(--ads-v2-border-width-outline) solid
var(--ads-v2-color-outline);
Expand Down
4 changes: 2 additions & 2 deletions app/client/packages/design-system/ads/src/List/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function ListItem(props: ListItemProps) {
} = props;
const isBlockDescription = descriptionType === "block";

const listItemhandleKeyDown = (e: React.KeyboardEvent) => {
const listItemHandleKeyDown = (e: React.KeyboardEvent) => {
if (!props.isDisabled && props.onClick) {
switch (e.key) {
case "Enter":
Expand Down Expand Up @@ -120,7 +120,7 @@ function ListItem(props: ListItemProps) {
>
<ContentTextWrapper
onClick={handleOnClick}
onKeyDown={listItemhandleKeyDown}
onKeyDown={listItemHandleKeyDown}
>
{startIcon}
{props.customTitleComponent ? (
Expand Down
22 changes: 17 additions & 5 deletions app/client/packages/design-system/ads/src/List/List.types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import type { ReactNode } from "react";

export type ListSizes = Extract<Sizes, "md" | "lg">;

export interface ListItemProps {
interface BaseListItemProps {
/** The icon to display before the list item title. */
startIcon?: ReactNode;
/** The control to display at the end. */
rightControl?: ReactNode;
/** */
/** Control the visibility trigger of right control */
rightControlVisibility?: "hover" | "always";
/** callback for when the list item is clicked */
onClick: () => void;
Expand All @@ -20,8 +20,6 @@ export interface ListItemProps {
size?: ListSizes;
/** Whether to show the list item in error state */
hasError?: boolean;
/** The title/label of the list item */
title: string;
/** Description text to be shown alongside the title */
description?: string;
/** `inline` type will show the description beside the title. `block` type will show the description
Expand All @@ -32,10 +30,24 @@ export interface ListItemProps {
className?: string;
/** id for the list item */
id?: string;
}

interface ListItemWithTitle extends BaseListItemProps {
/** The title/label of the list item */
title: string;
customTitleComponent?: never;
}

interface ListItemWithCustomTitleComponent extends BaseListItemProps {
title?: never;
/** customTitleComponent for the list item to use input component for name editing */
customTitleComponent?: ReactNode | ReactNode[];
customTitleComponent: ReactNode | ReactNode[];
}

export type ListItemProps =
| ListItemWithTitle
| ListItemWithCustomTitleComponent;

export interface ListProps {
items: ListItemProps[];
className?: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable no-console */
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";

import { EntityItem } from "./EntityItem";
import type { EntityItemProps } from "./EntityItem.types";
import { ExplorerContainer } from "../ExplorerContainer";
import { Flex, Button, Icon } from "../../..";

const meta: Meta<typeof EntityItem> = {
title: "ADS/Templates/Entity Explorer/Entity Item",
component: EntityItem,
};

export default meta;

const Template = (props: EntityItemProps) => {
const { name, nameEditorConfig } = props;

const onClick = () => console.log("Add clicked");

const rightControl = (
<Button isIconButton kind="tertiary" startIcon="comment-context-menu" />
);

const startIcon = <Icon name="apps-line" />;

return (
<Flex bg="white" overflow="hidden" width="400px">
<ExplorerContainer borderRight="STANDARD" height="500px" width="255px">
<Flex p="spaces-3">
<EntityItem
{...{
startIcon,
name,
nameEditorConfig,
onClick,
rightControl,
}}
/>
</Flex>
</ExplorerContainer>
</Flex>
);
};

export const Basic = Template.bind({}) as StoryObj;

Basic.args = {
name: "Entity Name",
};

export const InEditingMode = Template.bind({}) as StoryObj;

InEditingMode.args = {
name: "Entity Name",
nameEditorConfig: {
isEditing: true,
canEdit: true,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from "styled-components";
import { Text } from "../../..";

export const EntityEditableName = styled(Text)`
height: 32px;
flex: 1;
min-width: 3ch;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { useMemo, useState } from "react";
import { ListItem } from "../../../List";
import type { EntityItemProps } from "./EntityItem.types";
import { ContentTextWrapper } from "../../../List/List.styles";
// import { usePrevious } from "@mantine/hooks";
import { useEventCallback } from "usehooks-ts";
import { normaliseName } from "./utils";
import { EntityEditableName } from "./EntityItem.styled";

export const EntityItem = (props: EntityItemProps) => {
// const previousName = usePrevious(props.name);
const [editableName, setEditableName] = useState(props.name);

const handleTitleChange = useEventCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const value = normaliseName(e.target.value);

setEditableName(value);
props.nameEditorConfig?.validateName(value);
},
);

const inputProps = useMemo(
() => ({
onChange: handleTitleChange,
style: {
paddingTop: 0,
paddingBottom: 0,
height: "32px",
top: 0,
},
}),
[handleTitleChange],
);

const customTitle = useMemo(() => {
if (!props.nameEditorConfig) {
return <ContentTextWrapper>{props.name}</ContentTextWrapper>;
} else {
return (
<EntityEditableName inputProps={inputProps} isEditable kind="body-m">
{editableName}
</EntityEditableName>
);
}
}, [editableName, inputProps, props.name, props.nameEditorConfig]);

return <ListItem {...props} customTitleComponent={customTitle} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ListItemProps } from "../../../List";

export interface EntityItemProps
extends Omit<ListItemProps, "title" | "customTitleComponent"> {
name: string;
/** Control the name editing behaviour */
nameEditorConfig?: {
// Set editable based on user permissions
canEdit: boolean;
// State to control the editable state of the input
isEditing: boolean;
// Shows a loading spinner in place of the startIcon
isLoading: boolean;
// Called when user attempts to save a valid name
onEditComplete: () => void;
// Provide a function validate the new name
validateName: (newName: string) => string | null;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { EntityItem } from "./EntityItem";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const normaliseName = (value: string, limit?: number) => {
const separatorRegex = /\W+/;

return value
.split(separatorRegex)
.join("_")
.slice(0, limit || 30);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./SearchAndAdd";
export { EmptyState } from "./EmptyState";
export { NoSearchResults } from "./NoSearchResults";
export * from "./ExplorerContainer";
export * from "./EntityItem";