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

Add indicator of the number of active/inactive sources and destinations #2343

Merged
merged 3 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ const ConnectionTable: React.FC<IProps> = ({
accessor: "entityName",
customWidth: 40,
Cell: ({ cell, row }: CellProps<ITableDataItem>) => (
<NameCell value={cell.value} enabled={row.original.enabled} />
<NameCell
value={cell.value}
enabled={row.original.enabled}
status={row.original.status}
/>
),
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ConnectorCell from "./components/ConnectorCell";
import NameCell from "./components/NameCell";
import ConnectEntitiesCell from "./components/ConnectEntitiesCell";
import { EntityTableDataItem } from "./types";
import AllConnectionsStatusCell from "./components/AllConnectionsStatusCell";

const Content = styled.div`
margin: 0 32px 0 27px;
Expand Down Expand Up @@ -65,6 +66,14 @@ const ImplementationTable: React.FC<IProps> = ({
/>
),
},
{
Header: <FormattedMessage id="sources.status" />,
id: "status",
accessor: "connectEntities",
Cell: ({ cell }: CellProps<EntityTableDataItem>) => (
<AllConnectionsStatusCell connectEntities={cell.value} />
),
},
],
[entity]
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useMemo } from "react";

import { Status } from "../types";
import StatusIcon from "components/StatusIcon";

type AllConnectionsStatusCellProps = {
connectEntities: {
name: string;
connector: string;
status: string;
}[];
};

const AllConnectionsStatusCell: React.FC<AllConnectionsStatusCellProps> = ({
connectEntities,
}) => {
const active = useMemo(
() => connectEntities.filter((entity) => entity.status === Status.ACTIVE),
[connectEntities]
);

const inactive = useMemo(
() => connectEntities.filter((entity) => entity.status === Status.INACTIVE),
[connectEntities]
);

// TODO: add error status

if (!connectEntities.length) {
return null;
}

return (
<>
{active.length ? <StatusIcon success value={active.length} /> : null}
{inactive.length ? <StatusIcon inactive value={inactive.length} /> : null}
</>
);
};

export default AllConnectionsStatusCell;
18 changes: 12 additions & 6 deletions airbyte-webapp/src/components/EntityTable/components/NameCell.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from "react";
import styled from "styled-components";

// If we have errorStatus - will add it
// import StatusIcon from "../../../../../components/StatusIcon";
import StatusIcon from "components/StatusIcon";
import { Status } from "../types";

type IProps = {
value: string;
error?: boolean;
enabled?: boolean;
status?: string;
};

const Content = styled.div`
Expand All @@ -30,11 +30,17 @@ const Space = styled.div`
opacity: 0;
`;

const NameCell: React.FC<IProps> = ({ value, enabled }) => {
const NameCell: React.FC<IProps> = ({ value, enabled, status }) => {
return (
<Content>
<Space />
{/*{enabled ? <StatusIcon success={!error} /> : <Space />}*/}
{status ? (
<StatusIcon
success={status === Status.ACTIVE}
inactive={status === Status.INACTIVE}
/>
) : (
<Space />
)}
<Name enabled={enabled}>{value}</Name>
</Content>
);
Expand Down
4 changes: 3 additions & 1 deletion airbyte-webapp/src/components/EntityTable/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import FrequencyConfig from "data/FrequencyConfig.json";
import { AnalyticsService } from "core/analytics/AnalyticsService";
import ConnectionResource, { Connection } from "core/resources/Connection";
import useConnection from "components/hooks/services/useConnectionHook";
import { Status } from "./types";

const useSyncActions = (): {
changeStatus: (connection: Connection) => Promise<void>;
Expand All @@ -19,7 +20,8 @@ const useSyncActions = (): {
syncCatalog: connection.syncCatalog,
defaultNamespace: connection.defaultNamespace,
schedule: connection.schedule || null,
status: connection.status === "active" ? "inactive" : "active",
status:
connection.status === Status.ACTIVE ? Status.INACTIVE : Status.ACTIVE,
});

const frequency = FrequencyConfig.find(
Expand Down
8 changes: 8 additions & 0 deletions airbyte-webapp/src/components/EntityTable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type EntityTableDataItem = {
connectEntities: {
name: string;
connector: string;
status: string;
}[];
enabled: boolean;
lastSync?: number | null;
Expand All @@ -18,8 +19,15 @@ type ITableDataItem = {
connectorName: string;
enabled: boolean;
isSyncing?: boolean;
status?: string;
lastSync?: number | null;
schedule: ScheduleProperties | null;
};

enum Status {
ACTIVE = "active",
INACTIVE = "inactive",
}

export type { ITableDataItem, EntityTableDataItem };
export { Status };
6 changes: 4 additions & 2 deletions airbyte-webapp/src/components/EntityTable/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Connection } from "core/resources/Connection";
import { Source } from "core/resources/Source";
import { Destination } from "core/resources/Destination";
import { ITableDataItem, EntityTableDataItem } from "./types";
import { ITableDataItem, EntityTableDataItem, Status } from "./types";

// TODO: types in next methods look a bit ugly
export function getEntityTableData<
Expand Down Expand Up @@ -38,6 +38,7 @@ export function getEntityTableData<
name: connection[connectType]?.name || "",
// @ts-ignore ts is not that clever to infer such types
connector: connection[connectType]?.[`${connectType}Name`] || "",
status: connection.status,
}));

const sortBySync = entityConnections.sort((item1, item2) =>
Expand Down Expand Up @@ -69,8 +70,9 @@ export const getConnectionTableData = (
// @ts-ignore conditional types are not supported here
connectorName: connection[connectType]?.[`${connectType}Name`] || "",
lastSync: connection.lastSync,
enabled: connection.status === "active",
enabled: connection.status === Status.ACTIVE,
schedule: connection.schedule,
status: connection.status,
isSyncing: connection.isSyncing,
}));
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import React from "react";
import styled from "styled-components";
import { FormattedMessage, useIntl } from "react-intl";

import { H5 } from "components/Titles";
import { H3, H5 } from "components/Titles";
import { DropDown } from "components/DropDown";
import { IDataItem } from "components/DropDown/components/ListItem";

type IProps = {
type: "source" | "destination";
dropDownData: IDataItem[];
onSelect: (item: IDataItem) => void;
entity: string;
entityName: string;
entityIcon?: string;
};

const Content = styled.div`
Expand All @@ -20,33 +23,63 @@ const Content = styled.div`
padding: 0 32px 18px 27px;
`;

const TableItemTitle: React.FC<IProps> = ({ type, dropDownData, onSelect }) => {
const EntityType = styled(H5)`
color: ${({ theme }) => theme.greyColor55};
`;

const EntityInfo = styled(Content)`
justify-content: left;
padding-top: 15px;
padding-bottom: 39px;
`;

const EntityIcon = styled.img`
margin-right: 15px;
`;

const TableItemTitle: React.FC<IProps> = ({
type,
dropDownData,
onSelect,
entity,
entityName,
entityIcon,
}) => {
const formatMessage = useIntl().formatMessage;

return (
<Content>
<H5>
<FormattedMessage id={`tables.${type}s`} />
</H5>
<DropDown
onSelect={onSelect}
data={[
{
text: formatMessage({
id: `tables.${type}AddNew`,
}),
value: "create-new-item",
primary: true,
},
...dropDownData,
]}
hasFilter
withButton
textButton={formatMessage({
id: `tables.${type}Add`,
})}
/>
</Content>
<>
<EntityInfo>
{entityIcon && <EntityIcon src={entityIcon} height={40} alt={"ico"} />}
<div>
<H3 bold>{entityName}</H3>
<EntityType>{entity}</EntityType>
</div>
</EntityInfo>
<Content>
<H5>
<FormattedMessage id="tables.connections" />
</H5>
<DropDown
onSelect={onSelect}
data={[
{
text: formatMessage({
id: `tables.${type}AddNew`,
}),
value: "create-new-item",
primary: true,
},
...dropDownData,
]}
hasFilter
withButton
textButton={formatMessage({
id: `tables.${type}Add`,
})}
/>
</Content>
</>
);
};

Expand Down
39 changes: 33 additions & 6 deletions airbyte-webapp/src/components/StatusIcon/StatusIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,62 @@ import styled from "styled-components";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";

import PauseIcon from "./components/Pause";

type IProps = {
success?: boolean;
inactive?: boolean;
className?: string;
big?: boolean;
value?: string | number;
};

const getWidth = (props: IProps) => {
if (props.big) {
return props.value ? 57 : 40;
}

return props.value ? 37 : 20;
};

const Badge = styled.div<IProps>`
width: ${({ big }) => (big ? 40 : 20)}px;
width: ${(props) => getWidth(props)}px;
height: ${({ big }) => (big ? 40 : 20)}px;
background: ${(props) =>
props.success ? props.theme.successColor : props.theme.dangerColor};
props.success
? props.theme.successColor
: props.inactive
? props.theme.greyColor40
: props.theme.dangerColor};
box-shadow: 0 1px 2px ${({ theme }) => theme.shadowColor};
border-radius: 50%;
border-radius: ${({ value }) => (value ? "15px" : "50%")};
margin-right: 10px;
padding-top: 4px;
color: ${({ theme }) => theme.whiteColor};
font-size: ${({ big }) => (big ? 24 : 12)}px;
line-height: ${({ big }) => (big ? 33 : 12)}px;
text-align: center;
display: inline-block;
vertical-align: top;
`;

const Value = styled.span`
font-weight: 500;
font-size: 12px;
padding-left: 3px;
vertical-align: top;
`;

const StatusIcon: React.FC<IProps> = ({ success, className, big }) => (
<Badge success={success} className={className} big={big}>
{success ? (
const StatusIcon: React.FC<IProps> = (props) => (
<Badge {...props}>
{props.success ? (
<FontAwesomeIcon icon={faCheck} />
) : props.inactive ? (
<PauseIcon />
) : (
<FontAwesomeIcon icon={faTimes} />
)}
{props.value && <Value>{props.value}</Value>}
</Badge>
);

Expand Down
12 changes: 12 additions & 0 deletions airbyte-webapp/src/components/StatusIcon/components/Pause.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const PauseIcon = ({
color = "currentColor",
}: {
color?: string;
}): JSX.Element => (
<svg width="6" height="11" viewBox="0 0 6 11" fill="none">
<line x1="1" y1="1.5" x2="1" y2="10.5" stroke={color} stroke-width="2" />
<line x1="5" y1="1.5" x2="5" y2="10.5" stroke={color} stroke-width="2" />
</svg>
);

export default PauseIcon;
1 change: 1 addition & 0 deletions airbyte-webapp/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@
"tables.destinationIsValidatingBefore": "before you add a new source",
"tables.name": "Name",
"tables.connector": "Connector",
"tables.connections": "Connections",
"tables.sourceConnectWith": "Destination",
"tables.destinationConnectWith": "Source",
"tables.sources": "Sources",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ const DestinationItemPage: React.FC = () => {
type="source"
dropDownData={sourcesDropDownData}
onSelect={onSelect}
entityName={destination.name}
entity={destination.destinationName}
/>
{connectionsWithDestination.length ? (
<DestinationConnectionTable
Expand Down
Loading