feat(dev): insert current date and time command in super note (#1994)
This commit is contained in:
@@ -35,7 +35,6 @@ export default function HorizontalRulePlugin(): null {
|
|||||||
|
|
||||||
if (focusNode !== null) {
|
if (focusNode !== null) {
|
||||||
const horizontalRuleNode = $createHorizontalRuleNode();
|
const horizontalRuleNode = $createHorizontalRuleNode();
|
||||||
selection.insertParagraph();
|
|
||||||
selection.focus
|
selection.focus
|
||||||
.getNode()
|
.getNode()
|
||||||
.getTopLevelElementOrThrow()
|
.getTopLevelElementOrThrow()
|
||||||
|
|||||||
@@ -1041,7 +1041,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
padding: 2px 2px;
|
padding: 2px 0px;
|
||||||
border: none;
|
border: none;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -1051,7 +1051,7 @@ body {
|
|||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background-color: var(--sn-stylekit-contrast-border-color);
|
background-color: var(--sn-stylekit-secondary-background-color);
|
||||||
line-height: 2px;
|
line-height: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import ItemBubblePlugin from './Plugins/ItemBubblePlugin/ItemBubblePlugin'
|
|||||||
import { NodeObserverPlugin } from './Plugins/NodeObserverPlugin/NodeObserverPlugin'
|
import { NodeObserverPlugin } from './Plugins/NodeObserverPlugin/NodeObserverPlugin'
|
||||||
import { FilesController } from '@/Controllers/FilesController'
|
import { FilesController } from '@/Controllers/FilesController'
|
||||||
import FilesControllerProvider from '@/Controllers/FilesControllerProvider'
|
import FilesControllerProvider from '@/Controllers/FilesControllerProvider'
|
||||||
|
import DatetimePlugin from './Plugins/DateTimePlugin/DateTimePlugin'
|
||||||
|
|
||||||
const NotePreviewCharLimit = 160
|
const NotePreviewCharLimit = 160
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ export const BlockEditor: FunctionComponent<Props> = ({
|
|||||||
<FilePlugin />
|
<FilePlugin />
|
||||||
<ItemBubblePlugin />
|
<ItemBubblePlugin />
|
||||||
<BlockPickerMenuPlugin />
|
<BlockPickerMenuPlugin />
|
||||||
|
<DatetimePlugin />
|
||||||
<NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} />
|
<NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} />
|
||||||
<NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} />
|
<NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} />
|
||||||
</BlocksEditor>
|
</BlocksEditor>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { GetEmbedsBlocks } from './Blocks/Embeds'
|
|||||||
import { GetDynamicTableBlocks, GetTableBlock } from './Blocks/Table'
|
import { GetDynamicTableBlocks, GetTableBlock } from './Blocks/Table'
|
||||||
import Popover from '@/Components/Popover/Popover'
|
import Popover from '@/Components/Popover/Popover'
|
||||||
import { PopoverClassNames } from '../ClassNames'
|
import { PopoverClassNames } from '../ClassNames'
|
||||||
|
import { GetDatetimeBlocks } from './Blocks/DateTime'
|
||||||
|
|
||||||
export default function BlockPickerMenuPlugin(): JSX.Element {
|
export default function BlockPickerMenuPlugin(): JSX.Element {
|
||||||
const [editor] = useLexicalComposerContext()
|
const [editor] = useLexicalComposerContext()
|
||||||
@@ -45,6 +46,7 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
|
|||||||
GetQuoteBlock(editor),
|
GetQuoteBlock(editor),
|
||||||
GetCodeBlock(editor),
|
GetCodeBlock(editor),
|
||||||
GetDividerBlock(editor),
|
GetDividerBlock(editor),
|
||||||
|
...GetDatetimeBlocks(editor),
|
||||||
...GetAlignmentBlocks(editor),
|
...GetAlignmentBlocks(editor),
|
||||||
GetCollapsibleBlock(editor),
|
GetCollapsibleBlock(editor),
|
||||||
...GetEmbedsBlocks(editor),
|
...GetEmbedsBlocks(editor),
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { BlockPickerOption } from '../BlockPickerOption'
|
||||||
|
import { LexicalEditor } from 'lexical'
|
||||||
|
import { INSERT_DATETIME_COMMAND, INSERT_DATE_COMMAND, INSERT_TIME_COMMAND } from '../../Commands'
|
||||||
|
|
||||||
|
export function GetDatetimeBlocks(editor: LexicalEditor) {
|
||||||
|
return [
|
||||||
|
new BlockPickerOption('Current date and time', {
|
||||||
|
iconName: 'authenticator',
|
||||||
|
keywords: ['date'],
|
||||||
|
onSelect: () => editor.dispatchCommand(INSERT_DATETIME_COMMAND, 'datetime'),
|
||||||
|
}),
|
||||||
|
new BlockPickerOption('Current time', {
|
||||||
|
iconName: 'authenticator',
|
||||||
|
keywords: ['time'],
|
||||||
|
onSelect: () => editor.dispatchCommand(INSERT_TIME_COMMAND, 'datetime'),
|
||||||
|
}),
|
||||||
|
new BlockPickerOption('Current date', {
|
||||||
|
iconName: 'authenticator',
|
||||||
|
keywords: ['date'],
|
||||||
|
onSelect: () => editor.dispatchCommand(INSERT_DATE_COMMAND, 'datetime'),
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,3 +2,6 @@ import { createCommand, LexicalCommand } from 'lexical'
|
|||||||
|
|
||||||
export const INSERT_FILE_COMMAND: LexicalCommand<string> = createCommand('INSERT_FILE_COMMAND')
|
export const INSERT_FILE_COMMAND: LexicalCommand<string> = createCommand('INSERT_FILE_COMMAND')
|
||||||
export const INSERT_BUBBLE_COMMAND: LexicalCommand<string> = createCommand('INSERT_BUBBLE_COMMAND')
|
export const INSERT_BUBBLE_COMMAND: LexicalCommand<string> = createCommand('INSERT_BUBBLE_COMMAND')
|
||||||
|
export const INSERT_TIME_COMMAND: LexicalCommand<string> = createCommand('INSERT_TIME_COMMAND')
|
||||||
|
export const INSERT_DATE_COMMAND: LexicalCommand<string> = createCommand('INSERT_DATE_COMMAND')
|
||||||
|
export const INSERT_DATETIME_COMMAND: LexicalCommand<string> = createCommand('INSERT_DATETIME_COMMAND')
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||||
|
import {
|
||||||
|
COMMAND_PRIORITY_EDITOR,
|
||||||
|
$createTextNode,
|
||||||
|
$getSelection,
|
||||||
|
$isRangeSelection,
|
||||||
|
$createParagraphNode,
|
||||||
|
} from 'lexical'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { INSERT_DATETIME_COMMAND, INSERT_TIME_COMMAND, INSERT_DATE_COMMAND } from '../Commands'
|
||||||
|
import { mergeRegister } from '@lexical/utils'
|
||||||
|
import { $createHeadingNode } from '@lexical/rich-text'
|
||||||
|
import { formatDateAndTimeForNote, dateToHoursAndMinutesTimeString } from '@/Utils/DateUtils'
|
||||||
|
import { INSERT_HORIZONTAL_RULE_COMMAND } from '@lexical/react/LexicalHorizontalRuleNode'
|
||||||
|
|
||||||
|
export default function DatetimePlugin(): JSX.Element | null {
|
||||||
|
const [editor] = useLexicalComposerContext()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return mergeRegister(
|
||||||
|
editor.registerCommand<string>(
|
||||||
|
INSERT_DATETIME_COMMAND,
|
||||||
|
() => {
|
||||||
|
const now = new Date()
|
||||||
|
const selection = $getSelection()
|
||||||
|
|
||||||
|
if (!$isRangeSelection(selection)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = $createHeadingNode('h1')
|
||||||
|
const dateString = $createTextNode(formatDateAndTimeForNote(now, false))
|
||||||
|
dateString.setFormat('italic')
|
||||||
|
heading.append(dateString)
|
||||||
|
|
||||||
|
const timeNode = $createTextNode(dateToHoursAndMinutesTimeString(now))
|
||||||
|
timeNode.toggleFormat('superscript')
|
||||||
|
timeNode.toggleFormat('italic')
|
||||||
|
heading.append(timeNode)
|
||||||
|
|
||||||
|
const newLineNode = $createParagraphNode()
|
||||||
|
|
||||||
|
selection.insertNodes([heading, newLineNode])
|
||||||
|
|
||||||
|
editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined)
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_EDITOR,
|
||||||
|
),
|
||||||
|
editor.registerCommand<string>(
|
||||||
|
INSERT_DATE_COMMAND,
|
||||||
|
() => {
|
||||||
|
const now = new Date()
|
||||||
|
const selection = $getSelection()
|
||||||
|
|
||||||
|
if (!$isRangeSelection(selection)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = $createHeadingNode('h1')
|
||||||
|
const dateString = $createTextNode(formatDateAndTimeForNote(now, false))
|
||||||
|
dateString.setFormat('italic')
|
||||||
|
heading.append(dateString)
|
||||||
|
|
||||||
|
const newLineNode = $createParagraphNode()
|
||||||
|
|
||||||
|
selection.insertNodes([heading, newLineNode])
|
||||||
|
|
||||||
|
editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined)
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_EDITOR,
|
||||||
|
),
|
||||||
|
editor.registerCommand<string>(
|
||||||
|
INSERT_TIME_COMMAND,
|
||||||
|
() => {
|
||||||
|
const now = new Date()
|
||||||
|
const selection = $getSelection()
|
||||||
|
|
||||||
|
if (!$isRangeSelection(selection)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = $createHeadingNode('h2')
|
||||||
|
const dateString = $createTextNode(dateToHoursAndMinutesTimeString(now))
|
||||||
|
dateString.setFormat('italic')
|
||||||
|
heading.append(dateString)
|
||||||
|
|
||||||
|
const newLineNode = $createParagraphNode()
|
||||||
|
|
||||||
|
selection.insertNodes([heading, newLineNode])
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
COMMAND_PRIORITY_EDITOR,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}, [editor])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -29,6 +29,12 @@ export const formatDateAndTimeForNote = (date: Date, includeTime = true) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const dateToHoursAndMinutesTimeString = (date: Date) => {
|
||||||
|
return date.toLocaleTimeString(undefined, {
|
||||||
|
timeStyle: 'short',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function numHoursBetweenDates(date1: Date, date2: Date): number {
|
export function numHoursBetweenDates(date1: Date, date2: Date): number {
|
||||||
return Math.abs(date1.getTime() - date2.getTime()) / 3600000
|
return Math.abs(date1.getTime() - date2.getTime()) / 3600000
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user