From 6098f5767f7550bca59af614e5c6750db859f5d2 Mon Sep 17 00:00:00 2001 From: Joe Carstairs <118172583+jcarstairs-scottlogic@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:21:15 +0100 Subject: [PATCH] =?UTF-8?q?Revert=20"WIP:=20When=20friendly=20dates=20are?= =?UTF-8?q?=20enabled,=20group=20elements=20use=20friendly=20dat=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit c3fceeae7664490a80f3c5c7881bade658eca9cf. --- src/main/modules/Attributes.tsx | 48 +++++------- .../modules/DataRequest/CreateTodoObjects.tsx | 14 ++-- src/main/modules/DataRequest/SortAndGroup.tsx | 19 +---- src/main/modules/Date.tsx | 78 ++++--------------- src/renderer/Grid/Group.tsx | 10 +-- src/renderer/Shared.tsx | 78 +++++++++---------- src/types.tsx | 48 +++--------- 7 files changed, 98 insertions(+), 197 deletions(-) diff --git a/src/main/modules/Attributes.tsx b/src/main/modules/Attributes.tsx index e5ab34a2..4464b87b 100644 --- a/src/main/modules/Attributes.tsx +++ b/src/main/modules/Attributes.tsx @@ -1,24 +1,15 @@ -const attributes: Attributes = { +let attributes: Attributes = { priority: {}, projects: {}, contexts: {}, - due: {} as DateAttribute, - t: {} as DateAttribute, + due: {}, + t: {}, rec: {}, pm: {}, - created: {} as DateAttribute, - completed: {} as DateAttribute, + created: {}, + completed: {}, }; -function getDateAttributes(): DateAttributes { - return { - due: attributes.due, - t: attributes.t, - created: attributes.created, - completed: attributes.completed, - }; -} - function incrementCount(countObject: any, key: any | null, notify: boolean): void { if(key) { let previousCount: number = parseInt(countObject[key]?.count) || 0; @@ -30,35 +21,34 @@ function incrementCount(countObject: any, key: any | null, notify: boolean): voi } function updateAttributes(todoObjects: TodoObject[], sorting: Sorting[], reset: boolean) { - - const attributeKeys = Object.keys(attributes) as AttributeKey[]; - - for (const key of attributeKeys) { - - for (const attributeKey in attributes[key]) { + + Object.keys(attributes).forEach((key) => { + + Object.keys(attributes[key]).forEach((attributeKey) => { (reset) ? attributes[key] = {} : attributes[key][attributeKey].count = 0 - }; + }); - for (const todoObject of todoObjects) { + todoObjects.forEach((todoObject: TodoObject) => { const value = todoObject[key as keyof TodoObject]; const notify: boolean = (key === 'due') ? !!todoObject?.notify : false; - + if(Array.isArray(value)) { - for (const element of value) { + value.forEach((element) => { if(element !== null) { const attributeKey = element as keyof Attribute; - + incrementCount(attributes[key], attributeKey, notify); } - } + }); } else { if(value !== null) { incrementCount(attributes[key], value, notify); } } - } + }); attributes[key] = Object.fromEntries(Object.entries(attributes[key]).sort(([a], [b]) => a.localeCompare(b))); - } + }); + attributes = Object.fromEntries(sorting.map((item) => [item.value, attributes[item.value]])); } -export { attributes, getDateAttributes, updateAttributes }; +export { attributes, updateAttributes }; diff --git a/src/main/modules/DataRequest/CreateTodoObjects.tsx b/src/main/modules/DataRequest/CreateTodoObjects.tsx index 1f1d05fe..19546210 100644 --- a/src/main/modules/DataRequest/CreateTodoObjects.tsx +++ b/src/main/modules/DataRequest/CreateTodoObjects.tsx @@ -31,12 +31,12 @@ function createTodoObject(lineNumber: number, string: string, attributeType?: st content = JsTodoTxtObject.toString().replaceAll(' [LB] ', String.fromCharCode(16)); const body = JsTodoTxtObject.body().replaceAll(' [LB] ', ' '); - const speakingDates = extractSpeakingDates(body); - const due = speakingDates.due?.date || null; - const dueString = speakingDates.due?.string || null; - const notify = speakingDates.due?.notify || false; - const t = speakingDates.t?.date || null; - const tString = speakingDates.t?.string || null; + const speakingDates: DateAttributes = extractSpeakingDates(body); + const due = speakingDates['due:']?.date || null; + const dueString = speakingDates['due:']?.string || null; + const notify = speakingDates['due:']?.notify || false; + const t = speakingDates['t:']?.date || null; + const tString = speakingDates['t:']?.string || null; const hidden = extensions.some(extension => extension.key === 'h' && extension.value === '1'); const pm: string | number | null = extensions.find(extension => extension.key === 'pm')?.value || null; const rec = extensions.find(extension => extension.key === 'rec')?.value || null; @@ -97,4 +97,4 @@ function createTodoObjects(fileContent: string | null): TodoObject[] | [] { return todoObjects; } -export { createTodoObjects, createTodoObject, linesInFile }; +export { createTodoObjects, createTodoObject, linesInFile }; \ No newline at end of file diff --git a/src/main/modules/DataRequest/SortAndGroup.tsx b/src/main/modules/DataRequest/SortAndGroup.tsx index 59b72668..c3b717d5 100644 --- a/src/main/modules/DataRequest/SortAndGroup.tsx +++ b/src/main/modules/DataRequest/SortAndGroup.tsx @@ -1,6 +1,4 @@ import { config } from '../../config'; -import { getDateAttributes } from '../Attributes'; -import { friendlyDateGroup } from '../Date'; function sortAndGroupTodoObjects(todoObjects: TodoObject[], sorting: Sorting[]): TodoGroup { const fileSorting: boolean = config.get('fileSorting'); @@ -33,24 +31,13 @@ function sortAndGroupTodoObjects(todoObjects: TodoObject[], sorting: Sorting[]): return 0; } - function getGroupKey(todoObject: TodoObject, attributeKey: string) { - const useFriendlyDates = config.get('useHumanFriendlyDates'); - const isDateAttribute = Object.keys(getDateAttributes()).includes(attributeKey); - - if (useFriendlyDates && isDateAttribute) { - return friendlyDateGroup(todoObject[attributeKey]); - } - - return todoObject[attributeKey]; - } - function groupTodoObjectsByKey(todoObjects: TodoObject[], attributeKey: string) { const grouped: TodoGroup = {}; for (const todoObject of todoObjects) { - const groupKey = getGroupKey(todoObject, attributeKey); + const groupKey = todoObject[attributeKey] || null; if (!grouped[groupKey]) { grouped[groupKey] = { - title: todoObject[attributeKey], + title: groupKey, todoObjects: [], visible: false }; @@ -83,4 +70,4 @@ function sortAndGroupTodoObjects(todoObjects: TodoObject[], sorting: Sorting[]): return sortedAndGroupedTodoObjects; } -export { sortAndGroupTodoObjects }; +export { sortAndGroupTodoObjects }; \ No newline at end of file diff --git a/src/main/modules/Date.tsx b/src/main/modules/Date.tsx index da87b4de..fd51ca31 100644 --- a/src/main/modules/Date.tsx +++ b/src/main/modules/Date.tsx @@ -1,5 +1,5 @@ import Sugar from 'sugar'; -import dayjs, { Dayjs } from 'dayjs'; +import dayjs from 'dayjs'; import { config } from '../config'; function mustNotify(date: Date): boolean { @@ -9,9 +9,9 @@ function mustNotify(date: Date): boolean { } function replaceSpeakingDatesWithAbsoluteDates(string: string): string { - const speakingDates = extractSpeakingDates(string); - const due: DateAttribute = speakingDates.due; - const t: DateAttribute = speakingDates.t; + const speakingDates: DateAttributes = extractSpeakingDates(string); + const due: DateAttribute = speakingDates['due:']; + const t: DateAttribute = speakingDates['t:']; if(due.date) { string = string.replace(due.string!, due.date); } @@ -50,22 +50,22 @@ function processDateWithSugar(string: string, type: string): DateAttribute | nul return lastMatch; } -function extractSpeakingDates(body: string): Pick { - const expressions: { pattern: RegExp, key: 'due'|'t', type: string }[] = [ - { pattern: /due:(?!(\d{4}-\d{2}-\d{2}))(.*?)(?=t:|$)/g, key: 'due', type: 'relative' }, - { pattern: /due:(\d{4}-\d{2}-\d{2})/g, key: 'due', type: 'absolute' }, - { pattern: /t:(?!(\d{4}-\d{2}-\d{2}))(.*?)(?=due:|$)/g, key: 't', type: 'relative' }, - { pattern: /t:(\d{4}-\d{2}-\d{2})/g, key: 't', type: 'absolute' }, +function extractSpeakingDates(body: string): DateAttributes { + const expressions = [ + { pattern: /due:(?!(\d{4}-\d{2}-\d{2}))(.*?)(?=t:|$)/g, key: 'due:', type: 'relative' }, + { pattern: /due:(\d{4}-\d{2}-\d{2})/g, key: 'due:', type: 'absolute' }, + { pattern: /t:(?!(\d{4}-\d{2}-\d{2}))(.*?)(?=due:|$)/g, key: 't:', type: 'relative' }, + { pattern: /t:(\d{4}-\d{2}-\d{2})/g, key: 't:', type: 'absolute' }, ]; - const speakingDates: Pick = { - 'due': { + const speakingDates: DateAttributes = { + 'due:': { date: null, string: null, type: null, notify: false, }, - 't': { + 't:': { date: null, string: null, type: null, @@ -86,54 +86,4 @@ function extractSpeakingDates(body: string): Pick { return speakingDates; } -function friendlyDateGroup(date: Dayjs): FriendlyDateGroup | null { - const today = dayjs(); - - if (!date || !date.isValid()) { - return null; - } - - if (date.isBefore(today.subtract(1, 'week'))) { - return 'before-last-week'; - } - - if (date.isBefore(today.subtract(1, 'day'))) { - return 'last-week'; - } - - if (date.isBefore(today)) { - return 'yesterday'; - } - - if (date.isSame(today)) { - return 'today'; - } - - if (date.isSame(today.add(1, 'day'))) { - return 'tomorrow'; - } - - if (date.isBefore(today.add(1, 'week').add(1, 'day'))) { - return 'this-week'; - } - - if (date.isBefore(today.add(2, 'week').add(1, 'day'))) { - return 'next-week'; - } - - if (date.isBefore(today.add(1, 'month').add(1, 'day'))) { - return 'this-month'; - } - - if (date.isBefore(today.add(2, 'month').add(1, 'day'))) { - return 'next-month'; - } - - return 'after-next-month'; -} - -export { - extractSpeakingDates, - friendlyDateGroup, - replaceSpeakingDatesWithAbsoluteDates -}; +export { extractSpeakingDates, replaceSpeakingDatesWithAbsoluteDates }; diff --git a/src/renderer/Grid/Group.tsx b/src/renderer/Grid/Group.tsx index 9e9efdb9..2d5df24d 100644 --- a/src/renderer/Grid/Group.tsx +++ b/src/renderer/Grid/Group.tsx @@ -5,9 +5,8 @@ import Divider from '@mui/material/Divider'; import dayjs from 'dayjs'; import updateLocale from 'dayjs/plugin/updateLocale'; import { friendlyDate } from 'renderer/Shared'; -import type { i18n } from 'renderer/Settings/LanguageSelector'; -import { type WithTranslation, withTranslation } from 'react-i18next'; -import { getDateAttributes } from 'main/modules/Attributes'; +import { i18n } from 'renderer/Settings/LanguageSelector'; +import { WithTranslation, withTranslation } from 'react-i18next'; dayjs.extend(updateLocale); interface FormatGroupElementProps { @@ -19,13 +18,12 @@ interface FormatGroupElementProps { function formatGroupElement({ groupElement, settings, t, todotxtAttribute }: FormatGroupElementProps) { // If group element is a date, then format according to user preferences - const dateAttributeKeys = Object.keys(getDateAttributes()); if ( - dateAttributeKeys.includes(todotxtAttribute) + ['due', 't'].includes(todotxtAttribute) && dayjs(groupElement).isValid() && settings.useHumanFriendlyDates ) { - return friendlyDate(groupElement, todotxtAttribute, t).pop(); + return friendlyDate(groupElement, todotxtAttribute, settings, t).pop(); } // No transformation required: display as-is diff --git a/src/renderer/Shared.tsx b/src/renderer/Shared.tsx index c72b2e6b..ccf2c327 100644 --- a/src/renderer/Shared.tsx +++ b/src/renderer/Shared.tsx @@ -5,7 +5,6 @@ import calendar from 'dayjs/plugin/calendar'; import weekday from 'dayjs/plugin/weekday'; import updateLocale from 'dayjs/plugin/updateLocale'; import { i18n } from './Settings/LanguageSelector'; -import { friendlyDateGroup } from 'main/modules/Date'; dayjs.extend(relativeTime); dayjs.extend(duration); dayjs.extend(calendar); @@ -69,47 +68,48 @@ export const friendlyDate = (value: string, attributeKey: string, settings: Sett weekStart: settings.weekStart, }); + const today = dayjs(); const date = dayjs(value); - const group = friendlyDateGroup(date); - const results = []; - switch (group) { - case null: - // This should never happen, as `date` will always be a valid date - break; - case 'before-last-week': - results.push((attributeKey === 'due') ? t('drawer.attributes.overdue') : t('drawer.attributes.elapsed')); - break; - case 'last-week': - results.push((attributeKey === 'due') ? t('drawer.attributes.overdue') : t('drawer.attributes.elapsed')); - results.push(t('drawer.attributes.lastWeek')); - break; - case 'yesterday': - results.push((attributeKey === 'due') ? t('drawer.attributes.overdue') : t('drawer.attributes.elapsed')); - results.push(t('drawer.attributes.yesterday')); - break; - case 'today': - results.push(t('drawer.attributes.today')); - break; - case 'tomorrow': - results.push(t('drawer.attributes.tomorrow')); - break; - case 'this-week': - results.push(t('drawer.attributes.thisWeek')); - break; - case 'next-week': - results.push(t('drawer.attributes.nextWeek')); - break; - case 'this-month': - results.push(t('drawer.attributes.thisMonth')); - break; - case 'next-month': - results.push(t('drawer.attributes.nextMonth')); - break; - case 'after-next-month': - results.push(dayjs(date).format('YYYY-MM-DD')); - break; + if (date.isBefore(today, 'day')) { + results.push((attributeKey === 'due') ? t('drawer.attributes.overdue') : t('drawer.attributes.elapsed')); + } + + if (date.isAfter(today.subtract(1, 'week').startOf('week').subtract(1, 'day')) && date.isBefore(today.subtract(1, 'week').endOf('week'))) { + results.push(t('drawer.attributes.lastWeek')); + } + + if (date.isBefore(today.endOf('month')) && date.isAfter(today.subtract(1, 'day'), 'day')) { + results.push(t('drawer.attributes.thisMonth')); + } + + if (date.isSame(today, 'week')) { + results.push(t('drawer.attributes.thisWeek')); + } + + if (date.isSame(today.subtract(1, 'day'), 'day')) { + results.push(t('drawer.attributes.yesterday')); + } + + if (date.isSame(today, 'day')) { + results.push(t('drawer.attributes.today')); + } + + if (date.isSame(today.add(1, 'day'), 'day')) { + results.push(t('drawer.attributes.tomorrow')); + } + + if (date.isSame(today.add(1, 'week'), 'week')) { + results.push(t('drawer.attributes.nextWeek')); + } + + if (date.month() === today.add(1, 'month').month()) { + results.push(t('drawer.attributes.nextMonth')); + } + + if (date.isAfter(today.add(1, 'month').endOf('month'))) { + results.push(dayjs(date).format('YYYY-MM-DD')); } return results; diff --git a/src/types.tsx b/src/types.tsx index a1c62d1b..852da953 100644 --- a/src/types.tsx +++ b/src/types.tsx @@ -168,36 +168,24 @@ declare global { exclude: boolean; } - type AttributeKey = - 'priority' - | 'projects' - | 'contexts' - | 'due' - | 't' - | 'rec' - | 'pm' - | 'created' - | 'completed'; - - type DateAttributeKey = AttributeKey & ( - 'due' - | 't' - | 'created' - | 'completed' - ); - interface Attribute { [key: string]: number | boolean; } - type Attributes = { - [attributeKey in AttributeKey]: - attributeKey extends DateAttributeKey - ? DateAttribute - : { [key: string]: Attribute; }; + interface Attributes { + [key: string]: { + [key: string]: Attribute; + } } - type DateAttributes = Pick; + type DateAttributes = { + [key: string]: { + date: string | null; + string: string | null; + type: string | null; + notify: boolean; + }; + }; type DateAttribute = { date: string | null; @@ -241,18 +229,6 @@ declare global { }; type VisibleSettings = Record; - - type FriendlyDateGroup = - | 'before-last-week' - | 'last-week' - | 'yesterday' - | 'today' - | 'tomorrow' - | 'this-week' - | 'next-week' - | 'this-month' - | 'next-month' - | 'after-next-month'; } export {};