fix: link (#115)

* start

* .

* seeding connections

* .

* wip

* wip: learning state

* wip: notes section

* wip: many

* topics

* chore: update schema

* update package

* update sidebar

* update page section

* feat: profile

* fix: remove z index

* fix: wrong type

* add avatar

* add avatar

* wip

* .

* store page section key

* remove atom page section

* fix rerender

* fix rerender

* fix rerender

* fix rerender

* fix link

* search light/dark mode

* bubble menu ui

* .

* fix: remove unecessary code

* chore: mark as old for old schema

* chore: adapt new schema

* fix: add topic schema but null for now

* fix: add icon on personal link

* fix: list item

* fix: set url fetched when editing

* fix: remove image

* feat: add icon to link

* feat: custom url zod validation

* fix: metadata test

* chore: update utils

* fix: link

* fix: url fetcher

* .

* .

* fix: add link, section

* chore: seeder

* .

* .

* .

* .

* fix: change checkbox to learning state

* fix: click outside editing form

* feat: constant

* chore: move to master folder

* chore: adapt new schema

* chore: cli for new schema

* fix: new schema for dev seed

* fix: seeding

* update package

* chore: forcegraph seed

* bottombar

* if isEdit delete icon

* showCreate X button

* .

* options

* chore: implement topic from public global group

* chore: update learning state

* fix: change implementation for outside click

* chore: implement new form param

* chore: update env example

* feat: link form refs exception

* new page button layout, link topic search fixed

* chore: enable topic

* chore: update seed

* profile

* chore: move framer motion package from root to web and add nuqs

* chore: add LearningStateValue

* chore: implement active state

* profile

* chore: use fancy switch and update const

* feat: filter implementation

* dropdown menu

* .

* sidebar topics

* topic selected color

* feat: topic detail

* fix: collapsible page

* pages - sorted by, layout, visible mode

* .

* .

* .

* topic status sidebar

* topic button and count

* fix: topic

* page delete/topic buttons

* search ui

* selected topic for page

* selected topic status sidebar

* removed footer

* update package

* .

---------

Co-authored-by: Nikita <github@nikiv.dev>
Co-authored-by: marshennikovaolga <marshennikova@gmail.com>
Co-authored-by: Kisuyo <ig.intr3st@gmail.com>
This commit is contained in:
Aslam
2024-08-26 19:35:00 +07:00
committed by GitHub
parent 7cbfcc705b
commit 2d270706a5
77 changed files with 3002 additions and 1327 deletions

View File

@@ -1,18 +1,26 @@
"use client"
import React, { useCallback, useRef, useEffect } from "react"
import { LAEditor, LAEditorRef } from "@/components/la-editor"
// import { DetailPageHeader } from "./header" //dont need. check figma
import * as React from "react"
import { useAtom } from "jotai"
import { ID } from "jazz-tools"
import { PersonalPage } from "@/lib/schema/personal-page"
import { PersonalPage, Topic } from "@/lib/schema"
import { useCallback, useRef, useEffect, useState } from "react"
import { LAEditor, LAEditorRef } from "@/components/la-editor"
import { Content, EditorContent, useEditor } from "@tiptap/react"
import { StarterKit } from "@/components/la-editor/extensions/starter-kit"
import { Paragraph } from "@/components/la-editor/extensions/paragraph"
import { useAccount, useCoState } from "@/lib/providers/jazz-provider"
import { toast } from "sonner"
import { EditorView } from "prosemirror-view"
import { EditorView } from "@tiptap/pm/view"
import { Editor } from "@tiptap/core"
import { generateUniqueSlug } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { LaIcon } from "@/components/custom/la-icon"
import { pageTopicSelectorAtom } from "@/store/page"
import { TopicSelector } from "@/components/routes/link/form/partial/topic-selector"
import DeletePageModal from "@/components/custom/delete-modal"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"
const TITLE_PLACEHOLDER = "Page title"
@@ -25,7 +33,6 @@ export function DetailPageWrapper({ pageId }: { pageId: string }) {
<div className="flex flex-row">
<div className="flex h-full w-full">
<div className="relative flex min-w-0 grow basis-[760px] flex-col">
{/* <DetailPageHeader pageId={pageId as ID<PersonalPage>} /> */}
<DetailPageForm page={page} />
</div>
</div>
@@ -33,11 +40,13 @@ export function DetailPageWrapper({ pageId }: { pageId: string }) {
)
}
const DetailPageForm = ({ page }: { page: PersonalPage }) => {
export const DetailPageForm = ({ page }: { page: PersonalPage }) => {
const { me } = useAccount()
const titleEditorRef = useRef<Editor | null>(null)
const contentEditorRef = useRef<LAEditorRef>(null)
const [, setTopicSelectorOpen] = useAtom(pageTopicSelectorAtom)
const [selectedPageTopic, setSelectedPageTopic] = useState<Topic | null>(page.topic || null)
const [deleteModalOpen, setDeleteModalOpen] = useState(false)
const updatePageContent = (content: Content, model: PersonalPage) => {
model.content = content
@@ -59,11 +68,11 @@ const DetailPageForm = ({ page }: { page: PersonalPage }) => {
const personalPages = me.root?.personalPages?.toJSON() || []
const slug = generateUniqueSlug(personalPages, page.slug)
const capitalizedTitle = newTitle.charAt(0).toUpperCase() + newTitle.slice(1)
page.title = capitalizedTitle
const trimmedTitle = editor.getText().trim()
page.title = trimmedTitle
page.slug = slug
editor.commands.setContent(capitalizedTitle)
editor.commands.setContent(trimmedTitle)
}
const handleTitleKeyDown = useCallback((view: EditorView, event: KeyboardEvent) => {
@@ -74,44 +83,29 @@ const DetailPageForm = ({ page }: { page: PersonalPage }) => {
const { selection } = state
const { $anchor } = selection
switch (event.key) {
case "ArrowRight":
case "ArrowDown":
if ($anchor.pos === state.doc.content.size - 1) {
event.preventDefault()
contentEditorRef.current?.editor?.commands.focus("start")
return true
}
break
case "Enter":
if (!event.shiftKey) {
event.preventDefault()
contentEditorRef.current?.editor?.commands.focus("start")
return true
}
break
}
return false
}, [])
const handleContentKeyDown = useCallback((view: EditorView, event: KeyboardEvent) => {
const editor = contentEditorRef.current?.editor
if (!editor) return false
const { state } = editor
const { selection } = state
const { $anchor } = selection
if ((event.key === "ArrowLeft" || event.key === "ArrowUp") && $anchor.pos - 1 === 0) {
event.preventDefault()
titleEditorRef.current?.commands.focus("end")
return true
}
return false
}, [])
const handleContentKeyDown = useCallback((view: EditorView, event: KeyboardEvent) => {
const editor = contentEditorRef.current?.editor
if (!editor) return false
const { state } = editor
const { selection } = state
const { $anchor } = selection
return false
}, [])
const confirmDelete = (page: PersonalPage) => {
console.log("Deleting page:", page.id)
setDeleteModalOpen(false)
//TODO: add delete logic
}
const titleEditor = useEditor({
immediatelyRender: false,
extensions: [
@@ -159,11 +153,28 @@ const DetailPageForm = ({ page }: { page: PersonalPage }) => {
<div tabIndex={0} className="relative flex grow flex-col overflow-y-auto">
<div className="relative mx-auto flex h-full w-[calc(100%-40px)] shrink-0 grow flex-col sm:w-[calc(100%-80px)]">
<form className="flex shrink-0 flex-col">
<div className="mb-2 mt-8 py-1.5">
<div className="mb-2 mt-8 flex flex-row justify-between py-1.5">
<EditorContent
editor={titleEditor}
className="la-editor cursor-text select-text text-2xl font-semibold leading-[calc(1.33333)] tracking-[-0.00625rem]"
/>
<div className="items-center space-x-4">
<TopicSelector
onSelect={topic => {
page.topic = topic
setSelectedPageTopic(topic)
setTopicSelectorOpen(false)
}}
/>
<Button
type="button"
variant="secondary"
className="text-foreground bg-truncat"
onClick={() => setDeleteModalOpen(true)}
>
<LaIcon name="Trash" className="h-4 w-4" />
</Button>
</div>
</div>
<div className="flex flex-auto flex-col">
<div className="relative flex h-full max-w-full grow flex-col items-stretch p-0">
@@ -183,6 +194,15 @@ const DetailPageForm = ({ page }: { page: PersonalPage }) => {
</div>
</form>
</div>
<DeletePageModal
isOpen={deleteModalOpen}
onClose={() => setDeleteModalOpen(false)}
onConfirm={() => {
confirmDelete(page)
}}
title={page.title.charAt(0).toUpperCase() + page.title.slice(1)}
/>
</div>
)
}