Skip to content

Commit 7658c52

Browse files
Laurie T. Malauroboquat
Laurie T. Malau
authored andcommitted
Introduce project slug
Fixes #5847
1 parent 5b38a4a commit 7658c52

File tree

9 files changed

+63
-9
lines changed

9 files changed

+63
-9
lines changed

components/dashboard/src/projects/NewProject.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ export default function NewProject() {
170170
try {
171171
await getGitpodService().server.createProject({
172172
name: repo.name,
173+
slug: (repo.path ? repo.path : repo.name),
173174
cloneUrl: repo.cloneUrl,
174175
account: repo.account,
175176
provider,

components/dashboard/src/projects/Project.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default function () {
2626
const team = getCurrentTeam(location, teams);
2727

2828
const match = useRouteMatch<{ team: string, resource: string }>("/(t/)?:team/:resource");
29-
const projectName = match?.params?.resource;
29+
const projectSlug = match?.params?.resource;
3030

3131
const [project, setProject] = useState<Project | undefined>();
3232

@@ -61,14 +61,18 @@ export default function () {
6161
}, [project]);
6262

6363
const updateProject = async () => {
64-
if (!teams || !projectName) {
64+
if (!teams || !projectSlug) {
6565
return;
6666
}
6767
const projects = (!!team
6868
? await getGitpodService().server.getTeamProjects(team.id)
6969
: await getGitpodService().server.getUserProjects());
7070

71-
const project = projectName && projects.find(p => p.name === projectName);
71+
// Find project matching with slug, otherwise with name
72+
const project = projectSlug && projects.find(
73+
p => p.slug ? p.slug === projectSlug :
74+
p.name === projectSlug);
75+
7276
if (!project) {
7377
return;
7478
}
@@ -239,7 +243,7 @@ export default function () {
239243
</div>
240244
</ItemField>
241245
<ItemField className="flex items-center">
242-
<a className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1 cursor-pointer" href={prebuild ? `/${!!team ? 't/' + team.slug : 'projects'}/${projectName}/${prebuild.info.id}` : 'javascript:void(0)'}>
246+
<a className="text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1 cursor-pointer" href={prebuild ? `/${!!team ? 't/' + team.slug : 'projects'}/${projectSlug}/${prebuild.info.id}` : 'javascript:void(0)'}>
243247
{prebuild ? (<><div className="inline-block align-text-bottom mr-2 w-4 h-4">{statusIcon}</div>{status}</>) : (<span> </span>)}
244248
</a>
245249
<span className="flex-grow" />

components/dashboard/src/projects/Projects.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,29 @@ export default function () {
8585
return moment(lastPrebuilds.get(p1.id)?.info?.startedAt || '1970-01-01').diff(moment(lastPrebuilds.get(p0.id)?.info?.startedAt || '1970-01-01'));
8686
}
8787

88-
const teamOrUserSlug = !!team ? 't/'+team.slug : 'projects';
8988
let [ isRemoveModalVisible, setRemoveModalVisible ] = useState(false);
9089
let [ removeProjectHandler, setRemoveProjectHandler ] = useState<() => void>(()=> () => {})
9190
let [ willRemoveProject, setWillRemoveProject ] = useState<Project>()
9291

92+
function renderProjectLink(project: Project): React.ReactElement {
93+
let slug = '';
94+
const name = project.name;
95+
96+
if (project.slug) {
97+
slug = project.slug;
98+
} else {
99+
// For existing GitLab projects that don't have a slug yet
100+
slug = name;
101+
}
102+
103+
return (
104+
<Link to={`/${teamOrUserSlug}/${slug}`}>
105+
<span className="text-xl font-semibold">{name}</span>
106+
</Link>)
107+
}
108+
109+
const teamOrUserSlug = !!team ? 't/' + team.slug : 'projects';
110+
93111
return <>
94112

95113
{isRemoveModalVisible && <ConfirmationModal
@@ -137,9 +155,7 @@ export default function () {
137155
<div className="h-42 border border-gray-100 dark:border-gray-800 rounded-t-xl">
138156
<div className="h-32 p-6">
139157
<div className="flex text-gray-700 dark:text-gray-200 font-medium">
140-
<Link to={`/${teamOrUserSlug}/${p.name}`}>
141-
<span className="text-xl font-semibold">{p.name}</span>
142-
</Link>
158+
{renderProjectLink(p)}
143159
<span className="flex-grow" />
144160
<div className="justify-end">
145161
<ContextMenu menuEntries={[

components/gitpod-db/src/typeorm/entity/db-project.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ export class DBProject {
1818
@Column()
1919
name: string;
2020

21+
@Column()
22+
slug?: string;
23+
2124
@Column()
2225
cloneUrl: string;
2326

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import {MigrationInterface, QueryRunner} from "typeorm";
8+
import { columnExists } from "./helper/helper";
9+
10+
export class AddSlugToProject1634894637934 implements MigrationInterface {
11+
12+
public async up(queryRunner: QueryRunner): Promise<any> {
13+
if (!(await columnExists(queryRunner, "d_b_project", "slug"))) {
14+
await queryRunner.query("ALTER TABLE d_b_project ADD COLUMN `slug` varchar(255) NULL");
15+
}
16+
if (await columnExists(queryRunner, "d_b_project", "slug")) {
17+
await queryRunner.query("UPDATE d_b_project SET slug = name WHERE cloneUrl LIKE '%github%' AND slug IS NULL;");
18+
}
19+
}
20+
21+
public async down(queryRunner: QueryRunner): Promise<any> {
22+
}
23+
24+
}

components/gitpod-protocol/src/gitpod-service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
235235

236236
export interface CreateProjectParams {
237237
name: string;
238+
slug?: string;
238239
account: string;
239240
provider: string;
240241
cloneUrl: string;
@@ -256,6 +257,7 @@ export interface GetProviderRepositoriesParams {
256257
}
257258
export interface ProviderRepository {
258259
name: string;
260+
path?: string;
259261
account: string;
260262
accountAvatarUrl: string;
261263
cloneUrl: string;

components/gitpod-protocol/src/teams-projects-protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface ProjectConfig {
1414
export interface Project {
1515
id: string;
1616
name: string;
17+
slug?: string;
1718
cloneUrl: string;
1819
teamId?: string;
1920
userId?: string;

components/server/ee/src/gitlab/gitlab-app-support.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export class GitLabAppSupport {
3737
const projectsWithAccess = await api.Projects.all({ min_access_level: "40", perPage: 100 });
3838
for (const project of projectsWithAccess) {
3939
const anyProject = project as any;
40+
const path = anyProject.path as string;
4041
const fullPath = anyProject.path_with_namespace as string;
4142
const cloneUrl = anyProject.http_url_to_repo as string;
4243
const updatedAt = anyProject.last_activity_at as string;
@@ -45,6 +46,7 @@ export class GitLabAppSupport {
4546

4647
(account === usersGitLabAccount ? ownersRepos : result).push({
4748
name: project.name,
49+
path,
4850
account,
4951
cloneUrl,
5052
updatedAt,

components/server/src/projects/projects-service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,14 @@ export class ProjectsService {
9090
return result;
9191
}
9292

93-
async createProject({ name, cloneUrl, teamId, userId, appInstallationId }: CreateProjectParams): Promise<Project> {
93+
async createProject({ name, slug, cloneUrl, teamId, userId, appInstallationId }: CreateProjectParams): Promise<Project> {
9494
const projects = await this.getProjectsByCloneUrls([cloneUrl]);
9595
if (projects.length > 0) {
9696
throw new Error("Project for repository already exists.");
9797
}
9898
const project = Project.create({
9999
name,
100+
slug,
100101
cloneUrl,
101102
...(!!userId ? { userId } : { teamId }),
102103
appInstallationId

0 commit comments

Comments
 (0)