diff --git a/cognee-frontend/src/app/account/Account.tsx b/cognee-frontend/src/app/account/Account.tsx index c5cca42b7..067f302f4 100644 --- a/cognee-frontend/src/app/account/Account.tsx +++ b/cognee-frontend/src/app/account/Account.tsx @@ -13,8 +13,8 @@ export default function Account() { }; return ( -
- */} -
+
@@ -42,7 +42,7 @@ export default function Account() {
Plan
You are using open-source version. Subscribe to get access to hosted cognee with your data!
- Select a plan + Select a plan
diff --git a/cognee-frontend/src/app/dashboard/AddDataToCognee.tsx b/cognee-frontend/src/app/dashboard/AddDataToCognee.tsx index 60e2a4204..e0296d9c6 100644 --- a/cognee-frontend/src/app/dashboard/AddDataToCognee.tsx +++ b/cognee-frontend/src/app/dashboard/AddDataToCognee.tsx @@ -2,7 +2,7 @@ import { FormEvent, useCallback, useState } from "react"; import { LoadingIndicator } from "@/ui/App"; import { useModal } from "@/ui/elements/Modal"; -import { CloseIcon, PlusIcon } from "@/ui/Icons"; +import { CloseIcon, MinusIcon, PlusIcon } from "@/ui/Icons"; import { CTAButton, GhostButton, IconButton, Modal, NeutralButton, Select } from "@/ui/elements"; import addData from "@/modules/ingestion/addData"; @@ -16,16 +16,22 @@ interface AddDataToCogneeProps { } export default function AddDataToCognee({ datasets, refreshDatasets, useCloud = false }: AddDataToCogneeProps) { - const [filesForUpload, setFilesForUpload] = useState(null); + const [filesForUpload, setFilesForUpload] = useState([]); - const prepareFiles = useCallback((event: FormEvent) => { + const addFiles = useCallback((event: FormEvent) => { const formElements = event.currentTarget; - const files = formElements.files; + const newFiles = formElements.files; - setFilesForUpload(files); + if (newFiles?.length) { + setFilesForUpload((oldFiles) => [...oldFiles, ...Array.from(newFiles)]); + } }, []); - const processDataWithCognee = useCallback((state: object, event?: FormEvent) => { + const removeFile = useCallback((file: File) => { + setFilesForUpload((oldFiles) => oldFiles.filter((f) => f !== file)); + }, []); + + const processDataWithCognee = useCallback((state?: object, event?: FormEvent) => { event!.preventDefault(); if (!filesForUpload) { @@ -41,7 +47,7 @@ export default function AddDataToCognee({ datasets, refreshDatasets, useCloud = } : { name: "main_dataset", }, - Array.from(filesForUpload), + filesForUpload, useCloud ) .then(({ dataset_id, dataset_name }) => { @@ -57,7 +63,7 @@ export default function AddDataToCognee({ datasets, refreshDatasets, useCloud = useCloud, ) .then(() => { - setFilesForUpload(null); + setFilesForUpload([]); }); }); }, [filesForUpload, refreshDatasets, useCloud]); @@ -86,24 +92,25 @@ export default function AddDataToCognee({ datasets, refreshDatasets, useCloud =
Please select a {useCloud ? "cloud" : "local"} dataset to add data in.
If you don't have any, don't worry, we will create one for you.
- {!datasets.length && } - {datasets.map((dataset: Dataset, index) => ( - + {datasets.map((dataset: Dataset) => ( + ))} - + select files - {filesForUpload?.length && ( + {!!filesForUpload.length && (
selected files:
- {Array.from(filesForUpload || []).map((file) => ( -
+ {filesForUpload.map((file) => ( +
{file.name} +
))}
diff --git a/cognee-frontend/src/app/dashboard/Dashboard.tsx b/cognee-frontend/src/app/dashboard/Dashboard.tsx index 6da587ca7..75e3d7518 100644 --- a/cognee-frontend/src/app/dashboard/Dashboard.tsx +++ b/cognee-frontend/src/app/dashboard/Dashboard.tsx @@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { Header } from "@/ui/Layout"; import { SearchIcon } from "@/ui/Icons"; -import { Notebook } from "@/ui/elements"; +import { CTAButton, Notebook } from "@/ui/elements"; import { fetch, isCloudEnvironment } from "@/utils"; import { Notebook as NotebookType } from "@/ui/elements/Notebook/types"; import { useAuthenticatedUser } from "@/modules/auth"; @@ -111,8 +111,8 @@ export default function Dashboard({ accessToken }: DashboardProps) { const isCloudEnv = isCloudEnvironment(); return ( -
- */}
-
-
+
+
@@ -152,6 +152,12 @@ export default function Dashboard({ accessToken }: DashboardProps) { />
+ +
diff --git a/cognee-frontend/src/app/dashboard/InstanceDatasetsAccordion.tsx b/cognee-frontend/src/app/dashboard/InstanceDatasetsAccordion.tsx index f83dd79a2..f094f7caf 100644 --- a/cognee-frontend/src/app/dashboard/InstanceDatasetsAccordion.tsx +++ b/cognee-frontend/src/app/dashboard/InstanceDatasetsAccordion.tsx @@ -36,7 +36,8 @@ export default function InstanceDatasetsAccordion({ onDatasetsChange }: Instance }; checkConnectionToLocalCognee(); - }, [setCloudCogneeConnected, setLocalCogneeConnected]); + checkConnectionToCloudCognee(); + }, [checkConnectionToCloudCognee, setCloudCogneeConnected, setLocalCogneeConnected]); const { value: isCloudConnectedModalOpen, diff --git a/cognee-frontend/src/app/dashboard/NotebooksAccordion.tsx b/cognee-frontend/src/app/dashboard/NotebooksAccordion.tsx index 6c4e569cc..ffb4d0fa8 100644 --- a/cognee-frontend/src/app/dashboard/NotebooksAccordion.tsx +++ b/cognee-frontend/src/app/dashboard/NotebooksAccordion.tsx @@ -5,8 +5,8 @@ import { useBoolean } from "@/utils"; import { Accordion, CTAButton, GhostButton, IconButton, Input, Modal } from "@/ui/elements"; import { CloseIcon, MinusIcon, NotebookIcon, PlusIcon } from "@/ui/Icons"; import { Notebook } from "@/ui/elements/Notebook/types"; -import { LoadingIndicator } from "@/ui/App"; import { useModal } from "@/ui/elements/Modal"; +import { LoadingIndicator } from "@/ui/App"; interface NotebooksAccordionProps { notebooks: Notebook[]; @@ -60,7 +60,7 @@ export default function NotebooksAccordion({ .finally(() => setNotebookToRemove(null)); }; - const handleNotebookAdd = useCallback((_: object, formEvent?: FormEvent) => { + const handleNotebookAdd = useCallback((_: Notebook, formEvent?: FormEvent) => { if (!formEvent) { return; } @@ -71,6 +71,7 @@ export default function NotebooksAccordion({ const notebookName = formElements.notebookName.value.trim(); return addNotebook(notebookName) + .then(() => {}); }, [addNotebook]); const { @@ -79,7 +80,7 @@ export default function NotebooksAccordion({ closeModal: closeNewNotebookModal, confirmAction: handleNewNotebookSubmit, isActionLoading: isNewDatasetLoading, - } = useModal(false, handleNotebookAdd); + } = useModal(false, handleNotebookAdd); return ( <> @@ -91,7 +92,7 @@ export default function NotebooksAccordion({ tools={isNewDatasetLoading ? ( ) : ( - + openNewNotebookModal()}> )} > {notebooks.length === 0 && ( diff --git a/cognee-frontend/src/app/globals.css b/cognee-frontend/src/app/globals.css index 1007b2fb7..b49bc7dcf 100644 --- a/cognee-frontend/src/app/globals.css +++ b/cognee-frontend/src/app/globals.css @@ -11,7 +11,7 @@ --global-color-primary-active: #500cc5 !important; --global-color-primary-text: white !important; --global-color-secondary: #0DFF00 !important; - --global-background-default: #0D051C; + --global-background-default: #F4F4F4; --textarea-default-color: #0D051C !important; } @@ -20,6 +20,7 @@ body { height: 100%; max-width: 100vw; overflow-x: hidden; + background-color: var(--global-background-default); } a { diff --git a/cognee-frontend/src/app/plan/Plan.tsx b/cognee-frontend/src/app/plan/Plan.tsx index 1fc3477ea..3fd181270 100644 --- a/cognee-frontend/src/app/plan/Plan.tsx +++ b/cognee-frontend/src/app/plan/Plan.tsx @@ -1,12 +1,17 @@ +"use client"; + import Link from "next/link"; import { BackIcon, CheckIcon } from "@/ui/Icons"; import { CTAButton, NeutralButton } from "@/ui/elements"; import Header from "@/ui/Layout/Header"; +import { useAuthenticatedUser } from "@/modules/auth"; export default function Plan() { + const { user } = useAuthenticatedUser(); + return ( -
- */} -
+
- - - back - +
+ + + back + + + {/* */} +
-
+
Affordable and transparent pricing
-
+
Basic
-
Free
+
Free
-
+
+
Most Popular
On-prem Subscription
-
$2470 /per month
-
Save 20% yearly
+
$2470 /per month
+
Save 20% yearly
-
+
Cloud Subscription
-
$25 /per month
-
(beta pricing)
+
$25 /per month
+
(beta pricing)
-
-
Everything in the free plan, plus...
+
+
Everything in the free plan, plus...
-
License to use Cognee open source
-
Cognee tasks and pipelines
-
Custom schema and ontology generation
-
Integrated evaluations
-
More than 28 data sources supported
+
License to use Cognee open source
+
Cognee tasks and pipelines
+
Custom schema and ontology generation
+
Integrated evaluations
+
More than 28 data sources supported
-
-
Everything in the free plan, plus...
-
-
License to use Cognee open source and Cognee Platform
-
1 day SLA
-
On-prem deployment
-
Hands-on support
-
Architecture review
-
Roadmap prioritization
-
Knowledge transfer
+
+
Everything in the free plan, plus...
+
+
License to use Cognee open source and Cognee Platform
+
1 day SLA
+
On-prem deployment
+
Hands-on support
+
Architecture review
+
Roadmap prioritization
+
Knowledge transfer
-
-
Everything in the free plan, plus...
-
-
Fully hosted cloud platform
-
Multi-tenant architecture
-
Comprehensive API endpoints
-
Automated scaling and parallel processing
-
Ability to group memories per user and domain
-
Automatic updates and priority support
-
1 GB ingestion + 10,000 API calls
+
+
Everything in the free plan, plus...
+
+
Fully hosted cloud platform
+
Multi-tenant architecture
+
Comprehensive API endpoints
+
Automated scaling and parallel processing
+
Ability to group memories per user and domain
+
Automatic updates and priority support
+
1 GB ingestion + 10,000 API calls
- Try for free + + Try for free +
- Talk to us + + Talk to us +
- Sign up for Cogwit Beta + + Sign up for Cogwit Beta +
@@ -106,7 +127,7 @@ export default function Plan() {
On-prem
Cloud
-
+
Data Sources
28+
28+
@@ -134,19 +155,19 @@ export default function Plan() {
-
+
Can I change my plan anytime?
Yes, you can upgrade or downgrade your plan at any time. Changes take effect immediately.
-
+
What happens to my data if I downgrade?
Your data is preserved, but features may be limited based on your new plan constraints.
-
+
Do you offer educational discounts?
Yes, we offer special pricing for educational institutions and students. Contact us for details.
-
+
Is there a free trial for paid plans?
All new accounts start with a 14-day free trial of our Pro plan features.
diff --git a/cognee-frontend/src/ui/Layout/Header.tsx b/cognee-frontend/src/ui/Layout/Header.tsx index 2f26433e9..7a1d2e906 100644 --- a/cognee-frontend/src/ui/Layout/Header.tsx +++ b/cognee-frontend/src/ui/Layout/Header.tsx @@ -32,20 +32,21 @@ export default function Header({ user }: HeaderProps) { return ( <> -
+
Cognee Local
- +
Sync
- - Premium + + Premium + API keys {/*
*/} diff --git a/cognee-frontend/src/ui/elements/GhostButton.tsx b/cognee-frontend/src/ui/elements/GhostButton.tsx index a27a0ff94..dc252decd 100644 --- a/cognee-frontend/src/ui/elements/GhostButton.tsx +++ b/cognee-frontend/src/ui/elements/GhostButton.tsx @@ -1,7 +1,7 @@ import classNames from "classnames"; import { ButtonHTMLAttributes } from "react"; -export default function CTAButton({ children, className, ...props }: ButtonHTMLAttributes) { +export default function GhostButton({ children, className, ...props }: ButtonHTMLAttributes) { return ( ); diff --git a/cognee-frontend/src/ui/elements/Modal/useModal.ts b/cognee-frontend/src/ui/elements/Modal/useModal.ts index 4947d32ca..d28333995 100644 --- a/cognee-frontend/src/ui/elements/Modal/useModal.ts +++ b/cognee-frontend/src/ui/elements/Modal/useModal.ts @@ -1,8 +1,8 @@ import { FormEvent, useCallback, useState } from "react"; import { useBoolean } from "@/utils"; -export default function useModal(initiallyOpen?: boolean, confirmCallback?: (state: object, event?: FormEvent) => Promise | ConfirmActionReturnType) { - const [modalState, setModalState] = useState({}); +export default function useModal>(initiallyOpen?: boolean, confirmCallback?: (state: ModalState, event?: ConfirmActionEvent) => Promise | void) { + const [modalState, setModalState] = useState(); const [isActionLoading, setLoading] = useState(false); const { @@ -11,7 +11,7 @@ export default function useModal(initiallyOpen?: setFalse: closeModalInternal, } = useBoolean(initiallyOpen || false); - const openModal = useCallback((state?: object) => { + const openModal = useCallback((state?: ModalState) => { if (state) { setModalState(state); } @@ -20,20 +20,21 @@ export default function useModal(initiallyOpen?: const closeModal = useCallback(() => { closeModalInternal(); - setModalState({}); + setModalState({} as ModalState); }, [closeModalInternal]); - const confirmAction = useCallback((event?: FormEvent) => { + const confirmAction = useCallback((event?: ConfirmActionEvent) => { if (confirmCallback) { setLoading(true); - const maybePromise = confirmCallback(modalState, event); + const maybePromise = confirmCallback(modalState as ModalState, event); if (maybePromise instanceof Promise) { return maybePromise .finally(closeModal) .finally(() => setLoading(false)); } else { + closeModal(); return maybePromise; // Not a promise. } } diff --git a/cognee-frontend/src/ui/elements/Notebook/Notebook.tsx b/cognee-frontend/src/ui/elements/Notebook/Notebook.tsx index 31c716b96..1401f95b4 100644 --- a/cognee-frontend/src/ui/elements/Notebook/Notebook.tsx +++ b/cognee-frontend/src/ui/elements/Notebook/Notebook.tsx @@ -2,10 +2,11 @@ import { v4 as uuid4 } from "uuid"; import classNames from "classnames"; -import { Fragment, MutableRefObject, useCallback, useEffect, useRef, useState } from "react"; +import { Fragment, MouseEvent, MutableRefObject, useCallback, useEffect, useRef, useState } from "react"; -import { CaretIcon, PlusIcon } from "@/ui/Icons"; -import { IconButton, PopupMenu, TextArea } from "@/ui/elements"; +import { useModal } from "@/ui/elements/Modal"; +import { CaretIcon, CloseIcon, PlusIcon } from "@/ui/Icons"; +import { IconButton, PopupMenu, TextArea, Modal, GhostButton, CTAButton } from "@/ui/elements"; import { GraphControlsAPI } from "@/app/(graph)/GraphControls"; import GraphVisualization, { GraphVisualizationAPI } from "@/app/(graph)/GraphVisualization"; @@ -60,13 +61,26 @@ export default function Notebook({ notebook, updateNotebook, runCell }: Notebook updateNotebook(newNotebook); }, [notebook, updateNotebook]); - const handleCellRemove = useCallback((cell: Cell) => { + const removeCell = useCallback((cell: Cell, event?: MouseEvent) => { + event?.preventDefault(); + updateNotebook({ ...notebook, cells: notebook.cells.filter((c: Cell) => c.id !== cell.id), }); }, [notebook, updateNotebook]); + const { + isModalOpen: isRemoveCellConfirmModalOpen, + openModal: openCellRemoveConfirmModal, + closeModal: closeCellRemoveConfirmModal, + confirmAction: handleCellRemoveConfirm, + } = useModal(false, removeCell); + + const handleCellRemove = useCallback((cell: Cell) => { + openCellRemoveConfirmModal(cell); + }, [openCellRemoveConfirmModal]); + const handleCellInputChange = useCallback((notebook: NotebookType, cell: Cell, value: string) => { const newCell = {...cell, content: value }; @@ -134,100 +148,133 @@ export default function Notebook({ notebook, updateNotebook, runCell }: Notebook }; return ( -
-
{notebook.name}
+ <> +
+
{notebook.name}
- {notebook.cells.map((cell: Cell, index) => ( - -
-
- {cell.type === "code" ? ( - <> -
- - - -
+ {notebook.cells.map((cell: Cell, index) => ( + +
+
+ {cell.type === "code" ? ( + <> +
+ + + +
- + - {openCells.has(cell.id) && ( - <> + {openCells.has(cell.id) && ( + <> +