mirror of
https://github.com/khoj-ai/khoj.git
synced 2025-02-17 08:04:21 +00:00
Build UX to Connect and Manage Notion Integration via Settings Page
This commit is contained in:
parent
7ee179ee1f
commit
9d86cb57ac
1 changed files with 130 additions and 15 deletions
|
@ -57,6 +57,7 @@ import {
|
|||
PlugsConnected,
|
||||
ArrowCircleUp,
|
||||
ArrowCircleDown,
|
||||
ArrowsClockwise,
|
||||
} from "@phosphor-icons/react";
|
||||
|
||||
import NavMenu from "../components/navMenu/navMenu";
|
||||
|
@ -182,8 +183,9 @@ export default function SettingsView() {
|
|||
const { apiKeys, generateAPIKey, copyAPIKey, deleteAPIKey } = useApiKeys();
|
||||
const initialUserConfig = useUserConfig(true);
|
||||
const [userConfig, setUserConfig] = useState<UserConfig | null>(null);
|
||||
const [number, setNumber] = useState<string | undefined>(undefined);
|
||||
const [name, setName] = useState<string | undefined>(undefined);
|
||||
const [notionToken, setNotionToken] = useState<string | null>(null);
|
||||
const [number, setNumber] = useState<string | undefined>(undefined);
|
||||
const [otp, setOTP] = useState("");
|
||||
const [numberValidationState, setNumberValidationState] = useState<PhoneNumberValidationState>(PhoneNumberValidationState.Verified);
|
||||
const { toast } = useToast();
|
||||
|
@ -200,6 +202,7 @@ export default function SettingsView() {
|
|||
: PhoneNumberValidationState.Setup
|
||||
);
|
||||
setName(initialUserConfig?.given_name);
|
||||
setNotionToken(initialUserConfig?.notion_token ?? null);
|
||||
}, [initialUserConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -312,7 +315,7 @@ export default function SettingsView() {
|
|||
console.error('Error updating name:', error);
|
||||
toast({
|
||||
title: "⚠️ Failed to Update Profile",
|
||||
description: "Failed to update name. Try again or contact us at team@khoj.dev",
|
||||
description: "Failed to update name. Try again or contact team@khoj.dev",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -340,6 +343,94 @@ export default function SettingsView() {
|
|||
}
|
||||
};
|
||||
|
||||
const saveNotionToken = async () => {
|
||||
if (!notionToken) return;
|
||||
// Save Notion API key to server
|
||||
try {
|
||||
const response = await fetch(`/api/content/notion`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ token: notionToken }),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to save Notion API key');
|
||||
|
||||
// Set updated user settings
|
||||
if (userConfig) {
|
||||
let newUserConfig = userConfig;
|
||||
newUserConfig.notion_token = notionToken;
|
||||
setUserConfig(newUserConfig);
|
||||
}
|
||||
|
||||
// Notify user of Notion API key save
|
||||
toast({
|
||||
title: `✅ Saved Notion Settings`,
|
||||
description: `You Notion API key has been saved.`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error updating name:', error);
|
||||
toast({
|
||||
title: "⚠️ Failed to Save Notion Settings",
|
||||
description: "Failed to save Notion API key. Try again or contact team@khoj.dev",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const syncContent = async (type: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/content?t=${type}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (!response.ok) throw new Error(`Failed to sync content from ${type}`);
|
||||
|
||||
toast({
|
||||
title: `🔄 Syncing ${type}`,
|
||||
description: `Your ${type} content is being synced.`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error syncing content:', error);
|
||||
toast({
|
||||
title: `⚠️ Failed to Sync ${type}`,
|
||||
description: `Failed to sync ${type} content. Try again or contact team@khoj.dev`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const disconnectContent = async (type: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/content/${type}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
if (!response.ok) throw new Error(`Failed to disconnect ${type}`);
|
||||
|
||||
// Set updated user settings
|
||||
if (userConfig) {
|
||||
let newUserConfig = userConfig;
|
||||
newUserConfig.enabled_content_source.notion = false;
|
||||
setUserConfig(newUserConfig);
|
||||
}
|
||||
|
||||
// Notify user about disconnecting content source
|
||||
toast({
|
||||
title: `✅ Disconnected ${type}`,
|
||||
description: `Your ${type} integration to Khoj has been disconnected.`,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error disconnecting ${type}:`, error);
|
||||
toast({
|
||||
title: `⚠️ Failed to Disconnect ${type}`,
|
||||
description: `Failed to disconnect from ${type}. Try again or contact team@khoj.dev`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!userConfig) return <Loading />;
|
||||
|
||||
return (
|
||||
|
@ -497,23 +588,47 @@ export default function SettingsView() {
|
|||
</Card>
|
||||
<Card className={cardClassName}>
|
||||
<CardHeader className="text-xl flex flex-row"><NotionLogo className="h-7 w-7 mr-2" />Notion</CardHeader>
|
||||
<CardContent className="overflow-hidden pb-12 text-gray-400">
|
||||
Sync your Notion pages
|
||||
<CardContent className="grid gap-4">
|
||||
<p className="text-gray-400">Sync your Notion pages. See the <a href="https://docs.khoj.dev/data-sources/notion_integration/">setup instructions</a></p>
|
||||
{!userConfig.notion_oauth_url && (
|
||||
<Input
|
||||
onChange={(e) => setNotionToken(e.target.value)}
|
||||
value={notionToken || ""}
|
||||
placeholder="Enter the API Key of your Khoj integration on Notion"
|
||||
className="w-full border border-gray-300 rounded-lg px-4 py-6"
|
||||
/>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-wrap gap-4">
|
||||
<Button variant="outline" size="sm">
|
||||
{userConfig.enabled_content_source.notion && (
|
||||
<>
|
||||
<Files className="h-5 w-5 inline mr-1" />Manage
|
||||
</>
|
||||
) || (
|
||||
<>
|
||||
{(
|
||||
/* Show connect to notion button if notion oauth url setup and user disconnected*/
|
||||
userConfig.notion_oauth_url && !userConfig.enabled_content_source.notion
|
||||
?
|
||||
<Button variant="outline" size="sm" onClick={() => {window.open(userConfig.notion_oauth_url)}}>
|
||||
<Plugs className="h-5 w-5 inline mr-1" />Connect
|
||||
</>
|
||||
</Button>
|
||||
/* Show sync button if user connected to notion and API key unchanged */
|
||||
: userConfig.enabled_content_source.notion && notionToken === userConfig.notion_token
|
||||
?
|
||||
<Button variant="outline" size="sm" onClick={() => syncContent("notion")}>
|
||||
<ArrowsClockwise className="h-5 w-5 inline mr-1" />Sync
|
||||
</Button>
|
||||
/* Show set API key button notion oauth url not set setup */
|
||||
: !userConfig.notion_oauth_url
|
||||
?
|
||||
<Button variant="outline" size="sm" onClick={saveNotionToken} disabled={notionToken === userConfig.notion_token}>
|
||||
<FloppyDisk className="h-5 w-5 inline mr-1" />
|
||||
{userConfig.enabled_content_source.notion && "Update API Key" || "Set API Key"}
|
||||
</Button>
|
||||
: <></>
|
||||
)}
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" className={`${userConfig.enabled_content_source.notion || "hidden"}`}>
|
||||
<CloudSlash className="h-5 w-5 inline mr-1" />Disable
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className={`${userConfig.enabled_content_source.notion || "hidden"}`}
|
||||
onClick={() => disconnectContent("notion")}
|
||||
>
|
||||
<CloudSlash className="h-5 w-5 inline mr-1" />Disconnect
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
|
Loading…
Add table
Reference in a new issue