Skip to content

[dashboard] Re-implement default IDE switch for new dashboard #3482

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

Merged
merged 8 commits into from
Mar 19, 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
8 changes: 8 additions & 0 deletions components/dashboard/public/images/theia-gray.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions components/dashboard/public/images/vscode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions components/dashboard/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Notifications = React.lazy(() => import('./settings/Notifications'));
const Plans = React.lazy(() => import('./settings/Plans'));
const EnvironmentVariables = React.lazy(() => import('./settings/EnvironmentVariables'));
const GitIntegrations = React.lazy(() => import('./settings/GitIntegrations'));
const DefaultIDE = React.lazy(() => import('./settings/DefaultIDE'));
const Preferences = React.lazy(() => import('./settings/Preferences'));

function Loading() {
return (<h3>Loading...</h3>);
Expand Down Expand Up @@ -73,7 +73,7 @@ function App() {
<Route path="/plans" exact component={Plans} />
<Route path="/variables" exact component={EnvironmentVariables} />
<Route path="/integrations" exact component={GitIntegrations} />
<Route path="/default-ide" exact component={DefaultIDE} />
<Route path="/preferences" exact component={Preferences} />
</React.Fragment>
)}
</Switch>
Expand Down
19 changes: 19 additions & 0 deletions components/dashboard/src/components/SelectableCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface SelectableCardProps {
title: string;
selected: boolean;
className?: string;
onClick: () => void;
children?: React.ReactNode;
}

function SelectableCard(props: SelectableCardProps) {
return <div className={`rounded-xl px-4 py-3 flex flex-col cursor-pointer group border-2 ${props.selected ? 'border-green-600' : 'border-gray-300 hover:border-gray-400'} ${props.className || ''}`} onClick={props.onClick}>
<div className="flex items-center">
<p className={`w-full text-base font-semibold ${props.selected ? 'text-green-600' : 'text-gray-300 group-hover:text-gray-400'}`}>{props.title}</p>
<input className={props.selected ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'} type="radio" checked={props.selected} />
</div>
{props.children}
</div>;
}

export default SelectableCard;
21 changes: 0 additions & 21 deletions components/dashboard/src/components/SettingsPage.tsx

This file was deleted.

26 changes: 0 additions & 26 deletions components/dashboard/src/components/SubMenu.tsx

This file was deleted.

8 changes: 6 additions & 2 deletions components/dashboard/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@apply text-2xl text-gray-900 leading-9 font-semibold;
}
h4 {
@apply pb-2 text-sm font-medium text-gray-500;
@apply pb-2 text-sm font-medium text-gray-600;
}
p {
@apply text-sm text-gray-400;
Expand All @@ -37,7 +37,11 @@
}

input[type=text]::placeholder {
@apply text-gray-400
@apply text-gray-400;
}

input[disabled] {
@apply bg-gray-100 border-2 border-gray-300 text-gray-400;
}

}
23 changes: 11 additions & 12 deletions components/dashboard/src/settings/Account.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { User } from "@gitpod/gitpod-protocol";
import { useContext, useState } from "react";
import Modal from "../components/Modal";
import { SettingsPage } from "../components/SettingsPage";
import { UserContext } from "../user-context";
import settingsMenu from "./settings-menu";
import { SettingsPage } from "./SettingsPage";

export default function Account() {
const { user } = useContext(UserContext);
Expand All @@ -20,30 +19,30 @@ export default function Account() {
</div>
</Modal>

<SettingsPage title='Account' subtitle='Profile details' menuEntries={settingsMenu}>
<h3>Personal Information</h3>
<SettingsPage title='Account' subtitle='Profile details'>
<h3>Profile</h3>
<div className="flex flex-col lg:flex-row">
<div className="pb-6">
<div className="pt-6">
<div>
<div className="mt-4">
<h4>Name</h4>
<input type="text" value={user!.name} onChange={(v) => { console.log(v) }} />
<input type="text" disabled={true} value={user!.name} onChange={(v) => { console.log(v) }} />
</div>
<div className="pt-6">
<div className="mt-4">
<h4>Email</h4>
<input type="text" value={User.getPrimaryEmail(user!)} onChange={(v) => { console.log(v) }} />
<input type="text" disabled={true} value={User.getPrimaryEmail(user!)} onChange={(v) => { console.log(v) }} />
</div>
</div>
<div className="lg:pl-14">
<div className="pt-6">
<div className="mt-4">
<h4>Avatar</h4>
<img className="rounded-full w-24 h-24 border-2 border-transparent hover:border-indigo-400"
src={user!.avatarUrl} alt={user!.name} />
</div>
</div>
</div>
<h3 className="pt-14">Delete Account</h3>
<h3 className="mt-12">Delete Account</h3>
<p className="text-sm text-gray-400 pb-4">This action will remove all the data associated with your account in Gitpod.</p>
<button className="border-red-900 bg-red-500 hover:bg-red-700" onClick={() => setModal(true)}>Delete Account</button>
<button className="border-red-600 text-red-600 bg-white hover:border-red-800 hover:text-red-800" onClick={() => setModal(true)}>Delete Account</button>
Copy link
Contributor

@svenefftinge svenefftinge Mar 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that bg-white based on a design I missed?

Copy link
Contributor Author

@jankeromnes jankeromnes Mar 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a secondary button (outline vs plain color), cc @gtsiolis

Currently, it seems that all <button> have bg-green-600 by default:

button {
@apply cursor-pointer px-3 py-1 my-auto bg-green-600 hover:bg-green-700 border-2 border-green-800 text-gray-100 text-sm rounded-md;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For more context, see relevant specs in #3395.

</SettingsPage>
</div>;
}
12 changes: 0 additions & 12 deletions components/dashboard/src/settings/DefaultIDE.tsx

This file was deleted.

9 changes: 3 additions & 6 deletions components/dashboard/src/settings/EnvironmentVariables.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { SettingsPage } from "../components/SettingsPage";
import settingsMenu from './settings-menu';
import { SettingsPage } from "./SettingsPage";

export default function EnvVars() {
return <div>
<SettingsPage title='Environment Variables' subtitle='Configure environment variables for your workspaces' menuEntries={settingsMenu}>
<div className="lg:px-28 px-10 flex pt-10">
Environment Variables
</div>
<SettingsPage title='Environment Variables' subtitle='Configure environment variables for your workspaces'>
<h3>Environment Variables</h3>
</SettingsPage>
</div>;
}
9 changes: 3 additions & 6 deletions components/dashboard/src/settings/GitIntegrations.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { SettingsPage } from "../components/SettingsPage";
import settingsMenu from './settings-menu';
import { SettingsPage } from "./SettingsPage";

export default function GitIntegrations() {
return <div>
<SettingsPage title='Git Integrations' subtitle='Manage integration with your Git hosters' menuEntries={settingsMenu}>
<div className="lg:px-28 px-10 flex pt-10">
Git Hoster Access Control
</div>
<SettingsPage title='Git Integrations' subtitle='Manage integration with your Git hosters'>
<h3>Git Hoster Access Control</h3>
</SettingsPage>
</div>;
}
9 changes: 3 additions & 6 deletions components/dashboard/src/settings/Notifications.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { SettingsPage } from "../components/SettingsPage";
import settingsMenu from "./settings-menu";
import { SettingsPage } from "./SettingsPage";

export default function Notifications() {
return <div>
<SettingsPage title='Notifications' subtitle='Email notification preferences' menuEntries={settingsMenu}>
<div className="lg:px-28 px-10 flex pt-10">
Notifications
</div>
<SettingsPage title='Notifications' subtitle='Email notification preferences'>
<h3>Notifications</h3>
</SettingsPage>
</div>;
}
9 changes: 3 additions & 6 deletions components/dashboard/src/settings/Plans.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { SettingsPage } from "../components/SettingsPage";
import settingsMenu from "./settings-menu";
import { SettingsPage } from "./SettingsPage";

export default function Plans() {
return <div>
<SettingsPage title='Plans' subtitle='Plans and Usage' menuEntries={settingsMenu} >
<div className="lg:px-28 px-10 flex pt-10">
Plans
</div>
<SettingsPage title='Plans' subtitle='Plans and Usage'>
<h3>Plans</h3>
</SettingsPage>
</div>;
}
Expand Down
41 changes: 41 additions & 0 deletions components/dashboard/src/settings/Preferences.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useContext, useState } from "react";
import { getGitpodService } from "../service/service";
import SelectableCard from "../components/SelectableCard";
import { UserContext } from "../user-context";
import { SettingsPage } from "./SettingsPage";

export default function Preferences() {
const { user } = useContext(UserContext);
const [ defaultIde, setDefaultIde ] = useState<string>(user?.additionalData?.ideSettings?.defaultIde || 'theia');
const actuallySetDefaultIde = async (value: string) => {
const additionalData = user?.additionalData || {};
const settings = additionalData.ideSettings || {};
if (value === 'theia') {
delete settings.defaultIde;
} else {
settings.defaultIde = value;
}
additionalData.ideSettings = settings;
await getGitpodService().server.updateLoggedInUser({ additionalData });
setDefaultIde(value);
}

return <div>
<SettingsPage title='Preferences' subtitle='Configure your Default IDE for all workspaces.'>
<h3>Default IDE</h3>
<p className="text-base">Choose which IDE you want to use.</p>
<div className="mt-4 space-x-4 flex">
<SelectableCard className="w-36 h-40" title="VS Code" selected={defaultIde === 'code'} onClick={() => actuallySetDefaultIde('code')}>
<div className="flex-grow flex justify-center align-center">
<img className="w-16 filter-grayscale" src="/images/vscode.svg"/>
</div>
</SelectableCard>
<SelectableCard className="w-36 h-40" title="Theia" selected={defaultIde === 'theia'} onClick={() => actuallySetDefaultIde('theia')}>
<div className="flex-grow flex justify-center align-center">
<img className="w-16" src="/images/theia-gray.svg"/>
</div>
</SelectableCard>
</div>
</SettingsPage>
</div>;
}
37 changes: 37 additions & 0 deletions components/dashboard/src/settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Link } from "react-router-dom";
import Header from '../components/Header';
import settingsMenu from "./settings-menu";

export interface Props {
title: string;
subtitle: string;
children: React.ReactNode;
}

export function SettingsPage(p: Props) {
return <div>
<Header title={p.title} subtitle={p.subtitle}/>
<div className='lg:px-28 px-10 flex pt-9'>
<div>
<ul className="flex flex-col text-sm text-gray-500 pt-4 lg:pt-0 w-48 space-y-2">
{settingsMenu.map(e => {
let classes = "flex block py-2 font-sm px-4 rounded-md";
if (e.link.toLowerCase() === window.location.pathname) {
classes += " bg-gray-800 text-gray-50";
} else {
classes += " hover:bg-gray-100";
}
return <Link to={e.link} key={e.title}>
<li className={classes}>
{e.title}
</li>
</Link>;
})}
</ul>
</div>
<div className='ml-32 w-full pt-1'>
{p.children}
</div>
</div>
</div>;
}
4 changes: 2 additions & 2 deletions components/dashboard/src/settings/settings-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default [
link: '/integrations'
},
{
title: 'Default IDE',
link: '/default-ide'
title: 'Preferences',
link: '/preferences'
},
];
4 changes: 2 additions & 2 deletions components/dashboard/src/start/CreateWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, { Suspense } from "react";
import { CreateWorkspaceMode, WorkspaceCreationResult } from "@gitpod/gitpod-protocol";
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
import Modal from "../components/Modal";
import { StartPage, StartPhase } from "../components/StartPage";
import StartWorkspace from "./StartWorkspace";
import { getGitpodService } from "../service/service";
import { StartPage, StartPhase } from "./StartPage";
import StartWorkspace from "./StartWorkspace";

const WorkspaceLogs = React.lazy(() => import('./WorkspaceLogs'));

Expand Down
2 changes: 1 addition & 1 deletion components/dashboard/src/start/StartWorkspace.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import { DisposableCollection, WorkspaceInstance } from "@gitpod/gitpod-protocol";
import { GitpodHostUrl } from "@gitpod/gitpod-protocol/lib/util/gitpod-host-url";
import { StartPage, StartPhase } from "../components/StartPage";
import { getGitpodService } from "../service/service";
import { StartPage, StartPhase } from "./StartPage";

export interface StartWorkspaceProps {
workspaceId: string;
Expand Down
Loading