Skip to content

Commit

Permalink
jgclark.Dashboard 0.7.2
Browse files Browse the repository at this point in the history
  • Loading branch information
jgclark committed Nov 21, 2023
1 parent f8e5e3e commit 43def9e
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 38 deletions.
8 changes: 8 additions & 0 deletions jgclark.Dashboard/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
# 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.2] - 2023-11-21
### Changed
- Now removes a whole section when the last item in it is completed. (Apart from the 'TODAY' section which always remains, so that the add new task/checklist buttons are still available.)
- Removed the 'preview' effect when hovering the mouse over the open task or checklist marker: when moving the mouse too quickly, this could land up showing misleading state.
### Fixed
- Fix some 'move item' buttons not working in new Overdue Items section

## [0.7.1] - 2023-11-20
### Added
- 'Folders to ignore' setting now applies to the Overdue tasks section as well (resolves #496)
- add '->today' button on Yesterday section items
- two new experimental buttons on Overdue tasks, turned on by new checkbox at bottom of settings screen:
- complete an overdue task on the day it was due, not today
- toggle an item between being a task and a checklist
- the plugin should now auto-update to minor and point releases.

## [0.7.0] - 2023-11-17
### Added
Expand Down
4 changes: 2 additions & 2 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.1",
"plugin.lastUpdateInfo": "v0.7.1: 'folders to ignore' setting now applies to 'Overdue tasks' section. Two new experimental buttons.\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.version": "0.7.2",
"plugin.lastUpdateInfo": "v0.7.2: turn off 'preview' on task and checklist markers, as they can behave wrongly at speed. Other fixes and polish.\nv0.7.1: 'folders to ignore' setting now applies to 'Overdue tasks' section. Two new experimental buttons.\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
43 changes: 36 additions & 7 deletions jgclark.Dashboard/requiredFiles/commsSwitchboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,26 @@ async function completeTaskInDisplay(data) {
decrementItemCount("totalOpenCount")
incrementItemCount("totalDoneCount")
// update the section count, which is identified as the first part of the itemID
const sectionID = itemID.split('-')[0]
const sectionCountID = `section${sectionID}Count`
const sectionNum = itemID.split('-')[0]
const sectionID = `${sectionNum}-Section`
const sectionCountID = `section${sectionNum}Count`
decrementItemCount(sectionCountID)

// See if the only remaining item is the '> There are also ... items' line
const numItemsRemaining = getNumItemsInSection(`${sectionID}-Section`, 'TR')
if (numItemsRemaining === 1 && doesIDExist(`${sectionID}-Filter`)) {
const numItemsRemaining = getNumItemsInSection(sectionID, 'TR')
if (numItemsRemaining === 1 && doesIDExist(`${sectionNum}-Filter`)) {
// We need to un-hide the lower-priority items: do full refresh
sendMessageToPlugin('refresh', { itemID: '', type: '', filename: '', rawContent: '' }) // actionName, data
}

// See if we now have no remaining items at all
if (numItemsRemaining === 0) {
// Delete the whole section from the display
console.log(`completeTaskInDisplay: trying to delete rest of empty section: ${sectionID}`)
const sectionDIV = document.getElementById(sectionID)
const enclosingTR = findAncestor(sectionDIV, 'TR')
enclosingTR.remove()
}
}

/**
Expand Down Expand Up @@ -134,6 +144,15 @@ async function completeChecklistInDisplay(data) {
// We need to un-hide the lower-priority items: do full refresh
sendMessageToPlugin('refresh', { itemID: '', type: '', filename: '', rawContent: '' }) // actionName, data
}

// See if we now have no remaining items at all
if (numItemsRemaining === 0) {
// Delete the whole section from the display
console.log(`completeChecklistInDisplay: trying to delete rest of empty section: ${sectionID}`)
const sectionDIV = document.getElementById(sectionID)
const enclosingTR = findAncestor(sectionDIV, 'TR')
enclosingTR.remove()
}
}

/**
Expand Down Expand Up @@ -224,9 +243,7 @@ function toggleTypeInDisplay(data) {
/**
* Event handler for various button 'click' events
* Note: data is an object
* @param {string} filename
* @param {number} lineIndex
* @param {string} statusWas
* @param {Object} data
*/
function onClickDashboardItem(data) {
sendMessageToPlugin('onClickDashboardItem', data) // actionName, data
Expand All @@ -247,12 +264,24 @@ function onChangeCheckbox(settingName, state) {
* HELPER FUNCTIONS
*****************************************************************************/

function findAncestor(startElement, tagName) {
let currentElem = startElement
while (currentElem !== document.body) {
if (currentElem.tagName.toLowerCase() === tagName.toLowerCase()) {
return currentElem
}
currentElem = currentElem.parentElement
}
return false
}

function deleteHTMLItem(ID) {
// console.log(`deleteHTMLItem(${ID}) ...`)
const div = document.getElementById(ID)
if (div) {
// console.log(`innerHTML was: ${div.innerHTML}`)
div.innerHTML = ''
// Note: why not use div.remove() ?
} else {
console.log(`- ❗error❗ in deleteHTMLItem: couldn't find an elem with ID ${ID}`)
}
Expand Down
10 changes: 2 additions & 8 deletions jgclark.Dashboard/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,16 @@ const thisPluginID = 'jgclark.Dashboard'
export async function init(): Promise<void> {
try {
// Check for the latest version of the plugin, and if a minor update is available, install it and show a message
// Note: turned off, as it was causing too much noise in logs
// DataStore.installOrUpdatePluginsByID([pluginJson['plugin.id']], false, false, false).then((r) =>
// pluginUpdated(pluginJson, r),
// )
DataStore.installOrUpdatePluginsByID([pluginJson['plugin.id']], false, false, false)
} catch (error) {
logError(`${thisPluginID}/init`, JSP(error))
}
}

export async function onSettingsUpdated(): Promise<any> {
// Placeholder only to stop error in logs
if (!isHTMLWindowOpen(pluginJson['plugin.id'])) {
await showDashboardHTML(false, false) // don't need await in the case I think
await showDashboardHTML('settings', false) // don't need await in the case I think
}
// TEST: trying this empty return to see if stops console errors
return {}
}

export async function onUpdateOrInstall(): Promise<void> {
Expand Down
47 changes: 27 additions & 20 deletions jgclark.Dashboard/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import {
type Section,
type SectionItem,
} from './dashboardHelpers'
import { getDateStringFromCalendarFilename, getTodaysDateUnhyphenated, isValidCalendarNoteFilename } from '@helpers/dateTime'
import {
getDateStringFromCalendarFilename,
getTodaysDateUnhyphenated,
isValidCalendarNoteFilename
} from '@helpers/dateTime'
import { nowLocaleShortTime } from '@helpers/NPdateTime'
import { clo, JSP, logDebug, logError, logInfo, logWarn } from '@helpers/dev'
import { unsetPreference } from '@helpers/NPdev'
Expand Down Expand Up @@ -83,12 +87,13 @@ const receivingPluginID = "jgclark.Dashboard"; // the plugin ID of the plugin wh

/**
* Add event listener added to all todo + checklist icons
* Note: now not used, as on onClick is included in the HTML directly when generating the page.
*/
const addIconEventListenersScript = `
<!-- addIconEventListenersScript -->
<script type="text/javascript">
console.log('add Event Listeners to Icons ...');
// Note: mouseOverEvents now disabled at user request
const addMouseOverEvents = false;
function mouseenterTodoFunc() {
// console.log('mouseenterTodo ... after '+String(event.detail)+' clicks');
Expand Down Expand Up @@ -140,8 +145,10 @@ for (const thisTodo of allTodos) {
handleIconClick(thisId, 'open', thisFilename, thisTodo.dataset.encodedContent, metaModifier);
}, false);
// Add mouseover-type events to hint as to what's going to happen
thisTodo.addEventListener('mouseenter', mouseenterTodoFunc, false);
thisTodo.addEventListener('mouseleave', mouseleaveTodoFunc, false);
if (addMouseOverEvents) {
thisTodo.addEventListener('mouseenter', mouseenterTodoFunc, false);
thisTodo.addEventListener('mouseleave', mouseleaveTodoFunc, false);
}
}
console.log(String(allTodos.length) + ' sectionItemTodo ELs added (to icons)');
Expand All @@ -158,8 +165,10 @@ for (const thisChecklist of allChecklists) {
handleIconClick(thisId, 'checklist', thisFilename, thisChecklist.dataset.encodedContent, metaModifier);
}, false);
// Add mouseover-type events to hint as to what's going to happen
thisChecklist.addEventListener('mouseenter', mouseenterChecklistFunc, false);
thisChecklist.addEventListener('mouseleave', mouseleaveChecklistFunc, false);
if (addMouseOverEvents) {
thisChecklist.addEventListener('mouseenter', mouseenterChecklistFunc, false);
thisChecklist.addEventListener('mouseleave', mouseleaveChecklistFunc, false);
}
}
console.log(String(allChecklists.length) + ' sectionItemChecklist ELs added (to icons)');
</script>
Expand Down Expand Up @@ -242,8 +251,8 @@ const addButtonEventListenersScript = `
<script type="text/javascript">
function findAncestor(startElement, tagName) {
let currentElem = startElement;
while (currentElem != document.body) {
if (currentElem.tagName.toLowerCase() == tagName.toLowerCase()) { return currentElem; }
while (currentElem !== document.body) {
if (currentElem.tagName.toLowerCase() === tagName.toLowerCase()) { return currentElem; }
currentElem = currentElem.parentElement;
}
return false;
Expand Down Expand Up @@ -357,20 +366,19 @@ function handleContentClick(event, id, filename, content) {
console.log('handleContentClick( ' + id + ' / ' + filename + ' / ' +content + ' ) for event currentTarget: ' + event.currentTarget);
const encodedFilename = filename; // already encoded at this point. Was: encodeRFC3986URIComponent(filename);
const encodedContent = content; // already encoded at this point. Was: encodeRFC3986URIComponent(content);
// onClickDashboardItem( { itemID: id, type: 'showNoteInEditorFromFilename', encodedFilename: encodedFilename, encodedContent: encodedContent } );
onClickDashboardItem( { itemID: id, type: 'showLineInEditorFromFilename', encodedFilename: encodedFilename, encodedContent: encodedContent } ); // TEST: change from openNote.. to openLine...
onClickDashboardItem( { itemID: id, type: 'showLineInEditorFromFilename', encodedFilename: encodedFilename, encodedContent: encodedContent } ); // TEST: change from showNote.. to showLine...
}
// For clicking on checkbox
function handleCheckboxClick(cb) {
console.log("Checkbox for " + cb.name + " clicked, new value = " + cb.checked);
onChangeCheckbox(cb.name, cb.checked);
onChangeCheckbox(cb.name, cb.checked); // = sendMessageToPlugin('onChangeCheckbox', ...)
}
// For clicking on button in hoverExtraControls
function handleButtonClick(id, controlStr, filename, content) {
console.log("Button clicked on id: " + id + " for controlStr " + controlStr + ". filename: " + filename + " content: {" + content +"}");
onClickDashboardItem( { itemID: id, type: controlStr, encodedFilename: filename, encodedContent: content } );
onClickDashboardItem( { itemID: id, type: controlStr, encodedFilename: filename, encodedContent: content } ); // = sendMessageToPlugin('onClickDashboardItem', ...)
}
</script>
`
Expand Down Expand Up @@ -572,6 +580,7 @@ export async function showDashboardHTML(callType: string = 'manual', demoMode: b
}

for (const item of items) {
const isItemFromCalendarNote = isValidCalendarNoteFilename(item.filename)
let encodedFilename = encodeRFC3986URIComponent(item.filename)
let encodedContent = encodeRFC3986URIComponent(item.content)
let reviewNoteCount = 0 // count of note-review items
Expand Down Expand Up @@ -601,19 +610,19 @@ export async function showDashboardHTML(callType: string = 'manual', demoMode: b
// FIXME: [WebView Log] CommsBridge: onMessageReceived: received a message of type: completeTask with a payload // onMessageFromPlugin: starting with type: completeTask and data.itemID: ct // completeTask: for ID: ct // - error in replaceClassInID: couldn't find an elem with ID ctI to replace class fa-regular fa-circle-check
// FIXME: need to remove from Yesterday section
// FIXME: [WebView Log] CommsBridge: onMessageReceived: received a message of type: completeTask with a payload /// onMessageFromPlugin: starting with type: completeTask and data.itemID: ct // completeTask: for ID: ct // - error in replaceClassInID: couldn't find an elem with ID ctI to replace class fa-regular fa-circle-check"
// FIXME: errors when moving from Overdue to Today: "INFO | bridgeClickDashboardItem :: ID: t, type: moveFromCalToCal, filename: , content: {! Order more filter papers Edesia 80/200 x1000} // ❗️ERROR❗️ dateTime / getDateStringFromCalendarFilename :: Invalid calendar filename: // | DEBUG | bridgeClickDashboardItem :: move task from (invalid date) -> 'today'"
const controlTypesForThisSection = possibleControlTypes.filter((t) => t.sectionDateTypes.includes(section.dateType))
let tooltipContent = ''
if (controlTypesForThisSection.length > 0) {
tooltipContent = `\n <span class="hoverExtraControls" data-date-string="${section.filename}">`
tooltipContent = `\n <span class="hoverExtraControls" data-date-string="${encodedFilename}">` // now always pass filename of item, even if it is same as section.filename

// only want control types relevant for this section
for (const ct of controlTypesForThisSection) {
// tooltipContent += `\n/<!-- ${ct.controlStr} / ${ct.sectionDateTypes.join('')} / ${section.dateType} / ${item.filename} / ${section.filename} -->\n`
const buttonType = (ct.controlStr === 'tog')
? "toggleTypeButton"
: (ct.controlStr === 'ct')
? "completeThenButton"
: (ct.sectionDateTypes.includes(section.dateType))
// : (ct.sectionDateTypes.includes(section.dateType))
: isItemFromCalendarNote
? "moveButton"
: "changeDateButton"
tooltipContent += `<button class="${buttonType} hoverControlButton" data-control-str="${ct.controlStr}">${ct.displayString}</button>`
Expand All @@ -623,7 +632,7 @@ export async function showDashboardHTML(callType: string = 'manual', demoMode: b

// Do main work for the item
switch (item.type) {
case 'open': {
case 'open': { // open todo type
logDebug('showDashboardHTML', `- adding open taskContent for ${item.content} / ${itemNoteTitle}`)
// do icon col (was col3)
outputArray.push(
Expand All @@ -642,13 +651,12 @@ export async function showDashboardHTML(callType: string = 'manual', demoMode: b
} else {
paraContent = makeParaContentToLookLikeNPDisplayInHTML(item, '', 'all', 140)
}
// const cell4 = ` <td class="sectionItemContent sectionItem" data-encoded-filename="${encodedFilename}" data-encoded-content="${encodedContent}">\n <div class="content avoidColumnBreakHere tooltip">${paraContent}${tooltipContent}\n </div>\n </td>\n </tr>`
const cell4 = ` <td class="sectionItemContent sectionItem" data-encoded-filename="${encodedFilename}" data-encoded-content="${encodedContent}">\n <div class="avoidColumnBreakHere tooltip"><a class="content">${paraContent}</a>${tooltipContent}\n </div>\n </td>\n </tr>`
outputArray.push(cell4)
totalOpenItems++
break
}
case 'checklist': {
case 'checklist': { // open checklist type
logDebug('showDashboardHTML', `- adding checklist taskContent for ${item.content} / ${itemNoteTitle}`)
// do icon col (was col3)
outputArray.push(
Expand All @@ -664,7 +672,6 @@ export async function showDashboardHTML(callType: string = 'manual', demoMode: b
paraContent = makeParaContentToLookLikeNPDisplayInHTML(item, itemNoteTitle, 'all', 140)
}

// const cell4 = ` <td class="sectionItemContent sectionItem" data-encoded-filename="${encodedFilename}" data-encoded-content="${encodedContent}">\n <div class="content avoidColumnBreakHere tooltip">${paraContent}${tooltipContent}\n </div>\n </td>\n </tr>`
const cell4 = ` <td class="sectionItemContent sectionItem" data-encoded-filename="${encodedFilename}" data-encoded-content="${encodedContent}">\n <div class="avoidColumnBreakHere tooltip"><a class="content">${paraContent}</a>${tooltipContent}\n </div>\n </td>\n </tr>`
outputArray.push(cell4)
totalOpenItems++
Expand Down
4 changes: 3 additions & 1 deletion jgclark.Dashboard/src/pluginToHTMLBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,11 +290,13 @@ export async function bridgeClickDashboardItem(data: MessageDataObject) {
}
if (dateInterval === 't') {
// Special case to change to '>today'
// FIXME: errors reported here from new Overdue section, where we don't have filename?
startDateStr = getDateStringFromCalendarFilename(filename, true)
newDateStr = getTodaysDateHyphenated()
logDebug('bridgeClickDashboardItem', `move task from ${startDateStr} -> 'today'`)
} else if (dateInterval.match(RE_DATE_INTERVAL)) {
// Get the (ISO) current date on the task
// FIXME: errors reported here from new Overdue section, where we don't have filename?
startDateStr = getDateStringFromCalendarFilename(filename, true)
newDateStr = calcOffsetDateStr(startDateStr, dateInterval, 'offset') // 'longer'
logDebug('bridgeClickDashboardItem', `move task from ${startDateStr} -> ${newDateStr}`)
Expand All @@ -311,7 +313,7 @@ export async function bridgeClickDashboardItem(data: MessageDataObject) {
}

case 'updateTaskDate': {
// Instruction from a 'changeDateButton' to change date on a task
// Instruction from a 'changeDateButton' to change date on a task (in a project note)
// Note: Overloads ID with the dateInterval to use
const dateInterval = ID
let newDateStr = ''
Expand Down

0 comments on commit 43def9e

Please sign in to comment.