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

[feat] Added workspace class and editor preferences at Repo, Context and Global levels with cascade #30

Merged
merged 7 commits into from
Mar 16, 2023
86 changes: 75 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,81 @@
"Productivity"
],
"license": "MIT",
"preferences": [
{
"name": "preferredEditor",
"title": "Default Workspace Editor",
"description": "Choose your Preferred editor for Gitpod",
"type": "dropdown",
"data": [
{
"title": "VS Code Browser",
"value": "code"
},
{
"title": "VS Code Desktop",
"value": "code-desktop"
},
{
"title": "IntelliJ",
"value": "intellij"
},
{
"title": "GoLand",
"value": "goland"
},
{
"title": "PhpStorm",
"value": "phpstorm"
},
{
"title": "PyCharm",
"value": "pycharm"
},
{
"title": "RubyMine",
"value": "rubymine"
},
{
"title": "WebStorm",
"value": "webstorm"
},
{
"title": "Rider",
"value": "rider"
},
{
"title": "CLion",
"value": "clion"
}
],
Palanikannan1437 marked this conversation as resolved.
Show resolved Hide resolved
"required": true
},
{
"name": "useLatest",
"label": "Latest Release (Unstable)",
"description": "Use the latest version for each editor. Insiders for VS Code, EAP for JetBrains IDEs.",
"type": "checkbox",
"required": true
},
{
"name": "preferredEditorClass",
"title": "Default Workspace Class",
"description": "Up to 4 cores, 8GB RAM, 30GB storage in Standard and Up to 8 cores, 16GB RAM, 50GB storage in Large",
"type": "dropdown",
"data": [
{
"title": "Standard",
"value": "g1-standard"
},
{
"title": "Large",
"value": "g1-large"
}
],
"required": true
}
],
"commands": [
{
"name": "open_in_gitpod",
Expand Down Expand Up @@ -41,17 +116,6 @@
]
}
],

"preferences": [
{
"name": "personalAccessToken",
"title": "Personal Access Token",
"placeholder": "Visit https://github.com/settings/tokens",
"description": "Enter Classic Personal Access Token from GitHub",
"type": "password",
"required": true
}
],
"dependencies": {
"@graphql-codegen/cli": "^2.16.2",
"@graphql-codegen/typescript-graphql-request": "^4.5.8",
Expand Down
9 changes: 7 additions & 2 deletions src/components/BranchListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Action, ActionPanel, Color, List, open } from "@raycast/api";
import { Action, ActionPanel, Color, List, open, useNavigation } from "@raycast/api";

import { branchStatus, GitpodIcons } from "../../constants";
import { BranchDetailsFragment, UserFieldsFragment } from "../generated/graphql";
import OpenInGitpod from "../helpers/openInGitpod";
import ContextPreferences from "../preferences/context_preferences";

type BranchItemProps = {
branch: BranchDetailsFragment;
Expand All @@ -14,6 +16,7 @@ export default function BranchListItem({ branch, mainBranch, repository }: Branc
const accessories: List.Item.Accessory[] = [];
const branchURL = "https://github.com/" + repository + "/tree/" + branch.branchName;

const { push } = useNavigation();
if (branch.compData) {
if (branch.compData.status) {
switch (branch.compData.status.toString()) {
Expand Down Expand Up @@ -66,15 +69,17 @@ export default function BranchListItem({ branch, mainBranch, repository }: Branc
<Action
title="Open Branch in Gitpod"
onAction={() => {
open(`https://gitpod.io/#${branchURL}`);
OpenInGitpod(branchURL,"Branch",repository,branch.branchName)
}}
shortcut={{ modifiers: ["cmd"], key: "g" }}
/>
<Action
title="Open Branch in GitHub"
onAction={() => {
open(branchURL);
}}
/>
<Action title="Configure Workspace" onAction={()=> push(<ContextPreferences type="Branch" repository={repository} context={branch.branchName}/>)} shortcut={{ modifiers: ["cmd"], key: "w" }}/>
</ActionPanel>
}
/>
Expand Down
16 changes: 7 additions & 9 deletions src/components/IssueListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Action, ActionPanel, Icon, List, open } from "@raycast/api";
import { Action, ActionPanel, Icon, List, open, useNavigation } from "@raycast/api";
import { MutatePromise } from "@raycast/utils";
import { format } from "date-fns";

Expand All @@ -9,6 +9,8 @@ import {
UserFieldsFragment,
} from "../generated/graphql";
import { getIssueAuthor, getIssueStatus } from "../helpers/issue";
import OpenInGitpod from "../helpers/openInGitpod";
import ContextPreferences from "../preferences/context_preferences";

type IssueListItemProps = {
issue: IssueFieldsFragment;
Expand All @@ -20,6 +22,7 @@ type IssueListItemProps = {
};

export default function IssueListItem({ issue }: IssueListItemProps) {
const { push } = useNavigation();
const updatedAt = new Date(issue.updatedAt);

const author = getIssueAuthor(issue);
Expand Down Expand Up @@ -62,25 +65,20 @@ export default function IssueListItem({ issue }: IssueListItemProps) {
<Action
title="Open Issue in Gitpod"
onAction={() => {
open(`https://gitpod.io/#${issue.url}`);
OpenInGitpod(issue.url,"Issue",issue.repository.nameWithOwner, issue.title)
}}
shortcut={{ modifiers: ["cmd"], key: "g" }}
/>
<Action
title="View Issue in GitHub"
onAction={() => {
open(issue.url);
}}
/>
<Action title="Configure Workspace" onAction={()=> push(<ContextPreferences repository={issue.repository.nameWithOwner} type="Issue" context={issue.title} />)} shortcut={{ modifiers: ["cmd"], key: "w" }}/>
</ActionPanel>
}
/>
);
}

// <IssueActions issue={issue} mutateList={mutateList} viewer={viewer}>
// <Action.Push
// title="Show Details"
// icon={Icon.Sidebar}
// target={<IssueDetail initialIssue={issue} viewer={viewer} mutateList={mutateList} />}
// />
// </IssueActions>
29 changes: 10 additions & 19 deletions src/components/PullRequestListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { Action, ActionPanel, Icon, List, open } from "@raycast/api";
// import { MutatePromise } from "@raycast/utils";
import { Action, ActionPanel, Icon, List, open, useNavigation } from "@raycast/api";
import { format } from "date-fns";
import { pull } from "lodash";
import { useMemo } from "react";

import { MyPullRequestsQuery, PullRequestFieldsFragment, UserFieldsFragment } from "../generated/graphql";
import { PullRequestFieldsFragment, UserFieldsFragment } from "../generated/graphql";
import OpenInGitpod from "../helpers/openInGitpod";
import {
getCheckStateAccessory,
getNumberOfComments,
getPullRequestAuthor,
getPullRequestStatus,
getReviewDecision,
} from "../helpers/pull-request";

// import PullRequestActions from "./PullRequestActions";
// import PullRequestDetail from "./PullRequestDetail";
import ContextPreferences from "../preferences/context_preferences";

type PullRequestListItemProps = {
pullRequest: PullRequestFieldsFragment;
viewer?: UserFieldsFragment;
// mutateList: MutatePromise<MyPullRequestsQuery | undefined> | MutatePromise<PullRequestFieldsFragment[] | undefined>;
};

export default function PullRequestListItem({ pullRequest, viewer }: PullRequestListItemProps) {
export default function PullRequestListItem({ pullRequest}: PullRequestListItemProps) {
const updatedAt = new Date(pullRequest.updatedAt);
const { push } = useNavigation();

const numberOfComments = useMemo(() => getNumberOfComments(pullRequest), []);
const author = getPullRequestAuthor(pullRequest);
Expand Down Expand Up @@ -79,27 +78,19 @@ export default function PullRequestListItem({ pullRequest, viewer }: PullRequest
<Action
title="Open PR in Gitpod"
onAction={() => {
open(`https://gitpod.io/#${pullRequest.permalink}`);
OpenInGitpod(pullRequest.permalink, "Pull Request", pullRequest.repository.nameWithOwner,pullRequest.title);
}}
shortcut={{ modifiers: ["cmd"], key: "g" }}
/>
<Action
title="View PR in GitHub"
onAction={() => {
open(pullRequest.permalink);
}}
/>
<Action title="Configure Workspace" onAction={()=> push(<ContextPreferences type="Pull Request" repository={pullRequest.repository.nameWithOwner} context={pullRequest.title}/>)} shortcut={{ modifiers: ["cmd"], key: "w" }}/>
</ActionPanel>
}
/>
);
}

{
/* <PullRequestActions pullRequest={pullRequest} viewer={viewer} mutateList={mutateList}>
<Action.Push
title="Show Details"
icon={Icon.Sidebar}
target={<PullRequestDetail initialPullRequest={pullRequest} viewer={viewer} mutateList={mutateList} />}
/>
</PullRequestActions>; */
}
6 changes: 5 additions & 1 deletion src/components/RepositoryListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { MutatePromise } from "@raycast/utils";

import { GitpodIcons } from "../../constants";
import { ExtendedRepositoryFieldsFragment } from "../generated/graphql";
import OpenInGitpod from "../helpers/openInGitpod";
import { getGitHubUser } from "../helpers/users";
import SearchContext from "../open_repo_context";
import RepositoryPreference from "../preferences/repository_preferences";

type RepositoryListItemProps = {
repository: ExtendedRepositoryFieldsFragment;
Expand Down Expand Up @@ -81,7 +83,9 @@ export default function RepositoryListItem({ repository, isGitpodified, onVisit
push(<SearchContext repository={repository} />);
}}
/>
<Action title="Trigger Workspace" onAction={showLaunchToast} />
<Action title="Open Repo in GitHub" onAction={()=>open(repository.url)} />
<Action title="Trigger Workspace" onAction={()=>OpenInGitpod(repository.url,"Repository",repository.nameWithOwner)} shortcut={{ modifiers: ["cmd"], key: "g" }}/>
<Action title="Configure Workspace" onAction={()=> push(<RepositoryPreference repository={repository.nameWithOwner} />)} shortcut={{ modifiers: ["cmd"], key: "w" }}/>
</ActionPanel>
}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/SearchRepositoryDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export default function SearchRepositoryDropdown(props: { onFilterChange: (filte
return (
<List.Dropdown tooltip="Filter Repositories" onChange={props.onFilterChange} storeValue>
<List.Dropdown.Section>
<List.Dropdown.Item title={"All Repositories"} value={""} />
{viewer ? (
<List.Dropdown.Item
title={"My Repositories"}
value={`user:${viewer.login} ${viewer.organizations?.nodes?.map((org) => `org:${org?.login}`).join(" ")}`}
/>
) : null}
<List.Dropdown.Item title={"All Repositories"} value={""} />
</List.Dropdown.Section>

<List.Dropdown.Section>
Expand Down
41 changes: 41 additions & 0 deletions src/helpers/branch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { LocalStorage } from "@raycast/api";
import { useCachedState } from "@raycast/utils";
import { useEffect } from "react";

import { BranchDetailsFragment, ExtendedRepositoryFieldsFragment } from "../generated/graphql";

const VISITED_BRANCH_KEY = "VISITED_BRANCHES";
const VISITED_BRANCH_LENGTH = 10;

// History was stored in `LocalStorage` before, after migration it's stored in `Cache`
async function loadVisitedBranches() {
const item = await LocalStorage.getItem<string>(VISITED_BRANCH_KEY);
if (item) {
const parsed = JSON.parse(item).slice(0, VISITED_BRANCH_LENGTH);
return parsed as BranchDetailsFragment[];
} else {
return [];
}
}
export function useBranchHistory() {
const [history, setHistory] = useCachedState<BranchDetailsFragment[]>("BranchHistory", []);
const [migratedHistory, setMigratedHistory] = useCachedState<boolean>("migratedBranchHistory", false);

useEffect(() => {
if (!migratedHistory) {
loadVisitedBranches().then((branches) => {
setHistory(branches);
setMigratedHistory(true);
});
}
}, [migratedHistory]);

function visitBranch(branch: BranchDetailsFragment, repository: ExtendedRepositoryFieldsFragment) {
const visitedBranch = [branch, ...(history?.filter((item) => item.branchName !== branch.branchName) ?? [])];
LocalStorage.setItem(VISITED_BRANCH_KEY, JSON.stringify(visitedBranch));
const nextBranch = visitedBranch.slice(0, VISITED_BRANCH_LENGTH);
setHistory(nextBranch);
}

return { history, visitBranch };
}
55 changes: 55 additions & 0 deletions src/helpers/openInGitpod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { LocalStorage, open, showToast, Toast } from "@raycast/api";
import { getPreferenceValues } from "@raycast/api";

interface Preferences {
preferredEditor: string;
useLatest: boolean;
preferredEditorClass: "g1-standard" | "g1-large";
}

export default async function OpenInGitpod(contextUrl: string, type: "Branch" | "Pull Request" | "Issue" | "Repository", repository: string, context?: string) {
let preferences = getPreferenceValues<Preferences>();

if (type === "Branch" || type === "Pull Request" || type === "Issue") {
const item = await LocalStorage.getItem<string>(`${repository}%${context}`)
const contextPref = item ? await JSON.parse(item) : null
if (contextPref && contextPref.preferredEditor && contextPref.preferredEditorClass) {
preferences = contextPref
} else {
const repoItem = await LocalStorage.getItem<string>(`${repository}`);
const repoPref = repoItem ? await JSON.parse(repoItem) : null
if (repoPref && repoPref.preferredEditor && repoPref.preferredEditorClass) {
preferences = repoPref
}
}
} else if (type === "Repository") {
const item = await LocalStorage.getItem<string>(`${repository}`);
const repoPref = item ? await JSON.parse(item) : null
if (repoPref && repoPref.preferredEditor && repoPref.preferredEditorClass) {
preferences = repoPref
}
}

if (type === "Branch") {
//visit branch
} else if (type === "Pull Request") {
//vitit pr
} else if (type === "Issue") {
//visit issue
}

try {
await showToast({
title: "Launching your workspace",
style: Toast.Style.Success,
});
setTimeout(() => {
open(`https://gitpod.io/?useLatest=${preferences.useLatest}&editor=${preferences.preferredEditor}&workspaceClass=${preferences.preferredEditorClass}#${contextUrl}`);
Palanikannan1437 marked this conversation as resolved.
Show resolved Hide resolved
}, 1000);
} catch (error) {
await showToast({
title: "Error launching workspace",
style: Toast.Style.Failure,
});
}
}
Loading