Skip to content

Commit

Permalink
Summaries WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jgclark committed Oct 10, 2023
1 parent 86af048 commit 5b9a676
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 32 deletions.
4 changes: 2 additions & 2 deletions helpers/NPFrontMatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ export function _sanitizeFrontmatterText(originalText: string, removeTemplateTag
const unfilteredFmText = _getFMText(originalText)
const hasTags = hasTemplateTagsInFM(unfilteredFmText)
if (hasTags && !removeTemplateTagsInFM) {
logWarn(
logDebug(
`FYI: _sanitizeFrontmatterText: getAttributes was called for a template which has template tags in the frontmatter. This is generally only advisable if you send getAttributes with the second param set to true. Ignore this warning if you meant to do this and it's working fine for you. Template text was: "${originalText}"`,
)
}
Expand Down Expand Up @@ -623,6 +623,6 @@ export function getAttributes(templateData: string = '', removeTemplateTagsInFM?
*/
export function getBody(templateData: string = ''): string {
if (!templateData) return ''
const fmData = getSanitizedFmParts(templateData, true)
const fmData = getSanitizedFmParts(templateData)
return fmData && fmData?.body ? fmData.body : ''
}
8 changes: 8 additions & 0 deletions helpers/NPdateTime.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ export async function getPeriodStartEndDates(
logDebug('getPeriodStartEndDates', `starting with periodType = ${periodType}, TZOffset = ${TZOffset}, excludeToday? ${String(excludeToday)}.`)

switch (periodType) {
case 'today': {
fromDateMom = fromDateMom.startOf('day')
fromDate = fromDateMom.toDate()
toDateMom = toDateMom.endOf('day')
toDate = toDateMom.toDate()
periodString = 'today'
break
}
case 'lm': {
// fromDate = Calendar.addUnitToDate(Calendar.dateFrom(y, m, 1, 0, 0, 0), 'minute', -TZOffset) // go to start of this month
// fromDate = Calendar.addUnitToDate(fromDate, 'month', -1) // -1 month
Expand Down
7 changes: 4 additions & 3 deletions jgclark.Summaries/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# What's Changed in ⏱ Habits and Summaries plugin?
(And see the full [README](https://github.com/NotePlan/plugins/tree/main/jgclark.Summaries).)

<!-- ## [0.20.0b2] - 2023-10-??? (unreleased)
## [0.20.0b2] - 2023-10-??? (unreleased)
### Added
- ??? make below work with all options -->
- new **today progress** command that ???? This can also be invoked by an x-callback call, ??? or through a template call.
- ??? make below work with all options

## [0.20.0b1] - 2023-10-08 (unreleased)
### Added
- new **heatmap for tag** command that displays a 'heatmap' chart of a chosen tag's values for each day (e.g. all `@work(...)` values from daily notes)
- new **/Habits+Summaries:update plugin settings** command, that allows settings to be changed on iOS/iPadOS.
- new **Habits+Summaries:update plugin settings** command, that allows settings to be changed on iOS/iPadOS.

## [0.19.4] - 2023-09-26 unreleased
### Added
Expand Down
17 changes: 16 additions & 1 deletion jgclark.Summaries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This Plugin lets you do the following sorts of things:
<img alt="Habit Tracker example" src="ipu-2w-with-sparkline.jpg" width=360px/>

- show your progress over the last 2 weeks against your goal of getting an average 8 hours `@sleep`
- show your total Calorie count from different mentions in your daily note
- count every time you've noted you've visited `#family` or watched `#tv` this month
- count the times you've met with staff member `@alice` this year so far
- sum the length of your `@run`s in the last quarter
Expand Down Expand Up @@ -151,7 +152,21 @@ Note: The 'key' part and any string-based value part must be enclosed in **doubl

Note: The JSON parts needs to be **urlencoded** before it can be used. (For help with this, see the **Get-X-Callback-URL command** from the "Link Creator" Plugin. Select RUN a Plugin command > progressUpdate ...)

## periodStats command (aliases: statsPeriod, stp)
## 'today progress' command (alias: 'tp')
Sometimes you want to have a summary of progress on something within a day -- for example `@carlories(...)` or `@exercise(...)`. To summarise these from today's daily note use **today progress**, which works in the same way as **appendProgressUpdate**.

When run by the user as a /command, it inserts the output into the current note. Or you can run it from a
- template: is particularly designed to be used from a "Daily Note Template" by including a line like the following: `<%- todayProgressFromTemplate({todayProgressTotal: '@calories, @exercise', todayProgressHeading: 'Progress Today'}) %>`
- x-callback call: create a JSON version of "key":"value" pairs for parameters that are different from the normal saved settings, and then prefix with the string `noteplan://x-callback-url/runPlugin?pluginID=jgclark.Summaries&command=today%20progress&arg0=`. (See more details above.) For example: For example:
```
noteplan://x-callback-url/runPlugin?pluginID=jgclark.Summaries&command=today%20progress&arg0={"period": "2022-02-15", "excludeToday": true, "progressHeading": "Post-Birthday Habits", "showSparklines": true}
```

It has its own settings:
- #hashtags and @mentions to total: a comma separated list of the terms to total from today's note
- Today Progress heading: optional heading to insert before the results.

## 'periodStats' command (aliases: 'statsPeriod', 'stp')
This command generates some simple counts and other statistics of #hashtags or @mentions that you specify, and saves them into notes in a special 'Summaries' folder. For example:
- **count** every time you've noted you've visited family this month -- i.e. counts the number of times `#family` is mentioned in calendar notes this month
- **count** the times you've met with staff member Alice this year so far -- i.e. counts the number of times `@alice` is mentioned in calendar notes this year
Expand Down
47 changes: 44 additions & 3 deletions jgclark.Summaries/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"plugin.author": "Jonathan Clark",
"plugin.url": "https://github.com/NotePlan/plugins/tree/main/jgclark.Summaries/",
"plugin.changelog": "https://github.com/NotePlan/plugins/blob/main/jgclark.Summaries/CHANGELOG.md",
"plugin.version": "0.20.0",
"plugin.version": "0.20.0b2",
"plugin.lastUpdateInfo": "0.20.0: add new /heatmap command, and add refresh button to /periodStats output.\n0.19.3: bug fixes on 'weekly stats generation' commands.\n0.19.2: change date library.\n0.19.1: bug fix\n. 0.19.0: adds totals and averages for hashtags as well. Improve output of averages.\n0.18.0: offers full set of summary types in /periodStats as well as /progressUpdate. Bug fixes.\n0.17.3: fix edge case of malformed @mentions.\n0.17.2: fix edge cases in /periodStats\n0.17.1: worked around API bug when processing repeats like @repeats(1/7) in Summaries commands.",
"plugin.dependencies": [],
"plugin.script": "script.js",
Expand All @@ -33,12 +33,34 @@
{
"hidden": true,
"name": "progressUpdate",
"description": "x-callback entry point to appendProgressUpdate command",
"description": "template entry point to appendProgressUpdate command",
"jsFunction": "progressUpdate",
"arguments": [
"JSON-formatted parameter list"
]
},
{
"hidden": true,
"name": "todayProgressFromTemplate",
"description": "template entry point to makeTodayProgress command",
"jsFunction": "todayProgressFromTemplate",
"arguments": [
"comma-separated list of items to count",
"heading (optional)"
]
},
{
"name": "today progress",
"alias": [
"tp"
],
"description": "insert today's progress update",
"jsFunction": "makeTodayProgress",
"arguments": [
"comma-separated list of items to count",
"heading (optional)"
]
},
{
"name": "periodStats",
"alias": [
Expand Down Expand Up @@ -200,7 +222,7 @@
{
"key": "progressHeading",
"title": "Progress heading",
"description": "Heading to go before this output, to which is added the period that's covered. However, if it contains the string '{{PERIOD}}, then the covered period will be inserted in place of this string wherever you want in the heading.",
"description": "Heading to go before this output, to which is added the period that's covered. However, if it contains the string {{PERIOD}}, then the covered period will be inserted in place of this string wherever you want in the heading. If this is left blank, then no heading will be added.",
"type": "string",
"default": "Progress Update",
"required": false
Expand Down Expand Up @@ -272,6 +294,25 @@
{
"type": "separator"
},
{
"key": "todayProgressHeading",
"title": "Today Progress heading",
"description": "Heading to go before this output. If this is left blank, then no heading will be added.",
"type": "string",
"default": "Progress Update",
"required": false
},
{
"key": "todayProgressTotal",
"title": "#hashtags and @mentions to total",
"description": "List of #hashtags and @mentions to include in Today Progress updates.",
"type": "[string]",
"default": [],
"required": false
},
{
"type": "separator"
},
{
"type": "heading",
"title": "/periodStats command settings"
Expand Down
6 changes: 5 additions & 1 deletion jgclark.Summaries/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//-----------------------------------------------------------------------------
// Summary plugin commands
// Jonathan Clark
// Last updated 8.10.2023 for v0.20.0
// Last updated 10.10.2023 for v0.20.0
//-----------------------------------------------------------------------------

// export {
Expand All @@ -24,6 +24,10 @@ export {
makeProgressUpdate,
progressUpdate
} from './progress'
export {
makeTodayProgress,
todayProgressFromTemplate
} from './todayProgress'
export { statsPeriod } from './stats'

// allow changes in plugin.json to trigger recompilation
Expand Down
38 changes: 23 additions & 15 deletions jgclark.Summaries/src/progress.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ import { showMessage } from "../../helpers/userInput";
//-------------------------------------------------------------------------------

/**
* This is the entry point for x-callback use of makeProgressUpdate
* This is the entry point for template use of makeProgressUpdate
* @param {?string} params as JSON string
* @returns {string} - returns string to Template
* @returns {string} - returns string
*/
export async function progressUpdate(params: string = ''): Promise<string> {
try {
logDebug(pluginJson, `progressUpdate for xcb: Starting with params '${params}'`)
return await makeProgressUpdate(params, 'xcb') ?? '<error>'
logDebug(pluginJson, `progressUpdate (for template): Starting with params '${params}'`)
return await makeProgressUpdate(params, 'template') ?? '<error>'
}
catch (err) {
logError(pluginJson, 'progressUpdate (for xcb)' + err.message)
logError(pluginJson, 'progressUpdate (for template)' + err.message)
return '<error>' // for completeness
}
}
Expand All @@ -63,12 +63,12 @@ export async function makeProgressUpdate(params: string = '', source: string = '

// If there are params passed, then we've been called by a template command (and so use those).
if (params) {
logDebug(pluginJson, `makeProgressUpdate: Starting from '${source}' with params '${params}'`)
// logDebug(pluginJson, `makeProgressUpdate: Starting from '${source}' with params '${params}'`)
config = overrideSettingsWithEncodedTypedArgs(config, params)
// clo(config, `config after overriding with params '${params}'`)
} else {
// If no params are passed, then we've been called by a plugin command (and so use defaults from config).
logDebug(pluginJson, `makeProgressUpdate: Starting from '${source}' with no params`)
// logDebug(pluginJson, `makeProgressUpdate: Starting from '${source}' with no params`)
}

// Use configuration setting as default for time period
Expand Down Expand Up @@ -148,23 +148,31 @@ export async function makeProgressUpdate(params: string = '', source: string = '

await CommandBar.onMainThread()
CommandBar.showLoading(false)
logDebug('makeProgressUpdate', `- created progress update in${timer(startTime)}`)
logDebug('makeProgressUpdate', `- created progress update in ${timer(startTime)}`)

// If we have a heading specified, make heading, using periodAndPartStr or '{{PERIOD}}' if it exists. Add a refresh button.
// Create x-callback of form `noteplan://x-callback-url/runPlugin?pluginID=jgclark.Summaries&command=progressUpdate&arg0=...` with 'Refresh' pseudo-button
const xCallbackMD = createPrettyRunPluginLink('🔄 Refresh', 'jgclark.Summaries', 'progressUpdate', params)

const thisHeading = formatWithFields(config.progressHeading, { PERIOD: periodAndPartStr ? periodAndPartStr : periodString })
const headingAndXCBStr = `${thisHeading} ${xCallbackMD}`
const thisHeadingLine = `${'#'.repeat(config.headingLevel)} ${headingAndXCBStr}`

// Send output to chosen required destination:
// - if it's a template, then return the output text
// - if it's an x-callback or command, then write to a note
// - if it's from todayProgressUpdate, then write to daily note

// Send output to chosen required destination
// Now complicated because if we have params it could be either from x-callback or template call.
if (params && source !== 'xcb') {
if (source === 'template') {
// this was a template command call, so simply return the output text
logDebug('makeProgressUpdate', `-> returning text to template for '${thisHeading}: ${periodAndPartStr} for ${periodString}'`)
return `${'#'.repeat(config.headingLevel)} ${headingAndXCBStr}\n${output}`
logDebug('makeProgressUpdate', `-> returning text to template for '${thisHeading}' (${periodAndPartStr} for ${periodString})`)
return ((config.progressHeading !== '') ? `${'#'.repeat(config.headingLevel)} ${headingAndXCBStr}\n` : '') + output
}

if (source === 'todayProgressUpdate') {
config.progressDestination = 'daily'
}

// Else we were called by a plugin command.
// Else we were called by a plugin command or x-callback
// Now decide whether to write to current note or update the relevant section in the current Daily or Weekly note
switch (config.progressDestination) {
case 'daily': {
Expand Down
16 changes: 9 additions & 7 deletions jgclark.Summaries/src/summaryHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export type SummariesConfig = {
progressPeriod: string,
progressDestination: string,
progressHeading: string,
progressYesNoChars: string, // for progressUpdate ...
progressYesNoChars: string,
// for progressUpdate ...
progressHashtags: Array<string>,
progressHashtagsAverage: Array<string>,
progressHashtagsTotal: Array<string>,
Expand All @@ -60,7 +61,11 @@ export type SummariesConfig = {
progressMentionsTotal: Array<string>,
progressYesNo: Array<string>,
periodStatsShowSparklines: boolean,
periodStatsYesNo: Array<string>, // for periodStats ...
// for todayProgress ...
todayProgressHeading: string,
todayProgressTotal: Array<string>,
// for periodStats ...
periodStatsYesNo: Array<string>,
includedHashtags: Array<string>,
excludedHashtags: Array<string>,
includedMentions: Array<string>,
Expand Down Expand Up @@ -464,7 +469,7 @@ export function gatherOccurrences(periodString: string, fromDateStr: string, toD

// check this is one of the ones we're after, then add
if (caseInsensitiveMatch(mention, wantedItem)) {
// logDebug('gatherOccurrences', `- Found matching occurrence ${mention} on date ${n.filename}`)
logDebug('gatherOccurrences', `- Found matching occurrence ${mention} on date ${n.filename}`)
thisOcc.addOccurrence(mention, thisDateStr)
} else {
// logDebug('gatherOccurrences', `- x ${mention} not wanted`)
Expand Down Expand Up @@ -507,14 +512,11 @@ export function gatherOccurrences(periodString: string, fromDateStr: string, toD
let lastTag = ''
for (const tag of seenTags) {
// logDebug('gatherOccurrences', `orig: ${tag} ...`)
// const RE_HASHTAG_CAPTURE_NAME_AND_FLOAT = /(\#[\w\/]+)\/(-?\d+(\.\d+)?)$/
// const reMatches = tag.match(RE_HASHTAG_CAPTURE_NAME_AND_FLOAT) ?? []
// const tagWithoutClosingNumber = (reMatches.length >= 1) ? reMatches[1] : tag
const RE_HASHTAG_CAPTURE_TERMINAL_SLASH_AND_FLOAT = /\/(-?\d+(\.\d+)?)$/
const tagWithoutClosingNumber = tag.replace(RE_HASHTAG_CAPTURE_TERMINAL_SLASH_AND_FLOAT, '')
// logDebug('gatherOccurrences', ` ... this:${tagWithoutClosingNumber} last:${lastTag} `)
// if this tag is starting subset of the last one, assume this is an example of the bug, so skip this tag
if (caseInsensitiveStartsWith(tagWithoutClosingNumber, lastTag)) {
if (caseInsensitiveStartsWith(tag, lastTag)) {
// logDebug('calcHashtagStatsPeriod', `- Found ${tag} but ignoring as part of a longer hashtag of the same name`)
continue // skip this tag
}
Expand Down
Loading

0 comments on commit 5b9a676

Please sign in to comment.