Skip to content

Commit

Permalink
🪟 🎨 Refining BulkEditPanel component (#20474)
Browse files Browse the repository at this point in the history
* Adds handling for source defined and unavailable stream paths inside PillSelect

* Adds handling of unavailable cursor and primary key field for PillButton components

* Adds useMemo to SyncPathSelect component

* Add InfoText component for cursor field and primary key to match table design in Figma

* Removes animation for BulkEditPanel; Adds StreamPathSelect new property pillIfChangeUnavailable for cases when we need or not to render pill under unavailable to change path text

* Disables pointer event while PillButton is disabled

* Adds renderDisabledState property to control PillSelect content while disabled

* Changes renderDisabledState -> disabledLabel
  • Loading branch information
YatsukBogdan1 authored Jan 10, 2023
1 parent 8c35783 commit 94fcb13
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const SchemaHeader = styled(Header)<SchemaHeaderProps>`
background: ${({ theme }) => theme.primaryColor};
border-radius: 8px 8px 0 0;
padding: 10px;
transition: 0.3s ease-in;
`;

export function calculateSharedFields(selectedBatchNodes: SyncSchemaStream[]) {
Expand Down Expand Up @@ -143,6 +142,7 @@ export const BulkEditPanel: React.FC = () => {
</p>
<div className={styles.syncCellContent}>
<StreamPathSelect
withSourceDefinedPill
disabled={!cursorType}
variant="strong-blue"
isMulti={false}
Expand All @@ -159,6 +159,7 @@ export const BulkEditPanel: React.FC = () => {
</p>
<div className={styles.syncCellContent}>
<StreamPathSelect
withSourceDefinedPill
disabled={!pkType}
variant="strong-blue"
isMulti
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
.text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.streamPathSelect {
width: 100%;
min-width: 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from "react";
import React, { useMemo } from "react";
import { FormattedMessage } from "react-intl";

import { PillButtonVariant, PillSelect } from "components/ui/PillSelect";
import { Text } from "components/ui/Text";
import { Tooltip } from "components/ui/Tooltip";
import { InfoText, INFO_TEXT_VARIANT_BY_PILL_VARIANT } from "components/ui/InfoText";
import { PillButton, PillButtonVariant, PillSelect } from "components/ui/PillSelect";

import { Path } from "core/domain/catalog";

Expand All @@ -19,6 +18,10 @@ interface StreamPathSelectBaseProps {
placeholder?: React.ReactNode;
variant?: PillButtonVariant;
disabled?: boolean;
// This property is used for cases when the path is defined by source, therefore
// in some cases we need this path to render with pill background (BulkEditPanel) and
// in some cases it should be only text (StreamsTable)
withSourceDefinedPill?: boolean;
hasError?: boolean;
}

Expand All @@ -36,21 +39,30 @@ interface StreamPathSelectProps {

type PathPopoutProps = StreamPathSelectBaseProps & (StreamPathSelectMultiProps | StreamPathSelectProps);

export const StreamPathSelect: React.FC<PathPopoutProps> = (props) => {
if (props.pathType === "sourceDefined") {
export const StreamPathSelect: React.FC<PathPopoutProps> = ({
withSourceDefinedPill = false,
variant = "grey",
...props
}) => {
const SourceDefinedNode = useMemo(() => {
if (props.path && props.path.length > 0) {
const text = props.isMulti ? props.path.map(pathDisplayName).join(", ") : pathDisplayName(props.path);

return props.isMulti ? props.path.map(pathDisplayName).join(", ") : pathDisplayName(props.path);
}
return <FormattedMessage id="connection.catalogTree.sourceDefined" />;
}, [props.isMulti, props.path]);
if (props.pathType === "sourceDefined") {
if (withSourceDefinedPill) {
return (
<Text className={styles.text}>
<Tooltip placement="bottom-start" control={text}>
{text}
</Tooltip>
</Text>
<PillButton disabled variant={variant} className={styles.streamPathSelect}>
{SourceDefinedNode}
</PillButton>
);
}

return <FormattedMessage id="connection.catalogTree.sourceDefined" />;
return (
<InfoText variant={INFO_TEXT_VARIANT_BY_PILL_VARIANT[variant]} className={styles.streamPathSelect}>
{SourceDefinedNode}
</InfoText>
);
}

const options = props.paths.map((path) => ({
Expand All @@ -60,8 +72,9 @@ export const StreamPathSelect: React.FC<PathPopoutProps> = (props) => {

return (
<PillSelect
disabledLabel={<FormattedMessage id="connectionForm.bulkEdit.pillButtonLabel.notAvailable" />}
disabled={props.disabled}
variant={props.variant}
variant={variant}
options={options}
value={props.path}
isMulti={props.isMulti}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ exports[`<BulkEditPanel /> should render 1`] = `
>
<span
class="<removed-for-snapshot-test>"
/>
>
Not available
</span>
</div>
<svg
aria-hidden="true"
Expand Down Expand Up @@ -208,7 +210,9 @@ exports[`<BulkEditPanel /> should render 1`] = `
>
<span
class="<removed-for-snapshot-test>"
/>
>
Not available
</span>
</div>
<svg
aria-hidden="true"
Expand Down
50 changes: 50 additions & 0 deletions airbyte-webapp/src/components/ui/InfoText/InfoText.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
@use "scss/colors";
@use "scss/variables";

.container {
height: 19px;
max-width: 100%;
display: flex;
flex-direction: row;
align-items: center;
padding: 0;
border: none;
border-radius: variables.$border-radius-pill;
cursor: pointer;

&.grey {
.text {
color: colors.$grey-600;
}
}

&.blue {
.text {
color: colors.$blue-600;
}
}

&.green {
.text {
color: colors.$green-600;
}
}

&.red {
.text {
color: colors.$red-600;
}
}

&.lightGrey {
.text {
color: colors.$grey;
}
}

&.lightBlue {
.text {
color: colors.$blue-50;
}
}
}
31 changes: 31 additions & 0 deletions airbyte-webapp/src/components/ui/InfoText/InfoText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import classNames from "classnames";

import { Text } from "../Text";
import styles from "./InfoText.module.scss";

export type InfoTextVariant = "grey" | "light-grey" | "red" | "green" | "blue" | "light-blue";

const STYLES_BY_VARIANT: Readonly<Record<InfoTextVariant, string>> = {
grey: styles.grey,
blue: styles.blue,
green: styles.green,
red: styles.red,
"light-blue": styles.lightBlue,
"light-grey": styles.lightGrey,
};

interface InfoTextProps {
variant?: InfoTextVariant;
className?: string;
}

export const InfoText: React.FC<InfoTextProps> = ({ children, variant = "grey", className }) => {
const containerClassName = classNames(styles.container, STYLES_BY_VARIANT[variant], className);
return (
<div className={containerClassName}>
<Text as="span" size="xs" className={styles.text}>
{children}
</Text>
</div>
);
};
11 changes: 11 additions & 0 deletions airbyte-webapp/src/components/ui/InfoText/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PillButtonVariant } from "../PillSelect";
import { InfoTextVariant } from "./InfoText";

export const INFO_TEXT_VARIANT_BY_PILL_VARIANT: Record<PillButtonVariant, InfoTextVariant> = {
blue: "blue",
grey: "grey",
red: "red",
green: "green",
"strong-red": "red",
"strong-blue": "blue",
};
20 changes: 20 additions & 0 deletions airbyte-webapp/src/components/ui/InfoText/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ComponentStory, ComponentMeta } from "@storybook/react";

import { InfoText } from "./InfoText";

export default {
title: "UI/InfoText",
component: InfoText,
} as ComponentMeta<typeof InfoText>;

const Template: ComponentStory<typeof InfoText> = (args) => (
<div style={{ width: "300px" }}>
<InfoText {...args} />
</div>
);

export const InfoTextDefault = Template.bind({});
InfoTextDefault.args = {
variant: "grey",
children: "test",
};
2 changes: 2 additions & 0 deletions airbyte-webapp/src/components/ui/InfoText/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { InfoText } from "./InfoText";
export * from "./constants";
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
color: $text;
}

pointer-events: none;
background-color: $background;
}
}
Expand Down
7 changes: 5 additions & 2 deletions airbyte-webapp/src/components/ui/PillSelect/PillSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from "react";

import { Popout, PopoutProps } from "../Popout";
import { Tooltip } from "../Tooltip";
import { PillButton, PillButtonVariant } from "./PillButton";
Expand All @@ -7,10 +9,11 @@ type PickedPopoutProps = Pick<PopoutProps, "value" | "options" | "isMulti" | "on
interface PillSelectProps extends PickedPopoutProps {
variant?: PillButtonVariant;
disabled?: boolean;
disabledLabel?: React.ReactNode;
hasError?: boolean;
}

export const PillSelect: React.FC<PillSelectProps> = ({ className, ...props }) => {
export const PillSelect: React.FC<PillSelectProps> = ({ className, disabledLabel, ...props }) => {
const { isMulti, variant, disabled } = props;
return (
<Popout
Expand All @@ -36,7 +39,7 @@ export const PillSelect: React.FC<PillSelectProps> = ({ className, ...props }) =
className={className}
hasError={props?.hasError}
>
{label}
{(disabled && disabledLabel) || label}
</PillButton>
}
placement="bottom-start"
Expand Down
1 change: 1 addition & 0 deletions airbyte-webapp/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
"connectionForm.defaultSyncMode.message": "Set how Airbyte reads from the source and writes to the destination, across all streams <b>when the option is available</b>.",
"connectionForm.bulkEdit.cancel": "Cancel",
"connectionForm.bulkEdit.apply": "Apply",
"connectionForm.bulkEdit.pillButtonLabel.notAvailable": "Not available",
"connectionForm.nonBreakingChangesPreference.label": "Non-breaking schema updates detected*",
"connectionForm.nonBreakingChangesPreference.message": "Set how Airbyte handles syncs when it detects a non-breaking schema change in the source",
"connectionForm.nonBreakingChangesPreference.ignore": "Ignore",
Expand Down

0 comments on commit 94fcb13

Please sign in to comment.