diff --git a/packages/app-desktop/gui/NotePropertiesDialog.tsx b/packages/app-desktop/gui/NotePropertiesDialog.tsx index 8c6af91314..a096aa1678 100644 --- a/packages/app-desktop/gui/NotePropertiesDialog.tsx +++ b/packages/app-desktop/gui/NotePropertiesDialog.tsx @@ -9,7 +9,6 @@ import shim from '@joplin/lib/shim'; import { NoteEntity } from '@joplin/lib/services/database/types'; import { focus } from '@joplin/lib/utils/focusHandler'; import Dialog from './Dialog'; -const Datetime = require('react-datetime').default; const { clipboard } = require('electron'); const formatcoords = require('formatcoords'); @@ -48,6 +47,7 @@ class NotePropertiesDialog extends React.Component { private styleKey_: number; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private styles_: any; + private inputRef: React.RefObject; public constructor(props: Props) { super(props); @@ -55,6 +55,7 @@ class NotePropertiesDialog extends React.Component { this.revisionsLink_click = this.revisionsLink_click.bind(this); this.buttonRow_click = this.buttonRow_click.bind(this); this.okButton = React.createRef(); + this.inputRef = React.createRef(); this.state = { formNote: null, @@ -224,13 +225,11 @@ class NotePropertiesDialog extends React.Component { }); shim.setTimeout(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - if ((this.refs.editField as any).openCalendar) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - (this.refs.editField as any).openCalendar(); - } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - focus('NotePropertiesDialog::editPropertyButtonClick', (this.refs.editField as any)); + // Opens datetime-local fields with calendar + if (this.inputRef.current.showPicker) { + this.inputRef.current.showPicker(); + } else if (this.inputRef.current) { + focus('NotePropertiesDialog::editPropertyButtonClick', (this.inputRef.current)); } }, 100); } @@ -300,23 +299,14 @@ class NotePropertiesDialog extends React.Component { if (this.state.editedKey === key) { if (key.indexOf('_time') >= 0) { - controlComp = ( - onKeyDown(event), - style: styles.input, - }} - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - onChange={(momentObject: any) => { - this.setState({ editedValue: momentObject }); - }} - /> - ); + controlComp = this.setState({ editedValue: event.target.value })} + onKeyDown={event => onKeyDown(event)} + style={styles.input} + />; editCompHandler = () => { void this.saveProperty(); @@ -328,7 +318,7 @@ class NotePropertiesDialog extends React.Component { { this.setState({ editedValue: event.target.value }); }} diff --git a/packages/app-desktop/gui/PromptDialog.tsx b/packages/app-desktop/gui/PromptDialog.tsx index 46fd77f421..8b0ecf81ef 100644 --- a/packages/app-desktop/gui/PromptDialog.tsx +++ b/packages/app-desktop/gui/PromptDialog.tsx @@ -1,13 +1,13 @@ import * as React from 'react'; import { _ } from '@joplin/lib/locale'; import { themeStyle } from '@joplin/lib/theme'; -import time from '@joplin/lib/time'; -const Datetime = require('react-datetime').default; import CreatableSelect from 'react-select/creatable'; import Select from 'react-select'; import makeAnimated from 'react-select/animated'; import { focus } from '@joplin/lib/utils/focusHandler'; import Dialog from './Dialog'; +import { ChangeEvent } from 'react'; +import { formatDateTimeLocalToMs, isValidDate } from '@joplin/utils/time'; interface Props { themeId: number; @@ -204,16 +204,14 @@ export default class PromptDialog extends React.Component { if (this.props.onClose) { let outputAnswer = this.state.answer; if (this.props.inputType === 'datetime') { - // outputAnswer = anythingToDate(outputAnswer); - outputAnswer = time.anythingToDateTime(outputAnswer); + outputAnswer = isValidDate(outputAnswer) ? formatDateTimeLocalToMs(outputAnswer) : null; } this.props.onClose(accept ? outputAnswer : null, buttonType); } this.setState({ visible: false, answer: '' }); }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onChange = (event: any) => { + const onChange = (event: ChangeEvent) => { this.setState({ answer: event.target.value }); }; @@ -226,11 +224,6 @@ export default class PromptDialog extends React.Component { // return m.isValid() ? m.toDate() : null; // } - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onDateTimeChange = (momentObject: any) => { - this.setState({ answer: momentObject }); - }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const onSelectChange = (newValue: any) => { this.setState({ answer: newValue }); @@ -258,8 +251,13 @@ export default class PromptDialog extends React.Component { let inputComp = null; if (this.props.inputType === 'datetime') { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - inputComp = onDateTimeChange(momentObject)} />; + inputComp = ; } else if (this.props.inputType === 'tags') { // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied inputComp = onKeyDown(event)} />; diff --git a/packages/app-desktop/gui/WindowCommandsAndDialogs/commands/editAlarm.ts b/packages/app-desktop/gui/WindowCommandsAndDialogs/commands/editAlarm.ts index 47f7406641..949a35d437 100644 --- a/packages/app-desktop/gui/WindowCommandsAndDialogs/commands/editAlarm.ts +++ b/packages/app-desktop/gui/WindowCommandsAndDialogs/commands/editAlarm.ts @@ -4,6 +4,7 @@ import { _ } from '@joplin/lib/locale'; import { stateUtils } from '@joplin/lib/reducer'; import Note from '@joplin/lib/models/Note'; import time from '@joplin/lib/time'; +import { formatMsToDateTimeLocal } from '@joplin/utils/time'; import { NoteEntity } from '@joplin/lib/services/database/types'; export const declaration: CommandDeclaration = { @@ -29,7 +30,7 @@ export const runtime = (comp: any): CommandRuntime => { label: _('Set alarm:'), inputType: 'datetime', buttons: ['ok', 'cancel', 'clear'], - value: note.todo_due ? new Date(note.todo_due) : defaultDate, + value: note.todo_due ? formatMsToDateTimeLocal(note.todo_due) : formatMsToDateTimeLocal(defaultDate.getTime()), // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied onClose: async (answer: any, buttonType: string) => { let newNote: NoteEntity = null; @@ -42,7 +43,7 @@ export const runtime = (comp: any): CommandRuntime => { } else if (answer !== null) { newNote = { id: note.id, - todo_due: answer.getTime(), + todo_due: answer, }; } diff --git a/packages/app-desktop/package.json b/packages/app-desktop/package.json index 4f1cfbc21d..71470d07de 100644 --- a/packages/app-desktop/package.json +++ b/packages/app-desktop/package.json @@ -193,7 +193,6 @@ "pretty-bytes": "5.6.0", "re-resizable": "6.9.17", "react": "18.3.1", - "react-datetime": "3.2.0", "react-dom": "18.3.1", "react-redux": "8.1.3", "react-select": "5.8.0", diff --git a/packages/app-desktop/style.scss b/packages/app-desktop/style.scss index 259d6e0ff5..6a0ddc6966 100644 --- a/packages/app-desktop/style.scss +++ b/packages/app-desktop/style.scss @@ -24,7 +24,6 @@ // See https://sasscss.org/documentation/at-rules/import#plain-css-imports. @import url('style/icons/style.css'); @import url('vendor/lib/@fortawesome/fontawesome-free/css/all.min.css'); -@import url('vendor/lib/react-datetime/css/react-datetime.css'); @import url('vendor/lib/smalltalk/css/smalltalk.css'); @import url('vendor/lib/roboto-fontface/css/roboto/roboto-fontface.css'); @import url('vendor/lib/codemirror/lib/codemirror.css'); diff --git a/packages/app-desktop/tools/copyApplicationAssets.js b/packages/app-desktop/tools/copyApplicationAssets.js index a6c7bb5ffa..7e00b01694 100644 --- a/packages/app-desktop/tools/copyApplicationAssets.js +++ b/packages/app-desktop/tools/copyApplicationAssets.js @@ -85,7 +85,6 @@ async function main() { 'codemirror/addon/dialog/dialog.css', 'codemirror/lib/codemirror.css', 'mark.js/dist/mark.min.js', - 'react-datetime/css/react-datetime.css', 'roboto-fontface/css/roboto/roboto-fontface.css', 'smalltalk/css/smalltalk.css', 'smalltalk/dist/smalltalk.min.js', diff --git a/packages/utils/time.ts b/packages/utils/time.ts index f8d9598375..7478ce7182 100644 --- a/packages/utils/time.ts +++ b/packages/utils/time.ts @@ -145,3 +145,15 @@ export const formatMsToLocal = (ms: number, format: string|null = null) => { if (format === null) format = dateTimeFormat(); return dayjs(ms).format(format); }; + +export const formatMsToDateTimeLocal = (ms: number) => { + return formatMsToLocal(ms, 'YYYY-MM-DDTHH:mm'); +}; + +export const isValidDate = (anything: string) => { + return dayjs(anything).isValid(); +}; + +export const formatDateTimeLocalToMs = (anything: string) => { + return dayjs(anything).unix() * 1000; +}; diff --git a/yarn.lock b/yarn.lock index aac7cf330f..617a044068 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8324,7 +8324,6 @@ __metadata: pretty-bytes: 5.6.0 re-resizable: 6.9.17 react: 18.3.1 - react-datetime: 3.2.0 react-dom: 18.3.1 react-redux: 8.1.3 react-select: 5.8.0 @@ -39081,7 +39080,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.5.7, prop-types@npm:^15.5.8, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2": +"prop-types@npm:^15.5.8, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2": version: 15.7.2 resolution: "prop-types@npm:15.7.2" dependencies: @@ -39576,18 +39575,6 @@ __metadata: languageName: node linkType: hard -"react-datetime@npm:3.2.0": - version: 3.2.0 - resolution: "react-datetime@npm:3.2.0" - dependencies: - prop-types: ^15.5.7 - peerDependencies: - moment: ^2.16.0 - react: ^16.5.0 || ^17.0.0 || ^18.0.0 - checksum: c3407beb64f44cd5944252bee1c4565fc138e3f1e81d8e4fd00d2aeac564a18848ee9af5f51fbbb39bba588f8c2d659570384af1ce8378d4e0049a6bdb083655 - languageName: node - linkType: hard - "react-dev-utils@npm:^12.0.1": version: 12.0.1 resolution: "react-dev-utils@npm:12.0.1"