Skip to content

Commit 83bb44d

Browse files
committed
Further WIP for summary charting
1 parent 51637cb commit 83bb44d

3 files changed

Lines changed: 76 additions & 137 deletions

File tree

‎jgclark.Summaries/requiredFiles/chartStats.css‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -408,17 +408,14 @@ canvas {
408408
}
409409

410410
.heatmap-cell.completed {
411-
/* background: var(--accent-color); */
412-
/* background: var(--tint-color); */
413-
background: var(--fg-ok-color);
414-
/* border-color: var(--accent-color); */
411+
/* background: #32d74b; */
412+
background: color-mix(in oklch, var(--fg-main-color), green 80%);
415413
border-color: var(--border-color);
416414
}
417415

418416
.heatmap-cell.incomplete {
419417
/* background: #992e2e; */
420-
background: var(--fg-error-color);
421-
/* border-color: #992e2e; */
418+
background: color-mix(in oklch, var(--bg-main-color), red 80%);
422419
border-color: var(--border-color);
423420
}
424421

@@ -476,43 +473,46 @@ canvas {
476473
} */
477474

478475
/* Combined yes/no layout */
479-
.yesno-combined-wrapper {
480-
padding: 0.5rem 0.75rem;
481-
}
476+
.yesno-heatmap-section {
477+
padding: 0.25rem 0.5rem;
482478

483-
.yesno-habit-row {
484-
display: flex;
479+
480+
/* .yesno-habit-row { */
481+
display: grid;
482+
grid-template-columns: max-content max-content max-content auto;
485483
align-items: center;
486484
gap: 1rem;
487-
padding: 0.5rem 0;
488-
border-bottom: 1px solid var(--border-color);
485+
/* padding: 0; */
486+
/* border-bottom: 1px solid var(--border-color); */
489487
}
490488

491-
.yesno-habit-row:last-child {
489+
/* .yesno-habit-row:last-child {
492490
border-bottom: none;
493-
}
491+
} */
494492

495493
.yesno-habit-label {
496-
min-width: 10rem;
497494
font-size: 1rem;
498495
font-weight: 500;
499496
color: var(--text-primary);
500497
text-align: end;
498+
justify-self: end;
501499
}
502500

503501
.yesno-habit-viz {
504-
flex: 1;
505502
display: flex;
506503
align-items: center;
504+
justify-self: start;
507505
}
508506

509-
.yesno-habit-stats {
510-
min-width: 10rem;
507+
.yesno-habit-stat-completion {
508+
font-size: 0.85rem;
509+
color: var(--text-primary);
510+
text-align: end;
511+
justify-self: end;
512+
}
513+
.yesno-habit-stat-streak {
511514
font-size: 0.85rem;
512515
color: var(--text-primary);
513-
display: flex;
514-
gap: 0.75rem;
515-
text-align: left;
516-
justify-content: flex-start;
517-
align-items: center;
516+
text-align: end;
517+
justify-self: start;
518518
}

‎jgclark.Summaries/requiredFiles/chartStatsScripts.js‎

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -303,54 +303,66 @@
303303
return streak
304304
}
305305

306-
function createCombinedHeatmap() {
307-
const container = document.getElementById('yesno-combined-heatmap')
308-
if (!container) return
309-
container.innerHTML = ''
306+
function createYesNoHeatmapSection() {
307+
const row = document.getElementById('yesno-heatmap-section')
308+
if (!row) return
309+
310+
// const row = document.createElement('div')
311+
// row.className = 'yesno-habit-row'
312+
313+
row.innerHTML = ''
310314
yesNoHabits.forEach((habit, index) => {
311315
const data = yesNoData.counts[habit]
312316
const dates = yesNoData.dates
313-
const yesColor = '#32d74b'
314-
const noColor = '#992e2e'
317+
// const yesColor = '#32d74b'
318+
// const noColor = '#992e2e'
315319
const completionRate = calculateCompletionRate(data)
316320
const streak = calculateStreak(data)
317-
const row = document.createElement('div')
318-
row.className = 'yesno-habit-row'
319-
row.id = 'yesno-row-' + index
320-
row.style.display = 'flex'
321-
const label = document.createElement('div')
321+
322+
// const row = document.createElement('div')
323+
// row.className = 'yesno-habit-row'
324+
// row.id = 'yesno-row-' + index
325+
326+
const label = document.createElement('span')
322327
label.className = 'yesno-habit-label'
323328
label.textContent = habit
324329
row.appendChild(label)
325-
const vizContainer = document.createElement('div')
330+
331+
const vizContainer = document.createElement('span')
326332
vizContainer.className = 'yesno-habit-viz'
327-
const grid = document.createElement('div')
333+
const grid = document.createElement('span')
328334
grid.className = 'heatmap-grid'
329335
const dataToShow = data.slice(0, -1)
330336
const datesToShow = dates.slice(0, -1)
331337
dataToShow.forEach((value, i) => {
332338
const cell = document.createElement('div')
333339
cell.className = 'heatmap-cell ' + (value === 1 ? 'completed' : 'incomplete')
334340
cell.title = datesToShow[i] + ': ' + (value === 1 ? 'Completed' : 'Not completed')
335-
if (value === 1) {
336-
cell.style.background = yesColor
337-
cell.style.borderColor = yesColor
338-
} else {
339-
cell.style.background = noColor
340-
cell.style.borderColor = noColor
341-
}
341+
// if (value === 1) {
342+
// cell.style.background = yesColor
343+
// cell.style.borderColor = yesColor
344+
// } else {
345+
// cell.style.background = noColor
346+
// cell.style.borderColor = noColor
347+
// }
342348
grid.appendChild(cell)
343349
})
344350
vizContainer.appendChild(grid)
345351
row.appendChild(vizContainer)
346-
const stats = document.createElement('div')
347-
stats.className = 'yesno-habit-stats'
348-
stats.innerHTML = '<span>' + completionRate + '%</span><span>Streak: ' + streak + '</span>'
349-
row.appendChild(stats)
350-
container.appendChild(row)
352+
353+
const statCompletion = document.createElement('span')
354+
statCompletion.className = 'yesno-habit-stat-completion'
355+
statCompletion.textContent = completionRate + '%'
356+
row.appendChild(statCompletion)
357+
358+
const statStreak = document.createElement('span')
359+
statStreak.className = 'yesno-habit-stat-streak'
360+
statStreak.textContent = 'Streak: ' + streak
361+
row.appendChild(statStreak)
362+
// container.appendChild(row)
351363
})
352364
}
353365

354-
createCombinedHeatmap()
366+
createYesNoHeatmapSection()
355367
}
356368
})()

‎jgclark.Summaries/src/chartStats.js‎

Lines changed: 14 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import moment from 'moment/min/moment-with-locales'
4141
import { logAvailableSharedResources, logProvidedSharedResources } from '../../np.Shared/src/index.js'
4242
import { getSummariesSettings } from './summaryHelpers.js'
4343
import type { SummariesConfig } from './summarySettings.js'
44-
import { tailwindToHsl } from '@helpers/colors'
44+
import { colorToModernSpecWithOpacity } from '@helpers/colors'
4545
import { clo, JSP, logDebug, logError, logInfo, logTimer, logWarn } from '@helpers/dev'
4646
import { showHTMLV2, type HtmlWindowOptions } from '@helpers/HTMLView'
4747
import { COMPLETED_TASK_TYPES } from '@helpers/utils'
@@ -56,8 +56,6 @@ const chartJsLocalPath = './chart.umd.min.js'
5656

5757
// =====================================================================
5858
// CONFIGURATION CONSTANTS
59-
// TODO: Shift to plugin.json
60-
// TODO: Remove timeline toggle
6159
// =====================================================================
6260

6361
/**
@@ -70,7 +68,7 @@ const chartJsLocalPath = './chart.umd.min.js'
7068

7169
// // Yes/No habits tracked with [x] completed checkboxes (add or remove as needed)
7270
// // Format in daily notes: [x] Exercise or - [x] Exercise
73-
// // TODO: If not tag/mention then treat this way; otherwise take from .progressYesNo
71+
// // If not tag/mention then treat this way; otherwise take from .progressYesNo
7472
// yesNoHabits: [
7573
// '#pray',
7674
// '#stretches',
@@ -117,80 +115,8 @@ const chartJsLocalPath = './chart.umd.min.js'
117115
// =====================================================================
118116

119117
/**
120-
* Convert any CSS color to rgba with specified opacity
121-
* Supports: #RGB, #RRGGBB, #RRGGBBAA, named colors (red, blue), hsl(), rgb(), rgba()
122-
* @param {string} color - CSS color value
123-
* @param {number} opacity - Opacity value between 0 and 1 (default: 0.3)
124-
* @returns {string} RGBA color string
125-
*/
126-
function colorToRgba(colorIn: string, opacity: number = 0.3): string {
127-
let color = colorIn.trim()
128-
129-
// First convert Tailwind color names to hsl(), as we had that function already
130-
if (/^\w+-\d+$/.test(color)) {
131-
color = tailwindToHsl(color)
132-
}
133-
134-
// If already rgba() or rgb() or hsl(), add opacity if needed
135-
if (color.startsWith('rgb(') || color.startsWith('hsl(')) {
136-
// Convert rgb() or hsl() to rgba() or hsla() with opacity
137-
return color
138-
.replace('rgb(', `rgba(`)
139-
.replace(')', `, ${opacity})`)
140-
.replace('hsl(', `hsla(`)
141-
.replace(')', `, ${opacity})`)
142-
}
143-
144-
// If already rgba() or hsla(), return as-is
145-
if (color.startsWith('rgba(') || color.startsWith('hsla(')) {
146-
return color
147-
}
148-
149-
// Handle hex colors (#RGB, #RRGGBB, #RRGGBBAA)
150-
if (color.startsWith('#')) {
151-
let hex = color.substring(1)
152-
153-
// Expand shorthand #RGB to #RRGGBB
154-
if (hex.length === 3) {
155-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]
156-
}
157-
158-
// Parse RGB values
159-
const r = parseInt(hex.substring(0, 2), 16)
160-
const g = parseInt(hex.substring(2, 4), 16)
161-
const b = parseInt(hex.substring(4, 6), 16)
162-
163-
// Check if alpha channel is present (#RRGGBBAA)
164-
if (hex.length === 8) {
165-
const a = parseInt(hex.substring(6, 8), 16) / 255
166-
return `rgba(${r}, ${g}, ${b}, ${a})`
167-
}
168-
169-
return `rgba(${r}, ${g}, ${b}, ${opacity})`
170-
}
171-
172-
// For named colors (red, blue, etc.), wrap in rgba with opacity
173-
// This works because CSS will interpret it correctly
174-
return `rgba(${color}, ${opacity})`
175-
}
176-
177-
/**
178-
* Normalize color input - add # to hex if missing, or return as-is for other formats
179-
* @param {string} color - Color input from user
180-
* @returns {string} Normalized color
181-
*/
182-
// function normalizeColor(color: string): string {
183-
// color = color.trim()
184-
// // If it looks like hex without #, add it
185-
// if (/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$|^[0-9A-Fa-f]{8}$/.test(color)) {
186-
// return '#' + color
187-
// }
188-
// // Return as-is for named colors, rgb(), hsl(), etc.
189-
// return color
190-
// }
191-
192-
/**
193-
* Load custom colors from plugin settings (single chartColors key, comma-separated).
118+
* Load custom colors from plugin settings (single chartColors key, comma-separated).
119+
* Supports: #RGB, #RRGGBB, #RRGGBBAA, named CSS colors (e.g. red, blue), tailwind colors (amber-200, blue-500, etc.), hsl(), rgb(), rgba()
194120
* @returns {Array} Array of color objects with border, bg, and name properties
195121
*/
196122
async function loadCustomColors(): Promise<Array<{ border: string, bg: string, name: string }>> {
@@ -221,14 +147,13 @@ async function loadCustomColors(): Promise<Array<{ border: string, bg: string, n
221147
}
222148

223149
const colors = colorStrings.map(userColor => {
224-
const normalizedColor = userColor.toLowerCase()
225150
return {
226-
border: normalizedColor,
227-
bg: colorToRgba(userColor, 0.4),
228-
name: normalizedColor
151+
border: colorToModernSpecWithOpacity(userColor),
152+
bg: colorToModernSpecWithOpacity(userColor, 0.5),
153+
name: userColor
229154
}
230155
})
231-
// clo(colors, 'loadCustomColors :: colors')
156+
// clo(colors, 'loadCustomColors :: colors', 2)
232157
return colors
233158
}
234159
// ============================================================================
@@ -798,8 +723,8 @@ function generateYesNoFilterCheckboxes(habits: Array<string>): string {
798723
*/
799724
function generateYesNoCombinedContainer(): string {
800725
return `
801-
<div class="chart-wrapper yesno-combined-wrapper">
802-
<div class="viz-display" id="yesno-combined-heatmap"></div>
726+
<div class="chart-wrapper">
727+
<div class="viz-display yesno-heatmap-section" id="yesno-heatmap-section"></div>
803728
</div>
804729
`
805730
}
@@ -840,7 +765,7 @@ function generateClientScript(tagData: Object, yesNoData: Object, tags: Array<st
840765
} else {
841766
console.error('Chart Stats: initChartStats not loaded (chartStatsScripts.js)');
842767
}
843-
`
768+
`
844769
}
845770

846771
// ========================================================================
@@ -907,9 +832,11 @@ async function makeChartSummaryHTML(
907832
${chartJsLoaderScript}
908833
<!-- for NotePlan to use -->
909834
<link rel="stylesheet" href="chartStats.css">
835+
<script type="text/javascript" src="chartStatsScripts.js"></script>
836+
910837
<!-- for local development to use -->
911838
<link rel="stylesheet" href="../../jgclark.Summaries/chartStats.css">
912-
<script type="text/javascript" src="chartStatsScripts.js"></script>
839+
<script type="text/javascript" src="../../jgclark.Summaries/chartStatsScripts.js"></script>
913840
<style>${chartStyleVars}</style>
914841
</head>
915842

0 commit comments

Comments
 (0)