Got inspired by the OP, and just put together a hacky version of the dashboard. This needs Minimal theme, Dataview, and Obsidian Charts.
Here’s the main page:
---
cssclasses:
- fullwidth
---
'''dataviewjs
// Get all the DateTimes for days in the current calendar month.
function daysInThisMonth() {
var num = DateTime.now().daysInMonth
return Array.from({length: num},
(_, i) =>
DateTime.fromObject({
year: DateTime.now().year,
month: DateTime.now().month,
day: i + 1}))
}
function header() {
return [""].concat(daysInThisMonth().map( d => (d.day).toString() ))
}
// Get an array of Page objects corresponding to the dates,
// with undefined if the page is missing.
function dataPages(dates) {
var pages = dv.pages('#daily and -"Templates"')
return dates.map( d => pages.find(p => p.file.day.equals(d)))
}
// You'd want to do something different/smarter for each row.
function formatEntry(e) {
switch(e) {
case true:
return "🟩";
case false:
return "🟥";
default:
return "";
}
}
var allData = dataPages(daysInThisMonth())
dv.table(header(), [
["🍔"].concat(allData.map(d => d ? formatEntry(d["ate-well"]) : "")),
["🛌"].concat(allData.map(d => d ? formatEntry(d["slept-well"]) : "")),
["🫀"].concat(allData.map(d => d ? formatEntry(d["exercise-cardio"]) : "")),
])
// Just using fake data for now.
const testData = [8, 8, 8, 8, 8, 7, 7, 6, 6.5, 7, 8, 9]
const testData2 = [5, 7, 3, 6, 9, 8, 8, 5.5, 6.5, 2, 10, 9]
// In reality, you'd add a field (like my-mood) to the daily note and use something like
// testData = allData.map(d => d ? d["my-mood"] : undefined);
const chartData = {
data: {
labels: header().slice(1),
datasets: [{
type: 'bar',
label: 'Data',
data: testData,
backgroundColor: [ 'rgba(255, 99, 132, 0.2)' ],
borderColor: [ 'rgba(255, 99, 132, 1)' ],
borderWidth: 1,
},
{
type: 'bar',
label: 'Data 2',
data: testData2,
backgroundColor: [ 'rgba(99, 255, 132, 0.2)' ],
borderColor: [ 'rgba(99, 255, 132, 1)' ],
borderWidth: 1,
},
{
type: 'line',
label: 'Line Dataset',
data: [2, 10, 7, 8], // yes, more fake data
borderWidth: 3,
pointBorderWidth: 2,
pointRadius: 5,
pointBackgroundColor: [ 'rgba(99, 132, 255, 0.2)' ],
pointBorderColor: [ 'rgba(99, 132, 255, 1)' ],
borderColor: [ 'rgba(99, 132, 255, 1)' ],
}],
},
options: {
scales: {
yAxis: {
afterSetDimensions: function(axes) {
axes.labelAutoFit = false;
axes.maxWidth = 30;
axes.minWidth = 30;
}
}
},
plugins: {
legend: { // Could display legend if you want
display: false,
labels: {
color: 'rgb(255, 99, 132)'
}
}
},
layout: {
padding: {
left: 5
}
}
}
}
window.renderChart(chartData, this.container)
'''
The CSS was a pain:
/* selectively enable wide pages even with Minimal theme */
.fullwidth.markdown-source-view.mod-cm6.is-readable-line-width .cm-content,
.fullwidth.markdown-source-view.mod-cm6.is-readable-line-width .cm-line,
.fullwidth.markdown-source-view.mod-cm6.is-readable-line-width .cm-embed-block {
--line-width: 100rem;
--line-width-wide: 100rem;
}
.fullwidth.markdown-source-view.mod-cm6.is-readable-line-width .cm-preview-code-block {
--table-edge-cell-padding-first: 0px;
--table-cell-padding: 0px 0px;
--container-table-width: 100rem;
--max-width: 100%;
--container-chart-width: 88%;
--container-chart-max-width: 100%;
}
/* suppress # of rows next to first column */
.fullwidth .dataview.small-text {
display: none;
}
.fullwidth table td {
font-size: 14px;
color: #000000;
word-wrap: break-word;
border-left: 1px solid #222222 !important;
border-bottom: 1px solid #222222 !important;
}
.fullwidth .table-view-table tr td {
text-align: center;
padding: 8px 0px;
}
.fullwidth .table-view-table tr th {
min-width: 20px;
text-align: center;
}
.fullwidth .table-view-table tr th:nth-child(1) {
width: 35px; /* must equal chart yaxis label width + left padding */
text-align: center;
}
And a minimal version of my daily note (uses YYYY-MM-DD as the name format):
---
tags:
- "#daily"
---
Habit Tracking:
[slept-well:: true]
[ate-well:: false]
[exercise-cardio:: ]