Skip to content

Commit

Permalink
jgclark.Dashboard 0.7.1
Browse files Browse the repository at this point in the history
  • Loading branch information
jgclark committed Nov 20, 2023
1 parent 441a824 commit ed1973d
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 105 deletions.
88 changes: 83 additions & 5 deletions helpers/NPParagraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
hyphenatedDateString,
isScheduled,
nowShortDateTimeISOString,
SCHEDULED_WEEK_NOTE_LINK,
RE_SCHEDULED_ISO_DATE,
SCHEDULED_WEEK_NOTE_LINK,
SCHEDULED_QUARTERLY_NOTE_LINK,
SCHEDULED_MONTH_NOTE_LINK,
SCHEDULED_YEARLY_NOTE_LINK,
Expand All @@ -23,8 +23,9 @@ import { getNPWeekData, getMonthData, getYearData, getQuarterData, toLocaleDateT
import { clo, JSP, logDebug, logError, logInfo, logWarn, timer } from '@helpers/dev'
import { getNoteType } from '@helpers/note'
import { findStartOfActivePartOfNote, isTermInMarkdownPath, isTermInURL, smartPrependPara } from '@helpers/paragraph'
import { RE_FIRST_SCHEDULED_DATE_CAPTURE } from '@helpers/regex'
import { getLineMainContentPos } from '@helpers/search'
import { isOpen } from '@helpers/utils'
import { hasScheduledDate, isOpen } from '@helpers/utils'

const pluginJson = 'NPParagraph'

Expand Down Expand Up @@ -1306,12 +1307,33 @@ export function highlightParagraphInEditor(objectToTest: any, thenStopHighlight:

/**
* Appends a '@done(...)' date to the given paragraph if the user has turned on the setting 'add completion date'.
* TODO: Cope with non-daily scheduled dates
* @param {TParagraph} para
* @param {boolean} useScheduledDateAsCompletionDate?
* @returns
*/
export function markComplete(para: TParagraph): boolean {
export function markComplete(para: TParagraph, useScheduledDateAsCompletionDate: boolean = false): boolean {
if (para) {
const doneString = DataStore.preference('isAppendCompletionLinks') ? ` @done(${nowShortDateTimeISOString})` : ''
// Default to using current date/time
let dateString = nowShortDateTimeISOString
if (useScheduledDateAsCompletionDate) {
// But use scheduled date instead if found
if (hasScheduledDate(para.content)) {
const captureArr = para.content.match(RE_FIRST_SCHEDULED_DATE_CAPTURE) ?? []
clo(captureArr)
dateString = captureArr[1]
logDebug('markComplete', `will use scheduled date ${dateString} as completion date`)
} else {
// Use date of the note if it has one. (What does para.note.date return for non-daily calendar notes?)
if (para.note?.type === 'Calendar' && para.note.date) {
dateString = hyphenatedDate(para.note.date)
logDebug('markComplete', `will use date of note ${dateString} as completion date`)
}
}
} else {
dateString = nowShortDateTimeISOString
}
const doneString = DataStore.preference('isAppendCompletionLinks') ? ` @done(${dateString})` : ''

if (para.type === 'open') {
para.type = 'done'
Expand Down Expand Up @@ -1376,14 +1398,37 @@ export function completeItem(filenameIn: string, content: string): boolean {
if (typeof possiblePara === 'boolean') {
return false
}
return markComplete(possiblePara)
return markComplete(possiblePara, false)
}
catch (error) {
logError(pluginJson, `NPP/completeItem: ${error.message} for note '${filenameIn}'`)
return false
}
}

/**
* Complete a task/checklist item (given by 'content') in note (given by 'filenameIn').
* Designed to be called when you're not in an Editor (e.g. an HTML Window).
* Appends a '@done(...)' date to the line if the user has selected to 'add completion date' - but uses completion date of the day it was scheduled to be done.
* @param {string} filenameIn to look in
* @param {string} content to find
* @returns {boolean} true if succesful, false if unsuccesful
*/
export function completeItemEarlier(filenameIn: string, content: string): boolean {
try {
logDebug('NPP/completeItemEarlier', `starting with filename: ${filenameIn}, content: <${content}>`)
const possiblePara = findParaFromStringAndFilename(filenameIn, content)
if (typeof possiblePara === 'boolean') {
return false
}
return markComplete(possiblePara, true)
}
catch (error) {
logError(pluginJson, `NPP/completeItemEarlier: ${error.message} for note '${filenameIn}'`)
return false
}
}

/**
* Cancel a task/checklist item (given by 'content') in note (given by 'filenameIn').
* Designed to be called when you're not in an Editor (e.g. an HTML Window).
Expand Down Expand Up @@ -1614,3 +1659,36 @@ export function makeBasicParasFromContent(content: string): Array<any> {
return []
}
}

/**
* Toggle given paragraph type between (open) Task and Checklist
* @param {TParagraph} para to toggle
* @returns {ParagraphType} new type
*/
export function toggleTaskChecklistParaType(filename: string, content: string): string {
try {
// find para
const possiblePara: TParagraph | boolean = findParaFromStringAndFilename(filename, content)
if (typeof possiblePara === 'boolean') {
throw new Error('toggleTaskChecklistParaType: no para found')
}

// Get the paragraph to change
const thisPara = possiblePara
const thisNote = thisPara.note
const existingType = thisPara.type
logDebug('toggleTaskChecklistParaType', `toggling in filename: ${filename}`)
if (existingType === 'checklist') {
thisPara.type = 'open'
thisNote.updateParagraph(thisPara)
return 'open'
} else {
thisPara.type = 'checklist'
thisNote.updateParagraph(thisPara)
return 'checklist'
}
} catch (error) {
logError('toggleTaskChecklistParaType', error.message)
return '(error)'
}
}
43 changes: 38 additions & 5 deletions helpers/dateTime.js
Original file line number Diff line number Diff line change
Expand Up @@ -1014,17 +1014,20 @@ export function calcOffsetDate(baseDateStrIn: string, interval: string): Date |
* Calculate an offset date of any date interval NP supports, and return _in whichever format was supplied_.
* v5 method, using 'moment' library to avoid using NP calls, now extended to allow for Weekly, Monthly etc. strings as well.
* Moment docs: https://momentjs.com/docs/#/get-set/
* - 'baseDateIn' the base date as a string in any of the formats that NP supports: YYYY-MM-DD, YYYYMMDD (filename format), YYYY-Wnn, YYYY-MM, YYYY-Qn, YYYY.
* - 'offsetInterval' of form +nn[bdwmq] or -nn[bdwmq], where 'b' is weekday (i.e. Monday - Friday in Europe and Americas)
* - 'adaptOutputInterval' (optional). Options: 'shorter', 'longer', 'offset', 'base', 'day', 'week', 'month', 'quarter', 'year'
* @author @jgclark
*
* @param {string} baseDateIn the base date as a string in any of the formats that NP supports: YYYY-MM-DD, YYYYMMDD (filename format), YYYY-Wnn, YYYY-MM, YYYY-Qn, YYYY.
* @param {offsetInterval} string of form +nn[bdwmq] or -nn[bdwmq], where 'b' is weekday (i.e. Monday - Friday in Europe and Americas)
* @param {string?} adaptOutputInterval. Options:
* @param {string} offsetInterval of form +nn[bdwmq] or -nn[bdwmq], where 'b' is weekday (i.e. Monday - Friday in Europe and Americas)
* @param {string?} adaptOutputInterval. Options: 'shorter', 'longer', 'offset', 'base', 'day', 'week', 'month', 'quarter', 'year'
* - 'shorter': keep the shorter of the two calendar types. E.g. a daily date + 1w -> daily date. Or '2023-07' + '2w' -> '2023-W28'.
* - 'longer': use the longer of the two calendar types. E.g. a daily date + 1w -> weekly date.
* - 'offset': keep type of the offsetInterval.
* - 'base': (default) keep the type of the base date.
* @returns {string} new date in the same format that was supplied
* @test - available in jest file
* - 'day', 'week', 'month', 'quarter', 'year': lock to that calendar type.
* @returns {string} new date in the requested format
* @tests - available in jest file (though not for the most recent adaptOutputInterval options)
*/
export function calcOffsetDateStr(baseDateIn: string, offsetInterval: string, adaptOutputInterval: string = 'base'): string {
try {
Expand Down Expand Up @@ -1100,6 +1103,36 @@ export function calcOffsetDateStr(baseDateIn: string, offsetInterval: string, ad
}
break
}
case 'day': {
const offsetMomentFormat = getNPDateFormatForDisplayFromOffsetUnit('d')
newDateStr = moment(offsetDate).format(offsetMomentFormat)
logDebug('dateTime / cODS', `- 'month' output: changed format to ${offsetMomentFormat}`)
break
}
case 'week': {
const offsetMomentFormat = getNPDateFormatForDisplayFromOffsetUnit('w')
newDateStr = moment(offsetDate).format(offsetMomentFormat)
logDebug('dateTime / cODS', `- 'month' output: changed format to ${offsetMomentFormat}`)
break
}
case 'month': {
const offsetMomentFormat = getNPDateFormatForDisplayFromOffsetUnit('m')
newDateStr = moment(offsetDate).format(offsetMomentFormat)
logDebug('dateTime / cODS', `- 'month' output: changed format to ${offsetMomentFormat}`)
break
}
case 'quarter': {
const offsetMomentFormat = getNPDateFormatForDisplayFromOffsetUnit('q')
newDateStr = moment(offsetDate).format(offsetMomentFormat)
logDebug('dateTime / cODS', `- 'month' output: changed format to ${offsetMomentFormat}`)
break
}
case 'year': {
const offsetMomentFormat = getNPDateFormatForDisplayFromOffsetUnit('y')
newDateStr = moment(offsetDate).format(offsetMomentFormat)
logDebug('dateTime / cODS', `- 'month' output: changed format to ${offsetMomentFormat}`)
break
}
default: {
// i.e. 'base'
newDateStr = newDateStrFromBaseDateType
Expand Down
31 changes: 15 additions & 16 deletions helpers/note.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ export function filterNotesAgainstExcludeFolders(notes: Array<TNote>, excludedFo
let isInIgnoredFolder = false
excludedFolders.forEach((folder) => {
if (note.filename.includes(`${folder.trim()}/`)) {
// logDebug('note/filterNotesAgainstExcludeFolders', `ignoring folder="${folder}" note.filename="${note.filename}}"`)
logDebug('note/fNAEF', `ignoring folder="${folder}" note.filename="${note.filename}}"`)
isInIgnoredFolder = true
}
})
Expand All @@ -594,35 +594,34 @@ export function filterNotesAgainstExcludeFolders(notes: Array<TNote>, excludedFo
* @param {boolean} excludeNonMarkdownFiles - if true, exclude non-markdown files (must have .txt or .md to get through)
* @returns {Array<TNote>} - array of notes that are not in excluded folders
*/
export function filterParasAgainstExcludeFolders(paras: Array<TParagraph>, excludedFolders: Array<string>, excludeNonMarkdownFiles: boolean = false): Array<TParagraph> {
export function filterOutParasInExcludeFolders(paras: Array<TParagraph>, excludedFolders: Array<string>): Array<TParagraph> {
try {
if (!excludedFolders) {
logDebug('note/filterParasAgainstExcludeFolders', `excludedFolders list is empty, so will return all paras`)
logDebug('note/filterOutParasInExcludeFolders', `excludedFolders list is empty, so will return all paras`)
return paras
}
// $FlowIgnore(incompatible-type)
const noteList: Array<CoreNoteFields> = paras.map((p) => p.note)
if (noteList.length > 0) {
const noteListFiltered = filterNotesAgainstExcludeFolders(noteList, excludedFolders, excludeNonMarkdownFiles)

if (!noteListFiltered) {
logInfo('note/filterParasAgainstExcludeFolders', `all notes have been excluded`)
return []
}
const noteFilenameList: Array<string> = paras.map((p) => p.note.filename)
const dedupedNoteFilenameList = [...new Set(noteFilenameList)]
logDebug('note/filterOutParasInExcludeFolders', `noteFilenameList ${noteFilenameList.length} long; dedupedNoteFilenameList ${dedupedNoteFilenameList.length} long`)

if (dedupedNoteFilenameList.length > 0) {
const wantedFolders = getFilteredFolderList(excludedFolders)
// filter out paras not in these notes
const parasFiltered = paras.filter((p) => {
const thisNote = p.note
const isInIgnoredFolder = noteListFiltered.includes(thisNote)
return !isInIgnoredFolder
const thisNoteFilename = p.note?.filename ?? 'error'
const thisNoteFolder = getFolderFromFilename(thisNoteFilename)
const isInWantedFolder = wantedFolders.includes(thisNoteFolder)
// console.log(`${thisNoteFilename} isInWantedFolder = ${String(isInWantedFolder)}`)
return isInWantedFolder
})
return parasFiltered
} else {
logDebug('note/filterParasAgainstExcludeFolders', `found no corresponding notes`)
logDebug('note/filterOutParasInExcludeFolders', `found no corresponding notes`)
return []
}
} catch (err) {
logError('note/filterParasAgainstExcludeFolders', err)
logError('note/filterOutParasInExcludeFolders', err)
return []
}
}
Expand Down
1 change: 1 addition & 0 deletions helpers/regex.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

// Times, Dates
export const RE_SCHEDULED_DATES_G: RegExp = />(today|tomorrow|yesterday|(([0-9]{4})(-((0[1-9]|1[0-2])(-(0[1-9]|1[0-9]|2[0-9]|3[0-1]))?|Q[1-4]|W0[1-9]|W[1-4]\d|W5[0-3]))?))/g // from Eduard, but tweaked to ignore ones that start with @ rather than >
export const RE_FIRST_SCHEDULED_DATE_CAPTURE: RegExp = />((today|tomorrow|yesterday|(([0-9]{4})(-((0[1-9]|1[0-2])(-(0[1-9]|1[0-9]|2[0-9]|3[0-1]))?|Q[1-4]|W0[1-9]|W[1-4]\d|W5[0-3]))?)))/ // adapted from above
export const RE_ARROW_DATES_G: RegExp = />(today|tomorrow|yesterday|(([0-9]{4})(-((0[1-9]|1[0-2])(-(0[1-9]|1[0-9]|2[0-9]|3[0-1]))?|Q[1-4]|W0[1-9]|W[1-4]\d|W5[0-3]))?))</g // as above but with a closing '<'

// In helpers/dateTime.js:
Expand Down
5 changes: 5 additions & 0 deletions jgclark.Dashboard/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# What's changed in 🎛 Dashboard plugin?
For more details see the [plugin's README](https://github.com/NotePlan/plugins/tree/main/jgclark.Dashboard/).

## [0.7.1] - 2023-11-???
### Added
- add '->today' button on Yesterday section items
- ??? new button for completing an overdue task on the day it was due

## [0.7.0] - 2023-11-17
### Added
- new optional 'Overdue Tasks' section (requested by @dwertheimer and @george65). There are some new settings to help tailor this to your way of working.
Expand Down
51 changes: 37 additions & 14 deletions jgclark.Dashboard/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"plugin.author": "Jonathan Clark",
"plugin.url": "https://github.com/NotePlan/plugins/tree/main/jgclark.Dashboard/",
"plugin.changelog": "https://github.com/NotePlan/plugins/blob/main/jgclark.Dashboard/CHANGELOG.md",
"plugin.version": "0.7.0",
"plugin.lastUpdateInfo": "v0.7.0: new optional 'Yesterday' and 'Overdue' sections.???\nv0.6.3: tag/mention section now excludes tasks/checklists that are scheduled to future dates.\nv0.6.2: Adapt dashboard to use NotePlan's new multiple HTML windows capability.\nv0.6.1: adds new section for a specific #tag or @mention.\nv0.6.0: adds tooltip on displayed tasks that allows task to be moved on to next day, week etc. Adds lots of new theming support. Plus other visual polish and fixes.\nv0.5.1: display improvements + bug fixes.\nv0.5.0: Can now filter out lower-priority items. Can cancel or add tasks and checklists. New optional 'hastags/mentions to show' section.\nv0.4.2: various updates to window handling.v0.4.1: bug fix, polish and demo updates.",
"plugin.version": "0.7.1",
"plugin.lastUpdateInfo": "v0.7.1: ???\nv0.7.0: new optional 'Yesterday' and 'Overdue Tasks' sections.\nv0.6.3: tag/mention section now excludes tasks/checklists that are scheduled to future dates.\nv0.6.2: Adapt dashboard to use NotePlan's new multiple HTML windows capability.\nv0.6.1: adds new section for a specific #tag or @mention.\nv0.6.0: adds tooltip on displayed tasks that allows task to be moved on to next day, week etc. Adds lots of new theming support. Plus other visual polish and fixes.",
"plugin.requiredFiles": [
"commsSwitchboard.js",
"dashboard.css",
Expand Down Expand Up @@ -177,26 +177,34 @@
{
"key": "showYesterdaySection",
"title": "Show section for Yesterday?",
"description": "If true, then a 'Yesterday' section for Yesterday's open items will be added after the 'Today' section.",
"description": "Whether to show a 'Yesterday' section for Yesterday's open items, after the 'Today' section.",
"type": "bool",
"default": false,
"required": true
},
{
"key": "showMonthSection",
"hidden": true,
"title": "Show section for Monthly note?",
"description": "",
"key": "showWeekSection",
"title": "Show section for Week?",
"description": "Whether to show a 'Week' section for Week's open items, after the 'Today' section.",
"type": "bool",
"default": true,
"required": true
},
{
"key": "showMonthSection",
"title": "Show section for Month?",
"description": "Whether to show a 'Month' section for open items in this month's calendar note",
"type": "hidden",
"_type": "bool",
"default": true,
"required": true
},
{
"key": "showQuarterSection",
"hidden": true,
"title": "Show section for Quarterly note?",
"description": "",
"type": "bool",
"title": "Show section for Quarter?",
"description": "Whether to show a 'Qaurter' section for open items in this quarter's calendar note",
"type": "hidden",
"_type": "bool",
"default": true,
"required": true
},
Expand Down Expand Up @@ -233,14 +241,14 @@
"required": true
},
{
"type": "separator"
"_type": "separator"
},
{
"key": "showProjectSection",
"hidden": true,
"title": "Show section for Overdue Projects overdue for review?",
"description": "",
"type": "bool",
"type": "hidden",
"_type": "bool",
"default": true,
"required": true
},
Expand Down Expand Up @@ -283,6 +291,21 @@
"type": "bool",
"default": false,
"required": true
},
{
"type": "separator"
},
{
"type": "heading",
"title": "Experimental Features"
},
{
"key": "showExtraButtons",
"title": "Show extra buttons for overdue tasks?",
"description": "Show experimental extra control buttons on overdue tasks:\n- toggle between checklist and todo types\n- mark the task complete at the date it was due (not today).",
"type": "bool",
"default": false,
"required": true
}
]
}
Loading

0 comments on commit ed1973d

Please sign in to comment.