From 8b845ea424e0731d9c850c3e6604534bf5aeda86 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Thu, 30 Jun 2022 21:57:33 +0530 Subject: [PATCH] feat: add tag id to tag context menu (#1185) --- .../AccountMenu/GeneralAccountMenu.tsx | 2 +- .../ApplicationView/ApplicationView.tsx | 7 +- .../FileContextMenu/FileContextMenu.tsx | 2 +- .../Components/NotesOptions/NotesOptions.tsx | 12 +-- .../Preferences/Panes/Account/Sync.tsx | 2 +- .../Components/Tags/TagContextMenu.tsx | 101 +++++++++--------- .../Components/Tags/TagContextMenuWrapper.tsx | 28 +++++ .../{FormatLastSyncDate.ts => DateUtils.ts} | 8 ++ 8 files changed, 95 insertions(+), 67 deletions(-) create mode 100644 packages/web/src/javascripts/Components/Tags/TagContextMenuWrapper.tsx rename packages/web/src/javascripts/Utils/{FormatLastSyncDate.ts => DateUtils.ts} (51%) diff --git a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx index 4cc2b0a88..93df5edf8 100644 --- a/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx +++ b/packages/web/src/javascripts/Components/AccountMenu/GeneralAccountMenu.tsx @@ -12,7 +12,7 @@ import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator' import { MenuItemType } from '@/Components/Menu/MenuItemType' import WorkspaceSwitcherOption from './WorkspaceSwitcher/WorkspaceSwitcherOption' import { ApplicationGroup } from '@/Application/ApplicationGroup' -import { formatLastSyncDate } from '@/Utils/FormatLastSyncDate' +import { formatLastSyncDate } from '@/Utils/DateUtils' import Spinner from '@/Components/Spinner/Spinner' type Props = { diff --git a/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx b/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx index b3a6ee2bc..6bbe16091 100644 --- a/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx +++ b/packages/web/src/javascripts/Components/ApplicationView/ApplicationView.tsx @@ -17,13 +17,13 @@ import { FunctionComponent, useCallback, useEffect, useMemo, useState } from 're import RevisionHistoryModal from '@/Components/RevisionHistoryModal/RevisionHistoryModal' import PremiumModalProvider from '@/Hooks/usePremiumModal' import ConfirmSignoutContainer from '@/Components/ConfirmSignoutModal/ConfirmSignoutModal' -import TagsContextMenuWrapper from '@/Components/Tags/TagContextMenu' import { ToastContainer } from '@standardnotes/toast' import FilePreviewModalWrapper from '@/Components/FilePreview/FilePreviewModal' import ContentListView from '@/Components/ContentListView/ContentListView' import FileContextMenuWrapper from '@/Components/FileContextMenu/FileContextMenu' import PermissionsModalWrapper from '@/Components/PermissionsModal/PermissionsModalWrapper' import { PanelResizedData } from '@/Types/PanelResizedData' +import TagContextMenuWrapper from '@/Components/Tags/TagContextMenuWrapper' type Props = { application: WebApplication @@ -214,7 +214,10 @@ const ApplicationView: FunctionComponent = ({ application, mainApplicatio noteTagsController={viewControllerManager.noteTagsController} historyModalController={viewControllerManager.historyModalController} /> - + = observer(({ filesController, s return (
{ } } -const formatDate = (date: Date | undefined) => { - if (!date) { - return - } - return `${date.toDateString()} ${date.toLocaleTimeString()}` -} - const NoteAttributes: FunctionComponent<{ application: SNApplication note: SNNote @@ -93,9 +87,9 @@ const NoteAttributes: FunctionComponent<{ const readTime = useMemo(() => (typeof words === 'number' ? calculateReadTime(words) : 'N/A'), [words]) - const dateLastModified = useMemo(() => formatDate(note.userModifiedDate), [note.userModifiedDate]) + const dateLastModified = useMemo(() => formatDateForContextMenu(note.userModifiedDate), [note.userModifiedDate]) - const dateCreated = useMemo(() => formatDate(note.created_at), [note.created_at]) + const dateCreated = useMemo(() => formatDateForContextMenu(note.created_at), [note.created_at]) const editor = application.componentManager.editorForNote(note) const format = editor?.package_info?.file_type || 'txt' diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Sync.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Sync.tsx index b1ef43191..9bd67ef92 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Account/Sync.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Account/Sync.tsx @@ -5,7 +5,7 @@ import { STRING_GENERIC_SYNC_ERROR } from '@/Constants/Strings' import { observer } from 'mobx-react-lite' import { WebApplication } from '@/Application/Application' import { FunctionComponent, useState } from 'react' -import { formatLastSyncDate } from '@/Utils/FormatLastSyncDate' +import { formatLastSyncDate } from '@/Utils/DateUtils' import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup' import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment' diff --git a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx index c5cee3e63..f52abb7f6 100644 --- a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx @@ -1,36 +1,33 @@ -import { ViewControllerManager } from '@/Services/ViewControllerManager' import { observer } from 'mobx-react-lite' -import { useCallback, useEffect, useRef } from 'react' +import { useCallback, useEffect, useRef, useMemo } from 'react' import Icon from '@/Components/Icon/Icon' import Menu from '@/Components/Menu/Menu' import MenuItem from '@/Components/Menu/MenuItem' import { MenuItemType } from '@/Components/Menu/MenuItemType' import { usePremiumModal } from '@/Hooks/usePremiumModal' -import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur' import { SNTag } from '@standardnotes/snjs' -import { isControllerDealloced } from '@/Controllers/Abstract/IsControllerDealloced' +import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside' +import { NavigationController } from '@/Controllers/Navigation/NavigationController' +import HorizontalSeparator from '../Shared/HorizontalSeparator' +import { formatDateForContextMenu } from '@/Utils/DateUtils' -type WrapperProps = { - viewControllerManager: ViewControllerManager -} - -type ContextMenuProps = WrapperProps & { +type ContextMenuProps = { + navigationController: NavigationController + isEntitledToFolders: boolean selectedTag: SNTag } -const TagsContextMenu = observer(({ viewControllerManager, selectedTag }: ContextMenuProps) => { +const TagContextMenu = ({ navigationController, isEntitledToFolders, selectedTag }: ContextMenuProps) => { const premiumModal = usePremiumModal() - const { contextMenuOpen, contextMenuPosition, contextMenuMaxHeight } = viewControllerManager.navigationController + const { contextMenuOpen, contextMenuPosition, contextMenuMaxHeight } = navigationController const contextMenuRef = useRef(null) - const [closeOnBlur] = useCloseOnBlur(contextMenuRef, (open: boolean) => - viewControllerManager.navigationController.setContextMenuOpen(open), - ) + useCloseOnClickOutside(contextMenuRef, () => navigationController.setContextMenuOpen(false)) const reloadContextMenuLayout = useCallback(() => { - viewControllerManager.navigationController.reloadContextMenuLayout() - }, [viewControllerManager]) + navigationController.reloadContextMenuLayout() + }, [navigationController]) useEffect(() => { window.addEventListener('resize', reloadContextMenuLayout) @@ -40,28 +37,35 @@ const TagsContextMenu = observer(({ viewControllerManager, selectedTag }: Contex }, [reloadContextMenuLayout]) const onClickAddSubtag = useCallback(() => { - if (!viewControllerManager.featuresController.hasFolders) { + if (!isEntitledToFolders) { premiumModal.activate('Folders') return } - viewControllerManager.navigationController.setContextMenuOpen(false) - viewControllerManager.navigationController.setAddingSubtagTo(selectedTag) - }, [viewControllerManager, selectedTag, premiumModal]) + navigationController.setContextMenuOpen(false) + navigationController.setAddingSubtagTo(selectedTag) + }, [isEntitledToFolders, navigationController, selectedTag, premiumModal]) const onClickRename = useCallback(() => { - viewControllerManager.navigationController.setContextMenuOpen(false) - viewControllerManager.navigationController.editingTag = selectedTag - }, [viewControllerManager, selectedTag]) + navigationController.setContextMenuOpen(false) + navigationController.editingTag = selectedTag + }, [navigationController, selectedTag]) const onClickDelete = useCallback(() => { - viewControllerManager.navigationController.remove(selectedTag, true).catch(console.error) - }, [viewControllerManager, selectedTag]) + navigationController.remove(selectedTag, true).catch(console.error) + }, [navigationController, selectedTag]) + + const tagLastModified = useMemo( + () => formatDateForContextMenu(selectedTag.userModifiedDate), + [selectedTag.userModifiedDate], + ) + + const tagCreatedAt = useMemo(() => formatDateForContextMenu(selectedTag.created_at), [selectedTag.created_at]) return contextMenuOpen ? (
{ - viewControllerManager.navigationController.setContextMenuOpen(false) + navigationController.setContextMenuOpen(false) }} > - +
Add subtag
- {!viewControllerManager.featuresController.hasFolders && } + {!isEntitledToFolders && }
- + Rename - + Delete + +
+
+ Last modified: {tagLastModified} +
+
+ Created: {tagCreatedAt} +
+
+ Tag ID: {selectedTag.uuid} +
+
) : null -}) - -TagsContextMenu.displayName = 'TagsContextMenu' - -const TagsContextMenuWrapper = ({ viewControllerManager }: WrapperProps) => { - if (isControllerDealloced(viewControllerManager)) { - return null - } - - const selectedTag = viewControllerManager.navigationController.selected - - if (!selectedTag || !(selectedTag instanceof SNTag)) { - return null - } - - return } -export default observer(TagsContextMenuWrapper) +export default observer(TagContextMenu) diff --git a/packages/web/src/javascripts/Components/Tags/TagContextMenuWrapper.tsx b/packages/web/src/javascripts/Components/Tags/TagContextMenuWrapper.tsx new file mode 100644 index 000000000..059518b65 --- /dev/null +++ b/packages/web/src/javascripts/Components/Tags/TagContextMenuWrapper.tsx @@ -0,0 +1,28 @@ +import { observer } from 'mobx-react-lite' +import { SNTag } from '@standardnotes/snjs' +import TagContextMenu from './TagContextMenu' +import { NavigationController } from '@/Controllers/Navigation/NavigationController' +import { FeaturesController } from '@/Controllers/FeaturesController' + +type Props = { + navigationController: NavigationController + featuresController: FeaturesController +} + +const TagContextMenuWrapper = ({ navigationController, featuresController }: Props) => { + const selectedTag = navigationController.selected + + if (!selectedTag || !(selectedTag instanceof SNTag)) { + return null + } + + return ( + + ) +} + +export default observer(TagContextMenuWrapper) diff --git a/packages/web/src/javascripts/Utils/FormatLastSyncDate.ts b/packages/web/src/javascripts/Utils/DateUtils.ts similarity index 51% rename from packages/web/src/javascripts/Utils/FormatLastSyncDate.ts rename to packages/web/src/javascripts/Utils/DateUtils.ts index 0d10d18c4..90d7943bc 100644 --- a/packages/web/src/javascripts/Utils/FormatLastSyncDate.ts +++ b/packages/web/src/javascripts/Utils/DateUtils.ts @@ -3,3 +3,11 @@ import { dateToLocalizedString } from '@standardnotes/snjs/' export const formatLastSyncDate = (lastUpdatedDate: Date) => { return dateToLocalizedString(lastUpdatedDate) } + +export const formatDateForContextMenu = (date: Date | undefined) => { + if (!date) { + return + } + + return `${date.toDateString()} ${date.toLocaleTimeString()}` +}