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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { slackApi } from './slack-api';

export const slackQueryKeys = {
const slackQueryKeys = {
all: ['slack'] as const,
workspaces: () => [...slackQueryKeys.all, 'workspaces'] as const,
linkedUsers: (teamId: string) => [...slackQueryKeys.all, 'linked-users', teamId] as const,
Expand Down
44 changes: 22 additions & 22 deletions agents-manage-ui/src/features/work-apps/slack/api/slack-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,28 +127,6 @@ export const slackApi = {
return response.json();
},

async getLinkedUsers(teamId: string): Promise<{
linkedUsers: Array<{
id: string;
slackUserId: string;
slackTeamId: string;
slackUsername?: string;
slackEmail?: string;
userId: string;
linkedAt: string;
lastUsedAt?: string;
}>;
}> {
const response = await fetch(
`${getApiUrl()}/work-apps/slack/workspaces/${encodeURIComponent(teamId)}/users`,
{ credentials: 'include' }
);
if (!response.ok) {
return { linkedUsers: [] };
}
return response.json();
},

async listChannels(teamId: string): Promise<{
channels: Array<{
id: string;
Expand All @@ -174,6 +152,28 @@ export const slackApi = {
return response.json();
},

async getLinkedUsers(teamId: string): Promise<{
linkedUsers: Array<{
id: string;
slackUserId: string;
slackTeamId: string;
slackUsername?: string;
slackEmail?: string;
userId: string;
linkedAt: string;
lastUsedAt?: string;
}>;
}> {
const response = await fetch(
`${getApiUrl()}/work-apps/slack/workspaces/${encodeURIComponent(teamId)}/users`,
{ credentials: 'include' }
);
if (!response.ok) {
return { linkedUsers: [] };
}
return response.json();
},

async setChannelDefaultAgent(params: {
teamId: string;
channelId: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { WorkspaceDefaultSection } from './workspace-default-section';

export function AgentConfigurationCard() {
const { tenantId } = useParams<{ tenantId: string }>();
const { installedWorkspaces, actions } = useSlack();
const { installedWorkspaces } = useSlack();
const { isAdmin } = useIsOrgAdmin();

const [agents, setAgents] = useState<SlackAgentOption[]>([]);
Expand Down Expand Up @@ -132,18 +132,10 @@ export function AgentConfigurationCard() {
});

installedWorkspaces.refetch();
actions.setNotification({
type: 'success',
message: `Default agent set to "${config.agentName}"`,
action: 'connected',
});
toast.success(`Default agent set to "${config.agentName}"`);
} catch (error) {
console.error('Failed to save default agent:', error);
actions.setNotification({
type: 'error',
message: 'Failed to save default agent',
action: 'error',
});
toast.error('Failed to save default agent');
} finally {
setSavingDefault(false);
}
Expand Down Expand Up @@ -178,22 +170,14 @@ export function AgentConfigurationCard() {
)
);

actions.setNotification({
type: 'success',
message: `#${channelName} now uses "${config.agentName}"`,
action: 'connected',
});
toast.success(`#${channelName} now uses "${config.agentName}"`);
} catch (error) {
console.error('Failed to set channel agent:', error);
const errorMessage =
error instanceof Error && error.message.includes('forbidden')
? `You can only configure channels you're a member of`
: 'Failed to set channel agent';
actions.setNotification({
type: 'error',
message: errorMessage,
action: 'error',
});
toast.error(errorMessage);
} finally {
setSavingChannel(null);
}
Expand All @@ -213,22 +197,14 @@ export function AgentConfigurationCard() {
)
);

actions.setNotification({
type: 'success',
message: `#${channelName} now uses the workspace default`,
action: 'connected',
});
toast.success(`#${channelName} now uses the workspace default`);
} catch (error) {
console.error('Failed to reset channel:', error);
const errorMessage =
error instanceof Error && error.message.includes('forbidden')
? `You can only configure channels you're a member of`
: 'Failed to reset channel to default';
actions.setNotification({
type: 'error',
message: errorMessage,
action: 'error',
});
toast.error(errorMessage);
} finally {
setSavingChannel(null);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { SlackIcon } from 'lucide-react';
import { useEffect } from 'react';
import { toast } from 'sonner';
import { PageHeader } from '@/components/layout/page-header';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
Expand All @@ -14,12 +15,11 @@ import { useSlack } from '../context/slack-provider';
import { AgentConfigurationCard } from './agent-configuration-card';
import { LinkedUsersSection } from './linked-users-section';
import { MyLinkStatus } from './my-link-status';
import { NotificationBanner } from './notification-banner';
import { WorkspaceHero } from './workspace-hero';

export function SlackDashboard() {
const { user, installedWorkspaces, actions } = useSlack();
const { handleInstallClick, setNotification } = actions;
const { handleInstallClick } = actions;
const { isAdmin, isLoading: isLoadingRole } = useIsOrgAdmin();

const hasWorkspace = installedWorkspaces.data.length > 0;
Expand All @@ -34,18 +34,10 @@ export function SlackDashboard() {

if (error) {
if (error === 'access_denied') {
setNotification({
type: 'info',
message: 'Slack installation was cancelled.',
action: 'cancelled',
});
toast.info('Slack installation was cancelled.');
} else {
console.error('Slack OAuth Error:', error);
setNotification({
type: 'error',
message: `Slack installation failed: ${error}`,
action: 'error',
});
toast.error(`Slack installation failed: ${error}`);
}
window.history.replaceState({}, '', window.location.pathname);
return;
Expand All @@ -55,25 +47,16 @@ export function SlackDashboard() {
try {
const workspace = JSON.parse(workspaceData);

setNotification({
type: 'success',
message: `Workspace "${workspace.teamName}" installed successfully!`,
action: 'installed',
});

toast.success(`Workspace "${workspace.teamName}" installed successfully!`);
installedWorkspaces.refetch();
} catch (e) {
console.error('Failed to parse workspace data:', e);
setNotification({
type: 'error',
message: 'Failed to process workspace data',
action: 'error',
});
toast.error('Failed to process workspace data');
}

window.history.replaceState({}, '', window.location.pathname);
}
}, [setNotification, installedWorkspaces]);
}, [installedWorkspaces]);

return (
<TooltipProvider>
Expand Down Expand Up @@ -120,8 +103,6 @@ export function SlackDashboard() {
}
/>

<NotificationBanner />

{/* Workspace Status */}
<WorkspaceHero />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
'use client';

import { useQueryClient } from '@tanstack/react-query';
import { createContext, type ReactNode, use, useCallback, useEffect } from 'react';
import { createContext, type ReactNode, use, useCallback } from 'react';
import { toast } from 'sonner';
import { useAuthSession } from '@/hooks/use-auth';
import {
slackQueryKeys,
useSlackUninstallWorkspaceMutation,
useSlackWorkspacesQuery,
} from '../api/queries';
import { useSlackUninstallWorkspaceMutation, useSlackWorkspacesQuery } from '../api/queries';
import { slackApi } from '../api/slack-api';
import { useSlackStore } from '../store/slack-store';
import type { SlackNotification } from '../types';

interface SlackContextValue {
user: { id: string; email?: string; name?: string } | null;
Expand All @@ -31,15 +25,9 @@ interface SlackContextValue {
refetch: () => void;
};

ui: {
notification: SlackNotification | null;
};

actions: {
handleInstallClick: () => void;
uninstallWorkspace: (connectionId: string) => Promise<void>;
setNotification: (notification: SlackNotification | null) => void;
clearNotification: () => void;
};
}

Expand All @@ -52,21 +40,10 @@ interface SlackProviderProps {

export function SlackProvider({ children, tenantId }: SlackProviderProps) {
const { user, isLoading: isAuthLoading } = useAuthSession();
const queryClient = useQueryClient();

const notification = useSlackStore((state) => state.notification);
const setNotification = useSlackStore((state) => state.setNotification);
const clearNotification = useSlackStore((state) => state.clearNotification);

const workspacesQuery = useSlackWorkspacesQuery();
const uninstallMutation = useSlackUninstallWorkspaceMutation();

useEffect(() => {
if (notification?.type === 'success' && notification.action === 'installed') {
queryClient.invalidateQueries({ queryKey: slackQueryKeys.workspaces() });
}
}, [notification, queryClient]);

const handleInstallClick = useCallback(() => {
window.location.href = slackApi.getInstallUrl(tenantId);
}, [tenantId]);
Expand All @@ -75,22 +52,13 @@ export function SlackProvider({ children, tenantId }: SlackProviderProps) {
async (connectionId: string) => {
try {
await uninstallMutation.mutateAsync(connectionId);

setNotification({
type: 'success',
message: 'Workspace uninstalled successfully',
action: 'disconnected',
});
toast.success('Workspace uninstalled successfully');
} catch (error) {
console.error('Failed to uninstall workspace:', error);
setNotification({
type: 'error',
message: error instanceof Error ? error.message : 'Failed to uninstall workspace',
action: 'error',
});
toast.error(error instanceof Error ? error.message : 'Failed to uninstall workspace');
}
},
[uninstallMutation, setNotification]
[uninstallMutation]
);

const value: SlackContextValue = {
Expand All @@ -107,15 +75,9 @@ export function SlackProvider({ children, tenantId }: SlackProviderProps) {
refetch: () => workspacesQuery.refetch(),
},

ui: {
notification,
},

actions: {
handleInstallClick,
uninstallWorkspace,
setNotification,
clearNotification,
},
};

Expand Down
Loading