pict-section-activitygraph 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pict-section-activitygraph",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Pict section that renders a stacked-bar activity timeline: one bar per period, stacked by type or actor, across parallel domains. Themed SVG, no chart dependency.",
|
|
5
5
|
"main": "source/Pict-Section-ActivityGraph.js",
|
|
6
6
|
"scripts": {
|
|
@@ -140,9 +140,15 @@ function buildSVG(pModel)
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
let tmpChartTop = TOP + LEGEND_H;
|
|
143
|
-
|
|
143
|
+
const GROUP_H = 22; // a super-group (quarter/year) gets its own header band, so its label
|
|
144
|
+
// never shares a line with the per-row date labels.
|
|
145
|
+
// Count the super-group bands up front so the SVG height accounts for them.
|
|
146
|
+
let tmpGroupCount = 0;
|
|
147
|
+
let tmpScanGroup = null;
|
|
148
|
+
tmpPeriodOrder.forEach((pRow) => { let tmpG = _superGroup(pRow.PeriodStart, tmpPeriod); if (tmpG && tmpG !== tmpScanGroup) { tmpGroupCount += 1; tmpScanGroup = tmpG; } });
|
|
149
|
+
let tmpHeight = tmpChartTop + tmpPeriodOrder.length * ROW_H + tmpGroupCount * GROUP_H + 20;
|
|
144
150
|
let tmpSVG = [];
|
|
145
|
-
tmpSVG.push('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + WIDTH + ' ' + tmpHeight + '" width="100%" role="img" aria-label="System activity, one bar per ' + _esc(tmpPeriod) + ' stacked by ' + _esc(tmpStackBy) + '" font-family="-apple-system, Segoe UI, Roboto, sans-serif">');
|
|
151
|
+
tmpSVG.push('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + WIDTH + ' ' + tmpHeight + '" width="100%" role="img" aria-label="System activity, one bar per ' + _esc(tmpPeriod) + ' stacked by ' + _esc(tmpStackBy) + ', each column scaled 0 to ' + tmpMaxTotal + '" font-family="-apple-system, Segoe UI, Roboto, sans-serif">');
|
|
146
152
|
|
|
147
153
|
// legend
|
|
148
154
|
let tmpLegendX = PAD_L;
|
|
@@ -154,25 +160,29 @@ function buildSVG(pModel)
|
|
|
154
160
|
tmpLegendX += 20 + _esc(pKey).length * 7.2 + 14;
|
|
155
161
|
});
|
|
156
162
|
|
|
157
|
-
// column headers
|
|
163
|
+
// column headers: accent-colored title (left) + the axis scale (right). Both columns share one global
|
|
164
|
+
// max, so labeling each track's full-width value with the same number makes the shared, comparable
|
|
165
|
+
// 0-to-max scale explicit -- a track that fills the whole width equals that max.
|
|
158
166
|
tmpColumns.forEach((pCol, pIndex) =>
|
|
159
167
|
{
|
|
160
168
|
let tmpX = tmpColX[pIndex];
|
|
161
169
|
tmpSVG.push('<text x="' + tmpX + '" y="' + (tmpChartTop - 8) + '" font-size="13" font-weight="600" fill="' + (pCol.Accent || _C.text) + '">' + _esc(pCol.Title || pCol.Key) + '</text>');
|
|
162
170
|
tmpSVG.push('<rect x="' + tmpX + '" y="' + (tmpChartTop - 4) + '" width="' + Math.max(40, tmpColWidth * 0.4) + '" height="2" fill="' + (pCol.Accent || _C.border) + '"/>');
|
|
171
|
+
tmpSVG.push('<text x="' + (tmpX + tmpBarMax).toFixed(1) + '" y="' + (tmpChartTop - 8) + '" text-anchor="end" font-size="10" fill="' + _C.muted + '">0 to ' + tmpMaxTotal + '</text>');
|
|
163
172
|
});
|
|
164
173
|
|
|
165
|
-
// rows
|
|
174
|
+
// rows (running y, so a super-group header band pushes the rows below it down instead of overlapping)
|
|
166
175
|
let tmpPrevGroup = null;
|
|
167
|
-
|
|
176
|
+
let tmpY = tmpChartTop;
|
|
177
|
+
tmpPeriodOrder.forEach((pPeriodRow) =>
|
|
168
178
|
{
|
|
169
|
-
let tmpY = tmpChartTop + pRowIndex * ROW_H;
|
|
170
179
|
let tmpGroup = _superGroup(pPeriodRow.PeriodStart, tmpPeriod);
|
|
171
180
|
if (tmpGroup && tmpGroup !== tmpPrevGroup)
|
|
172
181
|
{
|
|
173
|
-
//
|
|
174
|
-
tmpSVG.push('<line x1="0" y1="' + (tmpY
|
|
175
|
-
tmpSVG.push('<text x="0" y="' + (tmpY +
|
|
182
|
+
// A band of its own: a boundary line, then the group label on its own line above the rows.
|
|
183
|
+
tmpSVG.push('<line x1="0" y1="' + (tmpY + 7) + '" x2="' + (WIDTH - PAD_R) + '" y2="' + (tmpY + 7) + '" stroke="' + _C.border + '" stroke-width="1"/>');
|
|
184
|
+
tmpSVG.push('<text x="0" y="' + (tmpY + 19) + '" font-size="11" font-weight="600" fill="' + _C.muted + '">' + _esc(tmpGroup) + '</text>');
|
|
185
|
+
tmpY += GROUP_H;
|
|
176
186
|
tmpPrevGroup = tmpGroup;
|
|
177
187
|
}
|
|
178
188
|
// period label
|
|
@@ -198,6 +208,7 @@ function buildSVG(pModel)
|
|
|
198
208
|
tmpSVG.push('<text x="' + (tmpX + 6).toFixed(1) + '" y="' + (tmpY + BAR_H) + '" font-size="11" font-weight="600" fill="' + _C.text + '">' + tmpCell.Total + '</text>');
|
|
199
209
|
}
|
|
200
210
|
});
|
|
211
|
+
tmpY += ROW_H;
|
|
201
212
|
});
|
|
202
213
|
|
|
203
214
|
tmpSVG.push('</svg>');
|