-
+
- {{ project.key }} - {{ project.name }}
- {{ project.siteName || project.siteUrl }}
+ {{ resource.name }}
+ {{ resource.url }}
diff --git a/src/app/components/workspace-integrations/workspace-integrations.spec.ts b/src/app/components/workspace-integrations/workspace-integrations.spec.ts
index ff63e6c..440a8b8 100644
--- a/src/app/components/workspace-integrations/workspace-integrations.spec.ts
+++ b/src/app/components/workspace-integrations/workspace-integrations.spec.ts
@@ -55,7 +55,7 @@ describe('WorkspaceIntegrationsComponent', () => {
mockIntegrationService.getJiraProjects.and.returnValue(of({
connected: false,
- projects: [],
+ resources: [],
lastSyncAt: undefined
}));
mockIntegrationService.connectJira.and.returnValue(of(void 0));
@@ -70,8 +70,7 @@ describe('WorkspaceIntegrationsComponent', () => {
provide: ActivatedRoute,
useValue: {
snapshot: {
- paramMap: convertToParamMap({ id: 'workspace-1' }),
- queryParamMap: convertToParamMap({})
+ paramMap: convertToParamMap({ id: 'workspace-1' })
}
}
}
diff --git a/src/app/components/workspace-integrations/workspace-integrations.ts b/src/app/components/workspace-integrations/workspace-integrations.ts
index 08564ec..7762db3 100644
--- a/src/app/components/workspace-integrations/workspace-integrations.ts
+++ b/src/app/components/workspace-integrations/workspace-integrations.ts
@@ -4,7 +4,7 @@ import { ActivatedRoute, RouterLink } from '@angular/router';
import { IntegrationService } from '../../services/integration.service';
import { GitHubRepo, SyncStatus } from '../../models/github-integration.model';
import { SlackChannel } from '../../models/slack-integration.model';
-import { JiraProject, JiraSyncStatus } from '../../models/jira-integration.model';
+import { AtlassianResource, JiraSyncStatus } from '../../models/jira-integration.model';
@Component({
selector: 'app-workspace-integrations',
@@ -41,7 +41,7 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
isSyncing = false;
isJiraConnected = false;
- jiraProjects: JiraProject[] = [];
+ jiraResources: AtlassianResource[] = [];
jiraLastSyncAt?: Date;
jiraSyncStatus?: JiraSyncStatus;
jiraFeedbackMessage = '';
@@ -49,25 +49,7 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
isJiraSyncing = false;
ngOnInit(): void {
- this.workspaceId = this.route.snapshot.paramMap.get('id') ||
- this.route.parent?.snapshot.paramMap.get('id') || '';
-
- // Check for OAuth redirect results
- const queryParams = this.route.snapshot.queryParamMap;
- const jiraStatus = queryParams.get('jira');
- if (jiraStatus === 'connected') {
- this.jiraFeedbackMessage = 'Jira connected successfully!';
- } else if (jiraStatus === 'failed') {
- this.jiraErrorMessage = 'Failed to connect Jira.';
- }
-
- const githubStatus = queryParams.get('github');
- if (githubStatus === 'connected') {
- this.githubFeedbackMessage = 'GitHub connected successfully!';
- } else if (githubStatus === 'failed') {
- this.githubErrorMessage = 'Failed to connect GitHub.';
- }
-
+ this.workspaceId = this.route.snapshot.paramMap.get('id') ?? '';
this.loadAllIntegrations();
window.addEventListener('focus', this.onWindowFocus);
}
@@ -98,9 +80,6 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
this.slackErrorMessage = '';
this.slackFeedbackMessage = 'Starting Slack connection...';
this.integrationService.connectSlack(this.workspaceId).subscribe({
- next: () => {
- this.slackFeedbackMessage = '';
- },
error: (error: Error) => {
this.slackErrorMessage = error.message;
this.slackFeedbackMessage = '';
@@ -119,9 +98,6 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
this.githubErrorMessage = '';
this.githubFeedbackMessage = 'Starting GitHub connection...';
this.integrationService.connectGitHub().subscribe({
- next: () => {
- this.githubFeedbackMessage = '';
- },
error: (error: Error) => {
this.githubErrorMessage = error.message;
this.githubFeedbackMessage = '';
@@ -141,9 +117,6 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
this.jiraErrorMessage = '';
this.jiraFeedbackMessage = 'Starting Jira connection...';
this.integrationService.connectJira(this.workspaceId).subscribe({
- next: () => {
- this.jiraFeedbackMessage = '';
- },
error: (error: Error) => {
this.jiraErrorMessage = error.message;
this.jiraFeedbackMessage = '';
@@ -289,7 +262,7 @@ export class WorkspaceIntegrationsComponent implements OnInit, OnDestroy {
private loadJira(): void {
this.integrationService.getJiraProjects(this.workspaceId).subscribe(response => {
this.isJiraConnected = response.connected;
- this.jiraProjects = response.projects;
+ this.jiraResources = response.resources;
this.jiraLastSyncAt = response.lastSyncAt;
});
}
diff --git a/src/app/models/jira-integration.model.ts b/src/app/models/jira-integration.model.ts
index 2172f58..7f398bf 100644
--- a/src/app/models/jira-integration.model.ts
+++ b/src/app/models/jira-integration.model.ts
@@ -2,10 +2,15 @@ export interface JiraProject {
id: string;
key: string;
name: string;
- avatarUrl?: string;
- siteId: string;
- siteName: string;
- siteUrl: string;
+ avatarUrl: string;
+}
+
+export interface AtlassianResource {
+ id: string;
+ url: string;
+ name: string;
+ scopes: string[];
+ avatarUrl: string;
}
export interface JiraSyncStatus {
@@ -16,6 +21,6 @@ export interface JiraSyncStatus {
export interface JiraIntegrationResponse {
connected: boolean;
- projects: JiraProject[];
- lastSyncAt?: Date;
+ resources: AtlassianResource[];
+ lastSyncAt?: string;
}
diff --git a/src/app/services/integration.service.ts b/src/app/services/integration.service.ts
index 9ebaf5b..f6aa728 100644
--- a/src/app/services/integration.service.ts
+++ b/src/app/services/integration.service.ts
@@ -1,8 +1,7 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
-import { catchError, map, Observable, of, switchMap, tap, throwError } from 'rxjs';
+import { catchError, map, Observable, of, switchMap, throwError } from 'rxjs';
import { GitHubConnectionState, GitHubRepo, SyncStatus } from '../models/github-integration.model';
-import { JiraIntegrationResponse, JiraProject, JiraSyncStatus } from '../models/jira-integration.model';
import { SlackConnectionState } from '../models/slack-integration.model';
import { toError } from './http-error';
@@ -38,10 +37,6 @@ interface GitHubSyncResponse {
status: string;
}
-interface JiraSyncResponse {
- status: string;
-}
-
@Injectable({
providedIn: 'root',
})
@@ -61,7 +56,6 @@ export class IntegrationService {
return this.getSlackAuthUrl(workspaceId).pipe(
map(({ authUrl }) => {
window.open(authUrl, '_blank');
- return;
}),
);
}
@@ -131,7 +125,6 @@ export class IntegrationService {
return this.getGitHubAuthUrl().pipe(
map(({ authUrl }) => {
window.open(authUrl, '_blank');
- return;
}),
);
}
@@ -189,48 +182,38 @@ export class IntegrationService {
);
}
- getJiraAuthUrl(workspaceId: string, redirectUrl?: string): Observable<{ authUrl: string }> {
- console.log('Fetching Jira Auth URL for workspace:', workspaceId);
- let params = new HttpParams().set('workspace_id', workspaceId);
- if (redirectUrl) {
- params = params.set('redirect_url', redirectUrl);
- }
+ getJiraAuthUrl(workspaceId: string): Observable<{ authUrl: string }> {
+ const params = new HttpParams().set('workspace_id', workspaceId);
return this.http.get
(`${this.apiUrl}/jira/auth`, { params }).pipe(
- tap(resp => console.log('Jira Auth URL response:', resp)),
map((response) => ({ authUrl: response.auth_url })),
- catchError((error) => {
- console.error('Jira Auth URL error:', error);
- return throwError(() => toError(error, 'Unable to start Jira connection.'));
- }),
+ catchError((error) => throwError(() => toError(error, 'Unable to start Jira connection.'))),
);
}
connectJira(workspaceId: string): Observable {
- const redirectUrl = window.location.origin + window.location.pathname;
- return this.getJiraAuthUrl(workspaceId, redirectUrl).pipe(
+ return this.getJiraAuthUrl(workspaceId).pipe(
map(({ authUrl }) => {
- window.location.href = authUrl;
- return;
+ window.open(authUrl, '_blank');
}),
);
}
- getJiraProjects(workspaceId: string): Observable {
+ getJiraProjects(workspaceId: string): Observable {
return this.getIntegrations(workspaceId).pipe(
switchMap((integrations) => {
const jiraIntegration = integrations.find((integration) => integration.provider === 'jira');
if (!jiraIntegration) {
return of({
connected: false,
- projects: [],
+ resources: [],
});
}
const params = new HttpParams().set('workspace_id', workspaceId);
- return this.http.get(`${this.apiUrl}/jira/projects`, { params }).pipe(
- map((projects) => ({
+ return this.http.get(`${this.apiUrl}/jira/projects`, { params }).pipe(
+ map((resources) => ({
connected: true,
- projects,
+ resources: resources,
lastSyncAt: jiraIntegration.updated_at ? new Date(jiraIntegration.updated_at) : undefined,
})),
);
@@ -246,13 +229,13 @@ export class IntegrationService {
);
}
- syncJira(workspaceId: string): Observable {
+ syncJira(workspaceId: string): Observable {
const params = new HttpParams().set('workspace_id', workspaceId);
- return this.http.post(`${this.apiUrl}/jira/sync`, {}, { params }).pipe(
+ return this.http.post(`${this.apiUrl}/jira/sync`, {}, { params }).pipe(
map((response) => {
return {
status: response.status === 'sync_started' ? 'in_progress' : 'failed',
- } as JiraSyncStatus;
+ };
}),
catchError((error) => throwError(() => toError(error, 'Unable to sync Jira.'))),
);
diff --git a/src/app/services/signal.service.ts b/src/app/services/signal.service.ts
index 4d8a94d..cf221a7 100644
--- a/src/app/services/signal.service.ts
+++ b/src/app/services/signal.service.ts
@@ -22,16 +22,9 @@ interface SignalResponse {
state?: 'open' | 'closed';
labels?: string[];
issueType?: string;
- issue_type?: string;
priority?: string;
projectKey?: string;
- project_key?: string;
- issueKey?: string;
- issue_key?: string;
- assigneeName?: string;
- assignee_name?: string;
assignees?: string[];
- status?: string;
};
received_at?: string;
}
@@ -98,19 +91,6 @@ export class SignalService {
};
}
- if (signal.source_type === 'jira') {
- const metadata = signal.source_metadata ?? {};
- return {
- ...metadata,
- issueType: metadata.issueType ?? metadata.issue_type,
- projectKey: metadata.projectKey ?? metadata.project_key,
- issueKey: metadata.issueKey ?? metadata.issue_key ?? signal.external_id,
- assignees: metadata.assigneeName || metadata.assignee_name
- ? [String(metadata.assigneeName ?? metadata.assignee_name)]
- : [],
- };
- }
-
return {
...(signal.source_metadata ?? {}),
};