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

Rename brickModalNoTags and BrickIcon to use package terminology #8773

Merged
merged 3 commits into from
Jul 9, 2024
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
52 changes: 33 additions & 19 deletions src/components/BrickIcon.tsx → src/components/PackageIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ import useAsyncState from "@/hooks/useAsyncState";
import MarketplaceListingIcon from "@/components/MarketplaceListingIcon";
import { type Nullishable } from "@/utils/nullishUtils";

function getDefaultBrickIcon<Instance extends PackageInstance>(
brick: Instance,
function getDefaultPackageIcon(
packageInstance: PackageInstance,
brickType: Nullishable<BrickType>,
): IconProp {
if ("schema" in brick) {
// Is an integration definition. See Integration/IntegrationABC
if ("schema" in packageInstance) {
return faCloud;
}

Expand All @@ -70,27 +71,35 @@ function getDefaultBrickIcon<Instance extends PackageInstance>(
}
}

if (brick instanceof TriggerStarterBrickABC) {
if (packageInstance instanceof TriggerStarterBrickABC) {
return faBolt;
}

if (brick instanceof ButtonStarterBrickABC) {
if (packageInstance instanceof ButtonStarterBrickABC) {
return faMousePointer;
}

if (brick instanceof ContextMenuStarterBrickABC) {
if (packageInstance instanceof ContextMenuStarterBrickABC) {
return faBars;
}

if (brick instanceof SidebarStarterBrickABC) {
if (packageInstance instanceof SidebarStarterBrickABC) {
return faColumns;
}

return faCube;
}

type BrickIconProps<T extends Metadata> = {
brick: T;
type PackageIconProps = {
/**
* A PackageInstance or Metadata object. Provide a PackageInstance instead of a Metadata to support brick type
* inference.
*
* @see PackageInstance
* @see Metadata
*/
packageOrMetadata: Metadata | PackageInstance;

size?: "1x" | "2x";

/**
Expand All @@ -108,29 +117,34 @@ type BrickIconProps<T extends Metadata> = {
};

/**
* A package icon. Provide a PackageInstance instead of a Metadata to support type inference.
* A package icon. Provide a PackageInstance instead of a Metadata to support brick type inference.
*
* WARNING: avoid rendering a lot of brick icons (20+) icons on a page at once. Each one waits for the marketplace
* WARNING: avoid rendering a lot of icons (20+) icons on a page at once. Each one waits for the marketplace
* listing and searches all the listings.
*
* @see Metadata
* @see PackageInstance
*/
const BrickIcon = <T extends Metadata>({
brick,
// As of 2.0.5, the Metadata and PackageInstance types are currently equivalent. But include both in the union to make
// the type signature more explicit.
const PackageIcon: React.FunctionComponent<PackageIconProps> = ({
packageOrMetadata,
size,
faIconClass,
inheritColor = false,
}: BrickIconProps<T>) => {
const { data: type } = useAsyncState(async () => getType(brick), [brick]);
}: PackageIconProps) => {
const { data: type } = useAsyncState(
async () => getType(packageOrMetadata),
[packageOrMetadata],
);
const defaultIcon = useMemo(
() => getDefaultBrickIcon(brick, type),
[brick, type],
() => getDefaultPackageIcon(packageOrMetadata, type),
[packageOrMetadata, type],
);

return (
<MarketplaceListingIcon
packageId={brick.id}
packageId={packageOrMetadata.id}
defaultIcon={defaultIcon}
size={size}
faIconClass={faIconClass}
Expand All @@ -139,4 +153,4 @@ const BrickIcon = <T extends Metadata>({
);
};

export default BrickIcon;
export default PackageIcon;
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
import React from "react";
import { type MarketplaceListing } from "@/types/contract";
import { Button } from "react-bootstrap";
import BrickIcon from "@/components/BrickIcon";
import PackageIcon from "@/components/PackageIcon";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons";
import SchemaTree from "@/components/schemaTree/SchemaTree";
import { type PackageInstance } from "@/types/registryTypes";
import { MARKETPLACE_URL } from "@/urlConstants";

type BrickDetailProps<T extends PackageInstance> = {
brick: T;
type PackageDetailProps<Instance extends PackageInstance> = {
packageInstance: Instance;
listing?: MarketplaceListing;
onSelect: () => void;
selectCaption: React.ReactNode;
};

const BrickDetail = <T extends PackageInstance>({
brick,
const PackageDetail = <Instance extends PackageInstance>({
packageInstance,
selectCaption = "Select",
listing,
onSelect,
}: BrickDetailProps<T>) => (
}: PackageDetailProps<Instance>) => (
<div>
<div className="d-flex justify-content-between mb-3">
<div>
<h4>
{brick.name} <BrickIcon brick={brick} />
{packageInstance.name}{" "}
<PackageIcon packageOrMetadata={packageInstance} />
</h4>
<code>{brick.id}</code>
<p>{brick.description}</p>
<code>{packageInstance.id}</code>
<p>{packageInstance.description}</p>
{listing && (
<a
href={`${MARKETPLACE_URL}${listing.id}/`}
Expand All @@ -43,7 +44,7 @@ const BrickDetail = <T extends PackageInstance>({
</div>
<div>
<Button
data-testid={`${brick.name} detail button`}
data-testid={`${packageInstance.name} detail button`}
variant="primary mr-1 text-nowrap"
size="lg"
onClick={onSelect}
Expand All @@ -53,25 +54,25 @@ const BrickDetail = <T extends PackageInstance>({
</div>
</div>

{"inputSchema" in brick && (
{"inputSchema" in packageInstance && (
<div className="small mb-3">
<h6 className="my-3">Input Schema</h6>
<SchemaTree schema={brick.inputSchema} />
<SchemaTree schema={packageInstance.inputSchema} />
</div>
)}
{"outputSchema" in brick && (
{"outputSchema" in packageInstance && (
<div className="small mb-3">
<h6 className="my-3">Output Schema</h6>
<SchemaTree schema={brick.outputSchema} />
<SchemaTree schema={packageInstance.outputSchema} />
</div>
)}
{"schema" in brick && (
{"schema" in packageInstance && (
<div className="small mb-3">
<h6 className="my-3">Schema</h6>
<SchemaTree schema={brick.schema} />
<SchemaTree schema={packageInstance.schema} />
</div>
)}
</div>
);

export default BrickDetail;
export default PackageDetail;
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,47 @@ import cx from "classnames";
// TODO: Refactor to properly share styles across components (e.g. full component inheritance);
// the "packageEditor/referenceTab/PackageResult" component probably doesn't expect to also affect a global component
import styles from "@/extensionConsole/pages/packageEditor/referenceTab/PackageResult.module.scss";
import BrickIcon from "@/components/BrickIcon";
import PackageIcon from "@/components/PackageIcon";
import { OfficialBadge } from "@/components/OfficialBadge";
import { type PackageInstance } from "@/types/registryTypes";

type BrickResultProps<T extends PackageInstance> = {
brick: T;
type PackageResultProps<Instance extends PackageInstance> = {
packageInstance: Instance;
onSelect: () => void;
onShowDetail: () => void;
active?: boolean;
selectCaption: React.ReactNode;
};

const BrickResult = <T extends PackageInstance>({
brick,
const PackageResult = <Instance extends PackageInstance>({
packageInstance,
onSelect,
onShowDetail,
selectCaption,
active,
}: BrickResultProps<T>) => (
}: PackageResultProps<Instance>) => (
<ListGroup.Item
onClick={onShowDetail}
className={cx(styles.root, { [styles.active ?? ""]: active, active })}
>
<div className="d-flex">
<div className="mr-2 text-muted">
<BrickIcon brick={brick} />
<PackageIcon packageOrMetadata={packageInstance} />
</div>
<div className={cx("flex-grow-1", styles.titleColumn)}>
<div className={styles.ellipsis}>{brick.name}</div>
<code className={cx("small", styles.id)}>{brick.id}</code>
<div className={styles.ellipsis}>{packageInstance.name}</div>
<code className={cx("small", styles.id)}>{packageInstance.id}</code>
<p className={cx("small mb-0", styles.ellipsis)}>
{/* Use a span if no description to ensure a consistent height for react-window */}
{brick.description ? `${brick.description}` : <span>&nbsp;</span>}
{packageInstance.description ? (
`${packageInstance.description}`
) : (
<span>&nbsp;</span>
)}
</p>
</div>
<div className={cx("flex-grow-0", styles.officialBadge)}>
<OfficialBadge id={brick.id} />
<OfficialBadge id={packageInstance.id} />
</div>
<div
className={cx(
Expand All @@ -69,7 +73,7 @@ const BrickResult = <T extends PackageInstance>({
variant="primary"
className="mb-1 text-nowrap"
onClick={onSelect}
data-testid={`${brick.name} button`}
data-testid={`${packageInstance.name} button`}
>
{selectCaption}
</Button>
Expand All @@ -78,4 +82,4 @@ const BrickResult = <T extends PackageInstance>({
</ListGroup.Item>
);

export default BrickResult;
export default PackageResult;
Loading
Loading