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

setting up slimmed down create workspace info for ide/class #18674

Closed
wants to merge 3 commits into from
Closed
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
4 changes: 2 additions & 2 deletions components/dashboard/src/components/SelectIDEComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ function capitalize(label?: string) {
return label && label[0].toLocaleUpperCase() + label.slice(1);
}

const IdeOptionElementSelected: FC<IdeOptionElementProps> = ({ option, useLatest, loading = false }) => {
export const IdeOptionElementSelected: FC<IdeOptionElementProps> = ({ option, useLatest, loading = false }) => {
let version: string | undefined, label: string | undefined, title: string;
if (!option) {
title = "Select Editor";
Expand Down Expand Up @@ -171,7 +171,7 @@ const IdeOptionElementSelected: FC<IdeOptionElementProps> = ({ option, useLatest
);
};

function IdeOptionElementInDropDown(p: IdeOptionElementProps): JSX.Element {
export function IdeOptionElementInDropDown(p: IdeOptionElementProps): JSX.Element {
const { option, useLatest } = p;
if (!option) {
return <></>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type WorkspaceClassDropDownElementSelectedProps = {
loading?: boolean;
};

const WorkspaceClassDropDownElementSelected: FC<WorkspaceClassDropDownElementSelectedProps> = ({
export const WorkspaceClassDropDownElementSelected: FC<WorkspaceClassDropDownElementSelectedProps> = ({
wsClass,
loading = false,
}) => {
Expand All @@ -104,7 +104,7 @@ const WorkspaceClassDropDownElementSelected: FC<WorkspaceClassDropDownElementSel
);
};

function WorkspaceClassDropDownElement(props: { wsClass: SupportedWorkspaceClass }): JSX.Element {
export function WorkspaceClassDropDownElement(props: { wsClass: SupportedWorkspaceClass }): JSX.Element {
const c = props.wsClass;
return (
<div className="flex ml-1 mt-1 flex-grow">
Expand Down
33 changes: 33 additions & 0 deletions components/dashboard/src/data/ide-options/ide-options-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { useQuery } from "@tanstack/react-query";
import { getGitpodService } from "../../service/service";
import { IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol";

export const useIDEOptions = () => {
return useQuery(
Expand All @@ -19,3 +20,35 @@ export const useIDEOptions = () => {
},
);
};

// TODO: update IDE Selector component to use this
export const useFilteredAndSortedIDEOptions = () => {
const { data, isLoading, ...rest } = useIDEOptions();
if (isLoading || !data) {
return { data: undefined, isLoading, ...rest };
}

return { data: sortedIdeOptions(data), isLoading: false, ...rest };
};

function filteredIdeOptions(ideOptions: IDEOptions) {
return IDEOptions.asArray(ideOptions).filter((x) => !x.hidden);
}

function sortedIdeOptions(ideOptions: IDEOptions) {
return filteredIdeOptions(ideOptions).sort((a, b) => {
// Prefer experimental options
if (a.experimental && !b.experimental) {
return -1;
}
if (!a.experimental && b.experimental) {
return 1;
}

if (!a.orderKey || !b.orderKey) {
return 0;
}

return parseInt(a.orderKey, 10) - parseInt(b.orderKey, 10);
});
}
4 changes: 2 additions & 2 deletions components/dashboard/src/icons/CaretDown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 15 additions & 6 deletions components/dashboard/src/workspaces/CreateWorkspacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import { Link } from "react-router-dom";
import { Button } from "../components/Button";
import Modal from "../components/Modal";
import RepositoryFinder from "../components/RepositoryFinder";
import SelectIDEComponent from "../components/SelectIDEComponent";
import SelectWorkspaceClassComponent from "../components/SelectWorkspaceClassComponent";
import { UsageLimitReachedModal } from "../components/UsageLimitReachedModal";
import { CheckboxInputField } from "../components/forms/CheckboxInputField";
import { Heading1 } from "../components/typography/headings";
Expand All @@ -40,6 +38,7 @@ import { useDirtyState } from "../hooks/use-dirty-state";
import { LinkButton } from "../components/LinkButton";
import { InputField } from "../components/forms/InputField";
import Alert from "../components/Alert";
import { WorkspaceDetails } from "./create-workspace/WorkspaceDetails";

export function CreateWorkspacePage() {
const { user, setUser } = useContext(UserContext);
Expand All @@ -64,7 +63,8 @@ export function CreateWorkspacePage() {
const [selectedIde, setSelectedIde, selectedIdeIsDirty] = useDirtyState(defaultIde);
const defaultWorkspaceClass = props.workspaceClass;
const [selectedWsClass, setSelectedWsClass, selectedWsClassIsDirty] = useDirtyState(defaultWorkspaceClass);
const [errorWsClass, setErrorWsClass] = useState<string | undefined>(undefined);
// TODO: handle errors in WorkspaceDetail
const [errorWsClass] = useState<string | undefined>(undefined);
const [contextURL, setContextURL] = useState<string | undefined>(
StartWorkspaceOptions.parseContextUrl(location.hash),
);
Expand Down Expand Up @@ -163,7 +163,8 @@ export function CreateWorkspacePage() {
},
[setSelectedIde, setUseLatestIde],
);
const [errorIde, setErrorIde] = useState<string | undefined>(undefined);
// TODO: handle errors in WorkspaceDetail
const [errorIde] = useState<string | undefined>(undefined);

const existingWorkspaces = useMemo(() => {
if (!workspaces.data || !CommitContext.is(workspaceContext.data)) {
Expand Down Expand Up @@ -385,7 +386,7 @@ export function CreateWorkspacePage() {
/>
</InputField>

<InputField error={errorIde}>
{/* <InputField error={errorIde}>
<SelectIDEComponent
onSelectionChange={onSelectEditorChange}
setError={setErrorIde}
Expand All @@ -404,7 +405,15 @@ export function CreateWorkspacePage() {
disabled={createWorkspaceMutation.isStarting}
loading={workspaceContext.isLoading}
/>
</InputField>
</InputField> */}

<WorkspaceDetails
selectedIDE={selectedIde || ""}
useLatestIDE={useLatestIde}
selectedWSClassID={selectedWsClass || ""}
onWSClassChange={setSelectedWsClass}
onIDEChange={onSelectEditorChange}
/>
</div>
<div className="w-full flex justify-end mt-3 space-x-2 px-6">
<Button
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { FC, useMemo } from "react";
import { useWorkspaceClasses } from "../../data/workspaces/workspace-classes-query";
import ContextMenu, { ContextMenuEntry } from "../../components/ContextMenu";
import { Button } from "../../components/Button";
import WorkspaceClassIcon from "../../icons/WorkspaceClass.svg";
import Arrow from "../../components/Arrow";
import { WorkspaceClassDropDownElement } from "../../components/SelectWorkspaceClassComponent";

type WorkspaceClassProps = {
selectedWSClassID: string;
onChange: (workspaceClass: string) => void;
};
export const WorkspaceClass: FC<WorkspaceClassProps> = ({ selectedWSClassID, onChange }) => {
const { data: workspaceClasses, isLoading } = useWorkspaceClasses();

const menuEntries = useMemo((): ContextMenuEntry[] => {
return (workspaceClasses || [])?.map((c) => ({
title: c.displayName,
customContent: <WorkspaceClassDropDownElement wsClass={c} />,
onClick: () => {
onChange(c.id);
},
}));
}, [workspaceClasses, onChange]);

const selectedWSClass = useMemo(() => {
if (!workspaceClasses) {
return;
}
const defaultClassID = workspaceClasses.find((ws) => ws.isDefault)?.id;

return workspaceClasses.find((ws) => ws.id === (selectedWSClassID || defaultClassID));
}, [selectedWSClassID, workspaceClasses]);

if (isLoading) {
return <span>...</span>;
}

return (
<ContextMenu menuEntries={menuEntries} customClasses="left-0">
<Button
type="secondary"
size="small"
icon={<img className="w-8 filter-grayscale" src={WorkspaceClassIcon} alt="logo" />}
>
<span className="font-semibold text-gray-600">{selectedWSClass?.displayName ?? "unknown"}</span>
{/* <div className="flex h-full pl-0 pr-1 py-1.5 text-gray-50">
<svg width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.293 7.293a1 1 0 0 1 1.414 0L10 10.586l3.293-3.293a1 1 0 1 1 1.414 1.414l-4 4a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 0-1.414Z"
fill="#78716C"
/>
<title>Toggle organization selection menu</title>
</svg>
</div> */}
<Arrow direction={"down"} />
{/* <span className="text-gray-600">
<img className="w-4" src={CaretDownIcon} alt="logo" />
</span> */}
</Button>
{/* <span className="font-semibold">{selectedWSClass?.displayName ?? "unknown"}</span> */}
</ContextMenu>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { FC } from "react";
import { WorkspaceClass } from "./WorkspaceClass";
import { WorkspaceIDE } from "./WorkspaceIDE";

type Props = {
selectedIDE: string;
useLatestIDE: boolean;
selectedWSClassID: string;
onWSClassChange: (workspaceClass: string) => void;
onIDEChange: (ide: string, useLatest: boolean) => void;
};
export const WorkspaceDetails: FC<Props> = ({
selectedIDE,
useLatestIDE,
selectedWSClassID,
onWSClassChange,
onIDEChange,
}) => {
return (
<div className="flex flex-row justify-start items-center gap-2 mt-4 mx-2">
<WorkspaceClass selectedWSClassID={selectedWSClassID} onChange={onWSClassChange} />
<span>with</span>
<WorkspaceIDE selectedIDE={selectedIDE} useLatestIDE={useLatestIDE} onChange={onIDEChange} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { FC, useMemo } from "react";
import ContextMenu, { ContextMenuEntry } from "../../components/ContextMenu";
import { useFilteredAndSortedIDEOptions } from "../../data/ide-options/ide-options-query";
import { Button } from "../../components/Button";
import Arrow from "../../components/Arrow";
import Editor from "../../icons/Editor.svg";
import { IdeOptionElementInDropDown } from "../../components/SelectIDEComponent";

type WorkspaceIDEProps = {
selectedIDE: string;
useLatestIDE: boolean;
onChange: (ide: string, useLatest: boolean) => void;
};
export const WorkspaceIDE: FC<WorkspaceIDEProps> = ({ selectedIDE, useLatestIDE, onChange }) => {
const { data: ideOptions, isLoading } = useFilteredAndSortedIDEOptions();

const menuEntries = useMemo((): ContextMenuEntry[] => {
return (ideOptions || []).map((ide) => ({
title: ide.title,
customContent: <IdeOptionElementInDropDown option={ide} useLatest={useLatestIDE} />,
onClick: () => {
onChange(ide.id, useLatestIDE);
},
}));
}, [ideOptions, onChange, useLatestIDE]);

const selectedOption = useMemo(() => {
if (!ideOptions) {
return;
}

return ideOptions.find((ide) => ide.id === selectedIDE);
}, [ideOptions, selectedIDE]);

if (isLoading) {
return <span>...</span>;
}

return (
<ContextMenu menuEntries={menuEntries} customClasses="right-0">
{/* {selectedOption ? (
<IdeOptionElementSelected option={selectedOption} useLatest={useLatestIDE} loading={isLoading} />
) : (
<span>Please select an Editor</span>
)} */}
<Button
type="secondary"
size="small"
icon={<img className="w-4 filter-grayscale" src={Editor} alt="logo" />}
>
{/* <span className="flex flex-row gap-1 items-center"> */}
{/* <img className="w-4 filter-grayscale" src={Editor} alt="logo" /> */}
<span className="font-semibold">{selectedOption?.title ?? "unknown"}</span>
{selectedOption?.label && (
<>
<span className="text-gray-300 dark:text-gray-600 font-normal">&middot;</span>
<span className="text-sm">{selectedOption?.label}</span>
</>
)}
<Arrow direction={"down"} />
{/* </span> */}
</Button>
</ContextMenu>
);
};
Loading