Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions src/composables/useKanbanDragAndDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,19 @@ export function useKanbanDragAndDrop(statusSchema: Record<string, string[]>) {
if (currentCat === 'complete') currentCat = 'done';

if (currentCat !== targetStatus) {
const possibleStatuses = statusSchema[targetStatus];
const statusName: string = (possibleStatuses && possibleStatuses.length > 0)
? (possibleStatuses[0] as string)
: (targetStatus === 'inProgress' ? 'In Progress' : targetStatus === 'todo' ? 'To Do' : 'Done');

dashboardStore.updateTaskStatus(task.key, { status: statusName });
if (dashboardStore.activeSource === 'trello') {
// Trello cards are moved by list ID, not by status name
const listId = dashboardStore.trelloListIds[targetStatus];
if (listId) {
dashboardStore.moveTrelloCard(task.key, listId);
}
} else {
const possibleStatuses = statusSchema[targetStatus];
const statusName: string = (possibleStatuses && possibleStatuses.length > 0)
? (possibleStatuses[0] as string)
: (targetStatus === 'inProgress' ? 'In Progress' : targetStatus === 'todo' ? 'To Do' : 'Done');
dashboardStore.updateTaskStatus(task.key, { status: statusName });
}
}
}
draggedTask.value = null;
Expand Down
11 changes: 10 additions & 1 deletion src/stores/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export const useDashboardStore = defineStore('dashboard', () => {
const activeSource = ref<'jira' | 'trello'>('jira');
const trelloBoards = ref<{ id: string; name: string }[]>([]);
const selectedTrelloBoardId = ref<string | null>(null);
// Maps status category → first Trello list ID (used for card moves via drag-and-drop)
const trelloListIds = ref<Record<string, string>>({});

// Auto-select first project when projects load but nothing is selected
watch(projects, (newProjects) => {
Expand Down Expand Up @@ -533,7 +535,11 @@ export const useDashboardStore = defineStore('dashboard', () => {
try {
const res = await apiClient.get('/api/trello/boards');
trelloBoards.value = res.data.boards || [];
if (!selectedTrelloBoardId.value && trelloBoards.value.length > 0) {
// Restore server-persisted board selection (mirrors Jira project selection)
const persistedId: string | null = res.data.selected_board_id ?? null;
if (persistedId && trelloBoards.value.find(b => b.id === persistedId)) {
selectedTrelloBoardId.value = persistedId;
} else if (!selectedTrelloBoardId.value && trelloBoards.value.length > 0) {
selectedTrelloBoardId.value = trelloBoards.value[0]?.id ?? null;
}
} catch (e: any) {
Expand Down Expand Up @@ -595,6 +601,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
inProgress: rawBoard.inProgress || [],
done: rawBoard.done || [],
};
trelloListIds.value = data.list_ids || {};
activities.value = data.all_activities || [];
_lastFetchTime = Date.now();
} catch (e: any) {
Expand Down Expand Up @@ -698,6 +705,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
activeSource.value = 'jira';
trelloBoards.value = [];
selectedTrelloBoardId.value = null;
trelloListIds.value = {};
_lastFetchTime = 0;
_lastFetchKey = null;
_inflightDashboard = null;
Expand Down Expand Up @@ -749,6 +757,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
activeSource,
trelloBoards,
selectedTrelloBoardId,
trelloListIds,
fetchTrelloBoards,
setActiveTrelloBoard,
setActiveSource,
Expand Down
3 changes: 1 addition & 2 deletions src/utils/connectService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const ENDPOINTS: Record<ConnectService, string> = {
jira: '/api/auth/jira/connect',
github: '/api/auth/github/connect',
notion: '/api/auth/notion/connect',
// Trello shares the same Atlassian OAuth as Jira — reconnecting Jira grants Trello access
trello: '/api/auth/jira/connect',
trello: '/api/auth/trello/connect',
};

/**
Expand Down
10 changes: 8 additions & 2 deletions src/views/AuthCallback.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ onMounted(async () => {
const jiraConnected = route.query.jira_connected === "true";
const notionConnected = route.query.notion_connected === "true";
const githubConnected = route.query.github_connected === "true";
const trelloConnected = route.query.trello_connected === "true";
const isNewUser = route.query.is_new_user === "true";
const openProfile = route.query.openProfile;

Expand Down Expand Up @@ -49,6 +50,10 @@ onMounted(async () => {
toast.success("Notion account connected successfully!");
}

if (trelloConnected) {
toast.success("Trello account connected successfully!");
}

// Check onboarding status
onboardingStore.checkOnboardingStatus();

Expand All @@ -57,7 +62,8 @@ onMounted(async () => {
type: 'OAUTH_SUCCESS',
jiraConnected,
githubConnected,
notionConnected
notionConnected,
trelloConnected,
};

// 1. Try BroadcastChannel (Modern & Robust)
Expand Down Expand Up @@ -90,7 +96,7 @@ onMounted(async () => {
// Return-from-integration callback → back to onboarding (to continue)
// Completed users → dashboard
if (!onboardingStore.onboardingCompleted) {
if (jiraConnected || githubConnected || notionConnected) {
if (jiraConnected || githubConnected || notionConnected || trelloConnected) {
router.push({ path: "/onboarding", query: { step: 2 } });
} else {
router.push("/onboarding");
Expand Down
30 changes: 20 additions & 10 deletions src/views/settings/IntegrationsSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,7 @@ const integrations = computed(() => [
description: 'Manage Trello boards and cards directly from your Kwillo dashboard.',
logo: '/trello.svg',
connected: authStore.trelloConnected,
color: 'hover:border-blue-500/20 hover:bg-blue-500/5',
note: authStore.jiraConnected && !authStore.trelloConnected
? 'Reconnect Jira to enable Trello access'
: undefined
color: 'hover:border-blue-500/20 hover:bg-blue-500/5'
}
]);

Expand Down Expand Up @@ -140,12 +137,25 @@ const toggleIntegration = async (id: "jira" | "github" | "notion" | string) => {
}
}
} else if (id === 'trello') {
// Trello uses the same Jira OAuth token — reconnect Jira to get Trello scopes
isConnecting.value[id] = true;
try {
await connectService('trello');
} finally {
isConnecting.value[id] = false;
if (!authStore.trelloConnected) {
isConnecting.value[id] = true;
try {
await connectService('trello');
} finally {
isConnecting.value[id] = false;
}
} else {
isConnecting.value[id] = true;
try {
await apiClient.delete("/api/auth/trello/disconnect");
toast.success("Trello disconnected successfully");
await authStore.fetchUser();
} catch (error) {
console.error("Failed to disconnect Trello:", error);
toast.error("Failed to disconnect Trello. Please try again.");
} finally {
isConnecting.value[id] = false;
}
}
} else {
console.log(`Toggling integration ${id}`);
Expand Down
Loading