Skip to content

Commit

Permalink
Merge pull request #249 from afspeirs/feat/add-folder-support
Browse files Browse the repository at this point in the history
feat: add folder support
  • Loading branch information
afspeirs authored Jan 28, 2024
2 parents e1793f5 + 9957af9 commit c6f16a9
Show file tree
Hide file tree
Showing 17 changed files with 596 additions and 103 deletions.
128 changes: 126 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"update": "npm run outdated -- -u"
},
"dependencies": {
"@headlessui-float/react": "^0.13.1",
"@headlessui/react": "^1.7.17",
"@headlessui/tailwindcss": "^0.2.0",
"@heroicons/react": "^2.0.18",
Expand Down
3 changes: 3 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export async function initialise() {
favourite: {
type: 'boolean',
},
folder: {
type: 'string',
},
id: {
type: 'string',
maxLength: 100, // <- the primary key must have set maxLength
Expand Down
10 changes: 10 additions & 0 deletions src/api/notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ export async function importNotes(collection: NoteCollection, files: Partial<Not
await collection.bulkInsert(notes);
}

export async function moveNote(note: NoteDocument, newFolder: string) {
await note?.patch({
date_modified: new Date().toISOString(),
folder: newFolder,
})
.then((note2) => toast(`"${getTitle(note.text)}" ${note2?.folder ? `moved to "${note2.folder}"` : 'removed from folder'}`, {
id: `move-${note2.id}`,
}));
}

export async function updateNote(note: NoteDocument, text: string) {
await note?.patch({
date_modified: new Date().toISOString(),
Expand Down
1 change: 1 addition & 0 deletions src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type NoteDocType = {
date_created: string,
date_modified: string,
favourite?: boolean,
folder?: string,
id: string,
text: string,
};
Expand Down
74 changes: 74 additions & 0 deletions src/components/FolderList/FolderListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Disclosure } from '@headlessui/react';
import { ChevronUpIcon } from '@heroicons/react/24/outline';
import { useAtomValue } from 'jotai';
import { useCallback } from 'react';
import { useRxData, type QueryConstructor } from 'rxdb-hooks';

import { type NoteDocType } from '@/api/types';
import { Button } from '@/components/Button';
// import { FolderContextMenu } from './FolderContextMenu';
import { NotesList } from '@/components/NotesList';
import { notesSearchAtom } from '@/context/notesSearch';
import { notesSortAtom, notesSortOptions } from '@/context/notesSort';
import { classNames } from '@/utils/classNames';
import type { FolderListItemProps } from './types';

export function FolderListItem({
folder,
}: FolderListItemProps) {
const search = useAtomValue(notesSearchAtom);
const sort = useAtomValue(notesSortAtom);
const notesQuery: QueryConstructor<NoteDocType> = useCallback(
(collection) => collection.find({
selector: {
folder: {
$eq: folder,
},
text: {
$regex: RegExp(search, 'i'),
},
},
sort: notesSortOptions[sort].value,
}),
[folder, search, sort],
);

const { result: notes, isFetching } = useRxData<NoteDocType>('notes', notesQuery);
return (
<li
key={folder}
className="group/folder-context-menu relative flex flex-col"
onContextMenu={(event) => event.preventDefault()}
>
<Disclosure>
{({ open }) => (
<>
<Disclosure.Button
as={Button}
secondaryAction={(
<ChevronUpIcon
className={classNames(
'h-6 w-6 transform transition-transform',
open ? 'rotate-180' : 'rotate-90',
)}
aria-hidden="true"
/>
)}
>
{folder}
</Disclosure.Button>
<Disclosure.Panel
className="w-full pl-8"
>
<NotesList
notes={notes}
isFetching={isFetching}
padding={false}
/>
</Disclosure.Panel>
</>
)}
</Disclosure>
</li>
);
}
61 changes: 61 additions & 0 deletions src/components/FolderList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useAtom, useAtomValue } from 'jotai';
import { useCallback, useEffect, useRef } from 'react';
import { ViewportList } from 'react-viewport-list';
import { useRxData, type QueryConstructor } from 'rxdb-hooks';

import type { NoteDocType } from '@/api/types';
import { foldersAtom } from '@/context/folders';
import { notesSearchAtom } from '@/context/notesSearch';
import { notesSortAtom, notesSortOptions } from '@/context/notesSort';
import { FolderListItem } from './FolderListItem';

export function FolderList() {
const ref = useRef<HTMLUListElement | null>(null);
// const setFolders = useSetAtom(foldersAtom);
const [folders, setFolders] = useAtom(foldersAtom);
const search = useAtomValue(notesSearchAtom);
const sort = useAtomValue(notesSortAtom);
const notesQuery: QueryConstructor<NoteDocType> = useCallback(
(collection) => collection.find({
selector: {
folder: {
$exists: true,
},
text: {
$regex: RegExp(search, 'i'),
},
},
sort: notesSortOptions[sort].value,
}),
[search, sort],
);

const { result: notes, isFetching } = useRxData<NoteDocType>('notes', notesQuery);

useEffect(() => {
const allFolders = notes.map((note) => note.folder ?? '').filter(Boolean);
const newFolders = [...new Set(allFolders)].sort();
// console.log(newFolders);
setFolders(newFolders);
}, [notes, setFolders]);

return (
<ul
role="list"
className="flex flex-col overflow-y-auto overflow-x-hidden mb-1"
ref={ref}
>
{isFetching && (
<li className="block p-3">Loading...</li>
)}
<ViewportList
viewportRef={ref}
items={folders}
>
{/* TODO: Maybe I should be passing this through to query the database less? */}
{/* // folderNotes={notes.filter((note) => note.folder === folder)} */}
{(folder) => <FolderListItem key={folder} folder={folder} />}
</ViewportList>
</ul>
);
}
8 changes: 8 additions & 0 deletions src/components/FolderList/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// import type { RxDocument } from 'rxdb';

// import type { NoteDocType } from '@/api/types';

export type FolderListItemProps = {
folder: string,
// folderNotes: RxDocument<NoteDocType>[],
};
Loading

0 comments on commit c6f16a9

Please sign in to comment.