From 156c562cc05ed30e1212e1e08c604a023ba0b562 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 15:25:37 +0000
Subject: [PATCH 01/45] Initial plan
From b7d8e206b395865ec24cbb8e70c96c2e7c51e506 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 15:30:08 +0000
Subject: [PATCH 02/45] Add Habit Tracker sample with two interactive tables
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 276 ++++++++++++++++++
1 file changed, 276 insertions(+)
create mode 100644 packages/web-deploy/json/habit-tracker.idoc.json
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
new file mode 100644
index 00000000..ef5e3d75
--- /dev/null
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -0,0 +1,276 @@
+{
+ "$schema": "../../../docs/schema/idoc_v1.json",
+ "title": "Habit Tracker",
+ "style": {
+ "css": [
+ "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
+ "body { display: grid; grid-template-areas: 'header header' 'habits progress' 'stats stats'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
+ ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
+ "#habits { grid-area: habits; }",
+ "#progress { grid-area: progress; }",
+ "#stats { grid-area: stats; }",
+ "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
+ "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
+ "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
+ ".stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 15px; }",
+ ".stat-card { background: #f7fafc; padding: 15px; border-radius: 8px; text-align: center; border: 1px solid #e2e8f0; }",
+ ".stat-number { font-size: 2em; font-weight: bold; color: #667eea; margin-bottom: 5px; }",
+ ".stat-label { color: #718096; font-size: 0.9em; }",
+ ".tabulator { border-radius: 8px; overflow: hidden; }",
+ ".tabulator .tabulator-header { background: #f7fafc; }",
+ ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
+ ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
+ ".tabulator .tabulator-row:hover { background: #f8fafc; }"
+ ]
+ },
+ "dataLoaders": [
+ {
+ "dataSourceName": "habitsData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {
+ "habit_id": 1,
+ "habit_name": "Morning Exercise",
+ "category": "Health",
+ "target_frequency": "Daily",
+ "current_streak": 5,
+ "best_streak": 12
+ },
+ {
+ "habit_id": 2,
+ "habit_name": "Read for 30min",
+ "category": "Learning",
+ "target_frequency": "Daily",
+ "current_streak": 3,
+ "best_streak": 21
+ },
+ {
+ "habit_id": 3,
+ "habit_name": "Meditate",
+ "category": "Wellness",
+ "target_frequency": "Daily",
+ "current_streak": 8,
+ "best_streak": 15
+ },
+ {
+ "habit_id": 4,
+ "habit_name": "Write Journal",
+ "category": "Wellness",
+ "target_frequency": "Daily",
+ "current_streak": 2,
+ "best_streak": 7
+ },
+ {
+ "habit_id": 5,
+ "habit_name": "Learn New Language",
+ "category": "Learning",
+ "target_frequency": "3x per week",
+ "current_streak": 1,
+ "best_streak": 4
+ },
+ {
+ "habit_id": 6,
+ "habit_name": "Call Family",
+ "category": "Social",
+ "target_frequency": "Weekly",
+ "current_streak": 2,
+ "best_streak": 8
+ }
+ ]
+ },
+ {
+ "dataSourceName": "progressData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true}
+ ]
+ }
+ ],
+ "variables": [
+ {
+ "variableId": "totalHabits",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('habitsData'))"
+ }
+ },
+ {
+ "variableId": "completionRateData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "ops": ["count", "sum"],
+ "fields": ["completed", "completed"],
+ "as": ["total_entries", "completed_count"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_entries * 100",
+ "as": "completion_rate"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "overallCompletionRate",
+ "type": "string",
+ "initialValue": "0%",
+ "calculation": {
+ "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
+ }
+ },
+ {
+ "variableId": "activeDaysData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["count"],
+ "fields": ["habit_id"],
+ "as": ["habits_tracked"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalActiveDays",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('activeDaysData'))"
+ }
+ },
+ {
+ "variableId": "averageStreak",
+ "type": "string",
+ "initialValue": "0",
+ "calculation": {
+ "dataSourceNames": ["habitsData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "ops": ["mean"],
+ "fields": ["current_streak"],
+ "as": ["avg_streak"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "avgStreakFormatted",
+ "type": "string",
+ "initialValue": "0.0",
+ "calculation": {
+ "vegaExpression": "format(data('averageStreak')[0] ? data('averageStreak')[0].avg_streak : 0, '.1f')"
+ }
+ }
+ ],
+ "groups": [
+ {
+ "groupId": "header",
+ "elements": [
+ "# 🎯 Habit Tracker",
+ "Track your daily habits and build consistent routines for personal growth."
+ ]
+ },
+ {
+ "groupId": "habits",
+ "elements": [
+ "## 📋 My Habits",
+ {
+ "type": "tabulator",
+ "dataSourceName": "habitsData",
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "habit_name", "title": "Habit", "width": 150},
+ {"field": "category", "title": "Category", "width": 100},
+ {"field": "target_frequency", "title": "Target", "width": 120},
+ {"field": "current_streak", "title": "Streak", "width": 80, "hozAlign": "center"},
+ {"field": "best_streak", "title": "Best", "width": 70, "hozAlign": "center"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "rowHeader": {
+ "width": 40,
+ "hozAlign": "center",
+ "formatter": "rownum"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "progress",
+ "elements": [
+ "## 📈 Recent Progress",
+ {
+ "type": "tabulator",
+ "dataSourceName": "progressData",
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "date", "title": "Date", "width": 100},
+ {"field": "habit_name", "title": "Habit", "width": 150},
+ {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "initialSort": [
+ {"column": "date", "dir": "desc"}
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "stats",
+ "elements": [
+ "## 📊 Statistics",
+ "
",
+ "
{{totalHabits}}
Active Habits
",
+ "
{{overallCompletionRate}}
Completion Rate
",
+ "
{{totalActiveDays}}
Days Tracked
",
+ "
{{avgStreakFormatted}}
Avg Streak
",
+ "
"
+ ]
+ }
+ ]
+}
\ No newline at end of file
From c67342c69b9255e0ca3ffa84c426cab41bfdf351 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 16:04:44 +0000
Subject: [PATCH 03/45] Remove HTML elements from habit tracker, use Markdown
formatting
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.github/copilot-instructions.md | 3 +++
.../web-deploy/json/habit-tracker.idoc.json | 18 ++++++++----------
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index d60b5441..52371c6e 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -42,7 +42,9 @@ Chartifact consists of several interoperating modules:
4. **Security**:
- Documents are rendered in sandboxed iframes.
+ - **NO HTML elements are allowed** - use only Markdown formatting.
- No custom JavaScript execution or raw HTML in Markdown.
+ - For layouts and styling, use only CSS classes applied to groups and standard Markdown elements.
## Examples
@@ -50,6 +52,7 @@ Chartifact consists of several interoperating modules:
- Examples in this repo use the json format and are compiled to markdown.
- If you are asked to create an example, do it in the packages/web-deploy/json folder, do not modify the destination folder docs/assets/examples - this will be populated by a build.
- The examples are built manually for now.
+- **IMPORTANT**: When creating examples, use only Markdown formatting - NO HTML elements are allowed. Use plain text, Markdown headers, bold/italic formatting, and CSS styling for visual presentation.
## Runtime host
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index ef5e3d75..346d1866 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -13,10 +13,6 @@
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
"h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
- ".stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-top: 15px; }",
- ".stat-card { background: #f7fafc; padding: 15px; border-radius: 8px; text-align: center; border: 1px solid #e2e8f0; }",
- ".stat-number { font-size: 2em; font-weight: bold; color: #667eea; margin-bottom: 5px; }",
- ".stat-label { color: #718096; font-size: 0.9em; }",
".tabulator { border-radius: 8px; overflow: hidden; }",
".tabulator .tabulator-header { background: #f7fafc; }",
".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
@@ -264,12 +260,14 @@
"groupId": "stats",
"elements": [
"## 📊 Statistics",
- "",
- "
{{totalHabits}}
Active Habits
",
- "
{{overallCompletionRate}}
Completion Rate
",
- "
{{totalActiveDays}}
Days Tracked
",
- "
{{avgStreakFormatted}}
Avg Streak
",
- "
"
+ "",
+ "**Active Habits:** {{totalHabits}}",
+ "",
+ "**Completion Rate:** {{overallCompletionRate}}",
+ "",
+ "**Days Tracked:** {{totalActiveDays}}",
+ "",
+ "**Average Streak:** {{avgStreakFormatted}} days"
]
}
]
From 9d7694c2ac74d93c4bab6e1d3601dbc6429e0c89 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 16:20:03 +0000
Subject: [PATCH 04/45] Remove hardcoded streaks from habits table, calculate
from progress data
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 61 ++++++++-----------
1 file changed, 26 insertions(+), 35 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 346d1866..539891e2 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -30,49 +30,37 @@
"habit_id": 1,
"habit_name": "Morning Exercise",
"category": "Health",
- "target_frequency": "Daily",
- "current_streak": 5,
- "best_streak": 12
+ "target_frequency": "Daily"
},
{
"habit_id": 2,
"habit_name": "Read for 30min",
"category": "Learning",
- "target_frequency": "Daily",
- "current_streak": 3,
- "best_streak": 21
+ "target_frequency": "Daily"
},
{
"habit_id": 3,
"habit_name": "Meditate",
"category": "Wellness",
- "target_frequency": "Daily",
- "current_streak": 8,
- "best_streak": 15
+ "target_frequency": "Daily"
},
{
"habit_id": 4,
"habit_name": "Write Journal",
"category": "Wellness",
- "target_frequency": "Daily",
- "current_streak": 2,
- "best_streak": 7
+ "target_frequency": "Daily"
},
{
"habit_id": 5,
"habit_name": "Learn New Language",
"category": "Learning",
- "target_frequency": "3x per week",
- "current_streak": 1,
- "best_streak": 4
+ "target_frequency": "3x per week"
},
{
"habit_id": 6,
"habit_name": "Call Family",
"category": "Social",
- "target_frequency": "Weekly",
- "current_streak": 2,
- "best_streak": 8
+ "target_frequency": "Weekly"
}
]
},
@@ -176,27 +164,32 @@
}
},
{
- "variableId": "averageStreak",
- "type": "string",
- "initialValue": "0",
+ "variableId": "totalCompletedEntries",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
"calculation": {
- "dataSourceNames": ["habitsData"],
+ "dataSourceNames": ["progressData"],
"dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "datum.completed === true"
+ },
{
"type": "aggregate",
- "ops": ["mean"],
- "fields": ["current_streak"],
- "as": ["avg_streak"]
+ "ops": ["count"],
+ "fields": ["completed"],
+ "as": ["completed_count"]
}
]
}
},
{
- "variableId": "avgStreakFormatted",
- "type": "string",
- "initialValue": "0.0",
+ "variableId": "totalCompleted",
+ "type": "number",
+ "initialValue": 0,
"calculation": {
- "vegaExpression": "format(data('averageStreak')[0] ? data('averageStreak')[0].avg_streak : 0, '.1f')"
+ "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
}
}
],
@@ -217,11 +210,9 @@
"dataSourceName": "habitsData",
"tabulatorOptions": {
"columns": [
- {"field": "habit_name", "title": "Habit", "width": 150},
- {"field": "category", "title": "Category", "width": 100},
- {"field": "target_frequency", "title": "Target", "width": 120},
- {"field": "current_streak", "title": "Streak", "width": 80, "hozAlign": "center"},
- {"field": "best_streak", "title": "Best", "width": 70, "hozAlign": "center"}
+ {"field": "habit_name", "title": "Habit", "width": 200},
+ {"field": "category", "title": "Category", "width": 120},
+ {"field": "target_frequency", "title": "Target", "width": 150}
],
"layout": "fitColumns",
"height": "300px",
@@ -267,7 +258,7 @@
"",
"**Days Tracked:** {{totalActiveDays}}",
"",
- "**Average Streak:** {{avgStreakFormatted}} days"
+ "**Total Completed:** {{totalCompleted}} habits"
]
}
]
From 985b366f0bc3313f844a2e7a46448b36d5cc4a68 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 16:24:14 +0000
Subject: [PATCH 05/45] Update copilot instructions to always provide preview
links automatically
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.github/copilot-instructions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 52371c6e..2b1e8842 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -58,4 +58,4 @@ Chartifact consists of several interoperating modules:
- There is a sandboxed runtime that securely renders documents available at https://microsoft.github.io/chartifact/view
- The url above can accept a `load` parameter to specify the document to render, for example https://microsoft.github.io/chartifact/view/?load=https://raw.githubusercontent.com/microsoft/chartifact/562d086/packages/web-deploy/json/sales-dashboard.idoc.json
-- If you are asked to create an example, please provide a link in the PR comments so it can be previewed.
+- **ALWAYS provide a preview link when creating or modifying examples** - include the preview link in PR comments and descriptions automatically so examples can be tested immediately without being asked.
From eb88f6cc1cbd17379954098a6446aba27cbbb322 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 17:43:50 +0000
Subject: [PATCH 06/45] Make both tables editable in habit tracker with proper
editors and updated statistics
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 24 +++++++++++--------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 539891e2..4f7b5970 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -104,7 +104,7 @@
"type": "number",
"initialValue": 0,
"calculation": {
- "vegaExpression": "length(data('habitsData'))"
+ "vegaExpression": "length(data('habitsDataTable'))"
}
},
{
@@ -113,7 +113,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressData"],
+ "dataSourceNames": ["progressDataTable"],
"dataFrameTransformations": [
{
"type": "aggregate",
@@ -143,7 +143,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressData"],
+ "dataSourceNames": ["progressDataTable"],
"dataFrameTransformations": [
{
"type": "aggregate",
@@ -169,7 +169,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressData"],
+ "dataSourceNames": ["progressDataTable"],
"dataFrameTransformations": [
{
"type": "filter",
@@ -208,11 +208,13 @@
{
"type": "tabulator",
"dataSourceName": "habitsData",
+ "variableId": "habitsDataTable",
+ "editable": true,
"tabulatorOptions": {
"columns": [
- {"field": "habit_name", "title": "Habit", "width": 200},
- {"field": "category", "title": "Category", "width": 120},
- {"field": "target_frequency", "title": "Target", "width": 150}
+ {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
+ {"field": "category", "title": "Category", "width": 120, "editor": "input"},
+ {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
],
"layout": "fitColumns",
"height": "300px",
@@ -232,11 +234,13 @@
{
"type": "tabulator",
"dataSourceName": "progressData",
+ "variableId": "progressDataTable",
+ "editable": true,
"tabulatorOptions": {
"columns": [
- {"field": "date", "title": "Date", "width": 100},
- {"field": "habit_name", "title": "Habit", "width": 150},
- {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross"}
+ {"field": "date", "title": "Date", "width": 100, "editor": "date"},
+ {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
+ {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
],
"layout": "fitColumns",
"height": "300px",
From af42e92d051ea1edc10260307800ffbb3055080a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 18:23:38 +0000
Subject: [PATCH 07/45] Add month filter dropdown and heatmap visualization to
habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 158 +++++++++++++++++-
1 file changed, 152 insertions(+), 6 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 4f7b5970..92d64e46 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -4,9 +4,11 @@
"style": {
"css": [
"body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'habits progress' 'stats stats'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
+ "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
+ "#controls { grid-area: controls; }",
+ "#heatmap { grid-area: heatmap; }",
"#habits { grid-area: habits; }",
"#progress { grid-area: progress; }",
"#stats { grid-area: stats; }",
@@ -94,11 +96,98 @@
{"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
{"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
{"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true}
+ {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
]
}
],
"variables": [
+ {
+ "variableId": "selectedMonth",
+ "type": "string",
+ "initialValue": "2024-01",
+ "input": {
+ "type": "dropdown",
+ "options": [
+ {"value": "All", "label": "All Months"},
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"}
+ ]
+ }
+ },
+ {
+ "variableId": "filteredProgressData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressDataTable"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "selectedMonth === 'All' || slice(datum.date, 0, 7) === selectedMonth"
+ }
+ ]
+ }
+ },
{
"variableId": "totalHabits",
"type": "number",
@@ -113,7 +202,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable"],
+ "dataSourceNames": ["filteredProgressData"],
"dataFrameTransformations": [
{
"type": "aggregate",
@@ -143,7 +232,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable"],
+ "dataSourceNames": ["filteredProgressData"],
"dataFrameTransformations": [
{
"type": "aggregate",
@@ -169,7 +258,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable"],
+ "dataSourceNames": ["filteredProgressData"],
"dataFrameTransformations": [
{
"type": "filter",
@@ -201,6 +290,63 @@
"Track your daily habits and build consistent routines for personal growth."
]
},
+ {
+ "groupId": "controls",
+ "elements": [
+ "## 🎛️ Filters",
+ "",
+ "**Month:** {{selectedMonth}}"
+ ]
+ },
+ {
+ "groupId": "heatmap",
+ "elements": [
+ "## 🗓️ Habit Completion Heatmap",
+ {
+ "type": "vega-lite",
+ "spec": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "filteredProgressData"},
+ "mark": {"type": "rect", "stroke": "#f1f5f9", "strokeWidth": 1},
+ "encoding": {
+ "x": {
+ "field": "date",
+ "type": "temporal",
+ "title": "Date",
+ "axis": {"format": "%b %d", "labelAngle": -45}
+ },
+ "y": {
+ "field": "habit_name",
+ "type": "nominal",
+ "title": "Habit",
+ "sort": null
+ },
+ "color": {
+ "field": "completed",
+ "type": "nominal",
+ "scale": {
+ "domain": [true, false],
+ "range": ["#22c55e", "#ef4444"]
+ },
+ "legend": {
+ "title": "Completed",
+ "values": [true, false],
+ "labelExpr": "datum.value ? 'Yes' : 'No'"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "habit_name", "type": "nominal", "title": "Habit"},
+ {"field": "completed", "type": "nominal", "title": "Completed"}
+ ]
+ },
+ "width": "container",
+ "height": 200,
+ "background": "transparent"
+ }
+ }
+ ]
+ },
{
"groupId": "habits",
"elements": [
@@ -230,7 +376,7 @@
{
"groupId": "progress",
"elements": [
- "## 📈 Recent Progress",
+ "## 📈 Progress (Filtered by Month)",
{
"type": "tabulator",
"dataSourceName": "progressData",
From 847450ca1541ab9d0740db9d8c2c7e1be9eb568b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 18:55:12 +0000
Subject: [PATCH 08/45] Fix dropdown and heatmap display in habit tracker - add
dropdown element to controls group
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 23 ++++++++++---------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 92d64e46..89825c99 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -162,16 +162,7 @@
{
"variableId": "selectedMonth",
"type": "string",
- "initialValue": "2024-01",
- "input": {
- "type": "dropdown",
- "options": [
- {"value": "All", "label": "All Months"},
- {"value": "2024-01", "label": "January 2024"},
- {"value": "2024-02", "label": "February 2024"},
- {"value": "2024-03", "label": "March 2024"}
- ]
- }
+ "initialValue": "All"
},
{
"variableId": "filteredProgressData",
@@ -295,7 +286,17 @@
"elements": [
"## 🎛️ Filters",
"",
- "**Month:** {{selectedMonth}}"
+ {
+ "type": "dropdown",
+ "variableId": "selectedMonth",
+ "label": "Select Month:",
+ "options": [
+ {"value": "All", "label": "All Months"},
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"}
+ ]
+ }
]
},
{
From 01b8ef4d318257b77f5bb17aa3e4d0a4ebcfce67 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 21:40:32 +0000
Subject: [PATCH 09/45] Fix dropdown options display and heatmap visualization
in habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.github/copilot-instructions.md | 14 +++
.../web-deploy/json/habit-tracker.idoc.json | 110 ++++++++++--------
2 files changed, 76 insertions(+), 48 deletions(-)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 2b1e8842..0ac5f168 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -46,6 +46,20 @@ Chartifact consists of several interoperating modules:
- No custom JavaScript execution or raw HTML in Markdown.
- For layouts and styling, use only CSS classes applied to groups and standard Markdown elements.
+## Component Capabilities and Constraints
+
+1. **Dropdown Components**:
+ - Dropdown options must be strings only - no objects with value/label properties
+ - Use simple string arrays for options: `"options": ["Option1", "Option2"]`
+ - For data-driven options, use `dynamicOptions` with a data source
+ - Objects in dropdown options will display as "[object Object]"
+
+2. **Chart Components**:
+ - Heatmaps and complex visualizations should use the `chart` type with `chartKey`
+ - Place chart specifications in the `resources.charts` section
+ - Reference charts using `{"type": "chart", "chartKey": "yourChartKey"}`
+ - Direct `vega-lite` type elements may not render properly for complex charts
+
## Examples
- Source code for examples is in the packages/web-deploy/json folder
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 89825c99..57ecf87e 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -23,6 +23,17 @@
]
},
"dataLoaders": [
+ {
+ "dataSourceName": "monthOptions",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"value": "All", "label": "All Months"},
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"}
+ ]
+ },
{
"dataSourceName": "habitsData",
"type": "inline",
@@ -290,12 +301,10 @@
"type": "dropdown",
"variableId": "selectedMonth",
"label": "Select Month:",
- "options": [
- {"value": "All", "label": "All Months"},
- {"value": "2024-01", "label": "January 2024"},
- {"value": "2024-02", "label": "February 2024"},
- {"value": "2024-03", "label": "March 2024"}
- ]
+ "dynamicOptions": {
+ "dataSourceName": "monthOptions",
+ "fieldName": "value"
+ }
}
]
},
@@ -304,47 +313,8 @@
"elements": [
"## 🗓️ Habit Completion Heatmap",
{
- "type": "vega-lite",
- "spec": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "filteredProgressData"},
- "mark": {"type": "rect", "stroke": "#f1f5f9", "strokeWidth": 1},
- "encoding": {
- "x": {
- "field": "date",
- "type": "temporal",
- "title": "Date",
- "axis": {"format": "%b %d", "labelAngle": -45}
- },
- "y": {
- "field": "habit_name",
- "type": "nominal",
- "title": "Habit",
- "sort": null
- },
- "color": {
- "field": "completed",
- "type": "nominal",
- "scale": {
- "domain": [true, false],
- "range": ["#22c55e", "#ef4444"]
- },
- "legend": {
- "title": "Completed",
- "values": [true, false],
- "labelExpr": "datum.value ? 'Yes' : 'No'"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "habit_name", "type": "nominal", "title": "Habit"},
- {"field": "completed", "type": "nominal", "title": "Completed"}
- ]
- },
- "width": "container",
- "height": 200,
- "background": "transparent"
- }
+ "type": "chart",
+ "chartKey": "heatmap"
}
]
},
@@ -412,5 +382,49 @@
"**Total Completed:** {{totalCompleted}} habits"
]
}
- ]
+ ],
+ "resources": {
+ "charts": {
+ "heatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "filteredProgressData"},
+ "mark": {"type": "rect", "stroke": "#f1f5f9", "strokeWidth": 1},
+ "encoding": {
+ "x": {
+ "field": "date",
+ "type": "temporal",
+ "title": "Date",
+ "axis": {"format": "%b %d", "labelAngle": -45}
+ },
+ "y": {
+ "field": "habit_name",
+ "type": "nominal",
+ "title": "Habit",
+ "sort": null
+ },
+ "color": {
+ "field": "completed",
+ "type": "nominal",
+ "scale": {
+ "domain": [true, false],
+ "range": ["#22c55e", "#ef4444"]
+ },
+ "legend": {
+ "title": "Completed",
+ "values": [true, false],
+ "labelExpr": "datum.value ? 'Yes' : 'No'"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "habit_name", "type": "nominal", "title": "Habit"},
+ {"field": "completed", "type": "nominal", "title": "Completed"}
+ ]
+ },
+ "width": "container",
+ "height": 200,
+ "background": "transparent"
+ }
+ }
+ }
}
\ No newline at end of file
From 3cdcdc7a4eabe0bbf3b9750454a0279b1b2f4919 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 22:43:46 +0000
Subject: [PATCH 10/45] Fix heatmap to show proper calendar-style visualization
with daily completion rates
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 79 ++++++++++++++-----
1 file changed, 60 insertions(+), 19 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 57ecf87e..3b853f40 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -190,6 +190,29 @@
]
}
},
+ {
+ "variableId": "dailyCompletionData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["sum", "count"],
+ "fields": ["completed", "completed"],
+ "as": ["completed_count", "total_habits"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ }
+ ]
+ }
+ },
{
"variableId": "totalHabits",
"type": "number",
@@ -387,42 +410,60 @@
"charts": {
"heatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "filteredProgressData"},
- "mark": {"type": "rect", "stroke": "#f1f5f9", "strokeWidth": 1},
+ "data": {"name": "dailyCompletionData"},
+ "title": "Daily Habit Completion Rate",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13
+ },
+ "axis": {
+ "domain": false
+ }
+ },
+ "mark": {
+ "type": "rect",
+ "stroke": "#ffffff",
+ "strokeWidth": 2
+ },
"encoding": {
"x": {
"field": "date",
- "type": "temporal",
- "title": "Date",
- "axis": {"format": "%b %d", "labelAngle": -45}
+ "timeUnit": "date",
+ "type": "ordinal",
+ "title": "Day of Month",
+ "axis": {
+ "labelAngle": 0,
+ "format": "%e"
+ }
},
"y": {
- "field": "habit_name",
- "type": "nominal",
- "title": "Habit",
- "sort": null
+ "field": "date",
+ "timeUnit": "month",
+ "type": "ordinal",
+ "title": "Month"
},
"color": {
- "field": "completed",
- "type": "nominal",
+ "field": "completion_rate",
+ "type": "quantitative",
"scale": {
- "domain": [true, false],
- "range": ["#22c55e", "#ef4444"]
+ "scheme": "greens",
+ "domain": [0, 1]
},
"legend": {
- "title": "Completed",
- "values": [true, false],
- "labelExpr": "datum.value ? 'Yes' : 'No'"
+ "title": "Completion Rate",
+ "format": ".0%"
}
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "habit_name", "type": "nominal", "title": "Habit"},
- {"field": "completed", "type": "nominal", "title": "Completed"}
+ {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
+ {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
+ {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
- "height": 200,
+ "height": 150,
"background": "transparent"
}
}
From b1ee0a3054f93ed5cdfc7b64dca34dc9559539df Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 22:55:52 +0000
Subject: [PATCH 11/45] Fix heatmap temporal encoding - use temporal type for
proper day display
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker.idoc.json | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 3b853f40..8c8d6b6e 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -209,6 +209,11 @@
"type": "formula",
"expr": "datum.completed_count / datum.total_habits",
"as": "completion_rate"
+ },
+ {
+ "type": "formula",
+ "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
+ "as": "date_parsed"
}
]
}
@@ -424,13 +429,14 @@
"mark": {
"type": "rect",
"stroke": "#ffffff",
- "strokeWidth": 2
+ "strokeWidth": 2,
+ "opacity": 0.8
},
"encoding": {
"x": {
"field": "date",
"timeUnit": "date",
- "type": "ordinal",
+ "type": "temporal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
@@ -440,7 +446,7 @@
"y": {
"field": "date",
"timeUnit": "month",
- "type": "ordinal",
+ "type": "temporal",
"title": "Month"
},
"color": {
From 3c5bc2111ba9b7d747edbcb59abac09fdb9a5581 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 23:32:24 +0000
Subject: [PATCH 12/45] Fix data reactivity issue - add explicit boolean to
numeric conversion for aggregations
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker.idoc.json | 27 ++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
index 8c8d6b6e..675c04d2 100644
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -4,7 +4,7 @@
"style": {
"css": [
"body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
+ "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'debug debug'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
"#controls { grid-area: controls; }",
@@ -12,6 +12,7 @@
"#habits { grid-area: habits; }",
"#progress { grid-area: progress; }",
"#stats { grid-area: stats; }",
+ "#debug { grid-area: debug; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
"h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
@@ -198,11 +199,16 @@
"calculation": {
"dataSourceNames": ["filteredProgressData"],
"dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
{
"type": "aggregate",
"groupby": ["date"],
"ops": ["sum", "count"],
- "fields": ["completed", "completed"],
+ "fields": ["completed_numeric", "completed_numeric"],
"as": ["completed_count", "total_habits"]
},
{
@@ -234,10 +240,15 @@
"calculation": {
"dataSourceNames": ["filteredProgressData"],
"dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
{
"type": "aggregate",
"ops": ["count", "sum"],
- "fields": ["completed", "completed"],
+ "fields": ["completed_numeric", "completed_numeric"],
"as": ["total_entries", "completed_count"]
},
{
@@ -409,6 +420,16 @@
"",
"**Total Completed:** {{totalCompleted}} habits"
]
+ },
+ {
+ "groupId": "debug",
+ "elements": [
+ "## 🔍 Debug: Daily Completion Data",
+ {
+ "type": "tabulator",
+ "dataSourceName": "dailyCompletionData"
+ }
+ ]
}
],
"resources": {
From 91310f43989ec90db52aa2a12d0f3d6d6161bc03 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 4 Sep 2025 23:57:22 +0000
Subject: [PATCH 13/45] Create enhanced habit tracker with category-based
insights and separate monthly/all-time views
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-enhanced.idoc.json | 612 ++++++++++++++++++
1 file changed, 612 insertions(+)
create mode 100644 packages/web-deploy/json/habit-tracker-enhanced.idoc.json
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
new file mode 100644
index 00000000..e21626b5
--- /dev/null
+++ b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
@@ -0,0 +1,612 @@
+{
+ "$schema": "../../../docs/schema/idoc_v1.json",
+ "title": "Enhanced Habit Tracker",
+ "style": {
+ "css": [
+ "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
+ "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'alltime alltime'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1400px; margin: 0 auto; }",
+ ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
+ "#controls { grid-area: controls; }",
+ "#heatmap { grid-area: heatmap; }",
+ "#habits { grid-area: habits; }",
+ "#progress { grid-area: progress; }",
+ "#stats { grid-area: stats; }",
+ "#alltime { grid-area: alltime; }",
+ "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
+ "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
+ "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
+ ".tabulator { border-radius: 8px; overflow: hidden; }",
+ ".tabulator .tabulator-header { background: #f7fafc; }",
+ ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
+ ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
+ ".tabulator .tabulator-row:hover { background: #f8fafc; }"
+ ]
+ },
+ "dataLoaders": [
+ {
+ "dataSourceName": "monthOptions",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ "2024-01",
+ "2024-02",
+ "2024-03"
+ ]
+ },
+ {
+ "dataSourceName": "habitsData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {
+ "habit_id": 1,
+ "habit_name": "Morning Exercise",
+ "category": "Health",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 2,
+ "habit_name": "Read for 30min",
+ "category": "Learning",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 3,
+ "habit_name": "Meditate",
+ "category": "Wellness",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 4,
+ "habit_name": "Write Journal",
+ "category": "Wellness",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 5,
+ "habit_name": "Learn New Language",
+ "category": "Learning",
+ "target_frequency": "3x per week"
+ },
+ {
+ "habit_id": 6,
+ "habit_name": "Call Family",
+ "category": "Social",
+ "target_frequency": "Weekly"
+ }
+ ]
+ },
+ {
+ "dataSourceName": "progressData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
+ ]
+ }
+ ],
+ "variables": [
+ {
+ "variableId": "selectedMonth",
+ "type": "string",
+ "initialValue": "2024-01"
+ },
+ {
+ "variableId": "enrichedProgressData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressDataTable", "habitsDataTable"],
+ "dataFrameTransformations": [
+ {
+ "type": "lookup",
+ "from": "habitsDataTable",
+ "key": "habit_id",
+ "fields": ["category", "target_frequency"],
+ "as": ["category", "target_frequency"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "filteredProgressData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["enrichedProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "slice(datum.date, 0, 7) === selectedMonth"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "monthlyHeatmapData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["sum", "count"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["completed_count", "total_habits"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ },
+ {
+ "type": "formula",
+ "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
+ "as": "date_parsed"
+ },
+ {
+ "type": "formula",
+ "expr": "date(datum.date)",
+ "as": "day_of_month"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "allTimeHeatmapData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["enrichedProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "groupby": ["date", "category"],
+ "ops": ["sum", "count"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["completed_count", "total_habits"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ },
+ {
+ "type": "formula",
+ "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
+ "as": "date_parsed"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalHabits",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('habitsDataTable'))"
+ }
+ },
+ {
+ "variableId": "completionRateData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "ops": ["count", "sum"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["total_entries", "completed_count"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_entries * 100",
+ "as": "completion_rate"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "overallCompletionRate",
+ "type": "string",
+ "initialValue": "0%",
+ "calculation": {
+ "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
+ }
+ },
+ {
+ "variableId": "activeDaysData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["count"],
+ "fields": ["habit_id"],
+ "as": ["habits_tracked"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalActiveDays",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('activeDaysData'))"
+ }
+ },
+ {
+ "variableId": "totalCompletedEntries",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "datum.completed === true"
+ },
+ {
+ "type": "aggregate",
+ "ops": ["count"],
+ "fields": ["completed"],
+ "as": ["completed_count"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalCompleted",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
+ }
+ }
+ ],
+ "groups": [
+ {
+ "groupId": "header",
+ "elements": [
+ "# 🎯 Enhanced Habit Tracker",
+ "Track your daily habits with category-based insights and comprehensive visualizations."
+ ]
+ },
+ {
+ "groupId": "controls",
+ "elements": [
+ "## 🎛️ Month Filter",
+ "",
+ {
+ "type": "dropdown",
+ "variableId": "selectedMonth",
+ "label": "Select Month:",
+ "dynamicOptions": {
+ "dataSourceName": "monthOptions"
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "heatmap",
+ "elements": [
+ "## 🗓️ Monthly Completion Calendar",
+ {
+ "type": "chart",
+ "chartKey": "monthlyHeatmap"
+ }
+ ]
+ },
+ {
+ "groupId": "habits",
+ "elements": [
+ "## 📋 My Habits",
+ {
+ "type": "tabulator",
+ "dataSourceName": "habitsData",
+ "variableId": "habitsDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
+ {"field": "category", "title": "Category", "width": 120, "editor": "input"},
+ {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "rowHeader": {
+ "width": 40,
+ "hozAlign": "center",
+ "formatter": "rownum"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "progress",
+ "elements": [
+ "## 📈 Progress (Filtered by Month)",
+ {
+ "type": "tabulator",
+ "dataSourceName": "progressData",
+ "variableId": "progressDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "date", "title": "Date", "width": 100, "editor": "date"},
+ {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
+ {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "initialSort": [
+ {"column": "date", "dir": "desc"}
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "stats",
+ "elements": [
+ "## 📊 Monthly Statistics",
+ "",
+ "**Active Habits:** {{totalHabits}}",
+ "",
+ "**Completion Rate:** {{overallCompletionRate}}",
+ "",
+ "**Days Tracked:** {{totalActiveDays}}",
+ "",
+ "**Total Completed:** {{totalCompleted}} habits"
+ ]
+ },
+ {
+ "groupId": "alltime",
+ "elements": [
+ "## 🌟 All-Time Habit Performance by Category",
+ {
+ "type": "chart",
+ "chartKey": "allTimeHeatmap"
+ }
+ ]
+ }
+ ],
+ "resources": {
+ "charts": {
+ "monthlyHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "monthlyHeatmapData"},
+ "title": "Daily Completion Rate - Selected Month",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 18
+ },
+ "axis": {
+ "domain": false
+ }
+ },
+ "mark": {
+ "type": "rect",
+ "stroke": "#ffffff",
+ "strokeWidth": 2,
+ "opacity": 0.8
+ },
+ "encoding": {
+ "x": {
+ "field": "day_of_month",
+ "type": "ordinal",
+ "title": "Day of Month",
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
+ },
+ "axis": {
+ "labelAngle": 0
+ }
+ },
+ "y": {
+ "datum": 1,
+ "type": "ordinal",
+ "title": ""
+ },
+ "color": {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "greens",
+ "domain": [0, 1]
+ },
+ "legend": {
+ "title": "Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
+ {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
+ {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ ]
+ },
+ "width": "container",
+ "height": 60,
+ "background": "transparent"
+ },
+ "allTimeHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "allTimeHeatmapData"},
+ "title": "All-Time Daily Completion by Category",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13
+ },
+ "axis": {
+ "domain": false
+ }
+ },
+ "mark": {
+ "type": "rect",
+ "stroke": "#ffffff",
+ "strokeWidth": 1,
+ "opacity": 0.8
+ },
+ "encoding": {
+ "x": {
+ "field": "date",
+ "timeUnit": "date",
+ "type": "temporal",
+ "title": "Day of Month",
+ "axis": {
+ "labelAngle": 0,
+ "format": "%e"
+ }
+ },
+ "y": {
+ "field": "category",
+ "type": "nominal",
+ "title": "Category",
+ "sort": ["Health", "Learning", "Wellness", "Social"]
+ },
+ "color": {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "viridis",
+ "domain": [0, 1]
+ },
+ "legend": {
+ "title": "Category Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "category", "type": "nominal", "title": "Category"},
+ {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
+ {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
+ {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ ]
+ },
+ "width": "container",
+ "height": 150,
+ "background": "transparent"
+ }
+ }
+ }
+}
\ No newline at end of file
From dbfe301d8a0907b408cd7f0aabe3084d5178b9ae Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:04:45 +0000
Subject: [PATCH 14/45] Fix dropdown field definition and simplify data flow
for enhanced habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-enhanced.idoc.json | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
index e21626b5..300ae517 100644
--- a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
@@ -29,9 +29,9 @@
"type": "inline",
"format": "json",
"content": [
- "2024-01",
- "2024-02",
- "2024-03"
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"}
]
},
{
@@ -199,7 +199,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["enrichedProgressData"],
+ "dataSourceNames": ["progressDataTable"],
"dataFrameTransformations": [
{
"type": "filter",
@@ -252,7 +252,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["enrichedProgressData"],
+ "dataSourceNames": ["progressDataTable"],
"dataFrameTransformations": [
{
"type": "formula",
@@ -261,7 +261,7 @@
},
{
"type": "aggregate",
- "groupby": ["date", "category"],
+ "groupby": ["date", "habit_name"],
"ops": ["sum", "count"],
"fields": ["completed_numeric", "completed_numeric"],
"as": ["completed_count", "total_habits"]
@@ -396,7 +396,8 @@
"variableId": "selectedMonth",
"label": "Select Month:",
"dynamicOptions": {
- "dataSourceName": "monthOptions"
+ "dataSourceName": "monthOptions",
+ "fieldName": "value"
}
}
]
@@ -478,7 +479,7 @@
{
"groupId": "alltime",
"elements": [
- "## 🌟 All-Time Habit Performance by Category",
+ "## 🌟 All-Time Habit Performance",
{
"type": "chart",
"chartKey": "allTimeHeatmap"
@@ -550,7 +551,7 @@
"allTimeHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "allTimeHeatmapData"},
- "title": "All-Time Daily Completion by Category",
+ "title": "All-Time Daily Completion by Habit",
"config": {
"view": {
"strokeWidth": 0,
@@ -578,10 +579,9 @@
}
},
"y": {
- "field": "category",
+ "field": "habit_name",
"type": "nominal",
- "title": "Category",
- "sort": ["Health", "Learning", "Wellness", "Social"]
+ "title": "Habit"
},
"color": {
"field": "completion_rate",
@@ -591,13 +591,13 @@
"domain": [0, 1]
},
"legend": {
- "title": "Category Completion Rate",
+ "title": "Habit Completion Rate",
"format": ".0%"
}
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "category", "type": "nominal", "title": "Category"},
+ {"field": "habit_name", "type": "nominal", "title": "Habit"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
From f57d7eb6b443b077de497fd03ea604f11cdac1c7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:07:01 +0000
Subject: [PATCH 15/45] Restore category-based analytics to all-time heatmap
with proper data joining
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-enhanced.idoc.json | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
index 300ae517..45eae154 100644
--- a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
@@ -199,7 +199,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable"],
+ "dataSourceNames": ["enrichedProgressData"],
"dataFrameTransformations": [
{
"type": "filter",
@@ -252,7 +252,7 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable"],
+ "dataSourceNames": ["enrichedProgressData"],
"dataFrameTransformations": [
{
"type": "formula",
@@ -261,7 +261,7 @@
},
{
"type": "aggregate",
- "groupby": ["date", "habit_name"],
+ "groupby": ["date", "category"],
"ops": ["sum", "count"],
"fields": ["completed_numeric", "completed_numeric"],
"as": ["completed_count", "total_habits"]
@@ -479,7 +479,7 @@
{
"groupId": "alltime",
"elements": [
- "## 🌟 All-Time Habit Performance",
+ "## 🌟 All-Time Habit Performance by Category",
{
"type": "chart",
"chartKey": "allTimeHeatmap"
@@ -551,7 +551,7 @@
"allTimeHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "allTimeHeatmapData"},
- "title": "All-Time Daily Completion by Habit",
+ "title": "All-Time Daily Completion by Category",
"config": {
"view": {
"strokeWidth": 0,
@@ -579,9 +579,10 @@
}
},
"y": {
- "field": "habit_name",
+ "field": "category",
"type": "nominal",
- "title": "Habit"
+ "title": "Category",
+ "sort": ["Health", "Learning", "Wellness", "Social"]
},
"color": {
"field": "completion_rate",
@@ -591,13 +592,13 @@
"domain": [0, 1]
},
"legend": {
- "title": "Habit Completion Rate",
+ "title": "Category Completion Rate",
"format": ".0%"
}
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "habit_name", "type": "nominal", "title": "Habit"},
+ {"field": "category", "type": "nominal", "title": "Category"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
From 356c2b700276cf3a3ef5d6a76efa4066e971a6ea Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:15:24 +0000
Subject: [PATCH 16/45] Fix heatmap axes: monthly view shows categories, annual
view shows months, add mobile layout
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-enhanced.idoc.json | 54 ++++++++++++-------
1 file changed, 34 insertions(+), 20 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
index 45eae154..6cd42a6c 100644
--- a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
@@ -5,6 +5,7 @@
"css": [
"body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
"body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'alltime alltime'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1400px; margin: 0 auto; }",
+ "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'alltime'; grid-template-columns: 1fr; } }",
".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
"#controls { grid-area: controls; }",
@@ -223,7 +224,7 @@
},
{
"type": "aggregate",
- "groupby": ["date"],
+ "groupby": ["date", "category"],
"ops": ["sum", "count"],
"fields": ["completed_numeric", "completed_numeric"],
"as": ["completed_count", "total_habits"]
@@ -261,7 +262,7 @@
},
{
"type": "aggregate",
- "groupby": ["date", "category"],
+ "groupby": ["date"],
"ops": ["sum", "count"],
"fields": ["completed_numeric", "completed_numeric"],
"as": ["completed_count", "total_habits"]
@@ -275,6 +276,16 @@
"type": "formula",
"expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
"as": "date_parsed"
+ },
+ {
+ "type": "formula",
+ "expr": "date(datum.date)",
+ "as": "day_of_month"
+ },
+ {
+ "type": "formula",
+ "expr": "timeFormat(datum.date, '%B')",
+ "as": "month_name"
}
]
}
@@ -441,7 +452,7 @@
{
"groupId": "progress",
"elements": [
- "## 📈 Progress (Filtered by Month)",
+ "## 📈 Progress",
{
"type": "tabulator",
"dataSourceName": "progressData",
@@ -479,7 +490,7 @@
{
"groupId": "alltime",
"elements": [
- "## 🌟 All-Time Habit Performance by Category",
+ "## 🌟 Annual Habit Performance",
{
"type": "chart",
"chartKey": "allTimeHeatmap"
@@ -492,7 +503,7 @@
"monthlyHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "monthlyHeatmapData"},
- "title": "Daily Completion Rate - Selected Month",
+ "title": "Daily Completion Rate by Category - Selected Month",
"config": {
"view": {
"strokeWidth": 0,
@@ -521,9 +532,10 @@
}
},
"y": {
- "datum": 1,
- "type": "ordinal",
- "title": ""
+ "field": "category",
+ "type": "nominal",
+ "title": "Category",
+ "sort": ["Health", "Learning", "Wellness", "Social"]
},
"color": {
"field": "completion_rate",
@@ -539,19 +551,20 @@
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "category", "type": "nominal", "title": "Category"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
- "height": 60,
+ "height": 120,
"background": "transparent"
},
"allTimeHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "allTimeHeatmapData"},
- "title": "All-Time Daily Completion by Category",
+ "title": "Annual Completion Calendar - All Categories",
"config": {
"view": {
"strokeWidth": 0,
@@ -569,20 +582,21 @@
},
"encoding": {
"x": {
- "field": "date",
- "timeUnit": "date",
- "type": "temporal",
+ "field": "day_of_month",
+ "type": "ordinal",
"title": "Day of Month",
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
+ },
"axis": {
- "labelAngle": 0,
- "format": "%e"
+ "labelAngle": 0
}
},
"y": {
- "field": "category",
+ "field": "month_name",
"type": "nominal",
- "title": "Category",
- "sort": ["Health", "Learning", "Wellness", "Social"]
+ "title": "Month",
+ "sort": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
},
"color": {
"field": "completion_rate",
@@ -592,13 +606,13 @@
"domain": [0, 1]
},
"legend": {
- "title": "Category Completion Rate",
+ "title": "Completion Rate",
"format": ".0%"
}
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "category", "type": "nominal", "title": "Category"},
+ {"field": "month_name", "type": "nominal", "title": "Month"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
From abb3835279d8e9178b8542dbb3c5b08ccfb9822f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:30:34 +0000
Subject: [PATCH 17/45] Fix monthlyHeatmapData by using raw data sources
instead of tabulator variables
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-enhanced.idoc.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
index 6cd42a6c..f2280a71 100644
--- a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
@@ -182,11 +182,11 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable", "habitsDataTable"],
+ "dataSourceNames": ["progressData", "habitsData"],
"dataFrameTransformations": [
{
"type": "lookup",
- "from": "habitsDataTable",
+ "from": "habitsData",
"key": "habit_id",
"fields": ["category", "target_frequency"],
"as": ["category", "target_frequency"]
From 21b7a89edd129b9969a07f4eaf34419e8ce1ebff Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:39:15 +0000
Subject: [PATCH 18/45] Create complete habit tracker with monthly filtering,
annual calendar view, and mobile layout
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 584 ++++++++++++++++++
1 file changed, 584 insertions(+)
create mode 100644 packages/web-deploy/json/habit-tracker-complete.idoc.json
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
new file mode 100644
index 00000000..6801ca8f
--- /dev/null
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -0,0 +1,584 @@
+{
+ "$schema": "../../../docs/schema/idoc_v1.json",
+ "title": "Complete Habit Tracker",
+ "style": {
+ "css": [
+ "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
+ "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'annual annual'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
+ "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'annual'; grid-template-columns: 1fr; } }",
+ ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
+ "#controls { grid-area: controls; }",
+ "#heatmap { grid-area: heatmap; }",
+ "#habits { grid-area: habits; }",
+ "#progress { grid-area: progress; }",
+ "#stats { grid-area: stats; }",
+ "#annual { grid-area: annual; }",
+ "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
+ "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
+ "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
+ ".tabulator { border-radius: 8px; overflow: hidden; }",
+ ".tabulator .tabulator-header { background: #f7fafc; }",
+ ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
+ ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
+ ".tabulator .tabulator-row:hover { background: #f8fafc; }"
+ ]
+ },
+ "dataLoaders": [
+ {
+ "dataSourceName": "monthOptions",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"}
+ ]
+ },
+ {
+ "dataSourceName": "habitsData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {
+ "habit_id": 1,
+ "habit_name": "Morning Exercise",
+ "category": "Health",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 2,
+ "habit_name": "Read for 30min",
+ "category": "Learning",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 3,
+ "habit_name": "Meditate",
+ "category": "Wellness",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 4,
+ "habit_name": "Write Journal",
+ "category": "Wellness",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_id": 5,
+ "habit_name": "Learn New Language",
+ "category": "Learning",
+ "target_frequency": "3x per week"
+ },
+ {
+ "habit_id": 6,
+ "habit_name": "Call Family",
+ "category": "Social",
+ "target_frequency": "Weekly"
+ }
+ ]
+ },
+ {
+ "dataSourceName": "progressData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
+ {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
+ ]
+ }
+ ],
+ "variables": [
+ {
+ "variableId": "selectedMonth",
+ "type": "string",
+ "initialValue": "2024-01"
+ },
+ {
+ "variableId": "filteredProgressData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressDataTable"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "slice(datum.date, 0, 7) === selectedMonth"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "dailyCompletionData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["sum", "count"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["completed_count", "total_habits"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ },
+ {
+ "type": "formula",
+ "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
+ "as": "date_parsed"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "annualCompletionData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressDataTable"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["sum", "count"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["completed_count", "total_habits"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ },
+ {
+ "type": "formula",
+ "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
+ "as": "date_parsed"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalHabits",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('habitsDataTable'))"
+ }
+ },
+ {
+ "variableId": "completionRateData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "ops": ["count", "sum"],
+ "fields": ["completed_numeric", "completed_numeric"],
+ "as": ["total_entries", "completed_count"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_entries * 100",
+ "as": "completion_rate"
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "overallCompletionRate",
+ "type": "string",
+ "initialValue": "0%",
+ "calculation": {
+ "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
+ }
+ },
+ {
+ "variableId": "activeDaysData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "aggregate",
+ "groupby": ["date"],
+ "ops": ["count"],
+ "fields": ["habit_id"],
+ "as": ["habits_tracked"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalActiveDays",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "length(data('activeDaysData'))"
+ }
+ },
+ {
+ "variableId": "totalCompletedEntries",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["filteredProgressData"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "datum.completed === true"
+ },
+ {
+ "type": "aggregate",
+ "ops": ["count"],
+ "fields": ["completed"],
+ "as": ["completed_count"]
+ }
+ ]
+ }
+ },
+ {
+ "variableId": "totalCompleted",
+ "type": "number",
+ "initialValue": 0,
+ "calculation": {
+ "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
+ }
+ }
+ ],
+ "groups": [
+ {
+ "groupId": "header",
+ "elements": [
+ "# 🎯 Complete Habit Tracker",
+ "Track your daily habits with monthly filtering and annual insights for building consistent routines."
+ ]
+ },
+ {
+ "groupId": "controls",
+ "elements": [
+ "## 🎛️ Filters",
+ "",
+ {
+ "type": "dropdown",
+ "variableId": "selectedMonth",
+ "label": "Select Month:",
+ "dynamicOptions": {
+ "dataSourceName": "monthOptions",
+ "fieldName": "value"
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "heatmap",
+ "elements": [
+ "## 🗓️ Monthly Habit Completion",
+ {
+ "type": "chart",
+ "chartKey": "monthlyHeatmap"
+ }
+ ]
+ },
+ {
+ "groupId": "habits",
+ "elements": [
+ "## 📋 My Habits",
+ {
+ "type": "tabulator",
+ "dataSourceName": "habitsData",
+ "variableId": "habitsDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
+ {"field": "category", "title": "Category", "width": 120, "editor": "input"},
+ {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "rowHeader": {
+ "width": 40,
+ "hozAlign": "center",
+ "formatter": "rownum"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "progress",
+ "elements": [
+ "## 📈 Progress",
+ {
+ "type": "tabulator",
+ "dataSourceName": "progressData",
+ "variableId": "progressDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "date", "title": "Date", "width": 100, "editor": "date"},
+ {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
+ {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
+ ],
+ "layout": "fitColumns",
+ "height": "300px",
+ "initialSort": [
+ {"column": "date", "dir": "desc"}
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "stats",
+ "elements": [
+ "## 📊 Statistics",
+ "",
+ "**Active Habits:** {{totalHabits}}",
+ "",
+ "**Completion Rate:** {{overallCompletionRate}}",
+ "",
+ "**Days Tracked:** {{totalActiveDays}}",
+ "",
+ "**Total Completed:** {{totalCompleted}} habits"
+ ]
+ },
+ {
+ "groupId": "annual",
+ "elements": [
+ "## 📅 Annual Calendar View",
+ {
+ "type": "chart",
+ "chartKey": "annualHeatmap"
+ }
+ ]
+ }
+ ],
+ "resources": {
+ "charts": {
+ "monthlyHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "dailyCompletionData"},
+ "title": "Daily Habit Completion Rate for Selected Month",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13
+ },
+ "axis": {
+ "domain": false
+ }
+ },
+ "mark": {
+ "type": "rect",
+ "stroke": "#ffffff",
+ "strokeWidth": 2,
+ "opacity": 0.8
+ },
+ "encoding": {
+ "x": {
+ "field": "date",
+ "timeUnit": "date",
+ "type": "temporal",
+ "title": "Day of Month",
+ "axis": {
+ "labelAngle": 0,
+ "format": "%e"
+ }
+ },
+ "color": {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "greens",
+ "domain": [0, 1]
+ },
+ "legend": {
+ "title": "Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
+ {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
+ {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ ]
+ },
+ "width": "container",
+ "height": 100,
+ "background": "transparent"
+ },
+ "annualHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {"name": "annualCompletionData"},
+ "title": "Annual Habit Completion Overview",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13
+ },
+ "axis": {
+ "domain": false
+ }
+ },
+ "mark": {
+ "type": "rect",
+ "stroke": "#ffffff",
+ "strokeWidth": 2,
+ "opacity": 0.8
+ },
+ "encoding": {
+ "x": {
+ "field": "date",
+ "timeUnit": "date",
+ "type": "temporal",
+ "title": "Day of Month",
+ "axis": {
+ "labelAngle": 0,
+ "format": "%e"
+ }
+ },
+ "y": {
+ "field": "date",
+ "timeUnit": "month",
+ "type": "temporal",
+ "title": "Month"
+ },
+ "color": {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "blues",
+ "domain": [0, 1]
+ },
+ "legend": {
+ "title": "Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
+ {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
+ {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ ]
+ },
+ "width": "container",
+ "height": 150,
+ "background": "transparent"
+ }
+ }
+ }
+}
\ No newline at end of file
From 42c83d993cfb44d4603726d1794ab30649e2b997 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 00:49:28 +0000
Subject: [PATCH 19/45] Fix desktop styling and add debug table for joined data
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 48 +++++++++++++++++--
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 6801ca8f..8a0e33c0 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -4,9 +4,9 @@
"style": {
"css": [
"body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'annual annual'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
- "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'annual'; grid-template-columns: 1fr; } }",
- ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'annual annual' 'debug debug'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
+ "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'annual' 'debug'; grid-template-columns: 1fr; } }",
+ "[id] { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
"#controls { grid-area: controls; }",
"#heatmap { grid-area: heatmap; }",
@@ -14,6 +14,7 @@
"#progress { grid-area: progress; }",
"#stats { grid-area: stats; }",
"#annual { grid-area: annual; }",
+ "#debug { grid-area: debug; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
"h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
@@ -354,6 +355,24 @@
"calculation": {
"vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
}
+ },
+ {
+ "variableId": "enrichedProgressData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["progressDataTable", "habitsDataTable"],
+ "dataFrameTransformations": [
+ {
+ "type": "lookup",
+ "from": "habitsDataTable",
+ "key": "habit_id",
+ "fields": ["category", "target_frequency"],
+ "as": ["category", "target_frequency"]
+ }
+ ]
+ }
}
],
"groups": [
@@ -463,6 +482,29 @@
"chartKey": "annualHeatmap"
}
]
+ },
+ {
+ "groupId": "debug",
+ "elements": [
+ "## 🔍 Debug: Progress with Categories",
+ {
+ "type": "tabulator",
+ "dataSourceName": "enrichedProgressData",
+ "tabulatorOptions": {
+ "columns": [
+ {"field": "date", "title": "Date", "width": 100},
+ {"field": "habit_name", "title": "Habit", "width": 150},
+ {"field": "category", "title": "Category", "width": 100},
+ {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross"}
+ ],
+ "layout": "fitColumns",
+ "height": "200px",
+ "initialSort": [
+ {"column": "date", "dir": "desc"}
+ ]
+ }
+ }
+ ]
}
],
"resources": {
From 0fa7923f2f1b243e4a9cf9e34beee756f6ce43e8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 01:53:47 +0000
Subject: [PATCH 20/45] Fix data lookup with correct syntax and remove habit_id
dependency
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 193 +++++++++---------
1 file changed, 98 insertions(+), 95 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 8a0e33c0..565dd7c5 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -42,37 +42,31 @@
"format": "json",
"content": [
{
- "habit_id": 1,
"habit_name": "Morning Exercise",
"category": "Health",
"target_frequency": "Daily"
},
{
- "habit_id": 2,
"habit_name": "Read for 30min",
"category": "Learning",
"target_frequency": "Daily"
},
{
- "habit_id": 3,
"habit_name": "Meditate",
"category": "Wellness",
"target_frequency": "Daily"
},
{
- "habit_id": 4,
"habit_name": "Write Journal",
"category": "Wellness",
"target_frequency": "Daily"
},
{
- "habit_id": 5,
"habit_name": "Learn New Language",
"category": "Learning",
"target_frequency": "3x per week"
},
{
- "habit_id": 6,
"habit_name": "Call Family",
"category": "Social",
"target_frequency": "Weekly"
@@ -84,90 +78,90 @@
"type": "inline",
"format": "json",
"content": [
- {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
+ {"date": "2024-01-15", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-15", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-15", "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-16", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-16", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-16", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-16", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-17", "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-17", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-17", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-17", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-18", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-18", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-18", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-18", "habit_name": "Call Family", "completed": true},
+ {"date": "2024-01-19", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-19", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-19", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-19", "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-01-19", "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-01-20", "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-20", "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-01-20", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-21", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-22", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-22", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-22", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-23", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-23", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-24", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-24", "habit_name": "Meditate", "completed": false},
+ {"date": "2024-01-25", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-01-25", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-01-26", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-01-26", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-27", "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-01-27", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-01-28", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-01-28", "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-01", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-01", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-01", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-02", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-02", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-02", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-03", "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-02-03", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-04", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-04", "habit_name": "Call Family", "completed": true},
+ {"date": "2024-02-05", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-05", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-05", "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-02-06", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-06", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-02-07", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-07", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-08", "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-02-08", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-02-09", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-02-09", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-02-10", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-02-10", "habit_name": "Learn New Language", "completed": false},
+ {"date": "2024-03-01", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-01", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-02", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-02", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-03", "habit_name": "Morning Exercise", "completed": false},
+ {"date": "2024-03-03", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-04", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-04", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-04", "habit_name": "Call Family", "completed": true},
+ {"date": "2024-03-05", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-05", "habit_name": "Write Journal", "completed": false},
+ {"date": "2024-03-06", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-06", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-07", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-07", "habit_name": "Learn New Language", "completed": true},
+ {"date": "2024-03-08", "habit_name": "Read for 30min", "completed": false},
+ {"date": "2024-03-08", "habit_name": "Write Journal", "completed": true},
+ {"date": "2024-03-09", "habit_name": "Morning Exercise", "completed": true},
+ {"date": "2024-03-09", "habit_name": "Meditate", "completed": true},
+ {"date": "2024-03-10", "habit_name": "Read for 30min", "completed": true},
+ {"date": "2024-03-10", "habit_name": "Call Family", "completed": true}
]
}
],
@@ -313,7 +307,7 @@
"type": "aggregate",
"groupby": ["date"],
"ops": ["count"],
- "fields": ["habit_id"],
+ "fields": ["habit_name"],
"as": ["habits_tracked"]
}
]
@@ -362,14 +356,23 @@
"isArray": true,
"initialValue": [],
"calculation": {
- "dataSourceNames": ["progressDataTable", "habitsDataTable"],
+ "dataSourceNames": [
+ "progressDataTable"
+ ],
"dataFrameTransformations": [
{
"type": "lookup",
"from": "habitsDataTable",
- "key": "habit_id",
- "fields": ["category", "target_frequency"],
- "as": ["category", "target_frequency"]
+ "key": "habit_name",
+ "fields": [
+ "habit_name"
+ ],
+ "values": ["category", "target_frequency"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.category || 'unknown'",
+ "as": "category"
}
]
}
From 6b360c52aee20455c8c1efa1bcfe40386e8b6f62 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 03:37:10 +0000
Subject: [PATCH 21/45] Fix calendar heatmap date positioning by changing from
temporal to ordinal encoding
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-complete.idoc.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 565dd7c5..76570e45 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -535,7 +535,7 @@
"x": {
"field": "date",
"timeUnit": "date",
- "type": "temporal",
+ "type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
@@ -588,7 +588,7 @@
"x": {
"field": "date",
"timeUnit": "date",
- "type": "temporal",
+ "type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
@@ -598,7 +598,7 @@
"y": {
"field": "date",
"timeUnit": "month",
- "type": "temporal",
+ "type": "ordinal",
"title": "Month"
},
"color": {
From a721372afc1cdf04599699b28dbb408015792058 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 03:54:42 +0000
Subject: [PATCH 22/45] Fix calendar heatmap date positioning by removing UTC
datetime conversion
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker-complete.idoc.json | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 76570e45..64ac24a5 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -210,11 +210,6 @@
"type": "formula",
"expr": "datum.completed_count / datum.total_habits",
"as": "completion_rate"
- },
- {
- "type": "formula",
- "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
- "as": "date_parsed"
}
]
}
@@ -243,11 +238,6 @@
"type": "formula",
"expr": "datum.completed_count / datum.total_habits",
"as": "completion_rate"
- },
- {
- "type": "formula",
- "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
- "as": "date_parsed"
}
]
}
From 2bdb4609341ee01df28d85af3df1299a665dae60 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 04:05:24 +0000
Subject: [PATCH 23/45] Fix calendar date positioning using utcParse for
consistent UTC date parsing
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 22 ++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 64ac24a5..6f442e7c 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -506,6 +506,12 @@
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "dailyCompletionData"},
"title": "Daily Habit Completion Rate for Selected Month",
+ "transform": [
+ {
+ "calculate": "utcParse(datum.date, '%Y-%m-%d')",
+ "as": "date_parsed"
+ }
+ ],
"config": {
"view": {
"strokeWidth": 0,
@@ -523,7 +529,7 @@
},
"encoding": {
"x": {
- "field": "date",
+ "field": "date_parsed",
"timeUnit": "date",
"type": "ordinal",
"title": "Day of Month",
@@ -545,7 +551,7 @@
}
},
"tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "date_parsed", "type": "temporal", "title": "Date"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
@@ -559,6 +565,12 @@
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "annualCompletionData"},
"title": "Annual Habit Completion Overview",
+ "transform": [
+ {
+ "calculate": "utcParse(datum.date, '%Y-%m-%d')",
+ "as": "date_parsed"
+ }
+ ],
"config": {
"view": {
"strokeWidth": 0,
@@ -576,7 +588,7 @@
},
"encoding": {
"x": {
- "field": "date",
+ "field": "date_parsed",
"timeUnit": "date",
"type": "ordinal",
"title": "Day of Month",
@@ -586,7 +598,7 @@
}
},
"y": {
- "field": "date",
+ "field": "date_parsed",
"timeUnit": "month",
"type": "ordinal",
"title": "Month"
@@ -604,7 +616,7 @@
}
},
"tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
+ {"field": "date_parsed", "type": "temporal", "title": "Date"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
From 390a4bbe51f65fc85914b0c28c339a3c803213f9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 06:53:39 +0000
Subject: [PATCH 24/45] Fix calendar date positioning with UTC timeUnit
transforms and formatType
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 43 ++++++++++++-------
1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 6f442e7c..e168dcd2 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -508,8 +508,10 @@
"title": "Daily Habit Completion Rate for Selected Month",
"transform": [
{
- "calculate": "utcParse(datum.date, '%Y-%m-%d')",
- "as": "date_parsed"
+ "field": "date",
+ "type": "timeunit",
+ "units": ["utcdate"],
+ "as": ["date_date", "date_date_end"]
}
],
"config": {
@@ -529,13 +531,13 @@
},
"encoding": {
"x": {
- "field": "date_parsed",
- "timeUnit": "date",
+ "field": "date_date",
"type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
- "format": "%e"
+ "format": "%e",
+ "formatType": "utc"
}
},
"color": {
@@ -551,7 +553,7 @@
}
},
"tooltip": [
- {"field": "date_parsed", "type": "temporal", "title": "Date"},
+ {"field": "date", "type": "temporal", "title": "Date"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
@@ -567,8 +569,16 @@
"title": "Annual Habit Completion Overview",
"transform": [
{
- "calculate": "utcParse(datum.date, '%Y-%m-%d')",
- "as": "date_parsed"
+ "field": "date",
+ "type": "timeunit",
+ "units": ["utcdate"],
+ "as": ["date_date", "date_date_end"]
+ },
+ {
+ "field": "date",
+ "type": "timeunit",
+ "units": ["utcmonth"],
+ "as": ["month_date", "month_date_end"]
}
],
"config": {
@@ -588,20 +598,23 @@
},
"encoding": {
"x": {
- "field": "date_parsed",
- "timeUnit": "date",
+ "field": "date_date",
"type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
- "format": "%e"
+ "format": "%e",
+ "formatType": "utc"
}
},
"y": {
- "field": "date_parsed",
- "timeUnit": "month",
+ "field": "month_date",
"type": "ordinal",
- "title": "Month"
+ "title": "Month",
+ "axis": {
+ "format": "%B",
+ "formatType": "utc"
+ }
},
"color": {
"field": "completion_rate",
@@ -616,7 +629,7 @@
}
},
"tooltip": [
- {"field": "date_parsed", "type": "temporal", "title": "Date"},
+ {"field": "date", "type": "temporal", "title": "Date"},
{"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
{"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
{"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
From 98dbfc4f83f3723b9c15eaf54878c8084439c7c0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 07:10:03 +0000
Subject: [PATCH 25/45] Fix x-axis undefined issue by using timeUnit in
encoding instead of transform
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 40 +++++--------------
1 file changed, 9 insertions(+), 31 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index e168dcd2..73423e16 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -506,14 +506,6 @@
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "dailyCompletionData"},
"title": "Daily Habit Completion Rate for Selected Month",
- "transform": [
- {
- "field": "date",
- "type": "timeunit",
- "units": ["utcdate"],
- "as": ["date_date", "date_date_end"]
- }
- ],
"config": {
"view": {
"strokeWidth": 0,
@@ -531,13 +523,13 @@
},
"encoding": {
"x": {
- "field": "date_date",
+ "field": "date",
+ "timeUnit": "utcdate",
"type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
- "format": "%e",
- "formatType": "utc"
+ "format": "%e"
}
},
"color": {
@@ -567,20 +559,6 @@
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "annualCompletionData"},
"title": "Annual Habit Completion Overview",
- "transform": [
- {
- "field": "date",
- "type": "timeunit",
- "units": ["utcdate"],
- "as": ["date_date", "date_date_end"]
- },
- {
- "field": "date",
- "type": "timeunit",
- "units": ["utcmonth"],
- "as": ["month_date", "month_date_end"]
- }
- ],
"config": {
"view": {
"strokeWidth": 0,
@@ -598,22 +576,22 @@
},
"encoding": {
"x": {
- "field": "date_date",
+ "field": "date",
+ "timeUnit": "utcdate",
"type": "ordinal",
"title": "Day of Month",
"axis": {
"labelAngle": 0,
- "format": "%e",
- "formatType": "utc"
+ "format": "%e"
}
},
"y": {
- "field": "month_date",
+ "field": "date",
+ "timeUnit": "utcmonth",
"type": "ordinal",
"title": "Month",
"axis": {
- "format": "%B",
- "formatType": "utc"
+ "format": "%B"
}
},
"color": {
From a84d315ae3425261c198c3dd2566a7fcb5495516 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 14:34:05 +0000
Subject: [PATCH 26/45] Fix x-axis to always show all days 1-31 in habit
tracker heatmaps
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-complete.idoc.json | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 73423e16..54edf944 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -527,6 +527,9 @@
"timeUnit": "utcdate",
"type": "ordinal",
"title": "Day of Month",
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
+ },
"axis": {
"labelAngle": 0,
"format": "%e"
@@ -580,6 +583,9 @@
"timeUnit": "utcdate",
"type": "ordinal",
"title": "Day of Month",
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
+ },
"axis": {
"labelAngle": 0,
"format": "%e"
From 92a831bdf5645312dfd12fa32eedcc5316a02269 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 14:41:15 +0000
Subject: [PATCH 27/45] Fix heatmap date positioning by removing manual scale
domain and using timeUnit date instead of utcdate
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker-complete.idoc.json | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 54edf944..ce13535a 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -524,12 +524,9 @@
"encoding": {
"x": {
"field": "date",
- "timeUnit": "utcdate",
+ "timeUnit": "date",
"type": "ordinal",
"title": "Day of Month",
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- },
"axis": {
"labelAngle": 0,
"format": "%e"
@@ -580,12 +577,9 @@
"encoding": {
"x": {
"field": "date",
- "timeUnit": "utcdate",
+ "timeUnit": "date",
"type": "ordinal",
"title": "Day of Month",
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- },
"axis": {
"labelAngle": 0,
"format": "%e"
@@ -593,7 +587,7 @@
},
"y": {
"field": "date",
- "timeUnit": "utcmonth",
+ "timeUnit": "month",
"type": "ordinal",
"title": "Month",
"axis": {
From bcfd56f2b48e2bbcff4dbc9ede0ccb270f2b82fd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 14:55:45 +0000
Subject: [PATCH 28/45] Fix heatmap to show complete calendar grid with proper
date positioning using sequence data generation and lookup joins
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 52 ++++++++++++++++++-
1 file changed, 50 insertions(+), 2 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index ce13535a..6e8d669e 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -504,7 +504,31 @@
"charts": {
"monthlyHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "dailyCompletionData"},
+ "data": {
+ "sequence": {
+ "start": 1,
+ "stop": 32
+ }
+ },
+ "transform": [
+ {
+ "calculate": "selectedMonth + '-' + format(datum.data, '02d')",
+ "as": "date_string"
+ },
+ {
+ "calculate": "datetime(year(datetime(selectedMonth + '-01')), month(datetime(selectedMonth + '-01')), datum.data)",
+ "as": "date"
+ },
+ {
+ "lookup": "date_string",
+ "from": {
+ "data": {"name": "dailyCompletionData"},
+ "key": "date",
+ "fields": ["completion_rate", "completed_count", "total_habits"]
+ },
+ "default": {"completion_rate": 0, "completed_count": 0, "total_habits": 0}
+ }
+ ],
"title": "Daily Habit Completion Rate for Selected Month",
"config": {
"view": {
@@ -557,7 +581,31 @@
},
"annualHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "annualCompletionData"},
+ "data": {
+ "sequence": {
+ "start": 1,
+ "stop": 366
+ }
+ },
+ "transform": [
+ {
+ "calculate": "datetime(2024, floor((datum.data - 1) / 31), ((datum.data - 1) % 31) + 1)",
+ "as": "date"
+ },
+ {
+ "calculate": "year(datum.date) + '-' + format(month(datum.date) + 1, '02d') + '-' + format(date(datum.date), '02d')",
+ "as": "date_string"
+ },
+ {
+ "lookup": "date_string",
+ "from": {
+ "data": {"name": "annualCompletionData"},
+ "key": "date",
+ "fields": ["completion_rate", "completed_count", "total_habits"]
+ },
+ "default": {"completion_rate": 0, "completed_count": 0, "total_habits": 0}
+ }
+ ],
"title": "Annual Habit Completion Overview",
"config": {
"view": {
From 28ab860eda4e8d36a48703e5aff6b8bfa36098f6 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 15:43:28 +0000
Subject: [PATCH 29/45] Simplify heatmap approach using explicit scale domains
to ensure complete 1-31 day coverage with correct positioning
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 58 +++----------------
1 file changed, 8 insertions(+), 50 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 6e8d669e..1ff83465 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -504,31 +504,7 @@
"charts": {
"monthlyHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {
- "sequence": {
- "start": 1,
- "stop": 32
- }
- },
- "transform": [
- {
- "calculate": "selectedMonth + '-' + format(datum.data, '02d')",
- "as": "date_string"
- },
- {
- "calculate": "datetime(year(datetime(selectedMonth + '-01')), month(datetime(selectedMonth + '-01')), datum.data)",
- "as": "date"
- },
- {
- "lookup": "date_string",
- "from": {
- "data": {"name": "dailyCompletionData"},
- "key": "date",
- "fields": ["completion_rate", "completed_count", "total_habits"]
- },
- "default": {"completion_rate": 0, "completed_count": 0, "total_habits": 0}
- }
- ],
+ "data": {"name": "dailyCompletionData"},
"title": "Daily Habit Completion Rate for Selected Month",
"config": {
"view": {
@@ -554,6 +530,9 @@
"axis": {
"labelAngle": 0,
"format": "%e"
+ },
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"color": {
@@ -581,31 +560,7 @@
},
"annualHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {
- "sequence": {
- "start": 1,
- "stop": 366
- }
- },
- "transform": [
- {
- "calculate": "datetime(2024, floor((datum.data - 1) / 31), ((datum.data - 1) % 31) + 1)",
- "as": "date"
- },
- {
- "calculate": "year(datum.date) + '-' + format(month(datum.date) + 1, '02d') + '-' + format(date(datum.date), '02d')",
- "as": "date_string"
- },
- {
- "lookup": "date_string",
- "from": {
- "data": {"name": "annualCompletionData"},
- "key": "date",
- "fields": ["completion_rate", "completed_count", "total_habits"]
- },
- "default": {"completion_rate": 0, "completed_count": 0, "total_habits": 0}
- }
- ],
+ "data": {"name": "annualCompletionData"},
"title": "Annual Habit Completion Overview",
"config": {
"view": {
@@ -631,6 +586,9 @@
"axis": {
"labelAngle": 0,
"format": "%e"
+ },
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"y": {
From d8fea63dea43540d9d47cc071e13d2d8a7444dd0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 16:31:23 +0000
Subject: [PATCH 30/45] Fix signal error by temporarily using hardcoded filter
to isolate the issue
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-complete.idoc.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 1ff83465..e3c9db5a 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -181,7 +181,7 @@
"dataFrameTransformations": [
{
"type": "filter",
- "expr": "slice(datum.date, 0, 7) === selectedMonth"
+ "expr": "slice(datum.date, 0, 7) === '2024-01'"
}
]
}
From 24ffdcbb460ea68072ec5f5d1433d7e54feb608e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 16:32:36 +0000
Subject: [PATCH 31/45] Fix selectedMonth variable reference by adding
variableDependencies declaration
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-complete.idoc.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index e3c9db5a..40daef15 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -178,10 +178,11 @@
"initialValue": [],
"calculation": {
"dataSourceNames": ["progressDataTable"],
+ "variableDependencies": ["selectedMonth"],
"dataFrameTransformations": [
{
"type": "filter",
- "expr": "slice(datum.date, 0, 7) === '2024-01'"
+ "expr": "slice(datum.date, 0, 7) === selectedMonth"
}
]
}
From a1daa2a7968af7432923eed2c0d52981b894b2b4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 18:34:17 +0000
Subject: [PATCH 32/45] Restart heatmaps using Seattle weather pattern - direct
data aggregation
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 53 ++++++-------------
1 file changed, 15 insertions(+), 38 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 40daef15..4cf98aa2 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -505,7 +505,7 @@
"charts": {
"monthlyHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "dailyCompletionData"},
+ "data": {"name": "filteredProgressData"},
"title": "Daily Habit Completion Rate for Selected Month",
"config": {
"view": {
@@ -516,28 +516,21 @@
"domain": false
}
},
- "mark": {
- "type": "rect",
- "stroke": "#ffffff",
- "strokeWidth": 2,
- "opacity": 0.8
- },
+ "mark": "rect",
"encoding": {
"x": {
"field": "date",
"timeUnit": "date",
"type": "ordinal",
- "title": "Day of Month",
+ "title": "Day",
"axis": {
"labelAngle": 0,
"format": "%e"
- },
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"color": {
- "field": "completion_rate",
+ "field": "completed",
+ "aggregate": "mean",
"type": "quantitative",
"scale": {
"scheme": "greens",
@@ -550,18 +543,15 @@
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
- {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
- {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ {"field": "completed", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
- "height": 100,
- "background": "transparent"
+ "height": 100
},
"annualHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "annualCompletionData"},
+ "data": {"name": "progressDataTable"},
"title": "Annual Habit Completion Overview",
"config": {
"view": {
@@ -572,37 +562,27 @@
"domain": false
}
},
- "mark": {
- "type": "rect",
- "stroke": "#ffffff",
- "strokeWidth": 2,
- "opacity": 0.8
- },
+ "mark": "rect",
"encoding": {
"x": {
"field": "date",
"timeUnit": "date",
"type": "ordinal",
- "title": "Day of Month",
+ "title": "Day",
"axis": {
"labelAngle": 0,
"format": "%e"
- },
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"y": {
"field": "date",
"timeUnit": "month",
"type": "ordinal",
- "title": "Month",
- "axis": {
- "format": "%B"
- }
+ "title": "Month"
},
"color": {
- "field": "completion_rate",
+ "field": "completed",
+ "aggregate": "mean",
"type": "quantitative",
"scale": {
"scheme": "blues",
@@ -615,14 +595,11 @@
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
- {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
- {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ {"field": "completed", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
- "height": 150,
- "background": "transparent"
+ "height": 150
}
}
}
From 88af37d0b6ff6bccab6244f54a839a76e0c07f4a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 19:22:22 +0000
Subject: [PATCH 33/45] Fix boolean aggregation and add complete day domain for
heatmaps
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 20 +++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 4cf98aa2..c5f1d970 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -517,6 +517,9 @@
}
},
"mark": "rect",
+ "transform": [
+ {"calculate": "datum.completed ? 1 : 0", "as": "completed_numeric"}
+ ],
"encoding": {
"x": {
"field": "date",
@@ -526,10 +529,13 @@
"axis": {
"labelAngle": 0,
"format": "%e"
+ },
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"color": {
- "field": "completed",
+ "field": "completed_numeric",
"aggregate": "mean",
"type": "quantitative",
"scale": {
@@ -543,7 +549,7 @@
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ {"field": "completed_numeric", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
@@ -563,6 +569,9 @@
}
},
"mark": "rect",
+ "transform": [
+ {"calculate": "datum.completed ? 1 : 0", "as": "completed_numeric"}
+ ],
"encoding": {
"x": {
"field": "date",
@@ -572,6 +581,9 @@
"axis": {
"labelAngle": 0,
"format": "%e"
+ },
+ "scale": {
+ "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
}
},
"y": {
@@ -581,7 +593,7 @@
"title": "Month"
},
"color": {
- "field": "completed",
+ "field": "completed_numeric",
"aggregate": "mean",
"type": "quantitative",
"scale": {
@@ -595,7 +607,7 @@
},
"tooltip": [
{"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
+ {"field": "completed_numeric", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
]
},
"width": "container",
From 53ef2681398405dcc8cf94cf6b9954266d35797d Mon Sep 17 00:00:00 2001
From: Dan Marshall
Date: Fri, 5 Sep 2025 13:21:47 -0700
Subject: [PATCH 34/45] Add initial implementation of Simple Habit Tracker with
heatmap visualization
---
.../json/habit-tracker-simple.idoc.json | 369 ++++++++++++++++++
1 file changed, 369 insertions(+)
create mode 100644 packages/web-deploy/json/habit-tracker-simple.idoc.json
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
new file mode 100644
index 00000000..921d9d31
--- /dev/null
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -0,0 +1,369 @@
+{
+ "$schema": "../../../docs/schema/idoc_v1.json",
+ "title": "Simple Habit Tracker",
+ "style": {
+ "css": [
+ "body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }",
+ "#header, #table, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white; text-align: center; }",
+ "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
+ "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
+ ".tabulator { max-width: 100%; overflow: auto; }",
+ ".tabulator .tabulator-table { min-width: fit-content; }",
+ "#heatmap .vega-embed .vega-actions { display: none; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr; grid-template-areas: 'header' 'table' 'heatmap'; }",
+ "#header { grid-area: header; }",
+ "#table { grid-area: table; min-width: 0; }",
+ "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }"
+ ]
+ },
+ "dataLoaders": [
+ {
+ "dataSourceName": "habitData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {
+ "date": "2024-01-01",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-01-01",
+ "habit": "Read",
+ "completed": false
+ },
+ {
+ "date": "2024-01-15",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-01-15",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-01-31",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-01-31",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-02-01",
+ "habit": "Exercise",
+ "completed": false
+ },
+ {
+ "date": "2024-02-01",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-02-14",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-02-14",
+ "habit": "Read",
+ "completed": false
+ },
+ {
+ "date": "2024-02-29",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-02-29",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-03-01",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-03-01",
+ "habit": "Read",
+ "completed": false
+ },
+ {
+ "date": "2024-03-17",
+ "habit": "Exercise",
+ "completed": false
+ },
+ {
+ "date": "2024-03-17",
+ "habit": "Read",
+ "completed": false
+ },
+ {
+ "date": "2024-03-31",
+ "habit": "Exercise",
+ "completed": false
+ },
+ {
+ "date": "2024-03-31",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-04-01",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-04-01",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-04-15",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-04-15",
+ "habit": "Read",
+ "completed": true
+ },
+ {
+ "date": "2024-04-30",
+ "habit": "Exercise",
+ "completed": true
+ },
+ {
+ "date": "2024-04-30",
+ "habit": "Read",
+ "completed": false
+ }
+ ]
+ }
+ ],
+ "variables": [
+ {
+ "variableId": "dailyCompletionData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": [
+ "habitDataTable"
+ ],
+ "dataFrameTransformations": [
+ {
+ "type": "formula",
+ "expr": "parseInt(slice(datum.date, 8, 10))",
+ "as": "day_of_month"
+ },
+ {
+ "type": "formula",
+ "expr": "parseInt(slice(datum.date, 5, 7))",
+ "as": "month_number"
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ },
+ {
+ "type": "aggregate",
+ "groupby": [
+ "date",
+ "day_of_month",
+ "month_number"
+ ],
+ "ops": [
+ "sum",
+ "count"
+ ],
+ "fields": [
+ "completed_numeric",
+ "completed_numeric"
+ ],
+ "as": [
+ "completed_count",
+ "total_habits"
+ ]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.completed_count / datum.total_habits",
+ "as": "completion_rate"
+ }
+ ]
+ }
+ }
+ ],
+ "groups": [
+ {
+ "groupId": "header",
+ "elements": [
+ "# 🎯 Simple Habit Tracker",
+ "A minimal habit tracker with editable data and heatmap visualization."
+ ]
+ },
+ {
+ "groupId": "table",
+ "elements": [
+ "## 📋 Habit Data",
+ {
+ "type": "tabulator",
+ "dataSourceName": "habitData",
+ "variableId": "habitDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "maxHeight": "210px",
+ "autoColumns": true,
+ "layout": "fitColumns"
+ }
+ }
+ ]
+ },
+ {
+ "groupId": "heatmap",
+ "elements": [
+ "## 🗓️ Completion Heatmap",
+ {
+ "type": "chart",
+ "chartKey": "completionHeatmap"
+ }
+ ]
+ }
+ ],
+ "resources": {
+ "charts": {
+ "completionHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {
+ "name": "dailyCompletionData"
+ },
+ "title": "Daily Habit Completion Rate",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13,
+ "fill": "transparent"
+ },
+ "axis": {
+ "domain": false
+ },
+ "background": "transparent"
+ },
+ "mark": "rect",
+ "encoding": {
+ "x": {
+ "field": "day_of_month",
+ "type": "ordinal",
+ "title": "Day",
+ "scale": {
+ "domain": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31
+ ]
+ }
+ },
+ "y": {
+ "field": "month_number",
+ "type": "ordinal",
+ "title": "Month",
+ "scale": {
+ "domain": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12
+ ]
+ },
+ "axis": {
+ "labelExpr": "['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][datum.value]"
+ }
+ },
+ "color": {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "greens",
+ "domain": [
+ 0,
+ 1
+ ]
+ },
+ "legend": {
+ "title": "Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {
+ "field": "date",
+ "type": "temporal",
+ "title": "Date"
+ },
+ {
+ "field": "completed_count",
+ "type": "quantitative",
+ "title": "Completed Habits"
+ },
+ {
+ "field": "total_habits",
+ "type": "quantitative",
+ "title": "Total Habits"
+ },
+ {
+ "field": "completion_rate",
+ "type": "quantitative",
+ "title": "Completion Rate",
+ "format": ".1%"
+ }
+ ]
+ },
+ "width": "container",
+ "height": 150
+ }
+ }
+ }
+}
\ No newline at end of file
From 2f7b27b0306158e4839686158ff244728ba54988 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 20:28:29 +0000
Subject: [PATCH 35/45] Add habits table with categories and data joining to
simple habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 86 ++++++++++++++++++-
1 file changed, 83 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index 921d9d31..b25416c7 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -11,13 +11,33 @@
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr; grid-template-areas: 'header' 'table' 'heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'habits table' 'debug debug' 'heatmap heatmap'; }",
"#header { grid-area: header; }",
+ "#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
- "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }"
+ "#debug { grid-area: debug; min-width: 0; }",
+ "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'debug' 'heatmap'; } }"
]
},
"dataLoaders": [
+ {
+ "dataSourceName": "habitsData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {
+ "habit_name": "Exercise",
+ "category": "Health",
+ "target_frequency": "Daily"
+ },
+ {
+ "habit_name": "Read",
+ "category": "Learning",
+ "target_frequency": "Daily"
+ }
+ ]
+ },
{
"dataSourceName": "habitData",
"type": "inline",
@@ -146,7 +166,35 @@
]
}
],
+ ],
"variables": [
+ {
+ "variableId": "enrichedHabitData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": [
+ "habitDataTable"
+ ],
+ "dataFrameTransformations": [
+ {
+ "type": "lookup",
+ "from": "habitsDataTable",
+ "key": "habit_name",
+ "fields": [
+ "habit"
+ ],
+ "values": ["category", "target_frequency"]
+ },
+ {
+ "type": "formula",
+ "expr": "datum.category || 'Unknown'",
+ "as": "category"
+ }
+ ]
+ }
+ },
{
"variableId": "dailyCompletionData",
"type": "object",
@@ -209,10 +257,27 @@
"A minimal habit tracker with editable data and heatmap visualization."
]
},
+ {
+ "groupId": "habits",
+ "elements": [
+ "## 🎯 Habits Configuration",
+ {
+ "type": "tabulator",
+ "dataSourceName": "habitsData",
+ "variableId": "habitsDataTable",
+ "editable": true,
+ "tabulatorOptions": {
+ "maxHeight": "180px",
+ "autoColumns": true,
+ "layout": "fitColumns"
+ }
+ }
+ ]
+ },
{
"groupId": "table",
"elements": [
- "## 📋 Habit Data",
+ "## 📋 Daily Progress",
{
"type": "tabulator",
"dataSourceName": "habitData",
@@ -226,6 +291,21 @@
}
]
},
+ {
+ "groupId": "debug",
+ "elements": [
+ "## 🔍 Debug: Enriched Data",
+ {
+ "type": "tabulator",
+ "dataSourceName": "enrichedHabitData",
+ "tabulatorOptions": {
+ "maxHeight": "200px",
+ "autoColumns": true,
+ "layout": "fitColumns"
+ }
+ }
+ ]
+ },
{
"groupId": "heatmap",
"elements": [
From d52f70c4dc55659843d96269cc8856b6ebd79245 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 22:28:16 +0000
Subject: [PATCH 36/45] Add month picker and filtered enriched data to simple
habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 57 +++++++++++++++++--
1 file changed, 52 insertions(+), 5 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index b25416c7..deb90db6 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -11,16 +11,28 @@
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'habits table' 'debug debug' 'heatmap heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'debug debug' 'heatmap heatmap'; }",
"#header { grid-area: header; }",
+ "#controls { grid-area: controls; min-width: 0; }",
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
"#debug { grid-area: debug; min-width: 0; }",
"#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
- "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'debug' 'heatmap'; } }"
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'debug' 'heatmap'; } }"
]
},
"dataLoaders": [
+ {
+ "dataSourceName": "monthOptions",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"value": "2024-01", "label": "January 2024"},
+ {"value": "2024-02", "label": "February 2024"},
+ {"value": "2024-03", "label": "March 2024"},
+ {"value": "2024-04", "label": "April 2024"}
+ ]
+ },
{
"dataSourceName": "habitsData",
"type": "inline",
@@ -166,8 +178,12 @@
]
}
],
- ],
"variables": [
+ {
+ "variableId": "selectedMonth",
+ "type": "string",
+ "initialValue": "2024-01"
+ },
{
"variableId": "enrichedHabitData",
"type": "object",
@@ -195,6 +211,22 @@
]
}
},
+ {
+ "variableId": "filteredEnrichedData",
+ "type": "object",
+ "isArray": true,
+ "initialValue": [],
+ "calculation": {
+ "dataSourceNames": ["enrichedHabitData"],
+ "variableDependencies": ["selectedMonth"],
+ "dataFrameTransformations": [
+ {
+ "type": "filter",
+ "expr": "slice(datum.date, 0, 7) === selectedMonth"
+ }
+ ]
+ }
+ },
{
"variableId": "dailyCompletionData",
"type": "object",
@@ -257,6 +289,21 @@
"A minimal habit tracker with editable data and heatmap visualization."
]
},
+ {
+ "groupId": "controls",
+ "elements": [
+ "## 🎛️ Month Filter",
+ {
+ "type": "dropdown",
+ "variableId": "selectedMonth",
+ "label": "Select Month:",
+ "dynamicOptions": {
+ "dataSourceName": "monthOptions",
+ "fieldName": "value"
+ }
+ }
+ ]
+ },
{
"groupId": "habits",
"elements": [
@@ -294,10 +341,10 @@
{
"groupId": "debug",
"elements": [
- "## 🔍 Debug: Enriched Data",
+ "## 🔍 Debug: Filtered Enriched Data (Selected Month)",
{
"type": "tabulator",
- "dataSourceName": "enrichedHabitData",
+ "dataSourceName": "filteredEnrichedData",
"tabulatorOptions": {
"maxHeight": "200px",
"autoColumns": true,
From 4a35cde8d677ff92f0d1ced76f761f9fefb59dac Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 5 Sep 2025 23:37:26 +0000
Subject: [PATCH 37/45] Add monthly category heatmap to simple habit tracker
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 97 ++++++++++++++++++-
1 file changed, 94 insertions(+), 3 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index deb90db6..9c40c84a 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -11,14 +11,15 @@
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'debug debug' 'heatmap heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'debug debug' 'monthly monthly' 'heatmap heatmap'; }",
"#header { grid-area: header; }",
"#controls { grid-area: controls; min-width: 0; }",
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
"#debug { grid-area: debug; min-width: 0; }",
+ "#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
"#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
- "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'debug' 'heatmap'; } }"
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'debug' 'monthly' 'heatmap'; } }"
]
},
"dataLoaders": [
@@ -353,10 +354,20 @@
}
]
},
+ {
+ "groupId": "monthly",
+ "elements": [
+ "## 📊 Monthly Heatmap by Category",
+ {
+ "type": "chart",
+ "chartKey": "monthlyHeatmap"
+ }
+ ]
+ },
{
"groupId": "heatmap",
"elements": [
- "## 🗓️ Completion Heatmap",
+ "## 🗓️ Annual Calendar View",
{
"type": "chart",
"chartKey": "completionHeatmap"
@@ -366,6 +377,86 @@
],
"resources": {
"charts": {
+ "monthlyHeatmap": {
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
+ "data": {
+ "name": "filteredEnrichedData"
+ },
+ "title": "Daily Habit Completion by Category (Selected Month)",
+ "config": {
+ "view": {
+ "strokeWidth": 0,
+ "step": 13,
+ "fill": "transparent"
+ },
+ "axis": {
+ "domain": false
+ },
+ "background": "transparent"
+ },
+ "transform": [
+ {
+ "calculate": "parseInt(slice(datum.date, 8, 10))",
+ "as": "day_of_month"
+ },
+ {
+ "calculate": "datum.completed ? 1 : 0",
+ "as": "completed_numeric"
+ }
+ ],
+ "mark": "rect",
+ "encoding": {
+ "x": {
+ "field": "day_of_month",
+ "type": "ordinal",
+ "title": "Day of Month",
+ "scale": {
+ "domain": [
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+ ]
+ }
+ },
+ "y": {
+ "field": "category",
+ "type": "nominal",
+ "title": "Category"
+ },
+ "color": {
+ "aggregate": "mean",
+ "field": "completed_numeric",
+ "type": "quantitative",
+ "scale": {
+ "scheme": "blues",
+ "domain": [0, 1]
+ },
+ "legend": {
+ "title": "Completion Rate",
+ "format": ".0%"
+ }
+ },
+ "tooltip": [
+ {
+ "field": "category",
+ "type": "nominal",
+ "title": "Category"
+ },
+ {
+ "field": "day_of_month",
+ "type": "ordinal",
+ "title": "Day"
+ },
+ {
+ "aggregate": "mean",
+ "field": "completed_numeric",
+ "type": "quantitative",
+ "title": "Completion Rate",
+ "format": ".1%"
+ }
+ ]
+ },
+ "width": "container",
+ "height": 120
+ },
"completionHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
From fd24d576901a19e415fc8f0cb1953fd8ea186017 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 6 Sep 2025 00:53:39 +0000
Subject: [PATCH 38/45] Remove debug table and fix rounded border styling for
all groups
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 24 ++++---------------
1 file changed, 5 insertions(+), 19 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index 9c40c84a..49c2f9c1 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -4,22 +4,22 @@
"style": {
"css": [
"body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }",
- "#header, #table, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header, #controls, #habits, #table, #monthly, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white; text-align: center; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'debug debug' 'monthly monthly' 'heatmap heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'monthly monthly' 'heatmap heatmap'; }",
"#header { grid-area: header; }",
"#controls { grid-area: controls; min-width: 0; }",
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
- "#debug { grid-area: debug; min-width: 0; }",
+
"#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
"#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
- "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'debug' 'monthly' 'heatmap'; } }"
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'monthly' 'heatmap'; } }"
]
},
"dataLoaders": [
@@ -339,21 +339,7 @@
}
]
},
- {
- "groupId": "debug",
- "elements": [
- "## 🔍 Debug: Filtered Enriched Data (Selected Month)",
- {
- "type": "tabulator",
- "dataSourceName": "filteredEnrichedData",
- "tabulatorOptions": {
- "maxHeight": "200px",
- "autoColumns": true,
- "layout": "fitColumns"
- }
- }
- ]
- },
+
{
"groupId": "monthly",
"elements": [
From a262dec2e28cae5cad04c2f4ce8ed57c93ebe971 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 6 Sep 2025 02:35:33 +0000
Subject: [PATCH 39/45] Enhance habit tracker with more categories and
comprehensive data showing streaks
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 434 +++++++++++++-----
1 file changed, 324 insertions(+), 110 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index 49c2f9c1..c078b6d1 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -45,138 +45,349 @@
"target_frequency": "Daily"
},
{
- "habit_name": "Read",
- "category": "Learning",
+ "habit_name": "Water Intake",
+ "category": "Health",
"target_frequency": "Daily"
- }
- ]
- },
- {
- "dataSourceName": "habitData",
- "type": "inline",
- "format": "json",
- "content": [
- {
- "date": "2024-01-01",
- "habit": "Exercise",
- "completed": true
},
{
- "date": "2024-01-01",
- "habit": "Read",
- "completed": false
- },
- {
- "date": "2024-01-15",
- "habit": "Exercise",
- "completed": true
- },
- {
- "date": "2024-01-15",
- "habit": "Read",
- "completed": true
- },
- {
- "date": "2024-01-31",
- "habit": "Exercise",
- "completed": true
- },
- {
- "date": "2024-01-31",
- "habit": "Read",
- "completed": true
- },
- {
- "date": "2024-02-01",
- "habit": "Exercise",
- "completed": false
- },
- {
- "date": "2024-02-01",
- "habit": "Read",
- "completed": true
- },
- {
- "date": "2024-02-14",
- "habit": "Exercise",
- "completed": true
- },
- {
- "date": "2024-02-14",
- "habit": "Read",
- "completed": false
- },
- {
- "date": "2024-02-29",
- "habit": "Exercise",
- "completed": true
- },
- {
- "date": "2024-02-29",
- "habit": "Read",
- "completed": true
- },
- {
- "date": "2024-03-01",
- "habit": "Exercise",
- "completed": true
- },
- {
- "date": "2024-03-01",
- "habit": "Read",
- "completed": false
- },
- {
- "date": "2024-03-17",
- "habit": "Exercise",
- "completed": false
+ "habit_name": "Sleep 8 Hours",
+ "category": "Health",
+ "target_frequency": "Daily"
},
{
- "date": "2024-03-17",
- "habit": "Read",
- "completed": false
+ "habit_name": "Read",
+ "category": "Learning",
+ "target_frequency": "Daily"
},
{
- "date": "2024-03-31",
- "habit": "Exercise",
- "completed": false
+ "habit_name": "Language Learning",
+ "category": "Learning",
+ "target_frequency": "Daily"
},
{
- "date": "2024-03-31",
- "habit": "Read",
- "completed": true
+ "habit_name": "Online Course",
+ "category": "Learning",
+ "target_frequency": "3x/week"
},
{
- "date": "2024-04-01",
- "habit": "Exercise",
- "completed": true
+ "habit_name": "Call Family",
+ "category": "Social",
+ "target_frequency": "2x/week"
},
{
- "date": "2024-04-01",
- "habit": "Read",
- "completed": true
+ "habit_name": "Social Activity",
+ "category": "Social",
+ "target_frequency": "Weekly"
},
{
- "date": "2024-04-15",
- "habit": "Exercise",
- "completed": true
+ "habit_name": "Meditation",
+ "category": "Wellness",
+ "target_frequency": "Daily"
},
{
- "date": "2024-04-15",
- "habit": "Read",
- "completed": true
+ "habit_name": "Gratitude Journal",
+ "category": "Wellness",
+ "target_frequency": "Daily"
},
{
- "date": "2024-04-30",
- "habit": "Exercise",
- "completed": true
+ "habit_name": "Deep Work Session",
+ "category": "Work",
+ "target_frequency": "Daily"
},
{
- "date": "2024-04-30",
- "habit": "Read",
- "completed": false
+ "habit_name": "Planning",
+ "category": "Work",
+ "target_frequency": "Daily"
}
]
+ },
+ {
+ "dataSourceName": "habitData",
+ "type": "inline",
+ "format": "json",
+ "content": [
+ {"date": "2024-01-01", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-01", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-01", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-01-01", "habit": "Read", "completed": true},
+ {"date": "2024-01-01", "habit": "Meditation", "completed": true},
+ {"date": "2024-01-01", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-01-02", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-02", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-02", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-02", "habit": "Read", "completed": true},
+ {"date": "2024-01-02", "habit": "Meditation", "completed": true},
+ {"date": "2024-01-02", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-01-03", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-03", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-03", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-03", "habit": "Read", "completed": true},
+ {"date": "2024-01-03", "habit": "Meditation", "completed": false},
+ {"date": "2024-01-03", "habit": "Online Course", "completed": true},
+ {"date": "2024-01-03", "habit": "Call Family", "completed": true},
+
+ {"date": "2024-01-04", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-04", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-04", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-04", "habit": "Read", "completed": false},
+ {"date": "2024-01-04", "habit": "Meditation", "completed": true},
+ {"date": "2024-01-04", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-01-05", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-05", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-05", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-01-05", "habit": "Read", "completed": true},
+ {"date": "2024-01-05", "habit": "Language Learning", "completed": true},
+ {"date": "2024-01-05", "habit": "Online Course", "completed": true},
+ {"date": "2024-01-05", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-01-06", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-06", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-06", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-06", "habit": "Read", "completed": true},
+ {"date": "2024-01-06", "habit": "Meditation", "completed": true},
+ {"date": "2024-01-06", "habit": "Social Activity", "completed": true},
+
+ {"date": "2024-01-07", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-07", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-07", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-07", "habit": "Read", "completed": false},
+ {"date": "2024-01-07", "habit": "Meditation", "completed": true},
+ {"date": "2024-01-07", "habit": "Planning", "completed": true},
+
+ {"date": "2024-01-08", "habit": "Exercise", "completed": false},
+ {"date": "2024-01-08", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-08", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-08", "habit": "Read", "completed": true},
+ {"date": "2024-01-08", "habit": "Language Learning", "completed": true},
+
+ {"date": "2024-01-10", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-10", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-10", "habit": "Read", "completed": true},
+ {"date": "2024-01-10", "habit": "Call Family", "completed": true},
+ {"date": "2024-01-10", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-01-12", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-12", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-12", "habit": "Read", "completed": true},
+ {"date": "2024-01-12", "habit": "Online Course", "completed": true},
+ {"date": "2024-01-12", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-01-15", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-15", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-15", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-01-15", "habit": "Read", "completed": true},
+ {"date": "2024-01-15", "habit": "Language Learning", "completed": true},
+ {"date": "2024-01-15", "habit": "Meditation", "completed": true},
+
+ {"date": "2024-01-20", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-20", "habit": "Read", "completed": false},
+ {"date": "2024-01-20", "habit": "Deep Work Session", "completed": true},
+ {"date": "2024-01-20", "habit": "Planning", "completed": true},
+
+ {"date": "2024-01-25", "habit": "Exercise", "completed": true},
+ {"date": "2024-01-25", "habit": "Water Intake", "completed": true},
+ {"date": "2024-01-25", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-01-25", "habit": "Read", "completed": true},
+ {"date": "2024-01-25", "habit": "Social Activity", "completed": true},
+
+ {"date": "2024-02-01", "habit": "Exercise", "completed": false},
+ {"date": "2024-02-01", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-01", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-01", "habit": "Read", "completed": true},
+ {"date": "2024-02-01", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-01", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-02-02", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-02", "habit": "Read", "completed": true},
+ {"date": "2024-02-02", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-02", "habit": "Language Learning", "completed": true},
+
+ {"date": "2024-02-03", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-03", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-03", "habit": "Read", "completed": true},
+ {"date": "2024-02-03", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-03", "habit": "Call Family", "completed": true},
+
+ {"date": "2024-02-04", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-04", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-04", "habit": "Read", "completed": false},
+ {"date": "2024-02-04", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-04", "habit": "Online Course", "completed": true},
+
+ {"date": "2024-02-05", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-05", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-05", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-05", "habit": "Read", "completed": true},
+ {"date": "2024-02-05", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-05", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-02-06", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-06", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-06", "habit": "Read", "completed": true},
+ {"date": "2024-02-06", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-06", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-02-07", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-07", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-07", "habit": "Read", "completed": true},
+ {"date": "2024-02-07", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-07", "habit": "Language Learning", "completed": true},
+
+ {"date": "2024-02-08", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-08", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-02-08", "habit": "Read", "completed": true},
+ {"date": "2024-02-08", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-08", "habit": "Online Course", "completed": true},
+
+ {"date": "2024-02-09", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-09", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-09", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-09", "habit": "Read", "completed": false},
+ {"date": "2024-02-09", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-09", "habit": "Planning", "completed": true},
+
+ {"date": "2024-02-10", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-10", "habit": "Read", "completed": true},
+ {"date": "2024-02-10", "habit": "Meditation", "completed": true},
+ {"date": "2024-02-10", "habit": "Social Activity", "completed": true},
+
+ {"date": "2024-02-14", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-14", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-14", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-14", "habit": "Read", "completed": false},
+ {"date": "2024-02-14", "habit": "Call Family", "completed": true},
+ {"date": "2024-02-14", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-02-20", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-20", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-20", "habit": "Read", "completed": true},
+ {"date": "2024-02-20", "habit": "Language Learning", "completed": true},
+ {"date": "2024-02-20", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-02-25", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-25", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-25", "habit": "Read", "completed": true},
+ {"date": "2024-02-25", "habit": "Online Course", "completed": true},
+ {"date": "2024-02-25", "habit": "Planning", "completed": true},
+
+ {"date": "2024-02-29", "habit": "Exercise", "completed": true},
+ {"date": "2024-02-29", "habit": "Water Intake", "completed": true},
+ {"date": "2024-02-29", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-02-29", "habit": "Read", "completed": true},
+ {"date": "2024-02-29", "habit": "Meditation", "completed": false},
+
+ {"date": "2024-03-01", "habit": "Exercise", "completed": true},
+ {"date": "2024-03-01", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-01", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-01", "habit": "Read", "completed": true},
+ {"date": "2024-03-01", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-03-02", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-02", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-02", "habit": "Read", "completed": true},
+ {"date": "2024-03-02", "habit": "Language Learning", "completed": true},
+ {"date": "2024-03-02", "habit": "Call Family", "completed": true},
+
+ {"date": "2024-03-03", "habit": "Exercise", "completed": true},
+ {"date": "2024-03-03", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-03", "habit": "Read", "completed": true},
+ {"date": "2024-03-03", "habit": "Meditation", "completed": true},
+ {"date": "2024-03-03", "habit": "Online Course", "completed": true},
+
+ {"date": "2024-03-04", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-04", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-03-04", "habit": "Read", "completed": true},
+ {"date": "2024-03-04", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-03-05", "habit": "Exercise", "completed": false},
+ {"date": "2024-03-05", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-05", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-05", "habit": "Read", "completed": true},
+ {"date": "2024-03-05", "habit": "Planning", "completed": true},
+
+ {"date": "2024-03-10", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-10", "habit": "Read", "completed": false},
+ {"date": "2024-03-10", "habit": "Language Learning", "completed": true},
+ {"date": "2024-03-10", "habit": "Social Activity", "completed": true},
+
+ {"date": "2024-03-15", "habit": "Exercise", "completed": true},
+ {"date": "2024-03-15", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-15", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-15", "habit": "Read", "completed": true},
+ {"date": "2024-03-15", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-03-17", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-17", "habit": "Read", "completed": false},
+ {"date": "2024-03-17", "habit": "Call Family", "completed": true},
+ {"date": "2024-03-17", "habit": "Meditation", "completed": true},
+
+ {"date": "2024-03-20", "habit": "Exercise", "completed": true},
+ {"date": "2024-03-20", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-20", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-20", "habit": "Read", "completed": true},
+ {"date": "2024-03-20", "habit": "Online Course", "completed": true},
+
+ {"date": "2024-03-25", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-25", "habit": "Read", "completed": true},
+ {"date": "2024-03-25", "habit": "Language Learning", "completed": true},
+ {"date": "2024-03-25", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-03-31", "habit": "Exercise", "completed": false},
+ {"date": "2024-03-31", "habit": "Water Intake", "completed": true},
+ {"date": "2024-03-31", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-03-31", "habit": "Read", "completed": true},
+ {"date": "2024-03-31", "habit": "Planning", "completed": true},
+
+ {"date": "2024-04-01", "habit": "Exercise", "completed": true},
+ {"date": "2024-04-01", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-01", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-04-01", "habit": "Read", "completed": true},
+ {"date": "2024-04-01", "habit": "Deep Work Session", "completed": true},
+
+ {"date": "2024-04-02", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-02", "habit": "Read", "completed": true},
+ {"date": "2024-04-02", "habit": "Language Learning", "completed": true},
+ {"date": "2024-04-02", "habit": "Meditation", "completed": true},
+
+ {"date": "2024-04-05", "habit": "Exercise", "completed": true},
+ {"date": "2024-04-05", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-05", "habit": "Sleep 8 Hours", "completed": false},
+ {"date": "2024-04-05", "habit": "Read", "completed": true},
+ {"date": "2024-04-05", "habit": "Call Family", "completed": true},
+
+ {"date": "2024-04-10", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-10", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-04-10", "habit": "Read", "completed": true},
+ {"date": "2024-04-10", "habit": "Online Course", "completed": true},
+ {"date": "2024-04-10", "habit": "Gratitude Journal", "completed": true},
+
+ {"date": "2024-04-15", "habit": "Exercise", "completed": true},
+ {"date": "2024-04-15", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-15", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-04-15", "habit": "Read", "completed": true},
+ {"date": "2024-04-15", "habit": "Language Learning", "completed": true},
+ {"date": "2024-04-15", "habit": "Social Activity", "completed": true},
+
+ {"date": "2024-04-20", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-20", "habit": "Read", "completed": false},
+ {"date": "2024-04-20", "habit": "Deep Work Session", "completed": true},
+ {"date": "2024-04-20", "habit": "Planning", "completed": true},
+
+ {"date": "2024-04-25", "habit": "Exercise", "completed": true},
+ {"date": "2024-04-25", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-25", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-04-25", "habit": "Read", "completed": true},
+ {"date": "2024-04-25", "habit": "Meditation", "completed": true},
+
+ {"date": "2024-04-30", "habit": "Exercise", "completed": true},
+ {"date": "2024-04-30", "habit": "Water Intake", "completed": true},
+ {"date": "2024-04-30", "habit": "Sleep 8 Hours", "completed": true},
+ {"date": "2024-04-30", "habit": "Read", "completed": false},
+ {"date": "2024-04-30", "habit": "Call Family", "completed": true}
+ ]
}
],
"variables": [
@@ -405,7 +616,10 @@
"y": {
"field": "category",
"type": "nominal",
- "title": "Category"
+ "title": "Category",
+ "scale": {
+ "domain": ["Health", "Learning", "Social", "Wellness", "Work"]
+ }
},
"color": {
"aggregate": "mean",
From 92d4280d311d8932ac8c6829c525f5c8a51657f8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 6 Sep 2025 05:25:38 +0000
Subject: [PATCH 40/45] Move month dropdown into monthly heatmap group
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-simple.idoc.json | 31 +++++++------------
1 file changed, 12 insertions(+), 19 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index c078b6d1..6389ec32 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -4,22 +4,21 @@
"style": {
"css": [
"body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }",
- "#header, #controls, #habits, #table, #monthly, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header, #habits, #table, #monthly, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white; text-align: center; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'controls controls' 'habits table' 'monthly monthly' 'heatmap heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'habits table' 'monthly monthly' 'heatmap heatmap'; }",
"#header { grid-area: header; }",
- "#controls { grid-area: controls; min-width: 0; }",
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
"#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
"#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
- "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'controls' 'habits' 'table' 'monthly' 'heatmap'; } }"
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'monthly' 'heatmap'; } }"
]
},
"dataLoaders": [
@@ -501,21 +500,6 @@
"A minimal habit tracker with editable data and heatmap visualization."
]
},
- {
- "groupId": "controls",
- "elements": [
- "## 🎛️ Month Filter",
- {
- "type": "dropdown",
- "variableId": "selectedMonth",
- "label": "Select Month:",
- "dynamicOptions": {
- "dataSourceName": "monthOptions",
- "fieldName": "value"
- }
- }
- ]
- },
{
"groupId": "habits",
"elements": [
@@ -555,6 +539,15 @@
"groupId": "monthly",
"elements": [
"## 📊 Monthly Heatmap by Category",
+ {
+ "type": "dropdown",
+ "variableId": "selectedMonth",
+ "label": "Select Month:",
+ "dynamicOptions": {
+ "dataSourceName": "monthOptions",
+ "fieldName": "value"
+ }
+ },
{
"type": "chart",
"chartKey": "monthlyHeatmap"
From 548824a9c7affd8361e77d0f3f9edfd965264412 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 6 Sep 2025 09:39:15 +0000
Subject: [PATCH 41/45] Update heatmap legends and chart titles to be shorter
and clearer
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-complete.idoc.json | 8 ++++----
packages/web-deploy/json/habit-tracker-simple.idoc.json | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index c5f1d970..6f8dbc0a 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -506,7 +506,7 @@
"monthlyHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "filteredProgressData"},
- "title": "Daily Habit Completion Rate for Selected Month",
+ "title": "Monthly progress by category",
"config": {
"view": {
"strokeWidth": 0,
@@ -543,7 +543,7 @@
"domain": [0, 1]
},
"legend": {
- "title": "Completion Rate",
+ "title": "% complete",
"format": ".0%"
}
},
@@ -558,7 +558,7 @@
"annualHeatmap": {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {"name": "progressDataTable"},
- "title": "Annual Habit Completion Overview",
+ "title": "Annual progress",
"config": {
"view": {
"strokeWidth": 0,
@@ -601,7 +601,7 @@
"domain": [0, 1]
},
"legend": {
- "title": "Completion Rate",
+ "title": "% complete",
"format": ".0%"
}
},
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index 6389ec32..ec7cb8d4 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -572,7 +572,7 @@
"data": {
"name": "filteredEnrichedData"
},
- "title": "Daily Habit Completion by Category (Selected Month)",
+ "title": "Monthly progress by category",
"config": {
"view": {
"strokeWidth": 0,
@@ -623,7 +623,7 @@
"domain": [0, 1]
},
"legend": {
- "title": "Completion Rate",
+ "title": "% complete",
"format": ".0%"
}
},
@@ -655,7 +655,7 @@
"data": {
"name": "dailyCompletionData"
},
- "title": "Daily Habit Completion Rate",
+ "title": "Annual progress",
"config": {
"view": {
"strokeWidth": 0,
@@ -744,7 +744,7 @@
]
},
"legend": {
- "title": "Completion Rate",
+ "title": "% complete",
"format": ".0%"
}
},
From 21f433c559684c6f3f8febfda904b96e374565e9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Sep 2025 05:31:20 +0000
Subject: [PATCH 42/45] Fix heatmap grid layout by adding explicit grid-column
spanning
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../web-deploy/json/habit-tracker-complete.idoc.json | 10 +++++-----
.../web-deploy/json/habit-tracker-simple.idoc.json | 4 ++--
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
index 6f8dbc0a..66f8c6cc 100644
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-complete.idoc.json
@@ -7,13 +7,13 @@
"body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'annual annual' 'debug debug'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
"@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'annual' 'debug'; grid-template-columns: 1fr; } }",
"[id] { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
- "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
- "#controls { grid-area: controls; }",
- "#heatmap { grid-area: heatmap; }",
+ "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; grid-column: 1 / -1; }",
+ "#controls { grid-area: controls; grid-column: 1 / -1; }",
+ "#heatmap { grid-area: heatmap; grid-column: 1 / -1; }",
"#habits { grid-area: habits; }",
"#progress { grid-area: progress; }",
- "#stats { grid-area: stats; }",
- "#annual { grid-area: annual; }",
+ "#stats { grid-area: stats; grid-column: 1 / -1; }",
+ "#annual { grid-area: annual; grid-column: 1 / -1; }",
"#debug { grid-area: debug; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index ec7cb8d4..a7dc32b4 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -16,8 +16,8 @@
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
- "#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
- "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
+ "#monthly { grid-area: monthly; min-width: 0; overflow: hidden; grid-column: 1 / -1; }",
+ "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; grid-column: 1 / -1; }",
"@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'monthly' 'heatmap'; } }"
]
},
From 67e99a749ec2155eb4dde2a4236aa2f2852450cf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Sep 2025 05:59:30 +0000
Subject: [PATCH 43/45] Revert complex grid-column changes to simplify layout
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
packages/web-deploy/json/habit-tracker-simple.idoc.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index a7dc32b4..ec7cb8d4 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -16,8 +16,8 @@
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
- "#monthly { grid-area: monthly; min-width: 0; overflow: hidden; grid-column: 1 / -1; }",
- "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; grid-column: 1 / -1; }",
+ "#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
+ "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
"@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'monthly' 'heatmap'; } }"
]
},
From 4dd3b5cce3399ce0c036592d5cd25217653d90c5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Sep 2025 16:51:12 +0000
Subject: [PATCH 44/45] Rename heatmap to annual and delete other habit tracker
files
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
.../json/habit-tracker-complete.idoc.json | 618 -----------------
.../json/habit-tracker-enhanced.idoc.json | 627 ------------------
.../json/habit-tracker-simple.idoc.json | 10 +-
.../web-deploy/json/habit-tracker.idoc.json | 498 --------------
4 files changed, 5 insertions(+), 1748 deletions(-)
delete mode 100644 packages/web-deploy/json/habit-tracker-complete.idoc.json
delete mode 100644 packages/web-deploy/json/habit-tracker-enhanced.idoc.json
delete mode 100644 packages/web-deploy/json/habit-tracker.idoc.json
diff --git a/packages/web-deploy/json/habit-tracker-complete.idoc.json b/packages/web-deploy/json/habit-tracker-complete.idoc.json
deleted file mode 100644
index 66f8c6cc..00000000
--- a/packages/web-deploy/json/habit-tracker-complete.idoc.json
+++ /dev/null
@@ -1,618 +0,0 @@
-{
- "$schema": "../../../docs/schema/idoc_v1.json",
- "title": "Complete Habit Tracker",
- "style": {
- "css": [
- "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'annual annual' 'debug debug'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
- "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'annual' 'debug'; grid-template-columns: 1fr; } }",
- "[id] { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
- "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; grid-column: 1 / -1; }",
- "#controls { grid-area: controls; grid-column: 1 / -1; }",
- "#heatmap { grid-area: heatmap; grid-column: 1 / -1; }",
- "#habits { grid-area: habits; }",
- "#progress { grid-area: progress; }",
- "#stats { grid-area: stats; grid-column: 1 / -1; }",
- "#annual { grid-area: annual; grid-column: 1 / -1; }",
- "#debug { grid-area: debug; }",
- "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
- "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
- "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
- ".tabulator { border-radius: 8px; overflow: hidden; }",
- ".tabulator .tabulator-header { background: #f7fafc; }",
- ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
- ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
- ".tabulator .tabulator-row:hover { background: #f8fafc; }"
- ]
- },
- "dataLoaders": [
- {
- "dataSourceName": "monthOptions",
- "type": "inline",
- "format": "json",
- "content": [
- {"value": "2024-01", "label": "January 2024"},
- {"value": "2024-02", "label": "February 2024"},
- {"value": "2024-03", "label": "March 2024"}
- ]
- },
- {
- "dataSourceName": "habitsData",
- "type": "inline",
- "format": "json",
- "content": [
- {
- "habit_name": "Morning Exercise",
- "category": "Health",
- "target_frequency": "Daily"
- },
- {
- "habit_name": "Read for 30min",
- "category": "Learning",
- "target_frequency": "Daily"
- },
- {
- "habit_name": "Meditate",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_name": "Write Journal",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_name": "Learn New Language",
- "category": "Learning",
- "target_frequency": "3x per week"
- },
- {
- "habit_name": "Call Family",
- "category": "Social",
- "target_frequency": "Weekly"
- }
- ]
- },
- {
- "dataSourceName": "progressData",
- "type": "inline",
- "format": "json",
- "content": [
- {"date": "2024-01-15", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-15", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-15", "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-16", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-16", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-16", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-16", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-17", "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-17", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-17", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-18", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-18", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-18", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-18", "habit_name": "Call Family", "completed": true},
- {"date": "2024-01-19", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-19", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-19", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-19", "habit_name": "Write Journal", "completed": false},
- {"date": "2024-01-19", "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-01-20", "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-20", "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-20", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-21", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-22", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-22", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-22", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-23", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-23", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-24", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-24", "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-25", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-25", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-26", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-26", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-27", "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-27", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-28", "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-28", "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-01", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-01", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-01", "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-02", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-02", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-02", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-03", "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-02-03", "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-04", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-04", "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-05", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-05", "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-05", "habit_name": "Write Journal", "completed": false},
- {"date": "2024-02-06", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-06", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-07", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-07", "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-08", "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-02-08", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-09", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-09", "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-10", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-10", "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-03-01", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-01", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-02", "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-02", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-03", "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-03-03", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-04", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-04", "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-04", "habit_name": "Call Family", "completed": true},
- {"date": "2024-03-05", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-05", "habit_name": "Write Journal", "completed": false},
- {"date": "2024-03-06", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-06", "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-07", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-07", "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-08", "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-03-08", "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-09", "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-09", "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-10", "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-10", "habit_name": "Call Family", "completed": true}
- ]
- }
- ],
- "variables": [
- {
- "variableId": "selectedMonth",
- "type": "string",
- "initialValue": "2024-01"
- },
- {
- "variableId": "filteredProgressData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["progressDataTable"],
- "variableDependencies": ["selectedMonth"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "slice(datum.date, 0, 7) === selectedMonth"
- }
- ]
- }
- },
- {
- "variableId": "dailyCompletionData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["sum", "count"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["completed_count", "total_habits"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_habits",
- "as": "completion_rate"
- }
- ]
- }
- },
- {
- "variableId": "annualCompletionData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["progressDataTable"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["sum", "count"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["completed_count", "total_habits"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_habits",
- "as": "completion_rate"
- }
- ]
- }
- },
- {
- "variableId": "totalHabits",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('habitsDataTable'))"
- }
- },
- {
- "variableId": "completionRateData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "ops": ["count", "sum"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["total_entries", "completed_count"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_entries * 100",
- "as": "completion_rate"
- }
- ]
- }
- },
- {
- "variableId": "overallCompletionRate",
- "type": "string",
- "initialValue": "0%",
- "calculation": {
- "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
- }
- },
- {
- "variableId": "activeDaysData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["count"],
- "fields": ["habit_name"],
- "as": ["habits_tracked"]
- }
- ]
- }
- },
- {
- "variableId": "totalActiveDays",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('activeDaysData'))"
- }
- },
- {
- "variableId": "totalCompletedEntries",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "datum.completed === true"
- },
- {
- "type": "aggregate",
- "ops": ["count"],
- "fields": ["completed"],
- "as": ["completed_count"]
- }
- ]
- }
- },
- {
- "variableId": "totalCompleted",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
- }
- },
- {
- "variableId": "enrichedProgressData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": [
- "progressDataTable"
- ],
- "dataFrameTransformations": [
- {
- "type": "lookup",
- "from": "habitsDataTable",
- "key": "habit_name",
- "fields": [
- "habit_name"
- ],
- "values": ["category", "target_frequency"]
- },
- {
- "type": "formula",
- "expr": "datum.category || 'unknown'",
- "as": "category"
- }
- ]
- }
- }
- ],
- "groups": [
- {
- "groupId": "header",
- "elements": [
- "# 🎯 Complete Habit Tracker",
- "Track your daily habits with monthly filtering and annual insights for building consistent routines."
- ]
- },
- {
- "groupId": "controls",
- "elements": [
- "## 🎛️ Filters",
- "",
- {
- "type": "dropdown",
- "variableId": "selectedMonth",
- "label": "Select Month:",
- "dynamicOptions": {
- "dataSourceName": "monthOptions",
- "fieldName": "value"
- }
- }
- ]
- },
- {
- "groupId": "heatmap",
- "elements": [
- "## 🗓️ Monthly Habit Completion",
- {
- "type": "chart",
- "chartKey": "monthlyHeatmap"
- }
- ]
- },
- {
- "groupId": "habits",
- "elements": [
- "## 📋 My Habits",
- {
- "type": "tabulator",
- "dataSourceName": "habitsData",
- "variableId": "habitsDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
- {"field": "category", "title": "Category", "width": 120, "editor": "input"},
- {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "rowHeader": {
- "width": 40,
- "hozAlign": "center",
- "formatter": "rownum"
- }
- }
- }
- ]
- },
- {
- "groupId": "progress",
- "elements": [
- "## 📈 Progress",
- {
- "type": "tabulator",
- "dataSourceName": "progressData",
- "variableId": "progressDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "date", "title": "Date", "width": 100, "editor": "date"},
- {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
- {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "initialSort": [
- {"column": "date", "dir": "desc"}
- ]
- }
- }
- ]
- },
- {
- "groupId": "stats",
- "elements": [
- "## 📊 Statistics",
- "",
- "**Active Habits:** {{totalHabits}}",
- "",
- "**Completion Rate:** {{overallCompletionRate}}",
- "",
- "**Days Tracked:** {{totalActiveDays}}",
- "",
- "**Total Completed:** {{totalCompleted}} habits"
- ]
- },
- {
- "groupId": "annual",
- "elements": [
- "## 📅 Annual Calendar View",
- {
- "type": "chart",
- "chartKey": "annualHeatmap"
- }
- ]
- },
- {
- "groupId": "debug",
- "elements": [
- "## 🔍 Debug: Progress with Categories",
- {
- "type": "tabulator",
- "dataSourceName": "enrichedProgressData",
- "tabulatorOptions": {
- "columns": [
- {"field": "date", "title": "Date", "width": 100},
- {"field": "habit_name", "title": "Habit", "width": 150},
- {"field": "category", "title": "Category", "width": 100},
- {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross"}
- ],
- "layout": "fitColumns",
- "height": "200px",
- "initialSort": [
- {"column": "date", "dir": "desc"}
- ]
- }
- }
- ]
- }
- ],
- "resources": {
- "charts": {
- "monthlyHeatmap": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "filteredProgressData"},
- "title": "Monthly progress by category",
- "config": {
- "view": {
- "strokeWidth": 0,
- "step": 13
- },
- "axis": {
- "domain": false
- }
- },
- "mark": "rect",
- "transform": [
- {"calculate": "datum.completed ? 1 : 0", "as": "completed_numeric"}
- ],
- "encoding": {
- "x": {
- "field": "date",
- "timeUnit": "date",
- "type": "ordinal",
- "title": "Day",
- "axis": {
- "labelAngle": 0,
- "format": "%e"
- },
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- }
- },
- "color": {
- "field": "completed_numeric",
- "aggregate": "mean",
- "type": "quantitative",
- "scale": {
- "scheme": "greens",
- "domain": [0, 1]
- },
- "legend": {
- "title": "% complete",
- "format": ".0%"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed_numeric", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
- ]
- },
- "width": "container",
- "height": 100
- },
- "annualHeatmap": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "progressDataTable"},
- "title": "Annual progress",
- "config": {
- "view": {
- "strokeWidth": 0,
- "step": 13
- },
- "axis": {
- "domain": false
- }
- },
- "mark": "rect",
- "transform": [
- {"calculate": "datum.completed ? 1 : 0", "as": "completed_numeric"}
- ],
- "encoding": {
- "x": {
- "field": "date",
- "timeUnit": "date",
- "type": "ordinal",
- "title": "Day",
- "axis": {
- "labelAngle": 0,
- "format": "%e"
- },
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- }
- },
- "y": {
- "field": "date",
- "timeUnit": "month",
- "type": "ordinal",
- "title": "Month"
- },
- "color": {
- "field": "completed_numeric",
- "aggregate": "mean",
- "type": "quantitative",
- "scale": {
- "scheme": "blues",
- "domain": [0, 1]
- },
- "legend": {
- "title": "% complete",
- "format": ".0%"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed_numeric", "aggregate": "mean", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
- ]
- },
- "width": "container",
- "height": 150
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json b/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
deleted file mode 100644
index f2280a71..00000000
--- a/packages/web-deploy/json/habit-tracker-enhanced.idoc.json
+++ /dev/null
@@ -1,627 +0,0 @@
-{
- "$schema": "../../../docs/schema/idoc_v1.json",
- "title": "Enhanced Habit Tracker",
- "style": {
- "css": [
- "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'alltime alltime'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1400px; margin: 0 auto; }",
- "@media (max-width: 768px) { body { grid-template-areas: 'header' 'controls' 'heatmap' 'habits' 'progress' 'stats' 'alltime'; grid-template-columns: 1fr; } }",
- ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
- "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
- "#controls { grid-area: controls; }",
- "#heatmap { grid-area: heatmap; }",
- "#habits { grid-area: habits; }",
- "#progress { grid-area: progress; }",
- "#stats { grid-area: stats; }",
- "#alltime { grid-area: alltime; }",
- "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
- "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
- "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
- ".tabulator { border-radius: 8px; overflow: hidden; }",
- ".tabulator .tabulator-header { background: #f7fafc; }",
- ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
- ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
- ".tabulator .tabulator-row:hover { background: #f8fafc; }"
- ]
- },
- "dataLoaders": [
- {
- "dataSourceName": "monthOptions",
- "type": "inline",
- "format": "json",
- "content": [
- {"value": "2024-01", "label": "January 2024"},
- {"value": "2024-02", "label": "February 2024"},
- {"value": "2024-03", "label": "March 2024"}
- ]
- },
- {
- "dataSourceName": "habitsData",
- "type": "inline",
- "format": "json",
- "content": [
- {
- "habit_id": 1,
- "habit_name": "Morning Exercise",
- "category": "Health",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 2,
- "habit_name": "Read for 30min",
- "category": "Learning",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 3,
- "habit_name": "Meditate",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 4,
- "habit_name": "Write Journal",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 5,
- "habit_name": "Learn New Language",
- "category": "Learning",
- "target_frequency": "3x per week"
- },
- {
- "habit_id": 6,
- "habit_name": "Call Family",
- "category": "Social",
- "target_frequency": "Weekly"
- }
- ]
- },
- {
- "dataSourceName": "progressData",
- "type": "inline",
- "format": "json",
- "content": [
- {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
- ]
- }
- ],
- "variables": [
- {
- "variableId": "selectedMonth",
- "type": "string",
- "initialValue": "2024-01"
- },
- {
- "variableId": "enrichedProgressData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["progressData", "habitsData"],
- "dataFrameTransformations": [
- {
- "type": "lookup",
- "from": "habitsData",
- "key": "habit_id",
- "fields": ["category", "target_frequency"],
- "as": ["category", "target_frequency"]
- }
- ]
- }
- },
- {
- "variableId": "filteredProgressData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["enrichedProgressData"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "slice(datum.date, 0, 7) === selectedMonth"
- }
- ]
- }
- },
- {
- "variableId": "monthlyHeatmapData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "groupby": ["date", "category"],
- "ops": ["sum", "count"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["completed_count", "total_habits"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_habits",
- "as": "completion_rate"
- },
- {
- "type": "formula",
- "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
- "as": "date_parsed"
- },
- {
- "type": "formula",
- "expr": "date(datum.date)",
- "as": "day_of_month"
- }
- ]
- }
- },
- {
- "variableId": "allTimeHeatmapData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["enrichedProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["sum", "count"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["completed_count", "total_habits"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_habits",
- "as": "completion_rate"
- },
- {
- "type": "formula",
- "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
- "as": "date_parsed"
- },
- {
- "type": "formula",
- "expr": "date(datum.date)",
- "as": "day_of_month"
- },
- {
- "type": "formula",
- "expr": "timeFormat(datum.date, '%B')",
- "as": "month_name"
- }
- ]
- }
- },
- {
- "variableId": "totalHabits",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('habitsDataTable'))"
- }
- },
- {
- "variableId": "completionRateData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "ops": ["count", "sum"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["total_entries", "completed_count"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_entries * 100",
- "as": "completion_rate"
- }
- ]
- }
- },
- {
- "variableId": "overallCompletionRate",
- "type": "string",
- "initialValue": "0%",
- "calculation": {
- "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
- }
- },
- {
- "variableId": "activeDaysData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["count"],
- "fields": ["habit_id"],
- "as": ["habits_tracked"]
- }
- ]
- }
- },
- {
- "variableId": "totalActiveDays",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('activeDaysData'))"
- }
- },
- {
- "variableId": "totalCompletedEntries",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "datum.completed === true"
- },
- {
- "type": "aggregate",
- "ops": ["count"],
- "fields": ["completed"],
- "as": ["completed_count"]
- }
- ]
- }
- },
- {
- "variableId": "totalCompleted",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
- }
- }
- ],
- "groups": [
- {
- "groupId": "header",
- "elements": [
- "# 🎯 Enhanced Habit Tracker",
- "Track your daily habits with category-based insights and comprehensive visualizations."
- ]
- },
- {
- "groupId": "controls",
- "elements": [
- "## 🎛️ Month Filter",
- "",
- {
- "type": "dropdown",
- "variableId": "selectedMonth",
- "label": "Select Month:",
- "dynamicOptions": {
- "dataSourceName": "monthOptions",
- "fieldName": "value"
- }
- }
- ]
- },
- {
- "groupId": "heatmap",
- "elements": [
- "## 🗓️ Monthly Completion Calendar",
- {
- "type": "chart",
- "chartKey": "monthlyHeatmap"
- }
- ]
- },
- {
- "groupId": "habits",
- "elements": [
- "## 📋 My Habits",
- {
- "type": "tabulator",
- "dataSourceName": "habitsData",
- "variableId": "habitsDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
- {"field": "category", "title": "Category", "width": 120, "editor": "input"},
- {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "rowHeader": {
- "width": 40,
- "hozAlign": "center",
- "formatter": "rownum"
- }
- }
- }
- ]
- },
- {
- "groupId": "progress",
- "elements": [
- "## 📈 Progress",
- {
- "type": "tabulator",
- "dataSourceName": "progressData",
- "variableId": "progressDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "date", "title": "Date", "width": 100, "editor": "date"},
- {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
- {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "initialSort": [
- {"column": "date", "dir": "desc"}
- ]
- }
- }
- ]
- },
- {
- "groupId": "stats",
- "elements": [
- "## 📊 Monthly Statistics",
- "",
- "**Active Habits:** {{totalHabits}}",
- "",
- "**Completion Rate:** {{overallCompletionRate}}",
- "",
- "**Days Tracked:** {{totalActiveDays}}",
- "",
- "**Total Completed:** {{totalCompleted}} habits"
- ]
- },
- {
- "groupId": "alltime",
- "elements": [
- "## 🌟 Annual Habit Performance",
- {
- "type": "chart",
- "chartKey": "allTimeHeatmap"
- }
- ]
- }
- ],
- "resources": {
- "charts": {
- "monthlyHeatmap": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "monthlyHeatmapData"},
- "title": "Daily Completion Rate by Category - Selected Month",
- "config": {
- "view": {
- "strokeWidth": 0,
- "step": 18
- },
- "axis": {
- "domain": false
- }
- },
- "mark": {
- "type": "rect",
- "stroke": "#ffffff",
- "strokeWidth": 2,
- "opacity": 0.8
- },
- "encoding": {
- "x": {
- "field": "day_of_month",
- "type": "ordinal",
- "title": "Day of Month",
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- },
- "axis": {
- "labelAngle": 0
- }
- },
- "y": {
- "field": "category",
- "type": "nominal",
- "title": "Category",
- "sort": ["Health", "Learning", "Wellness", "Social"]
- },
- "color": {
- "field": "completion_rate",
- "type": "quantitative",
- "scale": {
- "scheme": "greens",
- "domain": [0, 1]
- },
- "legend": {
- "title": "Completion Rate",
- "format": ".0%"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "category", "type": "nominal", "title": "Category"},
- {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
- {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
- {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
- ]
- },
- "width": "container",
- "height": 120,
- "background": "transparent"
- },
- "allTimeHeatmap": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "allTimeHeatmapData"},
- "title": "Annual Completion Calendar - All Categories",
- "config": {
- "view": {
- "strokeWidth": 0,
- "step": 13
- },
- "axis": {
- "domain": false
- }
- },
- "mark": {
- "type": "rect",
- "stroke": "#ffffff",
- "strokeWidth": 1,
- "opacity": 0.8
- },
- "encoding": {
- "x": {
- "field": "day_of_month",
- "type": "ordinal",
- "title": "Day of Month",
- "scale": {
- "domain": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
- },
- "axis": {
- "labelAngle": 0
- }
- },
- "y": {
- "field": "month_name",
- "type": "nominal",
- "title": "Month",
- "sort": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
- },
- "color": {
- "field": "completion_rate",
- "type": "quantitative",
- "scale": {
- "scheme": "viridis",
- "domain": [0, 1]
- },
- "legend": {
- "title": "Completion Rate",
- "format": ".0%"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "month_name", "type": "nominal", "title": "Month"},
- {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
- {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
- {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
- ]
- },
- "width": "container",
- "height": 150,
- "background": "transparent"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker-simple.idoc.json
index ec7cb8d4..3ca5940c 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker-simple.idoc.json
@@ -4,21 +4,21 @@
"style": {
"css": [
"body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }",
- "#header, #habits, #table, #monthly, #heatmap { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
+ "#header, #habits, #table, #monthly, #annual { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
"#header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; color: white; text-align: center; }",
"h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
"h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
".tabulator { max-width: 100%; overflow: auto; }",
".tabulator .tabulator-table { min-width: fit-content; }",
"#heatmap .vega-embed .vega-actions { display: none; }",
- "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'habits table' 'monthly monthly' 'heatmap heatmap'; }",
+ "body { display: grid; gap: 20px; grid-template-columns: 1fr 1fr; grid-template-areas: 'header header' 'habits table' 'monthly monthly' 'annual annual'; }",
"#header { grid-area: header; }",
"#habits { grid-area: habits; min-width: 0; }",
"#table { grid-area: table; min-width: 0; }",
"#monthly { grid-area: monthly; min-width: 0; overflow: hidden; }",
- "#heatmap { grid-area: heatmap; min-width: 0; overflow: hidden; }",
- "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'monthly' 'heatmap'; } }"
+ "#annual { grid-area: annual; min-width: 0; overflow: hidden; }",
+ "@media (max-width: 768px) { body { grid-template-columns: 1fr; grid-template-areas: 'header' 'habits' 'table' 'monthly' 'annual'; } }"
]
},
"dataLoaders": [
@@ -555,7 +555,7 @@
]
},
{
- "groupId": "heatmap",
+ "groupId": "annual",
"elements": [
"## 🗓️ Annual Calendar View",
{
diff --git a/packages/web-deploy/json/habit-tracker.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
deleted file mode 100644
index 675c04d2..00000000
--- a/packages/web-deploy/json/habit-tracker.idoc.json
+++ /dev/null
@@ -1,498 +0,0 @@
-{
- "$schema": "../../../docs/schema/idoc_v1.json",
- "title": "Habit Tracker",
- "style": {
- "css": [
- "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f8fafc; }",
- "body { display: grid; grid-template-areas: 'header header' 'controls controls' 'heatmap heatmap' 'habits progress' 'stats stats' 'debug debug'; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 1200px; margin: 0 auto; }",
- ".group { background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); border: 1px solid #e2e8f0; }",
- "#header { grid-area: header; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; border-radius: 12px; }",
- "#controls { grid-area: controls; }",
- "#heatmap { grid-area: heatmap; }",
- "#habits { grid-area: habits; }",
- "#progress { grid-area: progress; }",
- "#stats { grid-area: stats; }",
- "#debug { grid-area: debug; }",
- "h1 { margin: 0; padding: 20px 0; font-size: 2em; font-weight: 600; }",
- "h2 { margin: 0 0 15px 0; font-size: 1.4em; color: #2d3748; font-weight: 600; }",
- "h3 { margin: 0 0 10px 0; font-size: 1.1em; color: #4a5568; font-weight: 500; }",
- ".tabulator { border-radius: 8px; overflow: hidden; }",
- ".tabulator .tabulator-header { background: #f7fafc; }",
- ".tabulator .tabulator-header .tabulator-col { border-right: 1px solid #e2e8f0; }",
- ".tabulator .tabulator-row { border-bottom: 1px solid #f1f5f9; }",
- ".tabulator .tabulator-row:hover { background: #f8fafc; }"
- ]
- },
- "dataLoaders": [
- {
- "dataSourceName": "monthOptions",
- "type": "inline",
- "format": "json",
- "content": [
- {"value": "All", "label": "All Months"},
- {"value": "2024-01", "label": "January 2024"},
- {"value": "2024-02", "label": "February 2024"},
- {"value": "2024-03", "label": "March 2024"}
- ]
- },
- {
- "dataSourceName": "habitsData",
- "type": "inline",
- "format": "json",
- "content": [
- {
- "habit_id": 1,
- "habit_name": "Morning Exercise",
- "category": "Health",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 2,
- "habit_name": "Read for 30min",
- "category": "Learning",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 3,
- "habit_name": "Meditate",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 4,
- "habit_name": "Write Journal",
- "category": "Wellness",
- "target_frequency": "Daily"
- },
- {
- "habit_id": 5,
- "habit_name": "Learn New Language",
- "category": "Learning",
- "target_frequency": "3x per week"
- },
- {
- "habit_id": 6,
- "habit_name": "Call Family",
- "category": "Social",
- "target_frequency": "Weekly"
- }
- ]
- },
- {
- "dataSourceName": "progressData",
- "type": "inline",
- "format": "json",
- "content": [
- {"date": "2024-01-15", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-15", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-15", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-16", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-16", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-16", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-16", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-17", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-17", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-17", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-17", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-18", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-18", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-18", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-18", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-01-19", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-19", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-19", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-19", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-01-19", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-01-20", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-20", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-01-20", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-21", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-22", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-22", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-22", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-23", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-23", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-24", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-24", "habit_id": 3, "habit_name": "Meditate", "completed": false},
- {"date": "2024-01-25", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-01-25", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-01-26", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-01-26", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-27", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-01-27", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-01-28", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-01-28", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-01", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-02", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-02", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-03", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-02-03", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-04", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-02-05", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-05", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-02-06", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-06", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-02-07", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-07", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-08", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-02-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-02-09", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-02-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-02-10", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-02-10", "habit_id": 5, "habit_name": "Learn New Language", "completed": false},
- {"date": "2024-03-01", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-01", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-02", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-02", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-03", "habit_id": 1, "habit_name": "Morning Exercise", "completed": false},
- {"date": "2024-03-03", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-04", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-04", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-04", "habit_id": 6, "habit_name": "Call Family", "completed": true},
- {"date": "2024-03-05", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-05", "habit_id": 4, "habit_name": "Write Journal", "completed": false},
- {"date": "2024-03-06", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-06", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-07", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-07", "habit_id": 5, "habit_name": "Learn New Language", "completed": true},
- {"date": "2024-03-08", "habit_id": 2, "habit_name": "Read for 30min", "completed": false},
- {"date": "2024-03-08", "habit_id": 4, "habit_name": "Write Journal", "completed": true},
- {"date": "2024-03-09", "habit_id": 1, "habit_name": "Morning Exercise", "completed": true},
- {"date": "2024-03-09", "habit_id": 3, "habit_name": "Meditate", "completed": true},
- {"date": "2024-03-10", "habit_id": 2, "habit_name": "Read for 30min", "completed": true},
- {"date": "2024-03-10", "habit_id": 6, "habit_name": "Call Family", "completed": true}
- ]
- }
- ],
- "variables": [
- {
- "variableId": "selectedMonth",
- "type": "string",
- "initialValue": "All"
- },
- {
- "variableId": "filteredProgressData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["progressDataTable"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "selectedMonth === 'All' || slice(datum.date, 0, 7) === selectedMonth"
- }
- ]
- }
- },
- {
- "variableId": "dailyCompletionData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["sum", "count"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["completed_count", "total_habits"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_habits",
- "as": "completion_rate"
- },
- {
- "type": "formula",
- "expr": "datetime(year(datum.date), month(datum.date), date(datum.date))",
- "as": "date_parsed"
- }
- ]
- }
- },
- {
- "variableId": "totalHabits",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('habitsDataTable'))"
- }
- },
- {
- "variableId": "completionRateData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "formula",
- "expr": "datum.completed ? 1 : 0",
- "as": "completed_numeric"
- },
- {
- "type": "aggregate",
- "ops": ["count", "sum"],
- "fields": ["completed_numeric", "completed_numeric"],
- "as": ["total_entries", "completed_count"]
- },
- {
- "type": "formula",
- "expr": "datum.completed_count / datum.total_entries * 100",
- "as": "completion_rate"
- }
- ]
- }
- },
- {
- "variableId": "overallCompletionRate",
- "type": "string",
- "initialValue": "0%",
- "calculation": {
- "vegaExpression": "format(data('completionRateData')[0] ? data('completionRateData')[0].completion_rate : 0, '.1f') + '%'"
- }
- },
- {
- "variableId": "activeDaysData",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "aggregate",
- "groupby": ["date"],
- "ops": ["count"],
- "fields": ["habit_id"],
- "as": ["habits_tracked"]
- }
- ]
- }
- },
- {
- "variableId": "totalActiveDays",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "length(data('activeDaysData'))"
- }
- },
- {
- "variableId": "totalCompletedEntries",
- "type": "object",
- "isArray": true,
- "initialValue": [],
- "calculation": {
- "dataSourceNames": ["filteredProgressData"],
- "dataFrameTransformations": [
- {
- "type": "filter",
- "expr": "datum.completed === true"
- },
- {
- "type": "aggregate",
- "ops": ["count"],
- "fields": ["completed"],
- "as": ["completed_count"]
- }
- ]
- }
- },
- {
- "variableId": "totalCompleted",
- "type": "number",
- "initialValue": 0,
- "calculation": {
- "vegaExpression": "data('totalCompletedEntries')[0] ? data('totalCompletedEntries')[0].completed_count : 0"
- }
- }
- ],
- "groups": [
- {
- "groupId": "header",
- "elements": [
- "# 🎯 Habit Tracker",
- "Track your daily habits and build consistent routines for personal growth."
- ]
- },
- {
- "groupId": "controls",
- "elements": [
- "## 🎛️ Filters",
- "",
- {
- "type": "dropdown",
- "variableId": "selectedMonth",
- "label": "Select Month:",
- "dynamicOptions": {
- "dataSourceName": "monthOptions",
- "fieldName": "value"
- }
- }
- ]
- },
- {
- "groupId": "heatmap",
- "elements": [
- "## 🗓️ Habit Completion Heatmap",
- {
- "type": "chart",
- "chartKey": "heatmap"
- }
- ]
- },
- {
- "groupId": "habits",
- "elements": [
- "## 📋 My Habits",
- {
- "type": "tabulator",
- "dataSourceName": "habitsData",
- "variableId": "habitsDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "habit_name", "title": "Habit", "width": 200, "editor": "input"},
- {"field": "category", "title": "Category", "width": 120, "editor": "input"},
- {"field": "target_frequency", "title": "Target", "width": 150, "editor": "input"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "rowHeader": {
- "width": 40,
- "hozAlign": "center",
- "formatter": "rownum"
- }
- }
- }
- ]
- },
- {
- "groupId": "progress",
- "elements": [
- "## 📈 Progress (Filtered by Month)",
- {
- "type": "tabulator",
- "dataSourceName": "progressData",
- "variableId": "progressDataTable",
- "editable": true,
- "tabulatorOptions": {
- "columns": [
- {"field": "date", "title": "Date", "width": 100, "editor": "date"},
- {"field": "habit_name", "title": "Habit", "width": 150, "editor": "input"},
- {"field": "completed", "title": "✓", "width": 50, "hozAlign": "center", "formatter": "tickCross", "editor": "tickCross"}
- ],
- "layout": "fitColumns",
- "height": "300px",
- "initialSort": [
- {"column": "date", "dir": "desc"}
- ]
- }
- }
- ]
- },
- {
- "groupId": "stats",
- "elements": [
- "## 📊 Statistics",
- "",
- "**Active Habits:** {{totalHabits}}",
- "",
- "**Completion Rate:** {{overallCompletionRate}}",
- "",
- "**Days Tracked:** {{totalActiveDays}}",
- "",
- "**Total Completed:** {{totalCompleted}} habits"
- ]
- },
- {
- "groupId": "debug",
- "elements": [
- "## 🔍 Debug: Daily Completion Data",
- {
- "type": "tabulator",
- "dataSourceName": "dailyCompletionData"
- }
- ]
- }
- ],
- "resources": {
- "charts": {
- "heatmap": {
- "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
- "data": {"name": "dailyCompletionData"},
- "title": "Daily Habit Completion Rate",
- "config": {
- "view": {
- "strokeWidth": 0,
- "step": 13
- },
- "axis": {
- "domain": false
- }
- },
- "mark": {
- "type": "rect",
- "stroke": "#ffffff",
- "strokeWidth": 2,
- "opacity": 0.8
- },
- "encoding": {
- "x": {
- "field": "date",
- "timeUnit": "date",
- "type": "temporal",
- "title": "Day of Month",
- "axis": {
- "labelAngle": 0,
- "format": "%e"
- }
- },
- "y": {
- "field": "date",
- "timeUnit": "month",
- "type": "temporal",
- "title": "Month"
- },
- "color": {
- "field": "completion_rate",
- "type": "quantitative",
- "scale": {
- "scheme": "greens",
- "domain": [0, 1]
- },
- "legend": {
- "title": "Completion Rate",
- "format": ".0%"
- }
- },
- "tooltip": [
- {"field": "date", "type": "temporal", "title": "Date"},
- {"field": "completed_count", "type": "quantitative", "title": "Completed Habits"},
- {"field": "total_habits", "type": "quantitative", "title": "Total Habits"},
- {"field": "completion_rate", "type": "quantitative", "title": "Completion Rate", "format": ".1%"}
- ]
- },
- "width": "container",
- "height": 150,
- "background": "transparent"
- }
- }
- }
-}
\ No newline at end of file
From 87d1794e1e0d6f7503d98e6bd76eb4c898d8df3d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 8 Sep 2025 16:55:55 +0000
Subject: [PATCH 45/45] Remove 'simple' from habit tracker filename and content
Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
---
...habit-tracker-simple.idoc.json => habit-tracker.idoc.json} | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
rename packages/web-deploy/json/{habit-tracker-simple.idoc.json => habit-tracker.idoc.json} (99%)
diff --git a/packages/web-deploy/json/habit-tracker-simple.idoc.json b/packages/web-deploy/json/habit-tracker.idoc.json
similarity index 99%
rename from packages/web-deploy/json/habit-tracker-simple.idoc.json
rename to packages/web-deploy/json/habit-tracker.idoc.json
index 3ca5940c..ab42dde3 100644
--- a/packages/web-deploy/json/habit-tracker-simple.idoc.json
+++ b/packages/web-deploy/json/habit-tracker.idoc.json
@@ -1,6 +1,6 @@
{
"$schema": "../../../docs/schema/idoc_v1.json",
- "title": "Simple Habit Tracker",
+ "title": "Habit Tracker",
"style": {
"css": [
"body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }",
@@ -496,7 +496,7 @@
{
"groupId": "header",
"elements": [
- "# 🎯 Simple Habit Tracker",
+ "# 🎯 Habit Tracker",
"A minimal habit tracker with editable data and heatmap visualization."
]
},