From f2a4ccd21329ca0ec3b913d390828f7b4e2ac1b4 Mon Sep 17 00:00:00 2001 From: Dinesh Singh Date: Sat, 6 May 2023 22:50:39 +0530 Subject: [PATCH 1/5] Move Blocks In Views, Add New Block In View --- apps/webapp/src/App.tsx | 7 +- .../CreateTodoModal/TaskEditor/styled.tsx | 11 +- .../src/Components/Editor/Banner/styled.tsx | 7 + .../src/Components/Editor/ContentEditor.tsx | 23 ++- .../FleetContainer/useOnNewItem.tsx | 29 ++-- apps/webapp/src/Components/Modals.tsx | 7 +- .../src/Components/Modals/CreateTodoModal.tsx | 129 +++++++++++++-- .../Modals/DeleteSpaceModal/index.tsx | 10 +- .../src/Components/PreviewNoteModal/index.tsx | 20 ++- .../src/Components/Refactor/DeleteModal.tsx | 1 - apps/webapp/src/Components/TaskHeader.tsx | 41 +++++ .../src/Components/Todo/PrioritySelect.tsx | 3 +- apps/webapp/src/Components/Todo/Todo.tsx | 7 +- .../Views/ViewRenderer/KanbanView.tsx | 153 +++++++++++++----- .../src/Editor/Components/Combobox/index.tsx | 9 +- .../MultiCombobox/useMultiComboboxChange.ts | 1 - .../webapp/src/Editor/Hooks/useUpdateBlock.ts | 57 +++++-- apps/webapp/src/Hooks/API/useNodeAPI.ts | 27 +++- apps/webapp/src/Hooks/todo/useTodoKanban.ts | 22 ++- apps/webapp/src/Hooks/useOnUnload.ts | 3 + apps/webapp/src/Hooks/useSearch.ts | 8 + apps/webapp/src/Utils/convertValueToTasks.ts | 20 ++- apps/webapp/src/Views/ViewPage/index.tsx | 9 ++ apps/webapp/src/Workers/controller.ts | 10 ++ apps/webapp/src/Workers/search.ts | 20 ++- libs/core/src/API/Node.ts | 4 + libs/core/src/Stores/buffer.store.ts | 2 +- libs/core/src/Stores/content.store.ts | 2 +- libs/core/src/Stores/todo.store.ts | 27 +++- libs/core/src/Types/Search.ts | 8 + libs/core/src/Utils/dataTransform.ts | 2 + libs/core/src/Utils/routes.ts | 1 + .../src/Components/AIPreview/styled.tsx | 2 +- .../FloatingElements/Dropdown.style.tsx | 4 +- .../Components/FloatingElements/Dropdown.tsx | 12 ++ libs/shared/src/Components/Icons.tsx | 2 +- libs/shared/src/Components/InsertMenu.tsx | 42 ++++- 37 files changed, 607 insertions(+), 135 deletions(-) diff --git a/apps/webapp/src/App.tsx b/apps/webapp/src/App.tsx index 4f32e64b8..a8e21933f 100644 --- a/apps/webapp/src/App.tsx +++ b/apps/webapp/src/App.tsx @@ -13,6 +13,7 @@ import FloatingButton from './Components/FloatingButton' import Init from './Components/Init' import Main from './Components/Main' import Modals from './Components/Modals' +import { createViewFilterStore, ViewFilterProvider } from './Hooks/todo/useTodoFilters' import { useForceLogout } from './Stores/useAuth' import GlobalStyle from './Style/GlobalStyle' import Switch from './Switch' @@ -38,8 +39,10 @@ const AutoThemeSwitch = () => { const Providers: React.FC<{ children: React.ReactNode }> = ({ children }) => { return ( - - {children} + + + {children} + ) } diff --git a/apps/webapp/src/Components/CreateTodoModal/TaskEditor/styled.tsx b/apps/webapp/src/Components/CreateTodoModal/TaskEditor/styled.tsx index 3ff8b4d9d..9fe0c4039 100644 --- a/apps/webapp/src/Components/CreateTodoModal/TaskEditor/styled.tsx +++ b/apps/webapp/src/Components/CreateTodoModal/TaskEditor/styled.tsx @@ -4,8 +4,14 @@ import { CheckBoxWrapper, EditorStyles } from '@mexit/shared' import { ModalSection } from '../../../Style/Refactor' -export const TaskEditorWrapper = styled.section` - padding: ${({ theme }) => theme.spacing.small}; +export const TaskEditorWrapper = styled.section<{ withMaxHeight?: boolean }>` + padding: ${({ theme }) => theme.spacing.medium}; + border-radius: ${({ theme }) => theme.borderRadius.small}; + background: ${({ theme }) => theme.tokens.surfaces.app}; + margin: ${({ theme }) => theme.spacing.large} 0; + ${({ withMaxHeight }) => withMaxHeight && `height: 22vh;`} + max-height: 24vh; + overflow: hidden auto; ` export const TaskEditorStyle = styled(EditorStyles)` @@ -20,6 +26,7 @@ export const TaskEditorStyle = styled(EditorStyles)` export const ScrollableModalSection = styled(ModalSection)` width: 40vw; + min-width: 600px; max-height: 50vh; ${CheckBoxWrapper} { diff --git a/apps/webapp/src/Components/Editor/Banner/styled.tsx b/apps/webapp/src/Components/Editor/Banner/styled.tsx index 0958ff17d..46a2f2a5e 100644 --- a/apps/webapp/src/Components/Editor/Banner/styled.tsx +++ b/apps/webapp/src/Components/Editor/Banner/styled.tsx @@ -15,3 +15,10 @@ export const Group = styled.span` align-items: center; gap: ${({ theme }) => theme.spacing.small}; ` + +export const MediaGroup = styled(Group)` + @media (max-width: 1000px) { + flex-direction: column; + align-items: flex-start; + } +` diff --git a/apps/webapp/src/Components/Editor/ContentEditor.tsx b/apps/webapp/src/Components/Editor/ContentEditor.tsx index 0e50af7a3..126bf4916 100644 --- a/apps/webapp/src/Components/Editor/ContentEditor.tsx +++ b/apps/webapp/src/Components/Editor/ContentEditor.tsx @@ -21,7 +21,6 @@ import { EditorWrapper, isOnEditableElement } from '@mexit/shared' import { useComboboxOpen } from '../../Editor/Hooks/useComboboxOpen' import { useApi } from '../../Hooks/API/useNodeAPI' -import { createViewFilterStore, ViewFilterProvider } from '../../Hooks/todo/useTodoFilters' import { useKeyListener } from '../../Hooks/useChangeShortcutListener' import { useComments } from '../../Hooks/useComments' import { useBufferStore, useEditorBuffer } from '../../Hooks/useEditorBuffer' @@ -169,18 +168,16 @@ const ContentEditor = () => { return ( - - - + ) } diff --git a/apps/webapp/src/Components/FleetContainer/useOnNewItem.tsx b/apps/webapp/src/Components/FleetContainer/useOnNewItem.tsx index c2a07a7e6..42c3a3006 100644 --- a/apps/webapp/src/Components/FleetContainer/useOnNewItem.tsx +++ b/apps/webapp/src/Components/FleetContainer/useOnNewItem.tsx @@ -27,13 +27,6 @@ import { useSnippets } from '../../Hooks/useSnippets' import { useTaskFromSelection } from '../../Hooks/useTaskFromSelection' export const useOnNewItem = () => { - const ICONS = { - snippet: 'ri:quill-pen-line', - note: 'ri:file-list-2-line', - space: 'heroicons-outline:view-grid', - todo: 'ri:task-line' - } - const loadSnippet = useSnippetStore((store) => store.loadSnippet) const changeSpace = useUserPreferenceStore((store) => store.setActiveNamespace) @@ -66,6 +59,12 @@ export const useOnNewItem = () => { openModal(ModalsType.todo, todo) } + const onNewContent = () => { + openModal(ModalsType.todo, { + type: 'content' + }) + } + const onNewSnippet = () => { const snippetId = generateSnippetId() const snippetName = generateName().dashed @@ -107,12 +106,12 @@ export const useOnNewItem = () => { }) } - const getQuickNewItems = () => { + const getQuickNewItems = (withMIcon = false) => { const data = { note: { id: 0, name: 'New Note', - icon: ICONS.note, + icon: withMIcon ? DefaultMIcons.NOTE : DefaultMIcons.NOTE.value, onSelect: () => { const activeNamesapce = useUserPreferenceStore.getState().activeNamespace const spaceId = activeNamesapce ?? getDefaultNamespaceId() @@ -123,20 +122,26 @@ export const useOnNewItem = () => { space: { id: 1, name: 'New Space', - icon: ICONS.space, + icon: withMIcon ? DefaultMIcons.SPACE : DefaultMIcons.SPACE.value, onSelect: onNewSpace }, task: { id: 2, name: 'New Task', - icon: ICONS.todo, + icon: withMIcon ? DefaultMIcons.TASK : DefaultMIcons.TASK.value, onSelect: onNewTask }, snippet: { id: 3, name: 'New Snippet', - icon: ICONS.snippet, + icon: withMIcon ? DefaultMIcons.SNIPPET : DefaultMIcons.SNIPPET.value, onSelect: onNewSnippet + }, + content: { + id: 4, + name: 'New Content', + icon: withMIcon ? DefaultMIcons.TEXT : DefaultMIcons.TEXT.value, + onSelect: onNewContent } } diff --git a/apps/webapp/src/Components/Modals.tsx b/apps/webapp/src/Components/Modals.tsx index 8ad8031da..a007aaff0 100644 --- a/apps/webapp/src/Components/Modals.tsx +++ b/apps/webapp/src/Components/Modals.tsx @@ -4,11 +4,10 @@ import BlockModal from '../Editor/Components/Blocks/BlockModal' import HelpModal from '../Views/HelpModal' import ShareModal from './Mentions/ShareModal' -import CreateTodoModal from './Modals/CreateTodoModal' +import CreateTodoModal, { CreateNewSection } from './Modals/CreateTodoModal' import DeleteSpaceModal from './Modals/DeleteSpaceModal' import Lookup from './Modals/Lookup' import MangeSpacesModal from './Modals/ManageSpacesModal' -// import Refactor from './Refactor' import Delete from './Refactor/DeleteModal' import CreateReminderModal from './Reminders/CreateReminderModal' import TemplateModal from './Template/TemplateModal' @@ -28,7 +27,9 @@ const Modals = () => { - + + + diff --git a/apps/webapp/src/Components/Modals/CreateTodoModal.tsx b/apps/webapp/src/Components/Modals/CreateTodoModal.tsx index 9146ba379..36a72a077 100644 --- a/apps/webapp/src/Components/Modals/CreateTodoModal.tsx +++ b/apps/webapp/src/Components/Modals/CreateTodoModal.tsx @@ -3,25 +3,36 @@ import toast from 'react-hot-toast' import Modal from 'react-modal' import { getPlateEditorRef, PlateProvider } from '@udecode/plate' +import { useTheme } from 'styled-components' import { Button, DisplayShortcut, LoadingButton } from '@workduck-io/mex-components' import { tinykeys } from '@workduck-io/tinykeys' -import { ModalsType, mog, useModalStore } from '@mexit/core' +import { getDefaultContent, ModalsType, mog, useModalStore } from '@mexit/core' +import { DefaultMIcons, IconDisplay, InsertMenu, PrimaryText } from '@mexit/shared' import useUpdateBlock from '../../Editor/Hooks/useUpdateBlock' import { useApi } from '../../Hooks/API/useNodeAPI' -import { ModalControls, ModalHeader } from '../../Style/Refactor' +import { useCreateNewNote } from '../../Hooks/useCreateNewNote' +import { ModalControls } from '../../Style/Refactor' import TaskEditor from '../CreateTodoModal/TaskEditor' import { ScrollableModalSection, TaskEditorWrapper } from '../CreateTodoModal/TaskEditor/styled' +import { Group } from '../Editor/Banner/styled' +import Editor from '../Editor/Editor' -const CreateTodoModal = () => { +import { DeletionWarning, Header, Title } from './DeleteSpaceModal/styled' + +const CreateTodoModal = ({ children }) => { const isOpen = useModalStore((store) => store.open === ModalsType.todo) const setOpen = useModalStore((store) => store.toggleOpen) + const data = useModalStore((store) => store.data) const { addBlockInContent } = useUpdateBlock() const setModalData = useModalStore((store) => store.setData) const [isLoading, setIsLoading] = useState(false) + const { createNewNote } = useCreateNewNote() const { appendToNode } = useApi() + const theme = useTheme() + const [selectedNoteId, setSelectedNoteId] = useState() const onCreateTask = async () => { setIsLoading(true) @@ -31,8 +42,9 @@ const CreateTodoModal = () => { if (openedTodo) { try { if (todoBlock) { - await appendToNode(openedTodo.nodeid, todoBlock) - addBlockInContent(openedTodo.nodeid, todoBlock) + const noteId = selectedNoteId || openedTodo.nodeid + await appendToNode(noteId, todoBlock) + addBlockInContent(noteId, todoBlock) toast('Task created!') } } catch (err) { @@ -45,9 +57,45 @@ const CreateTodoModal = () => { } } + const onCreateContent = async () => { + setIsLoading(true) + + const content = getPlateEditorRef()?.children + try { + if (content) { + const noteId = selectedNoteId || '' + if (selectedNoteId) { + await appendToNode(noteId, content) + addBlockInContent(noteId, content) + } else { + createNewNote({ + noteContent: content, + noRedirect: true + }) + } + toast('Added Content!') + } + } catch (err) { + toast('Error occured while creating Task') + mog('Error occured while creating Task', { err }) + } finally { + setIsLoading(false) + setOpen(undefined) + } + } + + const handleCreate = () => { + if (data?.type === 'content') { + onCreateContent() + } else { + onCreateTask() + } + } + useEffect(() => { if (!isOpen) { setModalData(undefined) + setSelectedNoteId(null) } }, [isOpen]) @@ -77,16 +125,55 @@ const CreateTodoModal = () => { setOpen(undefined) } + const isContent = data?.type === 'content' + const description = !isContent + ? 'By default, new Task is added to Daily Tasks. You can select a different type of note from the menu if you prefer.' + : 'By defautl, new Content is saved as Drafts. You can select a different type of note from the menu if you prefer.' + return ( - - New Task - + +
+ + + Add a new  + <Group> + <IconDisplay + icon={isContent ? DefaultMIcons.TEXT : DefaultMIcons.TASK} + size={28} + color={theme.tokens.colors.primary.default} + />{' '} + <PrimaryText>{isContent ? 'Content' : 'Task'}</PrimaryText> + </Group>{' '} + ? + + +
+ + + {description} + { + setSelectedNoteId(noteId) + }} + /> + + + {children} +