diff --git a/apps/desktop/src/lib/config/uiFeatureFlags.ts b/apps/desktop/src/lib/config/uiFeatureFlags.ts index f72b07f71..ba010686d 100644 --- a/apps/desktop/src/lib/config/uiFeatureFlags.ts +++ b/apps/desktop/src/lib/config/uiFeatureFlags.ts @@ -20,3 +20,8 @@ export function featureBranchStacking(): Persisted { const key = 'branchStacking'; return persisted(false, key); } + +export function featureTopics(): Persisted { + const key = 'feature--topics'; + return persisted(false, key); +} diff --git a/apps/desktop/src/lib/gitHost/azure/azure.ts b/apps/desktop/src/lib/gitHost/azure/azure.ts index 0e905402b..6e065f6d7 100644 --- a/apps/desktop/src/lib/gitHost/azure/azure.ts +++ b/apps/desktop/src/lib/gitHost/azure/azure.ts @@ -36,6 +36,10 @@ export class AzureDevOps implements GitHost { return undefined; } + issueService() { + return undefined; + } + prService() { return undefined; } diff --git a/apps/desktop/src/lib/gitHost/bitbucket/bitbucket.ts b/apps/desktop/src/lib/gitHost/bitbucket/bitbucket.ts index 88be72da5..4d0e39478 100644 --- a/apps/desktop/src/lib/gitHost/bitbucket/bitbucket.ts +++ b/apps/desktop/src/lib/gitHost/bitbucket/bitbucket.ts @@ -40,6 +40,10 @@ export class BitBucket implements GitHost { return undefined; } + issueService() { + return undefined; + } + prService() { return undefined; } diff --git a/apps/desktop/src/lib/gitHost/github/github.ts b/apps/desktop/src/lib/gitHost/github/github.ts index f35ed7e60..fbe525d3e 100644 --- a/apps/desktop/src/lib/gitHost/github/github.ts +++ b/apps/desktop/src/lib/gitHost/github/github.ts @@ -2,6 +2,7 @@ import { GitHubBranch } from './githubBranch'; import { GitHubChecksMonitor } from './githubChecksMonitor'; import { GitHubListingService } from './githubListingService'; import { GitHubPrService } from './githubPrService'; +import { GitHubIssueService } from '$lib/gitHost/github/issueService'; import { Octokit } from '@octokit/rest'; import type { ProjectMetrics } from '$lib/metrics/projectMetrics'; import type { Persisted } from '$lib/persisted/persisted'; @@ -64,6 +65,13 @@ export class GitHub implements GitHost { ); } + issueService() { + if (!this.octokit) { + return; + } + return new GitHubIssueService(this.octokit, this.repo); + } + checksMonitor(sourceBranch: string) { if (!this.octokit) { return; diff --git a/apps/desktop/src/lib/gitHost/github/issueService.ts b/apps/desktop/src/lib/gitHost/github/issueService.ts new file mode 100644 index 000000000..869be6ca3 --- /dev/null +++ b/apps/desktop/src/lib/gitHost/github/issueService.ts @@ -0,0 +1,29 @@ +import type { GitHostIssueService } from '$lib/gitHost/interface/gitHostIssueService'; +import type { RepoInfo } from '$lib/url/gitUrl'; +import type { Octokit } from '@octokit/rest'; + +export class GitHubIssueService implements GitHostIssueService { + constructor( + private octokit: Octokit, + private repository: RepoInfo + ) {} + + async create(title: string, body: string, labels: string[]): Promise { + await this.octokit.rest.issues.create({ + repo: this.repository.name, + owner: this.repository.owner, + title, + body, + labels + }); + } + + async listLabels(): Promise { + return ( + await this.octokit.rest.issues.listLabelsForRepo({ + repo: this.repository.name, + owner: this.repository.owner + }) + ).data.map((label) => label.name); + } +} diff --git a/apps/desktop/src/lib/gitHost/gitlab/gitlab.ts b/apps/desktop/src/lib/gitHost/gitlab/gitlab.ts index b078a7226..6b269a6b9 100644 --- a/apps/desktop/src/lib/gitHost/gitlab/gitlab.ts +++ b/apps/desktop/src/lib/gitHost/gitlab/gitlab.ts @@ -41,6 +41,10 @@ export class GitLab implements GitHost { return undefined; } + issueService() { + return undefined; + } + prService() { return undefined; } diff --git a/apps/desktop/src/lib/gitHost/interface/gitHost.ts b/apps/desktop/src/lib/gitHost/interface/gitHost.ts index 1e343ccec..fa892ca17 100644 --- a/apps/desktop/src/lib/gitHost/interface/gitHost.ts +++ b/apps/desktop/src/lib/gitHost/interface/gitHost.ts @@ -1,4 +1,5 @@ import { buildContextStore } from '$lib/utils/context'; +import type { GitHostIssueService } from '$lib/gitHost/interface/gitHostIssueService'; import type { GitHostBranch } from './gitHostBranch'; import type { GitHostChecksMonitor } from './gitHostChecksMonitor'; import type { GitHostListingService } from './gitHostListingService'; @@ -8,6 +9,8 @@ export interface GitHost { // Lists PRs for the repo. listService(): GitHostListingService | undefined; + issueService(): GitHostIssueService | undefined; + // Detailed information about a specific PR. prService(): GitHostPrService | undefined; diff --git a/apps/desktop/src/lib/gitHost/interface/gitHostIssueService.ts b/apps/desktop/src/lib/gitHost/interface/gitHostIssueService.ts new file mode 100644 index 000000000..299ec6c26 --- /dev/null +++ b/apps/desktop/src/lib/gitHost/interface/gitHostIssueService.ts @@ -0,0 +1,4 @@ +export interface GitHostIssueService { + create(title: string, body: string, labels: string[]): Promise; + listLabels(): Promise; +} diff --git a/apps/desktop/src/lib/navigation/Navigation.svelte b/apps/desktop/src/lib/navigation/Navigation.svelte index 74508be6c..950afec27 100644 --- a/apps/desktop/src/lib/navigation/Navigation.svelte +++ b/apps/desktop/src/lib/navigation/Navigation.svelte @@ -6,8 +6,10 @@ import WorkspaceButton from './WorkspaceButton.svelte'; import Resizer from '../shared/Resizer.svelte'; import { Project } from '$lib/backend/projects'; + import { featureTopics } from '$lib/config/uiFeatureFlags'; import { ModeService } from '$lib/modes/service'; import EditButton from '$lib/navigation/EditButton.svelte'; + import TopicsButton from '$lib/navigation/TopicsButton.svelte'; import { persisted } from '$lib/persisted/persisted'; import { platformName } from '$lib/platform/platform'; import { SETTINGS, type Settings } from '$lib/settings/userSettings'; @@ -43,6 +45,8 @@ const modeService = getContext(ModeService); const mode = modeService.mode; + + const topicsEnabled = featureTopics(); @@ -120,6 +124,10 @@ {:else if $mode?.type === 'Edit'} {/if} + + {#if $topicsEnabled} + + {/if} diff --git a/apps/desktop/src/lib/navigation/TopicsButton.svelte b/apps/desktop/src/lib/navigation/TopicsButton.svelte new file mode 100644 index 000000000..2aba62cf4 --- /dev/null +++ b/apps/desktop/src/lib/navigation/TopicsButton.svelte @@ -0,0 +1,34 @@ + + + await goto(href)} +> + + {#if !isNavCollapsed} + {label} + {/if} + + + diff --git a/apps/desktop/src/lib/topics/CreateIssueModal.svelte b/apps/desktop/src/lib/topics/CreateIssueModal.svelte new file mode 100644 index 000000000..5722c8ce0 --- /dev/null +++ b/apps/desktop/src/lib/topics/CreateIssueModal.svelte @@ -0,0 +1,149 @@ + + + + +{#if issueService} + +

Create an issue

+ +
+

Title

+ +
+ +
+

Body

+