Sankey looks good now

This commit is contained in:
Rich Lott / Artful Robot 2025-03-31 12:14:01 +01:00
parent 8591d6c060
commit 216d9a46ee
3 changed files with 41 additions and 16 deletions

View file

@ -72,3 +72,10 @@ crm-contact-category-settings .hint {
crm-contact-category-settings .name-input-wrapper:focus-within .hint {
display: block;
}
/* Category Flows page */
.contact-cats-sankey {
background:white;
border-radius: 4px;
padding: 1rem;
}

View file

@ -38,7 +38,6 @@
<svg viewBox="0 0 {{ $ctrl.sankey.width }} {{ $ctrl.sankey.height }}"
width="{{$ctrl.sankey.width}}"
height="{{$ctrl.sankey.height}}"
style="width: 100%; height: auto;"
version="1.1" xmlns="http://www.w3.org/2000/svg"
>
<defs>
@ -51,7 +50,7 @@
</linearGradient>
</defs>
<g transform="translate({{$ctrl.sankey.labelWidth}})">
<g transform="translate({{$ctrl.sankey.iconWidth}})">
<path ng-repeat="p in $ctrl.sankey.snakes"
d="{{p.d}}"
fill="{{p.fill}}"
@ -61,7 +60,7 @@
</path>
</g>
<!-- to-side labels -->
<g transform="translate({{$ctrl.sankey.labelWidth + $ctrl.sankey.snakeWidth}})">
<g transform="translate({{$ctrl.sankey.iconWidth + $ctrl.sankey.snakeWidth}})">
<rect ng-repeat="toAna in $ctrl.sankey.analysisArray"
x=0
y="{{toAna.y}}"
@ -71,11 +70,14 @@
></rect>
<foreignobject ng-repeat="toAna in $ctrl.sankey.analysisArray"
x="20" y="{{toAna.y}}" width="{{$ctrl.sankey.labelWidth}}" height="{{toAna.thisCatHeight}}">
<span class=sankey-label style="display:block;color:{{toAna.cat.color}}"><i class="crm-i {{toAna.cat.icon}}" title="{{toAna.cat.label}}"></i></span>
<span class=sankey-label style="display:block;color:{{toAna.cat.color}}">
<i class="crm-i {{toAna.cat.icon}}" title="{{toAna.cat.label}}"></i>
{{toAna.cat.label}} {{toAna.now.toLocaleString()}}
</span>
</foreignobject>
</g>
<!-- from-side labels -->
<g transform="translate({{$ctrl.sankey.labelWidth - 16}})">
<g transform="translate({{$ctrl.sankey.iconWidth}})">
<rect ng-repeat="toAna in $ctrl.sankey.analysisArray"
x=0
y="{{toAna.y}}"
@ -83,9 +85,16 @@
height="{{toAna.fromCatHeight}}"
fill="{{toAna.cat.color}}"
></rect>
</g>
<g>
<foreignobject ng-repeat="toAna in $ctrl.sankey.analysisArray"
x="-32" y="{{toAna.y}}" width="32" height="{{toAna.thisCatHeight}}">
<span class=sankey-label style="display:block;color:{{toAna.cat.color}}"><i class="crm-i {{toAna.cat.icon}}" title="{{toAna.cat.label}}"></i></span>
x=0 y="{{toAna.y}}" width="{{$ctrl.sankey.iconWidth}}"
height="{{toAna.thisCatHeight}}">
<span class=sankey-label
title="{{toAna.previous}}"
style="display:block;text-align:center;color:{{toAna.cat.color}}"
><i class="crm-i {{toAna.cat.icon}}" title="{{toAna.cat.label}}"></i>
</span>
</foreignobject>
</g>
<!--

View file

@ -2,7 +2,6 @@
angular.module("crmContactcats").component("crmContactCategoryFlows", {
templateUrl: "~/crmContactcats/crmContactCategoryFlows.html",
controller: function($scope, $timeout, crmApi4, crmStatus, $document) {
const catHeightMin = 50, catHeightGap = 8;
var ts = ($scope.ts = CRM.ts(null)),
ctrl = this;
@ -19,9 +18,8 @@
: allFlowsData;
ctrl.loading = false;
const labelWidth = ctrl.sankey.labelWidth,
width = Math.max(600, document.querySelector('.contact-cats-sankey').clientWidth),
snakeWidth = width - 2*labelWidth;
const width = Math.max(600, document.querySelector('.contact-cats-sankey').clientWidth),
snakeWidth = width - ctrl.sankey.labelWidth - ctrl.sankey.iconWidth;
ctrl.sankey.width = width;
ctrl.sankey.snakeWidth = snakeWidth;
@ -79,7 +77,7 @@
});
// Allow a cat height to grow from its min to 3x min.
let maxCatHeight = 3 * catHeightMin;
let maxCatHeight = 3 * ctrl.sankey.catHeightMin;
let maxContactsAtOneCat = Math.max(... analysisArray.map(cat => Math.max(cat.now, cat.previous)));
let scale = maxCatHeight / maxContactsAtOneCat;
console.log({maxCatHeight, maxContactsAtOneCat,scale});
@ -92,8 +90,8 @@
toAna.y = accumulatedY;
toAna.toCatHeight = Math.max(1, Math.round(scale * toAna.now));
toAna.fromCatHeight = Math.max(1,Math.round(scale * toAna.previous));
toAna.thisCatHeight = Math.ceil(Math.max(catHeightMin, scale * Math.max(toAna.now, toAna.previous)));
accumulatedY += toAna.thisCatHeight + catHeightGap;
toAna.thisCatHeight = Math.ceil(Math.max(ctrl.sankey.catHeightMin, scale * Math.max(toAna.now, toAna.previous)));
accumulatedY += toAna.thisCatHeight + ctrl.sankey.catHeightGap;
// console.log({toCat: toAna.cat.label, toCatY: toAna.y, accumulatedY, thisCatHeight});
// Intialise source offsets for this category.
offsetWithinSourcesByCat[toAna.cat.id] = 0;
@ -103,7 +101,7 @@
return a.cat.presentation_order - b.cat.presentation_order;
})
});
ctrl.sankey.height = Math.ceil(accumulatedY);
ctrl.sankey.height = analysisArray[analysisArray.length -1].y + analysisArray[analysisArray.length -1].thisCatHeight;
// Make a list of snakes we need to draw.
const snakes = [];
@ -167,7 +165,18 @@
ctrl.startDate = new Date('2025-03-25');
ctrl.endDate = null;
ctrl.stats = null;
ctrl.sankey = { height: 500, width: 900, labelWidth: 150, snakeWidth: 600, snakes: [], analysisArray: [] };
ctrl.sankey = {
catHeightMin : 50,
labelWidth: 220,
iconWidth: 32,
catHeightGap: 8,
// the following values get overwritten.
height: 500,
width: 900,
snakeWidth: 600,
snakes: [],
analysisArray: []
};
if (useTestFixtures) {
ctrl.catDefs = [