Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions jgclark.Dashboard/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ For more details see the [plugin's documentation](https://github.com/NotePlan/pl
- TODO: enlarged default window size on iPads
-->

## [2.3.0.b10] 2025-09-03???
- Fix: the done count not including items from project notes
## [2.3.0.b10] 2025-09-???
### Changed
- When the "filter out lower-priority items" is on, this now calculated across all sections, not just each one independently. The label that says there are hidden items now includes "(click to show all)" text to make it clearer how to turn off the filter for that section.
### Fixed
- the done count not including items from project notes

## [2.3.0.b9] 2025-09-01
- Added tagCache age to section info (if 'Comparison' FFlag is turned on)
### Changes
- Add another check to regenerate or update tagMentionCache after 24 and 1 hour respectively
- Make 'Show folder name in note link?' setting indented under 'Show note link for tasks?'
- I have stopped some of the unnecessary generation of Project List. Let me know how it goes, @dwertheimer. (Will require rebuilding jgclark.Reviews plugin as well (to v1.2.4).)
- Also added some logging to track down when Project list generation is happening when it shouldn't be. If 'Show Section Timings' Flag is on, then it will also write a log to note "@Meta/Project Generation Log".
- Tweak some TaskDialog button labels
### Fixed
- Fix color of blockID marker in light mode themes
- Further fix to display of calendar events in tasks
- Tweak some TaskDialog button labels
### Dev
- Also added some logging to track down when Project list generation is happening when it shouldn't be. If 'Show Section Timings' Flag is on, then it will also write a log to note "@Meta/Project Generation Log".
- Added tagCache age to section info (if 'Comparison' FFlag is turned on)

## [2.3.0.b8] 2025-08-27
- Add temporary workaround for error in DataStore.listOverdueParagraphs() for regular Teamspace notes
Expand Down
42 changes: 17 additions & 25 deletions jgclark.Dashboard/src/react/components/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,14 @@
import React, { useEffect, useRef, useMemo } from 'react'
import useRefreshTimer from '../customHooks/useRefreshTimer.jsx'
import useWatchForResizes from '../customHooks/useWatchForResizes.jsx'
import {
dontDedupeSectionCodes,
sectionDisplayOrder,
sectionPriority,
} from '../../constants.js'
import { dontDedupeSectionCodes, sectionDisplayOrder, sectionPriority } from '../../constants.js'
import { copyUpdatedSectionItemData } from '../../dataGeneration.js'
import { findSectionItems } from '../../dashboardHelpers.js'
import { dashboardSettingDefs, dashboardFilterDefs } from '../../dashboardSettings.js'
import { useAppContext } from './AppContext.jsx'
import Dialog from './Dialog.jsx'
import { getSectionsWithoutDuplicateLines, countTotalSectionItems, countTotalVisibleSectionItems, sortSections, showSectionSettingItems } from './Section/sectionHelpers.js'
import { calculateMaxPriorityAcrossAllSections } from './Section/useSectionSortAndFilter.jsx'
import Header from './Header'
import IdleTimer from './IdleTimer.jsx'
import Section from './Section/Section.jsx'
Expand Down Expand Up @@ -109,7 +106,7 @@ const Dashboard = ({ pluginData }: Props): React$Node => {
const deduplicatedSections = useMemo(() => {
if (sections.length >= 1 && dashboardSettings.hideDuplicates) {
// FIXME: this seems to be called for every section, even on refresh when only 1 section is requested
// But TB and PROJ sections need to be ignored here, as they have different item types
// TB and PROJ sections need to be ignored here, as they have different item types
const dedupedSections = getSectionsWithoutDuplicateLines(origSections.slice(), ['filename', 'content'], sectionPriority, dontDedupeSectionCodes, dashboardSettings)
totalSectionItems = countTotalVisibleSectionItems(dedupedSections, dashboardSettings)

Expand Down Expand Up @@ -258,6 +255,15 @@ const Dashboard = ({ pluginData }: Props): React$Node => {
}
}, [pluginData.startDelayedRefreshTimer])

// Recalculate maximum priority when sections change (e.g., when items are removed)
useEffect(() => {
const newMaxPriority = calculateMaxPriorityAcrossAllSections(sections)
if (newMaxPriority !== pluginData.currentMaxPriorityFromAllVisibleSections) {
logInfo('Dashboard', `Recalculating max priority: ${pluginData.currentMaxPriorityFromAllVisibleSections} -> ${newMaxPriority}`)
updatePluginData({ ...pluginData, currentMaxPriorityFromAllVisibleSections: newMaxPriority }, `Recalculated max priority after sections changed: ${newMaxPriority}`)
}
}, [sections, pluginData.currentMaxPriorityFromAllVisibleSections])

//----------------------------------------------------------------------
// Handlers
//----------------------------------------------------------------------
Expand Down Expand Up @@ -292,25 +298,17 @@ const Dashboard = ({ pluginData }: Props): React$Node => {
return (
<div style={dashboardContainerStyle} tabIndex={0} ref={containerRef} className={pluginData.platform ?? ''}>
{autoUpdateEnabled && (
<IdleTimer
idleTime={parseInt(dashboardSettings?.autoUpdateAfterIdleTime ? dashboardSettings.autoUpdateAfterIdleTime : '15') * 60 * 1000}
onIdleTimeout={autoRefresh} />
<IdleTimer idleTime={parseInt(dashboardSettings?.autoUpdateAfterIdleTime ? dashboardSettings.autoUpdateAfterIdleTime : '15') * 60 * 1000} onIdleTimeout={autoRefresh} />
)}
{/* Note: this is where I might want to put further periodic data generation functions: completed task counter etc. */}
{reactSettings?.perspectivesTableVisible && (
<PerspectivesTable
perspectives={perspectiveSettings}
settingDefs={settingDefs}
onSave={hidePerspectivesTable}
onCancel={hidePerspectivesTable} />
<PerspectivesTable perspectives={perspectiveSettings} settingDefs={settingDefs} onSave={hidePerspectivesTable} onCancel={hidePerspectivesTable} />
)}
<div className="dashboard">
<Header lastFullRefresh={lastFullRefresh} />
<main>
{sections.map((section, index) => (
<Section key={index}
section={section}
onButtonClick={() => { }} />
<Section key={index} section={section} onButtonClick={() => {}} />
))}
</main>
<Dialog
Expand All @@ -321,16 +319,10 @@ const Dashboard = ({ pluginData }: Props): React$Node => {
/>
</div>
{pluginData.perspectiveChanging && (
<NonModalSpinner
textBelow="Switching perspectives"
style={{ container: { color: 'var(--tint-color)', textAlign: 'center', marginTop: '0.6rem', marginBottom: '0rem' } }}
/>
<NonModalSpinner textBelow="Switching perspectives" style={{ container: { color: 'var(--tint-color)', textAlign: 'center', marginTop: '0.6rem', marginBottom: '0rem' } }} />
)}
{pluginData?.logSettings?._logLevel === 'DEV' && (
<DebugPanel isVisible={showDebugPanel}
getContext={getContext}
testGroups={testGroups}
defaultExpandedKeys={['Context Variables', 'perspectiveSettings']} />
<DebugPanel isVisible={showDebugPanel} getContext={getContext} testGroups={testGroups} defaultExpandedKeys={['Context Variables', 'perspectiveSettings']} />
)}
<div id="tooltip-portal"></div>
</div>
Expand Down
13 changes: 7 additions & 6 deletions jgclark.Dashboard/src/react/components/ItemGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,25 @@ import { logDebug, logInfo } from '@helpers/react/reactDev.js'
type Props = {
items: Array<TSectionItem>,
thisSection: TSection,
onToggleShowAll?: () => void,
}

function ItemGrid({ items, thisSection }: Props): React$Node {
function ItemGrid({ items, thisSection, onToggleShowAll }: Props): React$Node {
const visibleItems = items.length
? items.map((item) => (
// Using a complex key to ensure React updates components when item content changes (not just when ID changes)
<ItemRow key={`${item.ID}_${item.para?.content || item.project?.title || ''}`} item={item} thisSection={thisSection} />
// Using a complex key to ensure React updates components when item content changes (not just when ID changes)
<ItemRow key={`${item.ID}_${item.para?.content || item.project?.title || ''}`} item={item} thisSection={thisSection} onToggleShowAll={onToggleShowAll} />
))
: []

// Calculate a subtle green background colour for the section if there are no items,
// Calculate a subtle green background colour for the section if there are no items,
// or if the first item is a congrats message,
// or if the section has asked for a coloured background.
const sectionBackgroundColor =
items.length === 0 || items[0].itemType === 'itemCongrats'
? `color-mix(in srgb, var(--bg-main-color), green 4%)`
: (thisSection.showColoredBackground && thisSection.sectionTitleColorPart)
? `color-mix(in srgb, var(--bg-main-color), var(--fg-${thisSection.sectionTitleColorPart}) 4%)`
: thisSection.showColoredBackground && thisSection.sectionTitleColorPart
? `color-mix(in srgb, var(--bg-main-color), var(--fg-${thisSection.sectionTitleColorPart}) 4%)`
: 'var(--bg-main-color)'
// if (sectionBackgroundColor !== 'var(--bg-main-color)') logDebug('ItemGrid', `sectionBackgroundColor: ${sectionBackgroundColor} from ${String(items.length)} items`)

Expand Down
55 changes: 22 additions & 33 deletions jgclark.Dashboard/src/react/components/ItemRow.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ import { logDebug, logInfo } from '@helpers/react/reactDev'
type Props = {
item: TSectionItem,
thisSection: TSection,
onToggleShowAll?: () => void,
}

/**
* Represents a row item within a section.
* Loads the proper Component depending on itemType
* Note: the contentClassName are CSS classes that are used to style the item row, and are defined in Section.css
*/
function ItemRow({ item, thisSection }: Props): Node {
function ItemRow({ item, thisSection, onToggleShowAll }: Props): Node {
const { itemType } = item

let congratsMessage = 'Nothing on this list'
Expand All @@ -37,38 +38,26 @@ function ItemRow({ item, thisSection }: Props): Node {
<>
{itemType === 'project' ? (
<ProjectItem item={item} />
)
: itemType === 'projectCongrats' ? (
<MessageOnlyItem message={'No Projects need reviewing: take a break'}
contentClassName="projectCongrats"
closingFAIconClassName="fa-solid fa-mug" />
)
: itemType === 'noSearchResults' ? (
<MessageOnlyItem message={item?.message ?? ''}
contentClassName="noSearchResults"
settingsDialogAnchor={item?.settingsDialogAnchor ?? ''} />
)
: itemType === 'preLimitOverdues' ? (
<MessageOnlyItem message={item?.message ?? ''}
contentClassName="noSearchResults"
settingsDialogAnchor={item?.settingsDialogAnchor ?? ''}
rowIconClassName="fa-regular fa-plus" />
)
: itemType === 'filterIndicator' ? (
<TasksFiltered item={item} />
)
: itemType === 'itemCongrats' ? (
<MessageOnlyItem message={congratsMessage}
contentClassName="itemCongrats"
closingFAIconClassName="fa-light fa-champagne-glasses pad-left" />
)
: itemType === 'info' ? (
<MessageOnlyItem message={item?.message ?? ''}
contentClassName="infoItem" />
)
: (
<TaskItem item={item} thisSection={thisSection} />
)}
) : itemType === 'projectCongrats' ? (
<MessageOnlyItem message={'No Projects need reviewing: take a break'} contentClassName="projectCongrats" closingFAIconClassName="fa-solid fa-mug" />
) : itemType === 'noSearchResults' ? (
<MessageOnlyItem message={item?.message ?? ''} contentClassName="noSearchResults" settingsDialogAnchor={item?.settingsDialogAnchor ?? ''} />
) : itemType === 'preLimitOverdues' ? (
<MessageOnlyItem
message={item?.message ?? ''}
contentClassName="noSearchResults"
settingsDialogAnchor={item?.settingsDialogAnchor ?? ''}
rowIconClassName="fa-regular fa-plus"
/>
) : itemType === 'filterIndicator' ? (
<TasksFiltered item={item} onToggleShowAll={onToggleShowAll} />
) : itemType === 'itemCongrats' ? (
<MessageOnlyItem message={congratsMessage} contentClassName="itemCongrats" closingFAIconClassName="fa-light fa-champagne-glasses pad-left" />
) : itemType === 'info' ? (
<MessageOnlyItem message={item?.message ?? ''} contentClassName="infoItem" />
) : (
<TaskItem item={item} thisSection={thisSection} />
)}
</>
)
}
Expand Down
Loading
Loading