From 75922f23283971fa59ea9c956d6eec4cd7502713 Mon Sep 17 00:00:00 2001 From: Joshua Tazman Reinier Date: Mon, 14 Oct 2024 06:06:34 -0400 Subject: [PATCH] 2.5.2 --- CHANGELOG.md | 8 +++++ dist/manifest.json | 2 +- manifest.json | 2 +- package.json | 1 + pnpm-lock.yaml | 19 ++++++++---- src/app/store.ts | 2 ++ src/components/App.tsx | 1 + src/components/Block.tsx | 21 +++----------- src/components/Day.tsx | 3 +- src/components/NewTask.tsx | 26 ++++++++++++----- src/components/Task.tsx | 2 +- src/main.ts | 28 +++++++++--------- src/services/calendarApi.ts | 2 ++ src/services/dragging.ts | 58 ++----------------------------------- src/services/parser.ts | 2 +- src/services/util.ts | 13 +++++++-- src/types/index.d.ts | 1 - 17 files changed, 84 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0467f9..ff19d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,14 @@ # Changelog +## 2.5.2 (10/14/2024) +**Changed:** +- "Do now" button is now "Do Today" + +**Fixed:** +- No longer displaying [remaining days as decimal](https://github.com/j-palindrome/obsidian-time-ruler/issues/133) +- Support [tag sorting](https://github.com/j-palindrome/obsidian-time-ruler/issues/96) + ## 2.5.0 (9/28/2024) **Added:** diff --git a/dist/manifest.json b/dist/manifest.json index 3a91f49..1cd46e0 100644 --- a/dist/manifest.json +++ b/dist/manifest.json @@ -1,7 +1,7 @@ { "id": "time-ruler", "name": "Time Ruler", - "version": "2.5.0", + "version": "2.5.2", "minAppVersion": "0.15.0", "description": "A drag-and-drop time ruler combining the best of a task list and a calendar view (integrates with Tasks, Full Calendar, and Dataview).", "author": "Joshua Tazman Reinier", diff --git a/manifest.json b/manifest.json index f7e189f..1cd46e0 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "time-ruler", "name": "Time Ruler", - "version": "2.5.1", + "version": "2.5.2", "minAppVersion": "0.15.0", "description": "A drag-and-drop time ruler combining the best of a task list and a calendar view (integrates with Tasks, Full Calendar, and Dataview).", "author": "Joshua Tazman Reinier", diff --git a/package.json b/package.json index 07b3a99..4897f6d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-timer-hook": "^3.0.7", "react-usestateref": "^1.0.8", "tiny-invariant": "^1.3.1", + "typescript": "^5.6.3", "zustand": "^4.4.6" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 821a4a4..ad9c50f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,6 +59,9 @@ dependencies: tiny-invariant: specifier: ^1.3.1 version: 1.3.3 + typescript: + specifier: ^5.6.3 + version: 5.6.3 zustand: specifier: ^4.4.6 version: 4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1) @@ -1033,7 +1036,7 @@ packages: resolution: {integrity: sha512-REKQtAuIOKDbvNH/th1C1gWmJWCP5tRn9T/mfZGZt4Zncgko7McXK0aSKFtEInipvgbZJ2nScivvyLdiWluSMw==} hasBin: true dependencies: - obsidian: github.com/obsidianmd/obsidian-api/8b2eda0f24285636c8aa116972643e5233a23dc1(@codemirror/state@6.4.1)(@codemirror/view@6.26.3) + obsidian: github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869(@codemirror/state@6.4.1)(@codemirror/view@6.26.3) tslib: 2.1.0 transitivePeerDependencies: - '@codemirror/state' @@ -1451,6 +1454,12 @@ packages: engines: {node: '>=12.20'} dev: false + /typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + dev: false + /update-browserslist-db@1.0.16(browserslist@4.23.0): resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true @@ -1560,11 +1569,11 @@ packages: style-mod: 4.1.2 dev: false - github.com/obsidianmd/obsidian-api/8b2eda0f24285636c8aa116972643e5233a23dc1(@codemirror/state@6.4.1)(@codemirror/view@6.26.3): - resolution: {tarball: https://codeload.github.com/obsidianmd/obsidian-api/tar.gz/8b2eda0f24285636c8aa116972643e5233a23dc1} - id: github.com/obsidianmd/obsidian-api/8b2eda0f24285636c8aa116972643e5233a23dc1 + github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869(@codemirror/state@6.4.1)(@codemirror/view@6.26.3): + resolution: {tarball: https://codeload.github.com/obsidianmd/obsidian-api/tar.gz/23947b58d372ea02225324308e31d36b4aa95869} + id: github.com/obsidianmd/obsidian-api/23947b58d372ea02225324308e31d36b4aa95869 name: obsidian - version: 1.5.7 + version: 1.7.2 peerDependencies: '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 diff --git a/src/app/store.ts b/src/app/store.ts index 97788fc..703ffd5 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -24,6 +24,7 @@ export type AppState = { calendar?: CalendarAPI } dragData: DragData | null + dragMode: 'ripple' | 'normal' findingTask: string | null inScroll: number searchStatus: boolean @@ -71,6 +72,7 @@ export const useAppStore = createWithEqualityFn(() => ({ inScroll: 0, searchStatus: false, viewMode: 'hour', + dragMode: 'normal', fileOrder: [], dailyNoteInfo: { format: 'YYYY-MM-DD', diff --git a/src/components/App.tsx b/src/components/App.tsx index 114fdb8..c787661 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -605,6 +605,7 @@ const Buttons = ({ ['path', 'Path', 'folder-tree'], ['priority', 'Priority', 'alert-circle'], ['hybrid', 'Hybrid', 'arrow-down-narrow-wide'], + ['tags', 'Tags', 'hash'], [false, 'None', 'x'], ].map( ([groupBy, title, src]: [ diff --git a/src/components/Block.tsx b/src/components/Block.tsx index 99ceed2..7dc92ff 100644 --- a/src/components/Block.tsx +++ b/src/components/Block.tsx @@ -71,31 +71,18 @@ export default function Block({ const sortedGroups = useAppStore((state) => { switch (state.settings.groupBy) { - case 'priority': + case false: + return _.entries(groupedTasks) + default: return _.sortBy( _.entries(groupedTasks), ([group]) => (group === UNGROUPED ? 0 : 1), - 0 - ) - case 'path': - return _.sortBy( - _.entries(groupedTasks), - ([group, _tasks]) => (group === UNGROUPED ? 0 : 1), - ([group, _tasks]) => - state.fileOrder.indexOf(parseFileFromPath(group)), - '1.0.position.start.line' - ) - case 'hybrid': - return _.sortBy( - _.entries(groupedTasks), - ([group, _tasks]) => (group === UNGROUPED ? 0 : 1), + 0, '1.0.priority', ([group, _tasks]) => state.fileOrder.indexOf(parseFileFromPath(group)), '1.0.position.start.line' ) - case false: - return _.entries(groupedTasks) } }, shallow) diff --git a/src/components/Day.tsx b/src/components/Day.tsx index ec1086e..e77729d 100644 --- a/src/components/Day.tsx +++ b/src/components/Day.tsx @@ -80,7 +80,8 @@ export default function Day({ ? false : isDateISO(scheduled) ? scheduled === startDate - : scheduled >= startISO && scheduled < endISO + : (isNow ? scheduled > startDate : scheduled >= startISO) && + scheduled < endISO const dueToday = !showingPastDates && diff --git a/src/components/NewTask.tsx b/src/components/NewTask.tsx index f6d1728..2e2ac4b 100644 --- a/src/components/NewTask.tsx +++ b/src/components/NewTask.tsx @@ -76,6 +76,13 @@ export default function NewTask({ dragContainer }: { dragContainer: string }) { : undefined ) + const checkForClick = () => { + if (!getters.get('dragData')) { + setters.set({ newTask: { task: { scheduled: undefined }, type: 'new' } }) + } + window.removeEventListener('mouseup', checkForClick) + } + return (
{draggingTask ? ( @@ -96,13 +103,18 @@ export default function NewTask({ dragContainer }: { dragContainer: string }) { )} ) : ( -
- {task.tags.length > 0 && ( + {task.tags.length > 0 && groupBy !== 'tags' && (
{task.tags.map((tag) => (
item .setIcon('ruler') - .setTitle('Do now') - .onClick(() => this.editTask(context, cursor.line, 'now')) - ) - menu.addItem((item) => - item - .setIcon('ruler') - .setTitle('Unschedule') - .onClick(() => this.editTask(context, cursor.line, 'unschedule')) + .setTitle('Do today') + .onClick(() => this.editTask(context, cursor.line, 'today')) ) + if (line.match(new RegExp(ISO_MATCH))) { + menu.addItem((item) => + item + .setIcon('ruler') + .setTitle('Unschedule') + .onClick(() => this.editTask(context, cursor.line, 'unschedule')) + ) + } } async editTask( context: MarkdownView, line: number, - modification: 'now' | 'unschedule' + modification: 'today' | 'unschedule' ) { invariant(context.file) const id = context.file.path.replace('.md', '') + '::' + line let scheduled: TaskProps['scheduled'] switch (modification) { - case 'now': - scheduled = toISO(roundMinutes(DateTime.now())) + case 'today': + scheduled = toISO(roundMinutes(DateTime.now()), true) break case 'unschedule': scheduled = '' diff --git a/src/services/calendarApi.ts b/src/services/calendarApi.ts index 3080990..b752e32 100644 --- a/src/services/calendarApi.ts +++ b/src/services/calendarApi.ts @@ -122,6 +122,8 @@ export default class CalendarAPI extends Component { events[thisId] = props } } else { + if (event.summary.includes('TEST')) console.log(event) + let end = DateTime.fromJSDate(event.end).setZone('local') if (end < dateBounds[0]) continue diff --git a/src/services/dragging.ts b/src/services/dragging.ts index 226aeb6..24f850b 100644 --- a/src/services/dragging.ts +++ b/src/services/dragging.ts @@ -20,15 +20,14 @@ export const onDragEnd = async ( ) => { const dropData = ev.over?.data.current as DropData | undefined const dragData = activeDragRef.current + const dragMode = getters.get('dragMode') if (ev.active.id === ev.over?.id) { setters.set({ dragData: null }) return } - if (dragData?.dragType === 'new_button' && !dropData) { - setters.set({ newTask: { task: { scheduled: undefined }, type: 'new' } }) - } else if (dragData?.dragType === 'task' && dropData?.type === 'move') { + if (dragData?.dragType === 'task' && dropData?.type === 'move') { setters.set({ newTask: { task: dragData, type: 'move' } }) } else if (dropData && dragData) { if (!isTaskProps(dropData)) { @@ -67,59 +66,6 @@ export const onDragEnd = async ( } } else { switch (dragData.dragType) { - case 'now': - if (!dropData.scheduled) break - - const dayStart = getters.get('settings').dayStartEnd[0] - const startOfDay = DateTime.now() - .startOf('day') - .plus({ hours: dayStart }) - const today = toISO(startOfDay) - const tomorrow = toISO(startOfDay.plus({ days: 1 })) - const tasks = getters.get('tasks') - const futureTasks: Record = {} - - for (let task of _.values(tasks)) { - if (task.completed) continue - const scheduled = parseTaskDate(task) - if ( - scheduled && - !isDateISO(scheduled) && - scheduled >= today && - scheduled < tomorrow - ) { - if (task.queryParent) continue - let parent = task.parent - while (parent) { - if (tasks[parent].queryParent) continue - parent = tasks[parent].parent - } - if (futureTasks[scheduled]) futureTasks[scheduled].push(task) - else futureTasks[scheduled] = [task] - } - } - - const tasksByTime = _.sortBy(_.entries(futureTasks), 0) - const { hours: shiftHours, minutes: shiftMinutes } = DateTime.fromISO( - dropData.scheduled - ) - .diff(DateTime.fromISO(tasksByTime[0][0])) - .shiftTo('hours', 'minutes') - - if (!confirm(`Shift tasks by ${shiftHours}h${shiftMinutes}m?`)) break - - for (let [time, tasks] of tasksByTime) { - const timeParse = DateTime.fromISO(time) - await setters.patchTasks( - tasks.map((task) => task.id), - { - scheduled: toISO( - timeParse.plus({ hours: shiftHours, minutes: shiftMinutes }) - ), - } - ) - } - break case 'new_button': setters.set({ newTask: { task: { scheduled: dropData.scheduled }, type: 'new' }, diff --git a/src/services/parser.ts b/src/services/parser.ts index 2fb5fc1..6fc6d5a 100644 --- a/src/services/parser.ts +++ b/src/services/parser.ts @@ -21,7 +21,7 @@ import { toISO, } from './util' -const ISO_MATCH = '\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2})?' +export const ISO_MATCH = '\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2})?' const TASKS_EMOJI_SEARCH = new RegExp( `[${_.values(keyToTasksEmoji).join('')}] ?(${ISO_MATCH})?`, 'giu' diff --git a/src/services/util.ts b/src/services/util.ts index 862bbb1..212b617 100644 --- a/src/services/util.ts +++ b/src/services/util.ts @@ -126,7 +126,12 @@ export const splitHeading = (heading: string) => { } export const getHeading = ( - { path, page, priority }: Pick, + { + path, + page, + priority, + tags, + }: Pick, dailyNoteInfo: AppState['dailyNoteInfo'], groupBy: AppState['settings']['groupBy'], hidePaths: string[] = [] @@ -136,9 +141,11 @@ export const getHeading = ( if ( groupBy === 'priority' || (groupBy === 'hybrid' && priority !== TaskPriorities.DEFAULT) - ) + ) { heading = priorityNumberToSimplePriority[priority] - else if (groupBy === 'path' || groupBy === 'hybrid') { + } else if (groupBy === 'tags') { + heading = tags.sort().join(', ') + } else if (groupBy === 'path' || groupBy === 'hybrid') { // replace daily note const file = parseFileFromPath(heading) const date = parseDateFromPath(file, dailyNoteInfo) diff --git a/src/types/index.d.ts b/src/types/index.d.ts index e3ff6a9..a68e870 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -95,7 +95,6 @@ declare global { | ({ dragType: 'time' } & { start: string; end?: string }) | ({ dragType: 'due' } & { task: TaskProps }) | { dragType: 'new_button' } - | { dragType: 'now' } type DropData = | Partial