Skip to content

Commit b206df6

Browse files
committed
[dashboard] Update the Project Configurator design
1 parent e6c7342 commit b206df6

File tree

6 files changed

+72
-39
lines changed

6 files changed

+72
-39
lines changed

components/dashboard/src/components/MonacoEditor.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ export default function MonacoEditor(props: { classes: string, disabled?: boolea
2222
enabled: false,
2323
},
2424
renderLineHighlight: 'none',
25+
lineNumbers: 'off',
26+
glyphMargin: false,
27+
folding: false,
2528
});
2629
editorRef.current.onDidChangeModelContent(() => {
2730
props.onChange(editorRef.current!.getValue());

components/dashboard/src/components/WorkspaceLogs.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export default class WorkspaceLogs extends React.Component<WorkspaceLogsProps, W
8282
}
8383

8484
render() {
85-
return <div className={`mt-6 ${this.props.classes || 'h-72 w-11/12 lg:w-3/5'} rounded-xl bg-black relative`}>
85+
return <div className={`${this.props.classes || 'h-72 w-11/12 lg:w-3/5'} rounded-xl bg-black relative`}>
8686
<div className="absolute top-0 left-0 bottom-0 right-0 m-6" ref={this.xTermParentRef}></div>
8787
</div>;
8888
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

components/dashboard/src/projects/ConfigureProject.tsx

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import PrebuildLogs from "../components/PrebuildLogs";
1111
import TabMenuItem from "../components/TabMenuItem";
1212
import { getGitpodService } from "../service/service";
1313
import { getCurrentTeam, TeamsContext } from "../teams/teams-context";
14-
import AlertBox from "../components/AlertBox";
14+
import Header from "../components/Header";
15+
import Spinner from "../icons/Spinner.svg";
16+
import PrebuildLogsEmpty from "../images/prebuild-logs-empty.svg";
17+
import PrebuildLogsEmptyDark from "../images/prebuild-logs-empty-dark.svg";
18+
import { ThemeContext } from "../theme-context";
1519

1620
const MonacoEditor = React.lazy(() => import('../components/MonacoEditor'));
1721

@@ -56,15 +60,16 @@ export default function () {
5660
const [ project, setProject ] = useState<Project | undefined>();
5761
const [ gitpodYml, setGitpodYml ] = useState<string>('');
5862
const [ dockerfile, setDockerfile ] = useState<string>('');
59-
const [ editorError, setEditorError ] = useState<React.ReactNode | null>(null);
63+
const [ editorMessage, setEditorMessage ] = useState<React.ReactNode | null>(null);
6064
const [ selectedEditor, setSelectedEditor ] = useState<'.gitpod.yml'|'.gitpod.Dockerfile'>('.gitpod.yml');
6165
const [ isEditorDisabled, setIsEditorDisabled ] = useState<boolean>(true);
6266
const [ workspaceCreationResult, setWorkspaceCreationResult ] = useState<WorkspaceCreationResult | undefined>();
67+
const { isDark } = useContext(ThemeContext);
6368

6469
useEffect(() => {
6570
// Disable editing while loading, or when the config comes from Git.
6671
setIsEditorDisabled(true);
67-
setEditorError(null);
72+
setEditorMessage(null);
6873
if (!teams) {
6974
return;
7075
}
@@ -73,19 +78,31 @@ export default function () {
7378
? await getGitpodService().server.getTeamProjects(team.id)
7479
: await getGitpodService().server.getUserProjects());
7580
const project = projects.find(p => p.name === routeMatch?.params.projectSlug);
76-
if (project) {
77-
setProject(project);
78-
getGitpodService().server.guessProjectConfiguration(project.id).then(conf => console.log('guessed', conf)).catch(err => console.error('could not guess', err));
79-
const configString = await getGitpodService().server.fetchProjectRepositoryConfiguration(project.id);
80-
if (configString) {
81-
// TODO(janx): Link to .gitpod.yml directly instead of just the cloneUrl.
82-
setEditorError(<span>A Gitpod configuration already exists in the project's <a className="gp-link" href={project.cloneUrl}>repository</a>.<br/>Please <a className="gp-link" href={`/#${project.cloneUrl}`}>edit it in Gitpod</a> instead.</span>);
83-
setGitpodYml(configString);
84-
} else {
85-
setIsEditorDisabled(false);
86-
setGitpodYml(project.config && project.config['.gitpod.yml'] || '');
87-
}
81+
if (!project) {
82+
return;
8883
}
84+
setProject(project);
85+
const guessedConfigStringPromise = getGitpodService().server.guessProjectConfiguration(project.id);
86+
const repoConfigString = await getGitpodService().server.fetchProjectRepositoryConfiguration(project.id);
87+
if (repoConfigString) {
88+
// TODO(janx): Link to .gitpod.yml directly instead of just the cloneUrl.
89+
setEditorMessage(<EditorMessage type="warning" heading="Configuration already exists in git." message="Run a prebuild and open a new workspace to edit configuration."/>);
90+
setGitpodYml(repoConfigString);
91+
return;
92+
}
93+
const guessedConfigString = await guessedConfigStringPromise;
94+
setIsEditorDisabled(false);
95+
if (guessedConfigString) {
96+
setEditorMessage(<EditorMessage type="success" heading="Project type detected." message="You can edit project configuration below before running a prebuild"/>);
97+
setGitpodYml(guessedConfigString);
98+
return;
99+
}
100+
if (project.config && project.config['.gitpod.yml']) {
101+
setGitpodYml(project.config['.gitpod.yml']);
102+
return;
103+
}
104+
setEditorMessage(<EditorMessage type="warning" heading="Project type could not be detected." message="You can edit project configuration below before running a prebuild."/>);
105+
setGitpodYml(TASKS.Other);
89106
})();
90107
}, [ teams, team ]);
91108

@@ -94,7 +111,7 @@ export default function () {
94111
return;
95112
}
96113
// (event.target as HTMLButtonElement).disabled = true;
97-
setEditorError(null);
114+
setEditorMessage(null);
98115
if (!!workspaceCreationResult) {
99116
setWorkspaceCreationResult(undefined);
100117
}
@@ -106,40 +123,50 @@ export default function () {
106123
});
107124
setWorkspaceCreationResult(result);
108125
} catch (error) {
109-
setEditorError(<span>{String(error)}</span>);
126+
setEditorMessage(<EditorMessage type="warning" heading="Could not run prebuild." message={String(error)}/>);
110127
}
111128
}
112129

113130
useEffect(() => { document.title = 'Configure Project — Gitpod' }, []);
114131

115-
return <div className="flex flex-col mt-24 mx-auto items-center">
116-
<h1>Configure Project</h1>
117-
<p className="text-gray-500 text-center text-base">Fully-automate your project's dev setup. <a className="gp-link" href="https://www.gitpod.io/docs/references/gitpod-yml">Learn more</a></p>
118-
<div className="mt-4 w-full flex">
119-
<div className="flex-1 m-8">
120-
{editorError && <AlertBox className="mb-2">{editorError}</AlertBox>}
121-
{!isEditorDisabled && <select className="w-full" defaultValue="" onChange={e => setGitpodYml(e.target.value)}>
122-
<option value="" disabled={true}></option>
123-
{Object.entries(TASKS).map(([ name, value ]) => <option value={value}>{name}</option>)}
124-
</select>}
125-
{!!dockerfile && <div className="flex justify-center border-b border-gray-200 dark:border-gray-800">
132+
return <>
133+
<Header title="Configuration" subtitle="View and edit project configuration." />
134+
<div className="lg:px-28 px-10 mt-8 flex space-x-4">
135+
<div className="w-96 h-96 rounded-xl overflow-hidden bg-gray-100 dark:bg-gray-700 flex flex-col">
136+
<div className="flex bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-600 px-6 pt-3">
126137
<TabMenuItem name=".gitpod.yml" selected={selectedEditor === '.gitpod.yml'} onClick={() => setSelectedEditor('.gitpod.yml')} />
127-
<TabMenuItem name=".gitpod.Dockerfile" selected={selectedEditor === '.gitpod.Dockerfile'} onClick={() => setSelectedEditor('.gitpod.Dockerfile')} />
128-
</div>}
138+
{!!dockerfile && <TabMenuItem name=".gitpod.Dockerfile" selected={selectedEditor === '.gitpod.Dockerfile'} onClick={() => setSelectedEditor('.gitpod.Dockerfile')} />}
139+
</div>
140+
{editorMessage}
141+
<img className="h-5 w-5 animate-spin" src={Spinner} />
129142
<Suspense fallback={<div />}>
130143
{selectedEditor === '.gitpod.yml' &&
131-
<MonacoEditor classes="mt-4 w-full h-64" disabled={isEditorDisabled} language="yaml" value={gitpodYml} onChange={setGitpodYml} />}
144+
<MonacoEditor classes="w-full flex-grow" disabled={isEditorDisabled} language="yaml" value={gitpodYml} onChange={setGitpodYml} />}
132145
{selectedEditor === '.gitpod.Dockerfile' &&
133-
<MonacoEditor classes="mt-4 w-full h-64" disabled={isEditorDisabled} language="dockerfile" value={dockerfile} onChange={setDockerfile} />}
146+
<MonacoEditor classes="w-full flex-grow" disabled={isEditorDisabled} language="dockerfile" value={dockerfile} onChange={setDockerfile} />}
134147
</Suspense>
135-
<div className="mt-2 flex justify-center space-x-2">
136-
<button disabled={isEditorDisabled} onClick={buildProject}>Save &amp; Test Configuration</button>
137-
</div>
138148
</div>
139-
<div className="flex-1 m-8">
140-
<h3 className="text-center">Output</h3>
141-
{!!workspaceCreationResult && <PrebuildLogs workspaceId={workspaceCreationResult.createdWorkspaceId} />}
149+
<div className="flex-grow h-96 rounded-xl overflow-hidden bg-gray-100 dark:bg-gray-700 flex flex-col">
150+
<div className="flex-grow flex">{workspaceCreationResult
151+
? <PrebuildLogs workspaceId={workspaceCreationResult.createdWorkspaceId} />
152+
: <div className="flex-grow flex flex-col items-center justify-center">
153+
<img className="w-14" role="presentation" src={isDark ? PrebuildLogsEmptyDark : PrebuildLogsEmpty} />
154+
<h3 className="text-center text-gray-500 dark:text-gray-50 mt-4">No Recent Prebuild</h3>
155+
<p className="text-center text-base text-gray-500 dark:text-gray-400 mt-2 w-64">Edit the project configuration on the left to get started. <a className="learn-more" href="https://www.gitpod.io/docs/config-gitpod-file/">Learn more</a>.</p>
156+
</div>
157+
}</div>
158+
<div className="h-20 px-6 bg-gray-50 dark:bg-gray-800 border-t border-gray-200 dark:border-gray-600 flex">
159+
<div className="flex-grow" />
160+
<button disabled={isEditorDisabled} onClick={buildProject}>Run Prebuild</button>
161+
</div>
142162
</div>
143163
</div>
164+
</>;
165+
}
166+
167+
function EditorMessage(props: { heading: string, message: string, type: 'success' | 'warning' }) {
168+
return <div className={`p-4 flex flex-col ${props.type === 'success' ? 'bg-green-50 text-green-700' : 'bg-yellow-50 text-yellow-700'}`}>
169+
<strong className={`font-semibold ${props.type === 'success' ? 'text-green-800' : 'text-yellow-800'}`}>{props.heading}</strong>
170+
<span>{props.message}</span>
144171
</div>;
145172
}

0 commit comments

Comments
 (0)