From cea30e3706b6a6e6ee2f1d83b5be16182af5ab54 Mon Sep 17 00:00:00 2001 From: Benjamin Leonard Date: Tue, 17 Dec 2024 14:57:02 +0000 Subject: [PATCH] Continued cleanup --- app/components/AsciidocBlocks/Document.tsx | 8 +- app/components/note/Editor.tsx | 73 +----- app/components/note/NoteForm.tsx | 167 +++----------- app/components/note/Sidebar.tsx | 32 +-- app/routes/notes_.$id.delete.tsx | 4 +- app/routes/notes_.$id.tsx | 20 +- app/routes/notes_.$id_.edit.tsx | 9 +- app/routes/notes_._index.tsx | 13 +- app/routes/notes_.create-rfd.tsx | 85 ------- app/routes/notes_.new.tsx | 6 +- app/routes/notes_.tsx | 4 +- app/routes/rfd.$slug.tsx | 2 +- app/styles/index.css | 12 - notes/bun.lockb | Bin 8290 -> 8674 bytes notes/db/note.db | 0 notes/package.json | 1 + package-lock.json | 247 +++++++++++++++++++++ package.json | 5 +- 18 files changed, 329 insertions(+), 359 deletions(-) delete mode 100644 app/routes/notes_.create-rfd.tsx delete mode 100644 notes/db/note.db diff --git a/app/components/AsciidocBlocks/Document.tsx b/app/components/AsciidocBlocks/Document.tsx index 7a73802..c1dfde7 100644 --- a/app/components/AsciidocBlocks/Document.tsx +++ b/app/components/AsciidocBlocks/Document.tsx @@ -9,16 +9,14 @@ import { useDelegatedReactRouterLinks } from '@oxide/design-system/components/di import { Content, type DocumentBlock } from '@oxide/react-asciidoc' import { useRef } from 'react' +// add styles for main +// max-w-full flex-shrink overflow-hidden 800:overflow-visible 800:pr-10 1200:w-[calc(100%-var(--toc-width))] 1200:pr-16 print:p-0 const CustomDocument = ({ document }: { document: DocumentBlock }) => { let ref = useRef(null) useDelegatedReactRouterLinks(ref, document.title) return ( -
+
) diff --git a/app/components/note/Editor.tsx b/app/components/note/Editor.tsx index 5d3ad6a..0a27f57 100644 --- a/app/components/note/Editor.tsx +++ b/app/components/note/Editor.tsx @@ -11,7 +11,7 @@ const EditorWrapper = ({ onChange, }: { body: string - onChange: (string) => void + onChange: (string: string | undefined) => void }) => { const monaco = useMonaco() @@ -37,69 +37,20 @@ const EditorWrapper = ({ ) } export default EditorWrapper - -// import loader from '@monaco-editor/loader' -// import { shikiToMonaco } from '@shikijs/monaco' -// import { type editor } from 'monaco-editor' -// import type * as Monaco from 'monaco-editor/esm/vs/editor/editor.api' -// import { useCallback, useEffect, useRef, useState } from 'react' -// import { getHighlighter } from 'shiki' - -// const Editor = () => { -// const containerRef = useRef(null) -// const monacoRef = useRef(null) -// const [isMonacoMounting, setIsMonacoMounting] = useState(true) -// const editorRef = useRef(null) -// const preventCreation = useRef(false) -// const [isEditorReady, setIsEditorReady] = useState(false) - -// useEffect(() => { -// const cancelable = loader.init() - -// cancelable -// .then((monaco) => (monacoRef.current = monaco) && setIsMonacoMounting(false)) -// .catch( -// (error) => -// error?.type !== 'cancelation' && -// console.error('Monaco initialization: error:', error), -// ) - -// return () => (editorRef.current ? editorRef.current!.dispose() : cancelable.cancel()) -// }, [containerRef]) - -// const createEditor = useCallback(() => { -// if (!containerRef.current || !monacoRef.current) return -// if (!preventCreation.current) { -// editorRef.current = monacoRef.current?.editor.create(containerRef.current, { -// automaticLayout: true, -// }) - -// monacoRef.current.editor.setTheme('vs-dark') - -// setIsEditorReady(true) -// preventCreation.current = true -// } -// }, []) - -// useEffect(() => { -// !isMonacoMounting && !isEditorReady && createEditor() -// }, [isMonacoMounting, isEditorReady, createEditor]) - -// console.log(monacoRef, containerRef) - -// return ( -//
-//
-//
-// ) -// } - -// export default Editor diff --git a/app/components/note/NoteForm.tsx b/app/components/note/NoteForm.tsx index e145464..876f935 100644 --- a/app/components/note/NoteForm.tsx +++ b/app/components/note/NoteForm.tsx @@ -5,38 +5,26 @@ * * Copyright Oxide Computer Company */ -import { useDialogStore, type DialogStore } from '@ariakit/react' -// import { StreamLanguage } from '@codemirror/language' -// import { EditorView } from '@codemirror/view' -// import Editor from '@monaco-editor/react' -import Asciidoc, { asciidoctor } from '@oxide/react-asciidoc' +import { Spinner } from '@oxide/design-system' +import { Asciidoc, prepareDocument } from '@oxide/react-asciidoc' import * as Dropdown from '@radix-ui/react-dropdown-menu' import { useFetcher, useLoaderData } from '@remix-run/react' -// import CodeMirror, { basicSetup, type ReactCodeMirrorRef } from '@uiw/react-codemirror' -import cn from 'classnames' -// import { asciidoc } from 'codemirror-asciidoc' import dayjs from 'dayjs' -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { opts } from '~/components/AsciidocBlocks' import { DropdownItem, DropdownLink, DropdownMenu } from '~/components/Dropdown' import Icon from '~/components/Icon' -// import { editorTheme } from '~/components/note/EditorTheme' import { useDebounce } from '~/hooks/use-debounce' -import { useRootLoaderData } from '~/root' +import { ad } from '~/utils/asciidoctor' -import { MinimalDocument } from '../AsciidocBlocks/MinimalDocument' -import Modal from '../Modal' -import Spinner from '../Spinner' -import { TextInput } from '../TextInput' import EditorWrapper from './Editor' import { SidebarIcon } from './Sidebar' -const ad = asciidoctor() - type EditorStatus = 'idle' | 'unsaved' | 'saving' | 'saved' | 'error' export const NoteForm = ({ + id, initialTitle = '', initialBody = '', updated, @@ -46,6 +34,7 @@ export const NoteForm = ({ sidebarOpen, setSidebarOpen, }: { + id: string initialTitle?: string initialBody?: string updated: string @@ -58,13 +47,10 @@ export const NoteForm = ({ const [status, setStatus] = useState('idle') const [body, setBody] = useState(initialBody) const [title, setTitle] = useState(initialTitle) - const inputRef = useRef(null) const debouncedBody = useDebounce(body, 750) const debouncedTitle = useDebounce(title, 750) - const createRfdDialog = useDialogStore() - useEffect(() => { const hasChanges = body !== initialBody || title !== initialTitle @@ -129,19 +115,21 @@ export const NoteForm = ({ ) const doc = useMemo(() => { - return ad.load(body, { - standalone: true, - sourcemap: true, - attributes: { - sectnums: false, - }, - }) + return prepareDocument( + ad.load(body, { + standalone: true, + sourcemap: true, + attributes: { + sectnums: false, + }, + }), + ) }, [body]) return ( <> -
+
- + {fetcher.data?.status === 'error' && (
{fetcher.data.error}
@@ -203,19 +191,10 @@ export const NoteForm = ({ width: `calc(${100 - leftPaneWidth}% - 2px)`, }} > - +
- ) } @@ -236,7 +215,7 @@ const SavingIndicator = ({ updated: string }) => { return ( -
+
{dayjs(updated).format('MMM D YYYY, h:mm A')} {status === 'unsaved' ? ( @@ -247,23 +226,22 @@ const SavingIndicator = ({ ) : status === 'saving' ? ( ) : ( - + )}
) } -const MoreDropdown = ({ dialog }: { dialog: DialogStore }) => { - const note = useLoaderData() +const MoreDropdown = ({ id, published }: { id: string; published: 1 | 0 }) => { const fetcher = useFetcher() const handleDelete = () => { if (window.confirm('Are you sure you want to delete this note?')) { fetcher.submit( - { id: note.id }, + { id: id }, { method: 'post', - action: `/notes/${note.id}/delete`, + action: `/notes/${id}/delete`, encType: 'application/x-www-form-urlencoded', }, ) @@ -271,7 +249,7 @@ const MoreDropdown = ({ dialog }: { dialog: DialogStore }) => { } const handlePublish = async () => { - const isPublished = note.published === 1 + const isPublished = published === 1 const confirmationMessage = isPublished ? 'Are you sure you want to unpublish this note?' : 'Are you sure you want to publish this note?' @@ -281,7 +259,7 @@ const MoreDropdown = ({ dialog }: { dialog: DialogStore }) => { { publish: isPublished ? 0 : 1 }, { method: 'post', - action: `/notes/${note.id}/publish`, + action: `/notes/${id}/publish`, encType: 'application/json', }, ) @@ -291,20 +269,13 @@ const MoreDropdown = ({ dialog }: { dialog: DialogStore }) => { return ( - + - View + View - {note.published ? 'Unpublish' : 'Publish'} - - { - dialog.setOpen(true) - }} - > - Create RFD from note + {published ? 'Unpublish' : 'Publish'} Delete @@ -313,83 +284,3 @@ const MoreDropdown = ({ dialog }: { dialog: DialogStore }) => { ) } - -const CreateRfdModal = ({ - initialTitle = '', - dialog, - body, -}: { - initialTitle?: string - dialog: DialogStore - body: string -}) => { - const [title, setTitle] = useState(initialTitle) - const newRfdNumber = useRootLoaderData().newRfdNumber - const fetcher = useFetcher() - - const handleSubmit = () => { - fetcher.submit( - { title, body }, - { - method: 'post', - action: `/notes/create-rfd`, - encType: 'application/json', - }, - ) - } - - const formDisabled = fetcher.state !== 'idle' - - return ( - - - setTitle(el.target.value)} - disabled={formDisabled} - /> - -
-          {`:state: prediscussion 
-:discussion:
-:authors:
-
-`}
-          = RFD {newRfdNumber} {title ? title : '{title}'}
-          {`
-
-`}
-          {body}
-          
-
- {fetcher.type === 'done' && !fetcher.data.ok && fetcher.data.message && ( -
- {fetcher.data.message} -
- )} -
-
- ) -} diff --git a/app/components/note/Sidebar.tsx b/app/components/note/Sidebar.tsx index d58e721..5111aa9 100644 --- a/app/components/note/Sidebar.tsx +++ b/app/components/note/Sidebar.tsx @@ -4,7 +4,7 @@ import cn from 'classnames' import { type ReactNode } from 'react' import Icon from '~/components/Icon' -import { type NoteItem } from '~/routes/note_' +import { type NoteItem } from '~/routes/notes_' const navLinkStyles = ({ isActive }: { isActive: boolean }) => { const activeStyle = isActive @@ -38,36 +38,22 @@ export const SidebarIcon = () => ( export const Sidebar = () => { const matches = useMatches() - const notes = matches[1].data.notes as NoteItem[] + const notes = matches && matches[1] && (matches[1].data.notes as NoteItem[]) return ( -