diff --git a/airbyte-webapp/src/components/EntityTable/ConnectionTable.module.scss b/airbyte-webapp/src/components/EntityTable/ConnectionTable.module.scss index 909820b5e170..261da7bd7e4b 100644 --- a/airbyte-webapp/src/components/EntityTable/ConnectionTable.module.scss +++ b/airbyte-webapp/src/components/EntityTable/ConnectionTable.module.scss @@ -1,10 +1,11 @@ -.tableHeaderButton { - background-color: inherit; - border: none; - color: inherit; - cursor: pointer; - font-size: inherit; - font-weight: inherit; - text-transform: inherit; - white-space: nowrap; +th.width30 { + width: 30%; +} + +.thEnabled { + width: 1%; +} + +.thConnectionSettings { + width: 1%; } diff --git a/airbyte-webapp/src/components/EntityTable/ConnectionTable.tsx b/airbyte-webapp/src/components/EntityTable/ConnectionTable.tsx index 18c0f4b3777c..4bf7c0644f52 100644 --- a/airbyte-webapp/src/components/EntityTable/ConnectionTable.tsx +++ b/airbyte-webapp/src/components/EntityTable/ConnectionTable.tsx @@ -1,10 +1,10 @@ +import { createColumnHelper } from "@tanstack/react-table"; import queryString from "query-string"; import React, { useCallback } from "react"; import { FormattedMessage } from "react-intl"; import { useNavigate } from "react-router-dom"; -import { CellProps } from "react-table"; -import { Table, SortableTableHeader } from "components/ui/Table"; +import { SortableTableHeader } from "components/ui/Table"; import { ConnectionScheduleType, SchemaChange } from "core/request/AirbyteClient"; import { FeatureItem, useFeature } from "hooks/services/Feature"; @@ -16,15 +16,17 @@ import { ConnectorNameCell } from "./components/ConnectorNameCell"; import { FrequencyCell } from "./components/FrequencyCell"; import { LastSyncCell } from "./components/LastSyncCell"; import { StatusCell } from "./components/StatusCell"; -import { ITableDataItem, SortOrderEnum } from "./types"; +import styles from "./ConnectionTable.module.scss"; +import { ConnectionTableDataItem, SortOrderEnum } from "./types"; +import { NextTable } from "../ui/NextTable"; -interface IProps { - data: ITableDataItem[]; +interface ConnectionTableProps { + data: ConnectionTableDataItem[]; entity: "source" | "destination" | "connection"; - onClickRow?: (data: ITableDataItem) => void; + onClickRow?: (data: ConnectionTableDataItem) => void; } -const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { +const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { const navigate = useNavigate(); const query = useQuery<{ sortBy?: string; order?: SortOrderEnum }>(); const allowAutoDetectSchema = useFeature(FeatureItem.AllowAutoDetectSchema); @@ -70,10 +72,12 @@ const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { const sortingData = React.useMemo(() => data.sort(sortData), [sortData, data]); + const columnHelper = createColumnHelper(); + const columns = React.useMemo( () => [ - { - Header: ( + columnHelper.accessor("name", { + header: () => ( onSortClick("name")} isActive={sortBy === "name"} @@ -82,20 +86,20 @@ const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { ), - headerHighlighted: true, - accessor: "name", - customWidth: 30, - responsive: true, - Cell: ({ cell, row }: CellProps) => ( + meta: { + thClassName: styles.width30, + responsive: true, + }, + cell: (props) => ( ), - }, - { - Header: ( + }), + columnHelper.accessor("entityName", { + header: () => ( onSortClick("entityName")} isActive={sortBy === "entityName"} @@ -106,16 +110,20 @@ const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { /> ), - headerHighlighted: true, - accessor: "entityName", - customWidth: 30, - responsive: true, - Cell: ({ cell, row }: CellProps) => ( - + meta: { + thClassName: styles.width30, + responsive: true, + }, + cell: (props) => ( + ), - }, - { - Header: ( + }), + columnHelper.accessor("connectorName", { + header: () => ( onSortClick("connectorName")} isActive={sortBy === "connectorName"} @@ -124,22 +132,30 @@ const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { ), - accessor: "connectorName", - customWidth: 30, - responsive: true, - Cell: ({ cell, row }: CellProps) => ( - + meta: { + thClassName: styles.width30, + responsive: true, + }, + cell: (props) => ( + ), - }, - { - Header: , - accessor: "scheduleData", - Cell: ({ cell, row }: CellProps) => ( - + }), + columnHelper.accessor("scheduleData", { + header: () => , + cell: (props) => ( + ), - }, - { - Header: ( + }), + columnHelper.accessor("lastSync", { + header: () => ( onSortClick("lastSync")} isActive={sortBy === "lastSync"} @@ -148,38 +164,37 @@ const ConnectionTable: React.FC = ({ data, entity, onClickRow }) => { ), - accessor: "lastSync", - Cell: ({ cell, row }: CellProps) => ( - - ), - }, - { - Header: , - accessor: "enabled", - customWidth: 1, - Cell: ({ cell, row }: CellProps) => ( + cell: (props) => , + }), + columnHelper.accessor("enabled", { + header: () => , + meta: { + thClassName: styles.thEnabled, + }, + cell: (props) => ( ), - }, - { - Header: "", - accessor: "connectionId", - customWidth: 1, - Cell: ({ cell }: CellProps) => , - }, + }), + columnHelper.accessor("connectionId", { + header: "", + meta: { + thClassName: styles.thConnectionSettings, + }, + cell: (props) => , + }), ], - [sortBy, sortOrder, entity, onSortClick, allowSync, allowAutoDetectSchema] + [columnHelper, sortBy, sortOrder, onSortClick, entity, allowAutoDetectSchema, allowSync] ); - return ; + return ; }; export default ConnectionTable; diff --git a/airbyte-webapp/src/components/EntityTable/ImplementationTable.module.scss b/airbyte-webapp/src/components/EntityTable/ImplementationTable.module.scss index 798678056755..f196a5fbb0db 100644 --- a/airbyte-webapp/src/components/EntityTable/ImplementationTable.module.scss +++ b/airbyte-webapp/src/components/EntityTable/ImplementationTable.module.scss @@ -3,3 +3,7 @@ padding-left: 32px !important; } } + +.thEntityName { + width: 40%; +} diff --git a/airbyte-webapp/src/components/EntityTable/ImplementationTable.tsx b/airbyte-webapp/src/components/EntityTable/ImplementationTable.tsx index aad9fc831f87..0f70ee0daa76 100644 --- a/airbyte-webapp/src/components/EntityTable/ImplementationTable.tsx +++ b/airbyte-webapp/src/components/EntityTable/ImplementationTable.tsx @@ -1,10 +1,11 @@ +import { createColumnHelper } from "@tanstack/react-table"; import queryString from "query-string"; import React, { useCallback } from "react"; import { FormattedMessage } from "react-intl"; import { useNavigate } from "react-router-dom"; -import { CellProps } from "react-table"; -import { Table, SortableTableHeader } from "components/ui/Table"; +import { NextTable } from "components/ui/NextTable"; +import { SortableTableHeader } from "components/ui/Table"; import { useQuery } from "hooks/useQuery"; @@ -64,10 +65,13 @@ const ImplementationTable: React.FC = ({ data, entity, onClickRow }) => ); const sortingData = React.useMemo(() => data.sort(sortData), [sortData, data]); + + const columnHelper = createColumnHelper(); + const columns = React.useMemo( () => [ - { - Header: ( + columnHelper.accessor("entityName", { + header: () => ( onSortClick("entity")} isActive={sortBy === "entity"} @@ -76,15 +80,13 @@ const ImplementationTable: React.FC = ({ data, entity, onClickRow }) => ), - headerHighlighted: true, - accessor: "entityName", - customWidth: 40, - Cell: ({ cell, row }: CellProps) => ( - - ), - }, - { - Header: ( + meta: { + thClassName: styles.thEntityName, + }, + cell: (props) => , + }), + columnHelper.accessor("connectorName", { + header: () => ( onSortClick("connector")} isActive={sortBy === "connector"} @@ -93,20 +95,22 @@ const ImplementationTable: React.FC = ({ data, entity, onClickRow }) => ), - accessor: "connectorName", - Cell: ({ cell, row }: CellProps) => ( - + cell: (props) => ( + ), - }, - { - Header: , - accessor: "connectEntities", - Cell: ({ cell, row }: CellProps) => ( - + }), + columnHelper.accessor("connectEntities", { + header: () => , + cell: (props) => ( + ), - }, - { - Header: ( + }), + columnHelper.accessor("lastSync", { + header: () => ( onSortClick("lastSync")} isActive={sortBy === "lastSync"} @@ -115,24 +119,22 @@ const ImplementationTable: React.FC = ({ data, entity, onClickRow }) => ), - accessor: "lastSync", - Cell: ({ cell, row }: CellProps) => ( - + cell: (props) => ( + ), - }, - { - Header: , + }), + columnHelper.accessor("connectEntities", { + header: () => , id: "status", - accessor: "connectEntities", - Cell: ({ cell }: CellProps) => , - }, + cell: (props) => , + }), ], - [entity, onSortClick, sortBy, sortOrder] + [columnHelper, entity, onSortClick, sortBy, sortOrder] ); return (
-
+ ); }; diff --git a/airbyte-webapp/src/components/EntityTable/components/AllConnectionsStatusCell.tsx b/airbyte-webapp/src/components/EntityTable/components/AllConnectionsStatusCell.tsx index d4aaeb2c3f46..e37d11e5ebf7 100644 --- a/airbyte-webapp/src/components/EntityTable/components/AllConnectionsStatusCell.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/AllConnectionsStatusCell.tsx @@ -17,7 +17,7 @@ interface AllConnectionStatusConnectEntity { name: string; connector: string; status: string; - lastSyncStatus: string; + lastSyncStatus: string | null; } interface AllConnectionsStatusCellProps { diff --git a/airbyte-webapp/src/components/EntityTable/components/FrequencyCell.tsx b/airbyte-webapp/src/components/EntityTable/components/FrequencyCell.tsx index 3a9e18f431cc..337581be2c3b 100644 --- a/airbyte-webapp/src/components/EntityTable/components/FrequencyCell.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/FrequencyCell.tsx @@ -9,7 +9,7 @@ import { ConnectionScheduleData, ConnectionScheduleType } from "core/request/Air import styles from "./FrequencyCell.module.scss"; interface FrequencyCellProps { - value: ConnectionScheduleData; + value?: ConnectionScheduleData; enabled?: boolean; scheduleType?: ConnectionScheduleType; } @@ -26,8 +26,8 @@ export const FrequencyCell: React.FC = ({ value, enabled, sc return ( ); diff --git a/airbyte-webapp/src/components/EntityTable/components/LastSyncCell.tsx b/airbyte-webapp/src/components/EntityTable/components/LastSyncCell.tsx index 3dac28390a86..5bff2c57eddb 100644 --- a/airbyte-webapp/src/components/EntityTable/components/LastSyncCell.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/LastSyncCell.tsx @@ -7,16 +7,16 @@ import { Text } from "components/ui/Text"; import styles from "./LastSyncCell.module.scss"; interface LastSyncCellProps { - timeInSecond: number; + timeInSeconds?: number | null; enabled?: boolean; } -export const LastSyncCell: React.FC = ({ timeInSecond, enabled }) => { +export const LastSyncCell: React.FC = ({ timeInSeconds, enabled }) => { return ( <> - {timeInSecond ? ( + {timeInSeconds ? ( - + ) : null} diff --git a/airbyte-webapp/src/components/EntityTable/types.ts b/airbyte-webapp/src/components/EntityTable/types.ts index fee917847008..a92e84b853c3 100644 --- a/airbyte-webapp/src/components/EntityTable/types.ts +++ b/airbyte-webapp/src/components/EntityTable/types.ts @@ -15,7 +15,7 @@ interface EntityTableDataItem { connectorIcon?: string; } -interface ITableDataItem { +interface ConnectionTableDataItem { connectionId: string; name: string; entityName: string; @@ -46,5 +46,5 @@ enum SortOrderEnum { ASC = "asc", } -export type { ITableDataItem, EntityTableDataItem }; +export type { ConnectionTableDataItem, EntityTableDataItem }; export { Status, SortOrderEnum }; diff --git a/airbyte-webapp/src/components/EntityTable/utils.tsx b/airbyte-webapp/src/components/EntityTable/utils.tsx index fa9c18b81acb..896d49dc3dbb 100644 --- a/airbyte-webapp/src/components/EntityTable/utils.tsx +++ b/airbyte-webapp/src/components/EntityTable/utils.tsx @@ -8,7 +8,7 @@ import { WebBackendConnectionListItem, } from "core/request/AirbyteClient"; -import { EntityTableDataItem, ITableDataItem, Status as ConnectionSyncStatus } from "./types"; +import { EntityTableDataItem, ConnectionTableDataItem, Status as ConnectionSyncStatus } from "./types"; const getConnectorTypeName = (connectorSpec: DestinationSnippetRead | SourceSnippetRead) => { return "sourceName" in connectorSpec ? connectorSpec.sourceName : connectorSpec.destinationName; @@ -74,7 +74,7 @@ export function getEntityTableData< export const getConnectionTableData = ( connections: WebBackendConnectionListItem[], type: "source" | "destination" | "connection" -): ITableDataItem[] => { +): ConnectionTableDataItem[] => { const connectType = type === "source" ? "destination" : "source"; return connections.map((connection) => ({ diff --git a/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.module.scss b/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.module.scss index 977725382454..fb58898d1bf1 100644 --- a/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.module.scss +++ b/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.module.scss @@ -4,6 +4,7 @@ $cell-height: 28px; $cell-padding: variables.$spacing-xl + variables.$spacing-sm; $cell-fixed-width: 100px; +$arrow-cell-fixed-width: 40px; .customTableStyle { td { @@ -12,27 +13,28 @@ $cell-fixed-width: 100px; } .headerGroupCell { - height: 58px; - background-color: colors.$white; - color: colors.$dark-blue; - font-weight: 700; - font-size: 16px; - line-height: $cell-height; - text-transform: capitalize; + &.light { + height: 58px; + color: colors.$dark-blue; + font-weight: 700; + font-size: 16px; + line-height: $cell-height; + text-transform: capitalize; + background-color: colors.$white; + } &:first-child { padding-left: $cell-padding; border-radius: 0; } - &:last-child { + &:not(:first-child) { padding-left: 0; } } .headerCell { color: colors.$grey; - background-color: colors.$grey-50; height: $cell-height; font-weight: 400; font-size: 12px; @@ -49,7 +51,7 @@ $cell-fixed-width: 100px; border-radius: 0; } - &:last-child { + &:not(:first-child) { padding-left: 0; border-radius: 0; } @@ -57,12 +59,11 @@ $cell-fixed-width: 100px; %bodyCell { height: $cell-height; - padding: 0; + padding: 0 $cell-padding 0 0; &:first-child { padding-left: $cell-padding; border-radius: 0; - min-width: 130px; } &:last-child { @@ -70,11 +71,18 @@ $cell-fixed-width: 100px; } } +.syncCell { + @extend %bodyCell; + + min-width: 0; +} + .textCell { @extend %bodyCell; color: colors.$dark-blue; max-width: 0; + min-width: 140px; } .dataTypeCell { @@ -98,6 +106,8 @@ $cell-fixed-width: 100px; .arrowCell { @extend %bodyCell; + width: $arrow-cell-fixed-width; + svg { color: colors.$grey-200; } diff --git a/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.tsx b/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.tsx index 4ad806d1e57c..5f7491f962eb 100644 --- a/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.tsx +++ b/airbyte-webapp/src/components/connection/CatalogTree/next/StreamDetailsPanel/StreamFieldsTable/StreamFieldsTable.tsx @@ -149,7 +149,7 @@ export const StreamFieldsTable: React.FC = ({ ), meta: { thClassName: classNames(styles.headerCell, styles["headerCell--syncCell"]), - tdClassName: styles.textCell, + tdClassName: styles.syncCell, }, }), ] @@ -260,7 +260,7 @@ export const StreamFieldsTable: React.FC = ({ header: () => , columns: sourceColumns, meta: { - thClassName: styles.headerGroupCell, + thClassName: classNames(styles.headerGroupCell, styles.light), }, }), columnHelper.group({ @@ -277,7 +277,7 @@ export const StreamFieldsTable: React.FC = ({ }, ], meta: { - thClassName: styles.headerGroupCell, + thClassName: classNames(styles.headerGroupCell, styles.light), }, }), columnHelper.group({ @@ -285,7 +285,7 @@ export const StreamFieldsTable: React.FC = ({ header: () => , columns: destinationColumns, meta: { - thClassName: styles.headerGroupCell, + thClassName: classNames(styles.headerGroupCell, styles.light), tdClassName: styles.bodyCell, }, }), @@ -293,5 +293,5 @@ export const StreamFieldsTable: React.FC = ({ [columnHelper, destination.icon, destinationColumns, source.icon, sourceColumns] ); - return columns={columns} data={tableData} className={styles.customTableStyle} />; + return light columns={columns} data={tableData} className={styles.customTableStyle} />; }; diff --git a/airbyte-webapp/src/components/connection/ConnectionForm/formConfig.tsx b/airbyte-webapp/src/components/connection/ConnectionForm/formConfig.tsx index 9606b700a6ee..915f11996f41 100644 --- a/airbyte-webapp/src/components/connection/ConnectionForm/formConfig.tsx +++ b/airbyte-webapp/src/components/connection/ConnectionForm/formConfig.tsx @@ -401,7 +401,7 @@ export const useInitialValues = ( initialValues.transformations = getInitialTransformations(operations); } - if (destDefinition.normalizationConfig.supported) { + if (destDefinition.normalizationConfig?.supported) { initialValues.normalization = getInitialNormalization(operations, isNotCreateMode); } diff --git a/airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.tsx b/airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.tsx index 01cd505877ff..5d6e11af1eea 100644 --- a/airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.tsx +++ b/airbyte-webapp/src/components/destination/DestinationConnectionTable/DestinationConnectionTable.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useNavigate } from "react-router-dom"; import { ConnectionTable } from "components/EntityTable"; -import { ITableDataItem } from "components/EntityTable/types"; +import { ConnectionTableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; import { WebBackendConnectionListItem } from "core/request/AirbyteClient"; @@ -19,7 +19,8 @@ export const DestinationConnectionTable: React.FC = ({ connections }) => const data = getConnectionTableData(connections, "destination"); - const clickRow = (source: ITableDataItem) => navigate(`../../../${RoutePaths.Connections}/${source.connectionId}`); + const clickRow = (source: ConnectionTableDataItem) => + navigate(`../../../${RoutePaths.Connections}/${source.connectionId}`); return (
diff --git a/airbyte-webapp/src/components/ui/NextTable/NextTable.module.scss b/airbyte-webapp/src/components/ui/NextTable/NextTable.module.scss index c1ee9ea51440..28292a0fd1ba 100644 --- a/airbyte-webapp/src/components/ui/NextTable/NextTable.module.scss +++ b/airbyte-webapp/src/components/ui/NextTable/NextTable.module.scss @@ -8,6 +8,11 @@ width: 100%; max-width: 100%; border-radius: variables.$border-radius-md; + box-shadow: 0 2px 4px colors.$cardShadowColor; + + &.light { + box-shadow: none; + } } .thead { @@ -18,14 +23,27 @@ // ---------
--------- .th { - background: colors.$grey-50; - color: colors.$grey; + background: colors.$dark-blue; + color: colors.$white; text-transform: uppercase; border-bottom: none; text-align: left; font-size: 10px; line-height: 12px; font-weight: 600; + width: auto; + padding: variables.$spacing-md variables.$spacing-lg variables.$spacing-md; + + &.light { + color: colors.$grey; + background-color: colors.$grey-50; + text-transform: capitalize; + border-bottom: none; + text-align: left; + font-size: 11px; + line-height: 12px; + font-weight: 400; + } &:first-child { padding-left: calc(variables.$spacing-2xl + variables.$spacing-sm); @@ -34,7 +52,7 @@ &:last-child { padding-left: variables.$spacing-lg; - border-radius: 0 variables.$border-radius-md 0 0; + border-radius: 0 variables.$spacing-md 0 0; } } @@ -43,6 +61,10 @@ background: colors.$white; cursor: auto; + &.clickable { + cursor: pointer; + } + &:hover { background-color: colors.$grey-50; } @@ -62,6 +84,10 @@ border-bottom: variables.$border-thin solid colors.$grey-100; width: auto; + &.responsive { + max-width: 0; + } + tr:last-child > & { border-bottom: none; diff --git a/airbyte-webapp/src/components/ui/NextTable/NextTable.tsx b/airbyte-webapp/src/components/ui/NextTable/NextTable.tsx index 0c3276a6d195..1643964d341f 100644 --- a/airbyte-webapp/src/components/ui/NextTable/NextTable.tsx +++ b/airbyte-webapp/src/components/ui/NextTable/NextTable.tsx @@ -4,14 +4,25 @@ import { PropsWithChildren } from "react"; import styles from "./NextTable.module.scss"; -export interface TableProps { - data: TData[]; - columns: Array>; - onClickRow?: (data: unknown) => void; +export interface TableProps { className?: string; + // We can leave type any here since useReactTable options.columns itself is waiting for Array> + // eslint-disable-next-line @typescript-eslint/no-explicit-any + columns: Array>; + data: T[]; + light?: boolean; + onClickRow?: (data: T) => void; + testId?: string; } -export const NextTable = ({ columns, data, onClickRow, className }: PropsWithChildren>) => { +export const NextTable = ({ + testId, + className, + columns, + data, + light, + onClickRow, +}: PropsWithChildren>) => { const table = useReactTable({ columns, data, @@ -19,35 +30,52 @@ export const NextTable = ({ columns, data, onClickRow, className }: Prop }); return ( - +
{table.getHeaderGroups().map((headerGroup) => ( - {headerGroup.headers.map((header) => ( - - ))} + {headerGroup.headers.map((header) => { + const { meta } = header.column.columnDef; + return ( + + ); + })} ))} - {table.getRowModel().rows.map((row) => ( - onClickRow?.(row.original)}> - {row.getVisibleCells().map((cell) => ( - - ))} - - ))} + {table.getRowModel().rows.map((row) => { + return ( + onClickRow?.(row.original)} + > + {row.getVisibleCells().map((cell) => ( + + ))} + + ); + })}
- {flexRender(header.column.columnDef.header, header.getContext())} - + {flexRender(header.column.columnDef.header, header.getContext())} +
- {flexRender(cell.column.columnDef.cell, cell.getContext())} -
+ {flexRender(cell.column.columnDef.cell, cell.getContext())} +
); diff --git a/airbyte-webapp/src/components/ui/NextTable/index.stories.tsx b/airbyte-webapp/src/components/ui/NextTable/index.stories.tsx index f50a67933058..2fea40bd3fb0 100644 --- a/airbyte-webapp/src/components/ui/NextTable/index.stories.tsx +++ b/airbyte-webapp/src/components/ui/NextTable/index.stories.tsx @@ -1,5 +1,5 @@ import { ComponentMeta, Story } from "@storybook/react"; -import { ColumnDef } from "@tanstack/react-table"; +import { createColumnHelper } from "@tanstack/react-table"; import { NextTable, TableProps } from "./NextTable"; @@ -27,17 +27,17 @@ const data: Item[] = [ { name: "2021", value: 200 }, ]; -const columns: Array> = [ - { +const columnHelper = createColumnHelper(); + +const columns = [ + columnHelper.accessor("name", { header: "Name", - accessorKey: "name", cell: ({ getValue }) => {getValue()}, - }, - { + }), + columnHelper.accessor("value", { header: "Value", - accessorKey: "value", cell: ({ getValue }) => getValue(), - }, + }), ]; export const Primary = Template().bind({}); diff --git a/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.module.scss b/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.module.scss index 4dd6c7628b1e..dfc9be48a4f7 100644 --- a/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.module.scss +++ b/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.module.scss @@ -1,4 +1,5 @@ @use "scss/variables"; +@use "scss/colors"; .content { padding: 0 variables.$spacing-2xl 0 variables.$spacing-lg; @@ -8,3 +9,33 @@ padding-right: 10px; min-width: 53px; } + +%lightBackgroundOverride { + &.light { + background-color: colors.$white; + } +} + +.thConnection { + @extend %lightBackgroundOverride; + + width: 30%; +} + +.thCreditsConsumed { + @extend %lightBackgroundOverride; + + padding-right: 0; +} + +.thCreditsConsumedPercent { + @extend %lightBackgroundOverride; + + padding-left: 0; +} + +.thConnectionId { + @extend %lightBackgroundOverride; + + width: 20%; +} diff --git a/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.tsx b/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.tsx index 45ff4f0209a6..607994b81248 100644 --- a/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.tsx +++ b/airbyte-webapp/src/packages/cloud/views/credits/CreditsPage/components/UsagePerConnectionTable.tsx @@ -1,11 +1,13 @@ +import { createColumnHelper } from "@tanstack/react-table"; +import classNames from "classnames"; import queryString from "query-string"; import React, { useCallback } from "react"; import { FormattedMessage, FormattedNumber } from "react-intl"; import { useNavigate } from "react-router-dom"; -import { CellProps } from "react-table"; import { SortOrderEnum } from "components/EntityTable/types"; -import { Table, SortableTableHeader } from "components/ui/Table"; +import { NextTable } from "components/ui/NextTable"; +import { SortableTableHeader } from "components/ui/Table"; import { Text } from "components/ui/Text"; import { useQuery } from "hooks/useQuery"; @@ -23,8 +25,8 @@ interface UsagePerConnectionTableProps { type FullTableProps = CreditConsumptionByConnector & { creditsConsumedPercent: number; - sourceIcon: string; - destinationIcon: string; + sourceIcon?: string; + destinationIcon?: string; }; const UsagePerConnectionTable: React.FC = ({ creditConsumption }) => { @@ -33,7 +35,7 @@ const UsagePerConnectionTable: React.FC = ({ credi const { sourceDefinitions } = useSourceDefinitionList(); const { destinationDefinitions } = useDestinationDefinitionList(); - const creditConsumptionWithPercent = React.useMemo(() => { + const creditConsumptionWithPercent = React.useMemo(() => { const sumCreditsConsumed = creditConsumption.reduce((a, b) => a + b.creditsConsumed, 0); return creditConsumption.map((item) => { const currentSourceDefinition = sourceDefinitions.find( @@ -42,13 +44,14 @@ const UsagePerConnectionTable: React.FC = ({ credi const currentDestinationDefinition = destinationDefinitions.find( (def) => def.destinationDefinitionId === item.destinationDefinitionId ); - - return { + const newItem: FullTableProps = { ...item, sourceIcon: currentSourceDefinition?.icon, destinationIcon: currentDestinationDefinition?.icon, creditsConsumedPercent: sumCreditsConsumed ? (item.creditsConsumed / sumCreditsConsumed) * 100 : 0, }; + + return newItem; }); }, [creditConsumption, sourceDefinitions, destinationDefinitions]); @@ -91,14 +94,21 @@ const UsagePerConnectionTable: React.FC = ({ credi ); const sortingData = React.useMemo( - () => creditConsumptionWithPercent.sort(sortData), + // This is temporary solution, since there is an issue with array that + // creditConsumptionWithPercent.sort(sortData) returns; when passed into useReactTable + // the reference to this array stays the same, so useReactTable is not updating the table, + // therefore sorting not working; after implementing native react table sorting mechanism + // this problem should be solved + () => [...creditConsumptionWithPercent.sort(sortData)], [sortData, creditConsumptionWithPercent] ); + const columnHelper = createColumnHelper(); + const columns = React.useMemo( () => [ - { - Header: ( + columnHelper.accessor("sourceDefinitionName", { + header: () => ( onSortClick("connection")} isActive={sortBy === "connection"} @@ -107,19 +117,20 @@ const UsagePerConnectionTable: React.FC = ({ credi ), - customWidth: 30, - accessor: "sourceDefinitionName", - Cell: ({ cell, row }: CellProps) => ( + meta: { + thClassName: classNames(styles.thConnection, styles.light), + }, + cell: (props) => ( ), - }, - { - Header: ( + }), + columnHelper.accessor("creditsConsumed", { + header: () => ( onSortClick("usage")} isActive={sortBy === "usage"} @@ -128,35 +139,36 @@ const UsagePerConnectionTable: React.FC = ({ credi ), - accessor: "creditsConsumed", - collapse: true, - customPadding: { right: 0 }, - Cell: ({ cell }: CellProps) => ( + meta: { + thClassName: classNames(styles.thCreditsConsumed, styles.light), + }, + cell: (props) => ( - + ), - }, - { - Header: "", - accessor: "creditsConsumedPercent", - customPadding: { left: 0 }, - Cell: ({ cell }: CellProps) => , - }, - // TODO: Replace to Grow column - { - Header: "", - accessor: "connectionId", - Cell:
, - customWidth: 20, - }, + }), + columnHelper.accessor("creditsConsumedPercent", { + header: "", + meta: { + thClassName: classNames(styles.thCreditsConsumedPercent, styles.light), + }, + cell: (props) => , + }), + columnHelper.accessor("connectionId", { + header: "", + cell: () =>
, + meta: { + thClassName: classNames(styles.thConnectionId, styles.light), + }, + }), ], - [onSortClick, sortBy, sortOrder] + [columnHelper, onSortClick, sortBy, sortOrder] ); return (
- + ); }; diff --git a/airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.tsx b/airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.tsx index 8c624dc0b524..3cd3f94e2f16 100644 --- a/airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.tsx +++ b/airbyte-webapp/src/packages/cloud/views/users/UsersSettingsView/UsersSettingsView.tsx @@ -1,12 +1,12 @@ import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { createColumnHelper } from "@tanstack/react-table"; import React, { useMemo } from "react"; import { FormattedMessage } from "react-intl"; -import { CellProps } from "react-table"; import { Button } from "components/ui/Button"; import { Heading } from "components/ui/Heading"; -import { Table } from "components/ui/Table"; +import { NextTable } from "components/ui/NextTable"; import { useTrackPage, PageTrackingCodes } from "hooks/services/Analytics"; import { useConfirmationModalService } from "hooks/services/ConfirmationModal"; @@ -71,20 +71,18 @@ export const UsersTable: React.FC = () => { const users = useListUsers(); const { user } = useAuthService(); + const columnHelper = createColumnHelper(); + const columns = useMemo( () => [ - { - Header: , - headerHighlighted: true, - accessor: "name", - Cell: ({ cell }: CellProps) => cell.value, - }, - { - Header: , - headerHighlighted: true, - accessor: "email", - Cell: ({ cell }: CellProps) => cell.value, - }, + columnHelper.accessor("name", { + header: () => , + cell: (props) => props.cell.getValue(), + }), + columnHelper.accessor("email", { + header: () => , + cell: (props) => props.cell.getValue(), + }), // TEMP: Currently all cloud users are admins. // Remove when there is more than role // { @@ -98,22 +96,20 @@ export const UsersTable: React.FC = () => { // accessor: "userId", // Cell: (_: CellProps) => "Admin", // }, - { - Header: , - headerHighlighted: true, - accessor: "status", - Cell: ({ row }: CellProps) => + columnHelper.accessor("status", { + header: () => , + cell: (props) => [ - user?.userId !== row.original.userId ? ( - + user?.userId !== props.row.original.userId ? ( + ) : null, ].filter(Boolean), - }, + }), ], - [workspaceId, user] + [columnHelper, user?.userId, workspaceId] ); - return
; + return ; }; export const UsersSettingsView: React.VFC = () => { diff --git a/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.module.scss b/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.module.scss index 762f089d5f29..7a531a29e5a6 100644 --- a/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.module.scss +++ b/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.module.scss @@ -11,3 +11,15 @@ padding-bottom: variables.$spacing-sm; } } + +.thName { + width: 25%; +} + +.thDockerRepository { + width: 36%; +} + +.thDockerImageTag { + width: 10%; +} diff --git a/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.tsx b/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.tsx index 9b6a6638609c..2bcd6fe1fa2f 100644 --- a/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.tsx +++ b/airbyte-webapp/src/pages/SettingsPage/pages/ConnectorsPage/components/ConnectorsView.tsx @@ -1,11 +1,11 @@ +import { createColumnHelper } from "@tanstack/react-table"; import { useCallback, useMemo } from "react"; import { FormattedMessage } from "react-intl"; -import { CellProps } from "react-table"; import { HeadTitle } from "components/common/HeadTitle"; import { FlexContainer, FlexItem } from "components/ui/Flex"; import { Heading } from "components/ui/Heading"; -import { Table } from "components/ui/Table"; +import { NextTable } from "components/ui/NextTable"; import { Connector, ConnectorDefinition } from "core/domain/connector"; import { DestinationDefinitionRead, SourceDefinitionRead } from "core/request/AirbyteClient"; @@ -35,8 +35,6 @@ interface ConnectorsViewProps { feedbackList: Record; } -const defaultSorting = [{ id: "name" }]; - const ConnectorsView: React.FC = ({ type, onUpdateVersion, @@ -70,58 +68,59 @@ const ConnectorsView: React.FC = ({ [allowUpdateConnectors, allowUploadCustomImage] ); + const columnHelper = createColumnHelper(); + const renderColumns = useCallback( (showVersionUpdateColumn: boolean) => [ - { - Header: , - accessor: "name", - customWidth: 25, - Cell: ({ cell, row }: CellProps) => ( + columnHelper.accessor("name", { + header: () => , + meta: { + thClassName: styles.thName, + }, + cell: (props) => ( ), - }, - { - Header: , - accessor: "dockerRepository", - customWidth: 36, - Cell: ({ cell, row }: CellProps) => ( - - ), - }, - { - Header: , - accessor: "dockerImageTag", - customWidth: 10, - }, + }), + columnHelper.accessor("dockerRepository", { + header: () => , + meta: { + thClassName: styles.thDockerRepository, + }, + cell: (props) => , + }), + columnHelper.accessor("dockerImageTag", { + header: () => , + meta: { + thClassName: styles.thDockerImageTag, + }, + }), ...(showVersionUpdateColumn ? [ - { - Header: ( + columnHelper.accessor("latestDockerImageTag", { + header: () => (
), - accessor: "latestDockerImageTag", - collapse: true, - Cell: ({ cell, row }: CellProps) => - allowUpdateConnectors || (allowUploadCustomImage && row.original.releaseStage === "custom") ? ( + cell: (props) => + allowUpdateConnectors || (allowUploadCustomImage && props.row.original.releaseStage === "custom") ? ( ) : null, - }, + }), ] : []), ], - [allowUpdateConnectors, allowUploadCustomImage, onUpdateVersion] + [columnHelper, allowUpdateConnectors, allowUploadCustomImage, onUpdateVersion] ); const renderHeaderControls = (section: "used" | "available") => @@ -174,7 +173,7 @@ const ConnectorsView: React.FC = ({ {renderHeaderControls("used")} -
+ )} @@ -187,7 +186,7 @@ const ConnectorsView: React.FC = ({ {renderHeaderControls("available")} -
+ diff --git a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx index 684dfaff955f..20b6ef4920c9 100644 --- a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx +++ b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useNavigate } from "react-router-dom"; import { ConnectionTable } from "components/EntityTable"; -import { ITableDataItem } from "components/EntityTable/types"; +import { ConnectionTableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; import { WebBackendConnectionListItem } from "core/request/AirbyteClient"; @@ -19,7 +19,8 @@ const SourceConnectionTable: React.FC = ({ connections }) => { const data = getConnectionTableData(connections, "source"); - const clickRow = (source: ITableDataItem) => navigate(`../../../${RoutePaths.Connections}/${source.connectionId}`); + const clickRow = (source: ConnectionTableDataItem) => + navigate(`../../../${RoutePaths.Connections}/${source.connectionId}`); return (
diff --git a/airbyte-webapp/src/pages/connections/AllConnectionsPage/ConnectionsTable.tsx b/airbyte-webapp/src/pages/connections/AllConnectionsPage/ConnectionsTable.tsx index 10c150152c4b..5248aed37382 100644 --- a/airbyte-webapp/src/pages/connections/AllConnectionsPage/ConnectionsTable.tsx +++ b/airbyte-webapp/src/pages/connections/AllConnectionsPage/ConnectionsTable.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useNavigate } from "react-router-dom"; import { ConnectionTable } from "components/EntityTable"; -import { ITableDataItem } from "components/EntityTable/types"; +import { ConnectionTableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; import { WebBackendConnectionListItem } from "core/request/AirbyteClient"; @@ -16,7 +16,7 @@ const ConnectionsTable: React.FC = ({ connections }) => { const data = getConnectionTableData(connections, "connection"); - const clickRow = (source: ITableDataItem) => navigate(`${source.connectionId}`); + const clickRow = (source: ConnectionTableDataItem) => navigate(`${source.connectionId}`); return ; }; diff --git a/airbyte-webapp/src/types/react-table.d.ts b/airbyte-webapp/src/types/react-table.d.ts index da1739be7a7c..8189bb3e85e4 100644 --- a/airbyte-webapp/src/types/react-table.d.ts +++ b/airbyte-webapp/src/types/react-table.d.ts @@ -7,7 +7,8 @@ import "@tanstack/react-table"; */ declare module "@tanstack/table-core" { interface ColumnMeta { - thClassName?: string; + responsive?: boolean; tdClassName?: string; + thClassName?: string; } }