Skip to content

Commit de5aa0a

Browse files
committed
feat: added workspace deletions
1 parent c35b77b commit de5aa0a

16 files changed

+318
-78
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ https://github.com/gitpod-samples/Gitpod-Raycast-Extension/assets/72302948/8b49a
3434

3535
1. Install Raycast to get started if you haven't by simply clicking on this button!
3636

37-
<a href="https://www.raycast.com/henitchobisa/gitpod"><img src="https://www.raycast.com/henitchobisa/gitpod/install_button@2x.png" height="64" alt="" style="height: 64px;"></a>
37+
<a href="https://www.raycast.com/Henit-Palani/gitpod"><img src="https://www.raycast.com/henitchobisa/gitpod/install_button@2x.png" height="64" alt="" style="height: 64px;"></a>
3838

3939
2. Navigate to the Raycast Store to Download the `Gitpod` extension
4040
![GithubLogin](/assets/Screenshots/NavigatingContexts/Download%20GItpod.png)

assets/Icons/file-diff.svg

Lines changed: 1 addition & 0 deletions
Loading

constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@ export const GitpodIcons = {
9292

9393
gitpod_logo_primary: { source: "logo-mark.svg" },
9494
gitpod_logo_secondary: { source: "logo-mark.svg", tintColor: statusColors.stopped },
95+
github_untracked: {source: "Icons/file-diff.svg", tintColor: UIColors.grey},
9596
};

package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@
4343
"type": "checkbox",
4444
"required": true
4545
},
46+
{
47+
"name" : "allow_delete_workspaces",
48+
"label" : "Allow Deleting Workspace",
49+
"description" : "Enable deleting workspaces from Extension",
50+
"type" : "checkbox",
51+
"required" : false
52+
},
4653
{
4754
"name": "preferredEditorClass",
4855
"title": "Default Workspace Class",

src/api/Gitpod/Models/IWorkspace.ts

Lines changed: 99 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type ICreateWorkspaceParams = {
1414
organizationId: string;
1515
ignoreRunningWorkspaceOnSameCommit: true;
1616
ignoreRunningPrebuild: true;
17+
worksspaceClass: "g1-standard" | "g1-large";
1718
ideSetting: {
1819
defaultIde: string;
1920
useLatestVersion: false;
@@ -35,6 +36,7 @@ export class IWorkspace implements GitpodDataModel {
3536
private ownerId: string;
3637
private projectId: string;
3738
private ideURL: string;
39+
private workspaceClass?: "g1-standard" | "g1-large";
3840
private context: {
3941
contextURL: string;
4042
git: {
@@ -49,6 +51,40 @@ export class IWorkspace implements GitpodDataModel {
4951
};
5052

5153
private repository: string;
54+
private totalUntrackedFiles?: number;
55+
private untrackedFiles?: string[];
56+
private recentFolders?: string[];
57+
58+
private totalUncommittedFiles?: number;
59+
private UncommittedFiles?: string[];
60+
61+
getUntrackedFiles() {
62+
return this.untrackedFiles
63+
}
64+
65+
getUncommittedFiles() {
66+
return this.UncommittedFiles
67+
}
68+
69+
getRecentFolders() {
70+
return this.recentFolders;
71+
}
72+
73+
getTotalUntrackedFiles() {
74+
return this.totalUntrackedFiles
75+
}
76+
77+
getTotatUncommittedFiles() {
78+
return this.totalUncommittedFiles
79+
}
80+
81+
getWorkspaceClass() {
82+
return this.workspaceClass
83+
}
84+
85+
setWorkspaceClass(workspaceClass: "g1-standard" | "g1-large") {
86+
this.workspaceClass = workspaceClass
87+
}
5288

5389
getIDEURL() {
5490
return this.ideURL;
@@ -125,28 +161,52 @@ export class IWorkspace implements GitpodDataModel {
125161
this.createdAt = workspace.status.instance.createdAt;
126162
this.ideURL = workspace.status.instance ? workspace.status.instance.status.url : "https://gitpod.io";
127163
this.repository = workspace.context.git.repository.name;
164+
165+
if (workspace.status.instance.status.gitStatus) {
166+
if (workspace.status.instance.status.gitStatus.totalUntrackedFiles) {
167+
this.totalUntrackedFiles = workspace.status.instance.status.gitStatus.totalUntrackedFiles;
168+
this.untrackedFiles = workspace.status.instance.status.gitStatus.untrackedFiles;
169+
}
170+
171+
if (workspace.status.instance.status.gitStatus.uncommitedFiles) {
172+
this.totalUncommittedFiles = workspace.status.instance.status.gitStatus.totalUncommitedFiles
173+
this.UncommittedFiles = workspace.status.instance.status.gitStatus.uncommitedFiles
174+
}
175+
}
176+
177+
if (workspace.status.instance.status.recentFolders) {
178+
this.recentFolders = workspace.status.instance.status.recentFolders as string[];
179+
}
128180
}
129181

130182
parse(json: string): IWorkspace {
131183
const data = JSON.parse(json);
132-
this.workspaceId = data.result.workspaceId;
133-
this.ownerId = data.result.ownerId;
134-
this.projectId = data.result.context.git.normalizedContextUrl.split("/").slice(-2)[0];
184+
const workspace = data.result;
185+
this.workspaceId = workspace.workspaceId;
186+
this.ownerId = workspace.ownerId;
187+
this.projectId = workspace.context.git.normalizedContextUrl.split("/").slice(-2)[0];
135188
this.context = {
136-
contextURL: data.result.context.contextUrl,
189+
contextURL: workspace.context.contextUrl,
137190
git: {
138-
normalizedContextUrl: data.result.context.git.normalizedContextUrl,
191+
normalizedContextUrl: workspace.context.git.normalizedContextUrl,
139192
},
140193
};
141-
this.repository = data.result.context.git.repository.name;
142-
this.instanceId = data.result.status.instance.instanceId;
143-
this.description = data.result.description;
194+
this.repository = workspace.context.git.repository.name;
195+
this.instanceId = workspace.status.instance.instanceId;
196+
this.description = workspace.description;
144197
this.status = {
145-
phase: data.result.status.instance.status.phase,
198+
phase: workspace.status.instance.status.phase,
146199
};
147-
this.ideURL = data.result.status.instance ? data.result.status.instance.status.url : "";
200+
this.ideURL = workspace.status.instance ? data.result.status.instance.status.url : "";
201+
202+
this.createdAt = workspace.status.instance.createdAt;
203+
204+
if (workspace.status.instance.status.gitStatus.totalUntrackedFiles) {
205+
this.totalUntrackedFiles = workspace.status.instance.status.gitStatus.totalUntrackedFiles;
206+
this.untrackedFiles = workspace.status.instance.status.gitStatus.untrackedFiles;
207+
}
148208

149-
this.createdAt = data.result.status.instance.createdAt;
209+
this.recentFolders = workspace.status.instance.status.recentFolders;
150210

151211
return this;
152212
}
@@ -270,27 +330,35 @@ export class IWorkspace implements GitpodDataModel {
270330

271331
const json = (await response.json()) as any;
272332

273-
json.result.map((workspace: unknown) => {
274-
const space = new IWorkspace(workspace, token);
275-
workspaceMap.set(space.workspaceId, space);
276-
});
333+
if (json.result) {
334+
json.result.map((workspace: unknown) => {
335+
const space = new IWorkspace(workspace, token);
336+
workspaceMap.set(space.workspaceId, space);
337+
});
338+
}
277339
return workspaceMap;
278340
};
279341

280-
// public delete = async () => {
281-
// const response = await fetch(workspaceURLs.deleteWorkspace, {
282-
// method: "GET",
283-
// headers: {
284-
// "Content-Type": "application/json",
285-
// Authorization: `Bearer ${this.token}`,
286-
// },
287-
// body: JSON.stringify({ workspaceId: this.workspaceId }),
288-
// });
289-
// const result = await response.json();
290-
// if (response.status !== 200) {
291-
// throw new Error(`Failed to delete workspace: ${result.message}`);
292-
// }
293-
294-
// this.dispose();
295-
// };
342+
public delete = async () => {
343+
344+
const workspace_id = this.workspaceId
345+
const response = await fetch(workspaceURLs.deleteWorkspace, {
346+
method: "POST",
347+
headers: {
348+
"content-type": "application/json",
349+
Authorization: `Bearer ${this.token}`,
350+
},
351+
body: JSON.stringify({ workspaceId: workspace_id }),
352+
});
353+
354+
if (response.status !== 200) {
355+
const error: IWorkspaceError = {
356+
name: "WorkspaceDeleteError",
357+
code: response.status,
358+
message: "Error Occured in Deleting Workspace",
359+
};
360+
throw error;
361+
}
362+
return workspace_id
363+
};
296364
}

src/api/Gitpod/Models/IWorkspaceUpdate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export interface IWorkspaceUpdate {
99
};
1010
phasePersisted: string;
1111
deleted: boolean;
12-
workspaceClass: string;
12+
workspaceClass: "g1-standard" | "g1-large";
1313
}
1414

1515
export function NewIWorkspaceUpdateObject(jsonObj: any): IWorkspaceUpdate {

src/api/Gitpod/WorkspaceManager.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export class WorkspaceManager extends EventEmitter {
3030
return WorkspaceManager.instance;
3131
}
3232

33+
deleteWorkspace(workspace_id: string){
34+
WorkspaceManager.workspaces.delete(workspace_id);
35+
return WorkspaceManager.workspaces;
36+
}
37+
3338
async init() {
3439
// this method will give you all the workspaces
3540
if (WorkspaceManager.instance) {
@@ -54,10 +59,13 @@ export class WorkspaceManager extends EventEmitter {
5459
// update when the workspace is not in the state
5560
targetWorkspace.setStatus(updateInstance.status);
5661
targetWorkspace.setIDEURL(updateInstance.ideUrl);
62+
if (!targetWorkspace.getWorkspaceClass()){
63+
targetWorkspace.setWorkspaceClass(updateInstance.workspaceClass)
64+
}
5765
WorkspaceManager.workspaces = WorkspaceManager.workspaces.set(updateInstance.workspaceId, targetWorkspace);
5866

5967
// Workspace has been updated, its time to tell our listeners i.e. UI Components, that workspaces have been updated and it's time to change things.
60-
this.emit("workspaceUpdated", targetWorkspace);
68+
this.emit("workspaceUpdated");
6169
});
6270

6371
WorkspaceManager.api.on("errorOccured", (error: IWorkspaceError) => {

src/components/BranchListItem.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Toast,
1111
getPreferenceValues,
1212
LocalStorage,
13+
copyTextToClipboard,
1314
} from "@raycast/api";
1415
import { usePromise } from "@raycast/utils";
1516

@@ -177,6 +178,22 @@ export default function BranchListItem({
177178
open(branchURL);
178179
}}
179180
/>
181+
<Action
182+
title="Copy Branch URL"
183+
onAction={async () => {
184+
visitBranch?.(branch, repository);
185+
await showToast({
186+
title: `Copying "${branch.branchName}" url`,
187+
style: Toast.Style.Animated,
188+
});
189+
copyTextToClipboard(branchURL);
190+
await showToast({
191+
title: `Copied "${branch.branchName}" url`,
192+
style: Toast.Style.Success,
193+
});
194+
}}
195+
shortcut={{ modifiers: ["cmd", "shift"], key: "enter" }}
196+
/>
180197
{!fromCache && (
181198
<Action
182199
title="Add Branch to Recents"

src/components/IssueListItem.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Toast,
1010
getPreferenceValues,
1111
LocalStorage,
12+
copyTextToClipboard,
1213
} from "@raycast/api";
1314
import { MutatePromise, usePromise } from "@raycast/utils";
1415
import { format } from "date-fns";
@@ -35,9 +36,9 @@ type IssueListItemProps = {
3536
changeBodyVisibility?: (state: boolean) => void;
3637
bodyVisible?: boolean;
3738
mutateList?:
38-
| MutatePromise<SearchCreatedIssuesQuery | undefined>
39-
| MutatePromise<SearchOpenIssuesQuery | undefined>
40-
| MutatePromise<IssueFieldsFragment[] | undefined>;
39+
| MutatePromise<SearchCreatedIssuesQuery | undefined>
40+
| MutatePromise<SearchOpenIssuesQuery | undefined>
41+
| MutatePromise<IssueFieldsFragment[] | undefined>;
4142
visitIssue?: (issue: IssueFieldsFragment) => void;
4243
removeIssue?: (issue: IssueFieldsFragment) => void;
4344
fromCache?: boolean;
@@ -133,6 +134,22 @@ export default function IssueListItem({
133134
open(issue.url);
134135
}}
135136
/>
137+
<Action
138+
title="Copy Issue URL"
139+
onAction={async () => {
140+
visitIssue?.(issue);
141+
await showToast({
142+
title: `Copying "${issue.title}" url`,
143+
style: Toast.Style.Animated,
144+
});
145+
copyTextToClipboard(issue.url);
146+
await showToast({
147+
title: `Copied "${issue.title}" url`,
148+
style: Toast.Style.Success,
149+
});
150+
}}
151+
shortcut={{ modifiers: ["cmd", "shift"], key: "enter" }}
152+
/>
136153
{!fromCache && (
137154
<Action
138155
title="Show Issue Preview"

src/components/PullRequestListItem.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Toast,
1010
getPreferenceValues,
1111
LocalStorage,
12+
copyTextToClipboard,
1213
} from "@raycast/api";
1314
import { usePromise } from "@raycast/utils";
1415
import { format } from "date-fns";
@@ -156,6 +157,22 @@ export default function PullRequestListItem({
156157
open(pullRequest.permalink);
157158
}}
158159
/>
160+
<Action
161+
title="Copy PR URL"
162+
onAction={async () => {
163+
visitPullReq?.(pullRequest);
164+
await showToast({
165+
title: `Copying "${pullRequest.title}" url`,
166+
style: Toast.Style.Animated,
167+
});
168+
copyTextToClipboard(pullRequest.permalink);
169+
await showToast({
170+
title: `Copied "${pullRequest.title}" url`,
171+
style: Toast.Style.Success,
172+
});
173+
}}
174+
shortcut={{ modifiers: ["cmd", "shift"], key: "enter" }}
175+
/>
159176
{!fromCache && (
160177
<Action
161178
title="Add PR to Recents"

0 commit comments

Comments
 (0)