Skip to content

Commit

Permalink
Add menu item for opening imported component/project in new tab
Browse files Browse the repository at this point in the history
Issue: https://linear.app/plasmic/issue/PLA-1501
Change-Id: I135fdd7be0cc82e7571460edf93e6e5e5b6bd09e
GitOrigin-RevId: ac72e3c43be8a11546c46092d9518627837bbf2c
  • Loading branch information
jaslong authored and Copybara committed Jan 8, 2024
1 parent 178b330 commit b1190ac
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 107 deletions.
17 changes: 15 additions & 2 deletions platform/wab/src/wab/client/cli-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import {
} from "@/wab/shared/ApiSchema";
import { isArenaType } from "@/wab/shared/Arenas";
import { getPublicUrl } from "@/wab/urls";
import { History, Location, LocationDescriptor } from "history";
import {
createPath,
History,
Location,
LocationDescriptor,
LocationDescriptorObject,
} from "history";
import L from "lodash";
import { compile, PathFunction } from "path-to-regexp";
import { match as Match, matchPath, useRouteMatch } from "react-router-dom";
Expand Down Expand Up @@ -320,7 +326,7 @@ export function mkProjectLocation({
branchVersion,
arenaType,
arenaUuidOrName,
}: ProjectLocationParams): LocationDescriptor {
}: ProjectLocationParams): LocationDescriptorObject {
const searchParams: [string, string][] = [];
if (branchName !== MainBranchId) {
searchParams.push([SEARCH_PARAM_BRANCH, branchName]);
Expand Down Expand Up @@ -351,6 +357,13 @@ export function mkProjectLocation({
};
}

export function openNewTab(location: LocationDescriptor) {
window.open(
typeof location === "string" ? location : createPath(location),
"_blank"
);
}

export class Router {
constructor(public history: History) {}
routeTo(path: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// This is a skeleton starter React component generated by Plasmic.
// This file is owned by you, feel free to edit as you see fit.
import { Component, ProjectDependency } from "@/wab/classes";
import {
Component,
isKnownProjectDependency,
ProjectDependency,
} from "@/wab/classes";
import { mkProjectLocation, openNewTab } from "@/wab/client/cli-routes";
import ListItem from "@/wab/client/components/ListItem";
import { MenuBuilder } from "@/wab/client/components/menu-builder";
import { DefaultComponentKindModal } from "@/wab/client/components/modals/DefaultComponentKindModal";
Expand Down Expand Up @@ -31,6 +36,7 @@ import {
isShownHostLessCodeComponent,
sortComponentsByName,
} from "@/wab/components";
import { MainBranchId } from "@/wab/shared/ApiSchema";
import { isMixedArena } from "@/wab/shared/Arenas";
import { FRAME_CAP } from "@/wab/shared/Labels";
import { isHostLessPackage } from "@/wab/sites";
Expand Down Expand Up @@ -190,13 +196,19 @@ const LeftComponentsPanel = observer(function LeftComponentsPanel(props: {}) {
<>
<VirtualGroupedList
items={items}
renderItem={(comp) => (
renderItem={(comp, group) => (
<ComponentRow
studioCtx={studioCtx}
readOnly={readOnly}
dep={
group && isKnownProjectDependency(group.group)
? group.group
: undefined
}
component={comp}
isPlainComponent={plainComponents.includes(comp)}
matcher={matcher}
onFindReferences={() => onFindReferences(comp)}
readOnly={readOnly || !plainComponents.includes(comp)}
onDuplicate={
readOnly
? undefined
Expand Down Expand Up @@ -288,29 +300,34 @@ export function buildCommonComponentMenuItems(

const ComponentRow = observer(function ComponentRow(props: {
studioCtx: StudioCtx;
readOnly: boolean;
/** if component is from a ProjectDependency */
dep: ProjectDependency | undefined;
component: Component;
isPlainComponent: boolean;
matcher: Matcher;
onFindReferences: () => void;
isDragging?: boolean;
dragHandleProps?: DraggableProvidedDragHandleProps;
readOnly?: boolean;
onDuplicate?: () => void;
}) {
const {
studioCtx,
readOnly,
dep,
component,
isPlainComponent,
matcher,
onFindReferences,
isDragging,
dragHandleProps,
readOnly,
onDuplicate,
} = props;
const overlay = () => {
const arena = studioCtx.currentArena;
const builder = new MenuBuilder();
builder.genSection(undefined, (push) => {
if (!readOnly) {
if (!readOnly && isPlainComponent) {
push(
<Menu.Item
key="open-dedicated-arena"
Expand Down Expand Up @@ -338,10 +355,31 @@ const ComponentRow = observer(function ComponentRow(props: {
);
}
}
if (dep) {
push(
<Menu.Item
key="open-imported-component"
onClick={() => {
openNewTab(
mkProjectLocation({
projectId: dep.projectId,
slug: component.name,
branchName: MainBranchId,
branchVersion: "latest",
arenaType: "component",
arenaUuidOrName: component.uuid,
})
);
}}
>
<strong>Open</strong> component in new tab
</Menu.Item>
);
}
});

builder.genSection(undefined, (push) => {
if (!readOnly) {
if (!readOnly && isPlainComponent) {
push(
<Menu.Item
key="rename"
Expand Down Expand Up @@ -373,7 +411,7 @@ const ComponentRow = observer(function ComponentRow(props: {
);
}

if (!readOnly) {
if (!readOnly && isPlainComponent) {
push(
<Menu.Item
key="convert_to_page"
Expand All @@ -397,7 +435,7 @@ const ComponentRow = observer(function ComponentRow(props: {
);

builder.genSection(undefined, (push) => {
if (!readOnly) {
if (!readOnly && isPlainComponent) {
push(
<Menu.Item
key="delete"
Expand Down Expand Up @@ -450,14 +488,18 @@ const ComponentRow = observer(function ComponentRow(props: {
style={{
paddingLeft: indent * 24,
}}
onClick={() => {
spawn(
studioCtx.change(({ success }) => {
studioCtx.switchToComponentArena(component);
return success();
})
);
}}
onClick={
isPlainComponent
? () => {
spawn(
studioCtx.change(({ success }) => {
studioCtx.switchToComponentArena(component);
return success();
})
);
}
: undefined
}
data-test-id={`listitem-component-${component.name}`}
>
{defaultComponentKind ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ProjectDependency } from "@/wab/classes";
import { U } from "@/wab/client/cli-routes";
import { openNewTab, U } from "@/wab/client/cli-routes";
import { WithContextMenu } from "@/wab/client/components/ContextMenu";
import { MenuBuilder } from "@/wab/client/components/menu-builder";
import {
Expand Down Expand Up @@ -62,15 +62,11 @@ const DependencyItem = observer(function DependencyItem(props: {
<Menu.Item
key="jump-newtab"
onClick={() => {
const win = window.open(
openNewTab(
U.project({
projectId: targetProjectId,
}),

"_blank"
})
);

win?.focus();
}}
>
Open project in new tab
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import ListSectionHeader from "@/wab/client/components/ListSectionHeader";
import { ListSpace } from "@/wab/client/components/widgets/ListStack";
import { sum } from "lodash";
import React from "react";
import { VariableSizeList } from "react-window";
import ListSectionHeader from "../ListSectionHeader";
import { ListSpace } from "../widgets/ListStack";

export interface Item<I> {
type: "item";
Expand All @@ -19,9 +19,16 @@ export interface Group<G, I> {

export type ItemOrGroup<G, I> = Item<I> | Group<G, I>;

interface GroupedItem<G, I> {
type: "grouped_item";
group: Group<G, I>;
item: Item<I>;
}
type Row<G, I> = Item<I> | Group<G, I> | GroupedItem<G, I>;

export function VirtualGroupedList<I, G>(props: {
items: (Item<I> | Group<G, I>)[];
renderItem: (item: I) => React.ReactNode;
renderItem: (item: I, group: Group<G, I> | undefined) => React.ReactNode;
itemHeight: number;
renderGroupHeader: (group: G) => React.ReactNode;
headerHeight: number;
Expand Down Expand Up @@ -50,14 +57,30 @@ export function VirtualGroupedList<I, G>(props: {
return !forceExpandAll && collapsed[item.key];
};

const flattenItems = (itms: ItemOrGroup<G, I>[]): ItemOrGroup<G, I>[] => {
return itms.flatMap((item) => {
if (item.type === "item") {
return item;
} else if (hideEmptyGroups && item.items.length === 0) {
const flattenItems = (
itemsOrGroups: ItemOrGroup<G, I>[],
group?: Group<G, I>
): Row<G, I>[] => {
return itemsOrGroups.flatMap((itemOrGroup) => {
if (itemOrGroup.type === "item") {
if (group) {
return {
type: "grouped_item",
group,
item: itemOrGroup,
};
} else {
return itemOrGroup;
}
} else if (hideEmptyGroups && itemOrGroup.items.length === 0) {
return [];
} else {
return [item, ...(isCollapsed(item) ? [] : flattenItems(item.items))];
return [
itemOrGroup,
...(isCollapsed(itemOrGroup)
? []
: flattenItems(itemOrGroup.items, itemOrGroup)),
];
}
});
};
Expand Down Expand Up @@ -104,24 +127,33 @@ export function VirtualGroupedList<I, G>(props: {
ref={listRef}
>
{({ data, index, style }) => {
const item = data[index];
if (item.type === "group") {
const row: Row<G, I> = data[index];
if (row.type === "group") {
return (
<ListSectionHeader
collapseState={isCollapsed(item) ? "collapsed" : "expanded"}
className={row.items.length > 0 ? "pointer" : undefined}
collapseState={isCollapsed(row) ? "collapsed" : "expanded"}
onToggle={() =>
setCollapsed({
...collapsed,
[item.key]: !collapsed[item.key],
[row.key]: !collapsed[row.key],
})
}
style={style}
>
{renderGroupHeader(item.group)}
{renderGroupHeader(row.group)}
</ListSectionHeader>
);
} else if (row.type === "grouped_item") {
return (
<li style={{ ...style }}>
{renderItem(row.item.item, row.group)}
</li>
);
} else {
return <li style={{ ...style }}>{renderItem(item.item)}</li>;
return (
<li style={{ ...style }}>{renderItem(row.item, undefined)}</li>
);
}
}}
</VariableSizeList>
Expand Down
Loading

0 comments on commit b1190ac

Please sign in to comment.