aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryxshv <[email protected]>2024-04-13 12:37:15 +0530
committeryxshv <[email protected]>2024-04-13 12:37:15 +0530
commitcd71d6b4f99c09eb4608eb59026bf884c7cc6acf (patch)
tree2b97210b0dfa77d6346c32e9c086f9c583f20282
parentnew route /spaces (diff)
downloadsupermemory-cd71d6b4f99c09eb4608eb59026bf884c7cc6acf.tar.xz
supermemory-cd71d6b4f99c09eb4608eb59026bf884c7cc6acf.zip
fix dialog to add spaces
-rw-r--r--apps/extension/package.json1
-rw-r--r--apps/extension/pnpm-lock.yaml135
-rw-r--r--apps/extension/src/SideBar.tsx55
-rw-r--r--apps/extension/src/background.ts35
-rw-r--r--apps/extension/src/components/FilterCombobox.tsx149
-rw-r--r--apps/extension/src/components/ui/dropdown-menu.tsx198
-rw-r--r--apps/web/src/app/api/spaces/route.ts9
-rw-r--r--apps/web/src/app/page.tsx5
-rw-r--r--apps/web/src/server/db/test.ts10
-rw-r--r--apps/web/types/memory.tsx7
10 files changed, 456 insertions, 148 deletions
diff --git a/apps/extension/package.json b/apps/extension/package.json
index 4c12ef20..a7f34ea6 100644
--- a/apps/extension/package.json
+++ b/apps/extension/package.json
@@ -12,6 +12,7 @@
},
"dependencies": {
"@radix-ui/react-dialog": "^1.0.5",
+ "@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-tooltip": "^1.0.7",
"cmdk": "^1.0.0",
diff --git a/apps/extension/pnpm-lock.yaml b/apps/extension/pnpm-lock.yaml
index e61391eb..ad6c187d 100644
--- a/apps/extension/pnpm-lock.yaml
+++ b/apps/extension/pnpm-lock.yaml
@@ -8,6 +8,9 @@ dependencies:
'@radix-ui/react-dialog':
specifier: ^1.0.5
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.0.6
'@radix-ui/react-popover':
specifier: ^1.0.7
@@ -668,6 +671,30 @@ packages:
react-dom: 18.2.0([email protected])
dev: false
+ resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.24.4
+ '@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-context': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-slot': 1.0.2(@types/[email protected])([email protected])
+ '@types/react': 18.2.75
+ '@types/react-dom': 18.2.24
+ react: 18.2.0
+ react-dom: 18.2.0([email protected])
+ dev: false
+
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
peerDependencies:
@@ -730,6 +757,20 @@ packages:
react-remove-scroll: 2.5.5(@types/[email protected])([email protected])
dev: false
+ resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.24.4
+ '@types/react': 18.2.75
+ react: 18.2.0
+ dev: false
+
resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
peerDependencies:
@@ -755,6 +796,33 @@ packages:
react-dom: 18.2.0([email protected])
dev: false
+ resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.24.4
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-context': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-id': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-menu': 2.0.6(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/[email protected])([email protected])
+ '@types/react': 18.2.75
+ '@types/react-dom': 18.2.24
+ react: 18.2.0
+ react-dom: 18.2.0([email protected])
+ dev: false
+
resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==}
peerDependencies:
@@ -807,6 +875,44 @@ packages:
react: 18.2.0
dev: false
+ resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.24.4
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-context': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-direction': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-focus-guards': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-focus-scope': 1.0.4(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-id': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-popper': 1.1.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-portal': 1.0.4(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-presence': 1.0.1(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-roving-focus': 1.0.4(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-slot': 1.0.2(@types/[email protected])([email protected])
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
+ '@types/react': 18.2.75
+ '@types/react-dom': 18.2.24
+ aria-hidden: 1.2.4
+ react: 18.2.0
+ react-dom: 18.2.0([email protected])
+ react-remove-scroll: 2.5.5(@types/[email protected])([email protected])
+ dev: false
+
resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==}
peerDependencies:
@@ -936,6 +1042,35 @@ packages:
react-dom: 18.2.0([email protected])
dev: false
+ resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.24.4
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-compose-refs': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-context': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-direction': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-id': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-primitive': 1.0.3(@types/[email protected])(@types/[email protected])([email protected])([email protected])
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/[email protected])([email protected])
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/[email protected])([email protected])
+ '@types/react': 18.2.75
+ '@types/react-dom': 18.2.24
+ react: 18.2.0
+ react-dom: 18.2.0([email protected])
+ dev: false
+
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
peerDependencies:
diff --git a/apps/extension/src/SideBar.tsx b/apps/extension/src/SideBar.tsx
index 890619ca..38b43a30 100644
--- a/apps/extension/src/SideBar.tsx
+++ b/apps/extension/src/SideBar.tsx
@@ -18,8 +18,9 @@ import {
DialogFooter,
DialogClose,
} from "./components/ui/dialog";
+import { Space } from "./types/memory";
-function sendUrlToAPI() {
+function sendUrlToAPI(spaces: number[]) {
// get the current URL
const url = window.location.href;
@@ -46,11 +47,14 @@ function SideBar() {
// }
// });
+
const [savedWebsites, setSavedWebsites] = useState<string[]>([]);
const [isSendingData, setIsSendingData] = useState(false);
- const [selectedSpaces, setSelectedSpaces] = useState<number[]>([0, 1]);
+ const [loading, setLoading] = useState(false)
+ const [spaces, setSpaces] = useState<Space[]>();
+ const [selectedSpaces, setSelectedSpaces] = useState<number[]>([]);
interface TweetData {
tweetText: string;
@@ -60,6 +64,15 @@ function SideBar() {
time: string;
}
+ const fetchSpaces = async () => {
+ setLoading(true)
+ chrome.runtime.sendMessage({ type: "fetchSpaces" }, (resp) => {
+ console.log(resp)
+ setSpaces(resp)
+ setLoading(false)
+ });
+ }
+
const fetchBookmarks = () => {
const tweets: TweetData[] = []; // Initialize an empty array to hold all tweet elements
@@ -205,7 +218,7 @@ function SideBar() {
) : (
<></>
)}
- <Dialog>
+ <Dialog onOpenChange={open => open === true && fetchSpaces()}>
<Tooltip delayDuration={300}>
<TooltipTrigger
className="anycontext-bg-transparent
@@ -215,15 +228,7 @@ function SideBar() {
<DialogTrigger asChild>
<button
onClick={() => {
- sendUrlToAPI();
- setIsSendingData(true);
- setTimeout(() => {
- setIsSendingData(false);
- setSavedWebsites([
- ...savedWebsites,
- window.location.href,
- ]);
- }, 1000);
+ return;
}}
disabled={savedWebsites.includes(window.location.href)}
className="anycontext-open-button disabled:anycontext-opacity-30 anycontext-bg-transparent
@@ -276,23 +281,27 @@ function SideBar() {
</DialogHeader>
<FilterSpaces
+ loading={loading}
className="anycontext-mr-auto"
selectedSpaces={selectedSpaces}
setSelectedSpaces={setSelectedSpaces}
name={"Add to Spaces"}
- spaces={[
- {
- name: "cool tech",
- id: 0,
- },
- {
- name: "cool libs",
- id: 1,
- },
- ]}
+ spaces={spaces ?? []}
/>
<DialogFooter className="anycontext-w-full anycontext-text-sm">
- <DialogClose>Add</DialogClose>
+ <DialogClose
+ onClick={() => {
+ sendUrlToAPI(selectedSpaces);
+ setIsSendingData(true);
+ setTimeout(() => {
+ setIsSendingData(false);
+ setSavedWebsites([
+ ...savedWebsites,
+ window.location.href,
+ ]);
+ }, 1000);
+ }}
+ >Add</DialogClose>
<DialogClose>Cancel</DialogClose>
</DialogFooter>
</DialogContent>
diff --git a/apps/extension/src/background.ts b/apps/extension/src/background.ts
index b3030e74..523a34e8 100644
--- a/apps/extension/src/background.ts
+++ b/apps/extension/src/background.ts
@@ -1,4 +1,5 @@
import { getEnv } from "./util";
+import { Space } from "./types/memory"
const backendUrl =
getEnv() === "development"
@@ -37,8 +38,10 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
return true;
} else if (request.type === "urlChange") {
+
const content = request.content;
const url = request.url;
+ const spaces = request.spaces
(async () => {
chrome.storage.local.get(["jwt"], ({ jwt }) => {
@@ -51,10 +54,40 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
headers: {
Authorization: `Bearer ${jwt}`,
},
- body: JSON.stringify({ pageContent: content, url }),
+ body: JSON.stringify({ pageContent: content, url, spaces }),
}).then((ers) => console.log(ers.status));
});
})();
+ } else if (request.type === "fetchSpaces") {
+
+ const run = () => chrome.storage.local.get(["jwt"], async ({ jwt }) => {
+ if (!jwt) {
+ console.error("No JWT found");
+ return;
+ }
+ const resp = await fetch(`${backendUrl}/api/spaces`, {
+ headers: {
+ Authorization: `Bearer ${jwt}`,
+ },
+ })
+
+ const data: {
+ message: "OK" | string;
+ data: Space[] | undefined;
+ } = await resp.json();
+
+ if (data.message === "OK" && data.data) {
+ sendResponse(data.data)
+ }
+
+ });
+
+ run()
+
+
+ return true;
+
+
} else if (request.type === "queryApi") {
const input = request.input;
const jwt = request.jwt;
diff --git a/apps/extension/src/components/FilterCombobox.tsx b/apps/extension/src/components/FilterCombobox.tsx
index f6215c03..1ff49d38 100644
--- a/apps/extension/src/components/FilterCombobox.tsx
+++ b/apps/extension/src/components/FilterCombobox.tsx
@@ -1,152 +1,67 @@
import * as React from "react";
-import { Check, ChevronsUpDown, X } from "lucide-react";
-
-import { cn } from "../lib/utils";
-import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
-} from "../components/ui/command";
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "../components/ui/popover";
+import { PlusCircleIcon, X } from "lucide-react";
import { Space } from "../types/memory";
+import { DropdownMenu, DropdownMenuContent, DropdownMenuItem } from "./ui/dropdown-menu";
+import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
- side?: "top" | "bottom";
- align?: "end" | "start" | "center";
- onClose?: () => void;
selectedSpaces: number[];
setSelectedSpaces: (
spaces: number[] | ((prev: number[]) => number[]),
) => void;
name: string;
spaces: Space[];
+ loading: boolean;
}
export function FilterSpaces({
- className,
- side = "bottom",
- align = "center",
- onClose,
+ loading,
selectedSpaces,
setSelectedSpaces,
- name,
spaces,
- ...props
}: Props) {
- const [open, setOpen] = React.useState(false);
console.log(selectedSpaces, spaces);
- const sortedSpaces = spaces.sort(({ id: a }, { id: b }) =>
- selectedSpaces.includes(a) && !selectedSpaces.includes(b)
- ? -1
- : selectedSpaces.includes(b) && !selectedSpaces.includes(a)
- ? 1
- : 0,
- );
+ const filteredSpaces = spaces.filter(space => selectedSpaces.includes(space.id))
+ const leftSpaces = spaces.filter(space => !selectedSpaces.includes(space.id))
- React.useEffect(() => {
- if (!open) {
- onClose?.();
- }
- }, [open]);
+ if (loading) {
+ return "Loading..."
+ }
return (
<div className="anycontext-flex anycontext-flex-wrap anycontext-gap-1 anycontext-text-sm anycontext-">
- {selectedSpaces.map((spaceid) => {
- const space = spaces.find((s) => s.id === spaceid)!;
- return <SpaceItem {...space} key={spaceid} onRemove={() => {}} />;
- })}
+ {filteredSpaces.length < 1 && "Add to a space"}
+ {filteredSpaces.map((space) => (
+ <SpaceItem {...space} key={space.id} onRemove={() => setSelectedSpaces(prev => prev.filter(s => s !== space.id))} />
+ ))}
+ {leftSpaces.length > 0 && (
+ <DropdownMenu>
+ <DropdownMenuTrigger className="anycontext-rounded-full">
+ <PlusCircleIcon className="anycontext-w-5 anycontext-h-5 [--anycontext-icon-stroke:white] dark:[--anycontext-icon-stroke:black]" stroke='var(--anycontext-icon-stroke)' fill='currentColor' />
+ </DropdownMenuTrigger>
+ <DropdownMenuContent>
+ {leftSpaces.map(space => (
+ <>
+ {loading && "Loading..."}
+ <DropdownMenuItem onClick={() => setSelectedSpaces(prev => [...prev, space.id])}>
+ {space.name}
+ </DropdownMenuItem>
+ </>
+ ))}
+ </DropdownMenuContent>
+ </DropdownMenu>
+ )}
</div>
);
- return (
- <Popover open={open} onOpenChange={setOpen}>
- <PopoverTrigger asChild>
- <button
- type={undefined}
- data-state-on={open}
- className={cn(
- "anycontext-combobox-button anycontext-w-fit",
- className,
- )}
- {...props}
- >
- {name}
- <ChevronsUpDown className="anycontext-h-4 anycontext-w-4" />
- <div
- data-state-on={selectedSpaces.length > 0}
- className="on:anycontext-flex anycontext-text-rgray-11 anycontext-border-rgray-6 anycontext-bg-rgray-2 anycontext-absolute anycontext-left-0 anycontext-top-0 anycontext-hidden anycontext-aspect-[1] anycontext-h-4 anycontext-w-4 anycontext--translate-x-1/3 anycontext--translate-y-1/3 anycontext-items-center anycontext-justify-center anycontext-rounded-full anycontext-border anycontext-text-center anycontext-text-[9px]"
- >
- {selectedSpaces.length}
- </div>
- </button>
- </PopoverTrigger>
- <PopoverContent
- onCloseAutoFocus={(e) => e.preventDefault()}
- align={align}
- side={side}
- className="anycontext-w-[200px] anycontext-p-0"
- >
- <Command
- filter={(val, search) =>
- spaces
- .find((s) => s.id.toString() === val)
- ?.name.toLowerCase()
- .includes(search.toLowerCase().trim())
- ? 1
- : 0
- }
- >
- <CommandInput placeholder="Filter spaces..." />
- <CommandList asChild>
- <div>
- <CommandEmpty>Nothing found</CommandEmpty>
- <CommandGroup>
- {sortedSpaces.map((space) => (
- <CommandItem
- key={space.id}
- value={space.id.toString()}
- onSelect={(val) => {
- setSelectedSpaces((prev: number[]) =>
- prev.includes(parseInt(val))
- ? prev.filter((v) => v !== parseInt(val))
- : [...prev, parseInt(val)],
- );
- }}
- asChild
- >
- <div className="anycontext-text-black/90 dark:anycontext-text-white/90">
- {space.name}
- <Check
- data-state-on={selectedSpaces.includes(space.id)}
- className={cn(
- "on:anycontext-opacity-100 anycontext-ml-auto anycontext-h-4 anycontext-w-4 anycontext-opacity-0",
- )}
- />
- </div>
- </CommandItem>
- ))}
- </CommandGroup>
- </div>
- </CommandList>
- </Command>
- </PopoverContent>
- </Popover>
- );
}
function SpaceItem({ name, onRemove }: { onRemove: () => void } & Space) {
return (
<div className="anycontext-flex anycontext-justify-center anycontext-items-center anycontext-gap-2 anycontext-p-1 anycontext-pl-2 anycontext-pr-3 anycontext-rounded-full anycontext-bg-black/5 dark:anycontext-bg-white/5 anycontext-border-white/20 dark:anycontext-border-black/20 border">
- <button className="anycontext-flex hover:anycontext-bg-transparent anycontext-justify-center anycontext-scale-110 anycontext-items-center focus-visible:anycontext-outline-none anycontext-rounded-full anycontext-w-3 anycontext-bg-black/5 dark:anycontext-bg-white/5 anycontext-h-3 anycontext-text-transparent hover:anycontext-text-black dark:hover:anycontext-text-white">
+ <button onClick={onRemove} className="anycontext-flex hover:anycontext-bg-transparent anycontext-justify-center anycontext-scale-110 anycontext-items-center focus-visible:anycontext-outline-none anycontext-rounded-full anycontext-w-3 anycontext-bg-black/5 dark:anycontext-bg-white/5 anycontext-h-3 anycontext-text-transparent hover:anycontext-text-black dark:hover:anycontext-text-white">
<X className="anycontext-w-3 anycontext-h-3" />
</button>
{name}
diff --git a/apps/extension/src/components/ui/dropdown-menu.tsx b/apps/extension/src/components/ui/dropdown-menu.tsx
new file mode 100644
index 00000000..2e9a95b8
--- /dev/null
+++ b/apps/extension/src/components/ui/dropdown-menu.tsx
@@ -0,0 +1,198 @@
+import * as React from "react"
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import { Check, ChevronRight, Circle } from "lucide-react"
+
+import { cn } from "../../lib/utils"
+
+const DropdownMenu = DropdownMenuPrimitive.Root
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+ <DropdownMenuPrimitive.SubTrigger
+ ref={ref}
+ className={cn(
+ "anycontext-flex anycontext-cursor-default anycontext-select-none anycontext-items-center anycontext-rounded-sm anycontext-px-2 anycontext-py-1.5 anycontext-text-sm anycontext-outline-none focus:anycontext-bg-stone-100 data-[state=open]:anycontext-bg-stone-100 dark:focus:anycontext-bg-stone-800 dark:data-[state=open]:anycontext-bg-stone-800",
+ inset && "anycontext-pl-8",
+ className
+ )}
+ {...props}
+ >
+ {children}
+ <ChevronRight className="anycontext-ml-auto anycontext-h-4 anycontext-w-4" />
+ </DropdownMenuPrimitive.SubTrigger>
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
+>(({ className, ...props }, ref) => (
+ <DropdownMenuPrimitive.SubContent
+ ref={ref}
+ className={cn(
+ "anycontext-z-50 anycontext-min-w-[8rem] anycontext-overflow-hidden anycontext-rounded-md anycontext-border anycontext-border-stone-200 anycontext-bg-white anycontext-p-1 anycontext-text-stone-950 anycontext-shadow-lg data-[state=open]:anycontext-animate-in data-[state=closed]:anycontext-animate-out data-[state=closed]:anycontext-fade-out-0 data-[state=open]:anycontext-fade-in-0 data-[state=closed]:anycontext-zoom-out-95 data-[state=open]:anycontext-zoom-in-95 data-[side=bottom]:anycontext-slide-in-from-top-2 data-[side=left]:anycontext-slide-in-from-right-2 data-[side=right]:anycontext-slide-in-from-left-2 data-[side=top]:anycontext-slide-in-from-bottom-2 dark:anycontext-border-stone-800 dark:anycontext-bg-stone-950 dark:anycontext-text-stone-50",
+ className
+ )}
+ {...props}
+ />
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.Content>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
+>(({ className, sideOffset = 4, ...props }, ref) => (
+ <DropdownMenuPrimitive.Portal>
+ <DropdownMenuPrimitive.Content
+ ref={ref}
+ sideOffset={sideOffset}
+ className={cn(
+ "anycontext-z-50 anycontext-min-w-[8rem] anycontext-overflow-hidden anycontext-rounded-md anycontext-border anycontext-border-stone-200 anycontext-bg-white anycontext-p-1 anycontext-text-stone-950 anycontext-shadow-md data-[state=open]:anycontext-animate-in data-[state=closed]:anycontext-animate-out data-[state=closed]:anycontext-fade-out-0 data-[state=open]:anycontext-fade-in-0 data-[state=closed]:anycontext-zoom-out-95 data-[state=open]:anycontext-zoom-in-95 data-[side=bottom]:anycontext-slide-in-from-top-2 data-[side=left]:anycontext-slide-in-from-right-2 data-[side=right]:anycontext-slide-in-from-left-2 data-[side=top]:anycontext-slide-in-from-bottom-2 dark:anycontext-border-stone-800 dark:anycontext-bg-stone-950 dark:anycontext-text-stone-50",
+ className
+ )}
+ {...props}
+ />
+ </DropdownMenuPrimitive.Portal>
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.Item>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+ <DropdownMenuPrimitive.Item
+ ref={ref}
+ className={cn(
+ "anycontext-relative anycontext-flex anycontext-cursor-default anycontext-select-none anycontext-items-center anycontext-rounded-sm anycontext-px-2 anycontext-py-1.5 anycontext-text-sm anycontext-outline-none anycontext-transition-colors focus:anycontext-bg-stone-100 focus:anycontext-text-stone-900 data-[disabled]:anycontext-pointer-events-none data-[disabled]:anycontext-opacity-50 dark:focus:anycontext-bg-stone-800 dark:focus:anycontext-text-stone-50",
+ inset && "anycontext-pl-8",
+ className
+ )}
+ {...props}
+ />
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
+>(({ className, children, checked, ...props }, ref) => (
+ <DropdownMenuPrimitive.CheckboxItem
+ ref={ref}
+ className={cn(
+ "anycontext-relative anycontext-flex anycontext-cursor-default anycontext-select-none anycontext-items-center anycontext-rounded-sm anycontext-py-1.5 anycontext-pl-8 anycontext-pr-2 anycontext-text-sm anycontext-outline-none anycontext-transition-colors focus:anycontext-bg-stone-100 focus:anycontext-text-stone-900 data-[disabled]:anycontext-pointer-events-none data-[disabled]:anycontext-opacity-50 dark:focus:anycontext-bg-stone-800 dark:focus:anycontext-text-stone-50",
+ className
+ )}
+ checked={checked}
+ {...props}
+ >
+ <span className="anycontext-absolute anycontext-left-2 anycontext-flex anycontext-h-3.5 anycontext-w-3.5 anycontext-items-center anycontext-justify-center">
+ <DropdownMenuPrimitive.ItemIndicator>
+ <Check className="anycontext-h-4 anycontext-w-4" />
+ </DropdownMenuPrimitive.ItemIndicator>
+ </span>
+ {children}
+ </DropdownMenuPrimitive.CheckboxItem>
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
+>(({ className, children, ...props }, ref) => (
+ <DropdownMenuPrimitive.RadioItem
+ ref={ref}
+ className={cn(
+ "anycontext-relative anycontext-flex anycontext-cursor-default anycontext-select-none anycontext-items-center anycontext-rounded-sm anycontext-py-1.5 anycontext-pl-8 anycontext-pr-2 anycontext-text-sm anycontext-outline-none anycontext-transition-colors focus:anycontext-bg-stone-100 focus:anycontext-text-stone-900 data-[disabled]:anycontext-pointer-events-none data-[disabled]:anycontext-opacity-50 dark:focus:anycontext-bg-stone-800 dark:focus:anycontext-text-stone-50",
+ className
+ )}
+ {...props}
+ >
+ <span className="anycontext-absolute anycontext-left-2 anycontext-flex anycontext-h-3.5 anycontext-w-3.5 anycontext-items-center anycontext-justify-center">
+ <DropdownMenuPrimitive.ItemIndicator>
+ <Circle className="anycontext-h-2 anycontext-w-2 anycontext-fill-current" />
+ </DropdownMenuPrimitive.ItemIndicator>
+ </span>
+ {children}
+ </DropdownMenuPrimitive.RadioItem>
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.Label>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+ <DropdownMenuPrimitive.Label
+ ref={ref}
+ className={cn(
+ "anycontext-px-2 anycontext-py-1.5 anycontext-text-sm anycontext-font-semibold",
+ inset && "anycontext-pl-8",
+ className
+ )}
+ {...props}
+ />
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
+>(({ className, ...props }, ref) => (
+ <DropdownMenuPrimitive.Separator
+ ref={ref}
+ className={cn("anycontext--mx-1 anycontext-my-1 anycontext-h-px anycontext-bg-stone-100 dark:anycontext-bg-stone-800", className)}
+ {...props}
+ />
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes<HTMLSpanElement>) => {
+ return (
+ <span
+ className={cn("anycontext-ml-auto anycontext-text-xs anycontext-tracking-widest anycontext-opacity-60", className)}
+ {...props}
+ />
+ )
+}
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+}
diff --git a/apps/web/src/app/api/spaces/route.ts b/apps/web/src/app/api/spaces/route.ts
index 1e1aeba7..d6cc096b 100644
--- a/apps/web/src/app/api/spaces/route.ts
+++ b/apps/web/src/app/api/spaces/route.ts
@@ -3,6 +3,8 @@ import { sessions, space, users } from "@/server/db/schema";
import { eq } from "drizzle-orm";
import { NextRequest, NextResponse } from "next/server";
+export const runtime = "edge"
+
export async function GET(req: NextRequest) {
const token =
@@ -33,6 +35,7 @@ export async function GET(req: NextRequest) {
.from(sessions)
.where(eq(sessions.sessionToken, token!));
+
if (!sessionData || sessionData.length === 0) {
return new Response(
JSON.stringify({ message: "Invalid Key, session not found." }),
@@ -55,12 +58,14 @@ export async function GET(req: NextRequest) {
const user = userData[0]
-
const spaces = await db
.select()
.from(space)
.where(eq(space.user, user.id))
- .all()
+ .all();
+
+
+ console.log('data', spaces)
return NextResponse.json({
message: "OK",
diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx
index 419daa5a..1cbe6217 100644
--- a/apps/web/src/app/page.tsx
+++ b/apps/web/src/app/page.tsx
@@ -56,7 +56,10 @@ export default async function Home() {
const collectedSpaces = await db
.select()
.from(space)
- .where(and(eq(space.user, userData.id), not(eq(space.name, "none"))));
+ .where(eq(space.user, userData.id))
+ .all();
+
+ console.log(collectedSpaces)
// Fetch only first 3 content of each spaces
let contents: (typeof storedContent.$inferSelect)[] = [];
diff --git a/apps/web/src/server/db/test.ts b/apps/web/src/server/db/test.ts
new file mode 100644
index 00000000..9cb8f2b5
--- /dev/null
+++ b/apps/web/src/server/db/test.ts
@@ -0,0 +1,10 @@
+import { db } from "."
+import { space, user } from "./schema"
+
+const user = await db.select(user).all()
+
+await db.insert(space).values([
+ {
+
+ }
+])
diff --git a/apps/web/types/memory.tsx b/apps/web/types/memory.tsx
index ff0dc94c..287f763c 100644
--- a/apps/web/types/memory.tsx
+++ b/apps/web/types/memory.tsx
@@ -5,7 +5,7 @@ import {
storedContent,
StoredContent,
} from "@/server/db/schema";
-import { asc, and, eq, inArray, notExists } from "drizzle-orm";
+import { asc, and, eq, inArray, notExists, sql, exists } from "drizzle-orm";
export async function fetchContentForSpace(
spaceId: number,
@@ -19,9 +19,8 @@ export async function fetchContentForSpace(
.select()
.from(storedContent)
.where(
- inArray(
- storedContent.id,
- db.select().from(space).where(eq(space.id, spaceId)),
+ exists(
+ db.select().from(contentToSpace).where(and(eq(contentToSpace.spaceId, spaceId), eq(contentToSpace.contentId, storedContent.id))),
),
).orderBy(asc(storedContent.title))