Skip to content

Commit

Permalink
feat(console): icon for custom resources (#6588)
Browse files Browse the repository at this point in the history
Resolves #6587
  • Loading branch information
polamoros authored May 29, 2024
1 parent a79bc5c commit d2490f5
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 58 deletions.
2 changes: 2 additions & 0 deletions apps/wing-console/console/design-system/src/resource-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface ResourceIconProps extends IconProps {
forceDarken?: boolean;
solid?: boolean;
color?: Colors | string;
icon?: string;
}

export interface IconComponent extends FunctionComponent<IconProps> {}
Expand All @@ -32,6 +33,7 @@ export const ResourceIcon = ({
const Component = getResourceIconComponent(resourceType, {
solid,
resourceId: resourcePath,
icon: props.icon,
});
const colors = getResourceIconColors({
resourceType,
Expand Down
106 changes: 55 additions & 51 deletions apps/wing-console/console/design-system/src/utils/icon-utils.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,6 @@
import {
ArchiveBoxIcon,
BeakerIcon,
BoltIcon,
CalculatorIcon,
ClockIcon,
CloudIcon,
CubeIcon,
GlobeAltIcon,
MegaphoneIcon,
QueueListIcon,
TableCellsIcon,
KeyIcon,
} from "@heroicons/react/24/outline";
import {
ArchiveBoxIcon as SolidArchiveBoxIcon,
BeakerIcon as SolidBeakerIcon,
BoltIcon as SolidBoltIcon,
CalculatorIcon as SolidCalculatorIcon,
ClockIcon as SolidClockIcon,
CloudIcon as SolidCloudIcon,
GlobeAltIcon as SolidGlobeAltIcon,
MegaphoneIcon as SolidMegaphoneIcon,
QueueListIcon as SolidQueueListIcon,
TableCellsIcon as SolidTableCellsIcon,
KeyIcon as SolidKeyIcon,
} from "@heroicons/react/24/solid";
import * as OutlineHeroIcons from "@heroicons/react/24/outline";
import * as SolidHeroIcons from "@heroicons/react/24/solid";

import { ReactIcon } from "../icons/react-icon.js";
import { RedisIcon } from "../icons/redis-icon.js";

import type { Colors } from "./colors.js";
Expand All @@ -38,52 +12,75 @@ const matchTest = (path: string) => {
return isTest.test(path);
};

const getHeroIconName = (heroiconId: string): string => {
const parts = heroiconId.split("-");
const resourceName = parts
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join("");
return `${resourceName}Icon`;
};

export const getResourceIconComponent = (
resourceType: string | undefined,
{ solid = true, resourceId }: { solid?: boolean; resourceId?: string } = {},
{
solid = true,
resourceId,
icon,
}: { solid?: boolean; resourceId?: string; icon?: string } = {},
) => {
const iconSet = solid ? SolidHeroIcons : OutlineHeroIcons;

if (resourceId && matchTest(resourceId)) {
return solid ? SolidBeakerIcon : BeakerIcon;
return iconSet.BeakerIcon;
}
if (icon) {
// icon is a heroicon id string, e.g. "academic-cap" so we need to convert it to the actual component
// @ts-ignore
let iconComponent = iconSet[getHeroIconName(icon)];
if (iconComponent) {
return iconComponent;
}
}

switch (resourceType) {
case "@winglang/sdk.cloud.Bucket": {
return solid ? SolidArchiveBoxIcon : ArchiveBoxIcon;
return iconSet.ArchiveBoxIcon;
}
case "@winglang/sdk.cloud.Function": {
return solid ? SolidBoltIcon : BoltIcon;
return iconSet.BoltIcon;
}
case "@winglang/sdk.cloud.Queue": {
return solid ? SolidQueueListIcon : QueueListIcon;
return iconSet.QueueListIcon;
}
case "@winglang/sdk.cloud.Website": {
return solid ? SolidGlobeAltIcon : GlobeAltIcon;
return iconSet.GlobeAltIcon;
}
case "@winglang/sdk.cloud.Counter": {
return solid ? SolidCalculatorIcon : CalculatorIcon;
return iconSet.CalculatorIcon;
}
case "@winglang/sdk.cloud.Topic": {
return solid ? SolidMegaphoneIcon : MegaphoneIcon;
return iconSet.MegaphoneIcon;
}
case "@winglang/sdk.cloud.Api": {
return solid ? SolidCloudIcon : CloudIcon;
return iconSet.CloudIcon;
}
case "@winglang/sdk.ex.Table": {
return solid ? SolidTableCellsIcon : TableCellsIcon;
return iconSet.TableCellsIcon;
}
case "@winglang/sdk.cloud.Schedule": {
return solid ? SolidClockIcon : ClockIcon;
return iconSet.ClockIcon;
}
case "@winglang/sdk.ex.Redis": {
return RedisIcon;
}
case "@winglang/sdk.std.Test": {
return solid ? SolidBeakerIcon : BeakerIcon;
return iconSet.BeakerIcon;
}
case "@winglang/sdk.cloud.Secret": {
return solid ? SolidKeyIcon : KeyIcon;
return iconSet.KeyIcon;
}
default: {
return CubeIcon;
return iconSet.CubeIcon;
}
}
};
Expand Down Expand Up @@ -159,6 +156,21 @@ export const getResourceIconColors = (options: {
forceDarken?: boolean;
color?: Colors | string;
}) => {
let color: Colors =
options.color && Object.keys(colors).includes(options.color)
? (options.color as Colors)
: "slate";

let defaultColor = [
colors[color].default,
options.darkenOnGroupHover && colors[color].groupHover,
options.forceDarken && colors[color].forceDarken,
];

if (options.color) {
return defaultColor;
}

switch (options.resourceType) {
case "@winglang/sdk.cloud.Bucket": {
return [
Expand Down Expand Up @@ -231,15 +243,7 @@ export const getResourceIconColors = (options: {
];
}
default: {
let color: Colors =
options.color && Object.keys(colors).includes(options.color)
? (options.color as Colors)
: "slate";
return [
colors[color].default,
options.darkenOnGroupHover && colors[color].groupHover,
options.forceDarken && colors[color].forceDarken,
];
return defaultColor;
}
}
};
2 changes: 2 additions & 0 deletions apps/wing-console/console/server/src/router/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,11 +320,13 @@ export const createAppRouter = () => {
id: sourceNode.id,
path: sourceNode.path,
type: getResourceType(sourceNode, simulator),
display: sourceNode.display,
},
target: {
id: targetNode?.id ?? "",
path: targetNode?.path ?? "",
type: (targetNode && getResourceType(targetNode, simulator)) ?? "",
display: targetNode.display,
},
inflights: targetInflight
? [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface NodeDisplay {
sourceModule?: string;
hidden?: boolean;
color?: string;
icon?: string;
}

export interface NodeConnection {
Expand Down
21 changes: 19 additions & 2 deletions apps/wing-console/console/ui/src/features/map-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ interface WrapperProps {
fqn: string;
highlight?: boolean;
onClick?: () => void;
color?: string;
icon?: string;
}

const Wrapper: FunctionComponent<PropsWithChildren<WrapperProps>> = memo(
({ name, fqn, highlight, onClick, children }) => {
({ name, fqn, highlight, onClick, children, color, icon }) => {
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div
Expand Down Expand Up @@ -80,7 +82,12 @@ const Wrapper: FunctionComponent<PropsWithChildren<WrapperProps>> = memo(
"border-b border-slate-200 dark:border-slate-800",
)}
>
<ResourceIcon className="size-4 -ml-0.5" resourceType={fqn} />
<ResourceIcon
className="size-4 -ml-0.5"
resourceType={fqn}
icon={icon}
color={color}
/>

<span
className={clsx(
Expand All @@ -106,6 +113,8 @@ interface ContainerNodeProps {
resourceType?: string;
highlight?: boolean;
onClick?: () => void;
color?: string;
icon?: string;
}

const ContainerNode: FunctionComponent<PropsWithChildren<ContainerNodeProps>> =
Expand All @@ -127,6 +136,8 @@ const ContainerNode: FunctionComponent<PropsWithChildren<ContainerNodeProps>> =
fqn={props.resourceType!}
highlight={props.highlight}
onClick={props.onClick}
color={props.color}
icon={props.icon}
>
<div className="p-4">
<NodeChildren>
Expand All @@ -153,6 +164,7 @@ interface ConstructNodeProps {
hasChildNodes?: boolean;
onSelectedNodeIdChange: (id: string | undefined) => void;
color?: string;
icon?: string;
}

const ConstructNode: FunctionComponent<PropsWithChildren<ConstructNodeProps>> =
Expand All @@ -167,6 +179,7 @@ const ConstructNode: FunctionComponent<PropsWithChildren<ConstructNodeProps>> =
children,
hasChildNodes,
color,
icon,
}) => {
const select = useCallback(
() => onSelectedNodeIdChange(id),
Expand Down Expand Up @@ -243,6 +256,7 @@ const ConstructNode: FunctionComponent<PropsWithChildren<ConstructNodeProps>> =
className="size-4 -ml-0.5"
resourceType={fqn}
color={color}
icon={icon}
/>

<span
Expand Down Expand Up @@ -320,6 +334,8 @@ const ConstructNode: FunctionComponent<PropsWithChildren<ConstructNodeProps>> =
resourceType={fqn}
highlight={highlight}
onClick={select}
color={color}
icon={icon}
>
<NodeChildren>
{inflights.length > 0 && renderedNode}
Expand Down Expand Up @@ -594,6 +610,7 @@ export const MapView = memo(
name={name ?? ""}
fqn={fqn ?? ""}
color={props.constructTreeNode.display?.color}
icon={props.constructTreeNode.display?.icon}
inflights={info.type === "construct" ? info.inflights : []}
onSelectedNodeIdChange={props.onSelectedNodeIdChange}
highlight={props.selectedNodeId === props.constructTreeNode.path}
Expand Down
1 change: 1 addition & 0 deletions apps/wing-console/console/ui/src/services/use-explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const createTreeMenuItemFromExplorerTreeItem = (
resourcePath={item.id}
className="w-4 h-4"
color={item.display?.color}
icon={item.display?.icon}
/>
) : undefined,
children: item.childItems?.map((item) =>
Expand Down
2 changes: 2 additions & 0 deletions apps/wing-console/console/ui/src/ui/edge-metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const EdgeMetadata = ({
resourceType={source.type}
resourcePath={source.path}
color={source.display?.color}
icon={source.display?.icon}
/>
</div>
<div className="truncate">{source.id}</div>
Expand All @@ -134,6 +135,7 @@ export const EdgeMetadata = ({
resourceType={target.type}
resourcePath={target.path}
color={target.display?.color}
icon={target.display?.icon}
/>
</div>
<div className="truncate">{target.id}</div>
Expand Down
1 change: 1 addition & 0 deletions apps/wing-console/console/ui/src/ui/explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const createTreeMenuItemFromExplorerTreeItem = (
resourcePath={item.label}
className="w-4 h-4"
color={item.display?.color}
icon={item.display?.icon}
/>
) : undefined,
children: item.childItems?.map((item) =>
Expand Down
17 changes: 13 additions & 4 deletions apps/wing-console/console/ui/src/ui/resource-metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getResourceIconComponent,
Attribute,
ScrollableArea,
getResourceIconColors,
} from "@wingconsole/design-system";
import type { NodeDisplay } from "@wingconsole/server";
import classNames from "classnames";
Expand Down Expand Up @@ -82,13 +83,18 @@ export const ResourceMetadata = memo(
"interact",
"interact-actions",
]);

const icon = useMemo(() => {
return getResourceIconComponent(node.type, {
resourceId: node.id,
icon: node.display?.icon,
});
}, [node]);

const { resourceGroup, connectionsGroups } = useMemo(() => {
const connectionsGroupsArray: ConnectionsGroup[] = [];
let resourceGroup: AttributeGroup | undefined;
if (node.props) {
const icon = getResourceIconComponent(node.type, {
resourceId: node.id,
});
switch (node.type) {
case "@winglang/sdk.cloud.Function": {
resourceGroup = {
Expand Down Expand Up @@ -181,6 +187,7 @@ export const ResourceMetadata = memo(
resourcePath={relationship.path}
className="w-4 h-4"
color={relationship.display?.color}
icon={relationship.display?.icon}
/>
),
})),
Expand All @@ -199,6 +206,7 @@ export const ResourceMetadata = memo(
resourcePath={relationship.path}
className="w-4 h-4"
color={relationship.display?.color}
icon={relationship.display?.icon}
/>
),
})),
Expand Down Expand Up @@ -247,6 +255,7 @@ export const ResourceMetadata = memo(
resourceType={node.type}
resourcePath={node.path}
color={node.display?.color}
icon={node.display?.icon}
/>
</div>

Expand All @@ -259,7 +268,7 @@ export const ResourceMetadata = memo(
</div>
{resourceUI.data && resourceUI.data.length > 0 && (
<InspectorSection
icon={CubeIcon}
icon={icon ?? CubeIcon}
text={nodeLabel ?? "Properties"}
open={openInspectorSections.includes("resourceUI")}
onClick={() => toggleInspectorSection("resourceUI")}
Expand Down
Loading

0 comments on commit d2490f5

Please sign in to comment.