Skip to content

Commit cf19f44

Browse files
committed
feat(devindex): Add Impact column with Heuristics visualization (#9178)
1 parent 4e9366d commit cf19f44

3 files changed

Lines changed: 131 additions & 0 deletions

File tree

apps/devindex/view/home/GridContainer.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import BaseGridContainer from '../../../../src/grid/Container.mjs';
22
import Contributors from '../../store/Contributors.mjs';
3+
import Heuristics from './component/Heuristics.mjs';
34
import StatusToolbar from './StatusToolbar.mjs';
45

56
const
@@ -180,6 +181,15 @@ class GridContainer extends BaseGridContainer {
180181
cellAlign : 'right',
181182
defaultSortDirection: 'DESC',
182183
renderer : ({value}) => (value || 0).toFixed(2)
184+
}, {
185+
type : 'component',
186+
dataField: 'heuristics',
187+
text : 'Impact',
188+
width : 100,
189+
component: ({record}) => ({
190+
module : Heuristics,
191+
heuristics : record.heuristics || record.hm
192+
})
183193
}, {
184194
dataField: 'activity',
185195
text : `Activity (${activityDuration}y)`,
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import Component from '../../../../../src/component/Base.mjs';
2+
3+
/**
4+
* @class DevIndex.view.home.component.Heuristics
5+
* @extends Neo.component.Base
6+
*/
7+
class Heuristics extends Component {
8+
static config = {
9+
/**
10+
* @member {String} className='DevIndex.view.home.component.Heuristics'
11+
* @protected
12+
*/
13+
className: 'DevIndex.view.home.component.Heuristics',
14+
/**
15+
* @member {String[]} cls=['devindex-heuristics']
16+
*/
17+
cls: ['devindex-heuristics'],
18+
/**
19+
* @member {Object|null} heuristics_=null
20+
*/
21+
heuristics_: null,
22+
/**
23+
* @member {Object} _vdom
24+
*/
25+
_vdom:
26+
{cn: [
27+
{tag: 'span', cls: ['devindex-badge']}, // Velocity
28+
{tag: 'span', cls: ['devindex-badge']}, // Acceleration
29+
{tag: 'span', cls: ['devindex-badge']} // Consistency
30+
]}
31+
}
32+
33+
/**
34+
* @param {Object|null} value
35+
* @param {Object|null} oldValue
36+
*/
37+
afterSetHeuristics(value, oldValue) {
38+
let me = this,
39+
{vdom} = me,
40+
nodes = vdom.cn,
41+
badges, v, a, c;
42+
43+
if (value) {
44+
({v, a, c} = value);
45+
badges = [];
46+
47+
// 1. Velocity (v)
48+
if (v > 1000) {
49+
badges.push({cls: 'fire', icon: '🔥', title: 'Velocity: Superhuman (>1k/day)'})
50+
} else if (v > 100) {
51+
badges.push({cls: 'bolt', icon: '⚡', title: 'Velocity: High (>100/day)'})
52+
}
53+
54+
// 2. Acceleration (a)
55+
if (a > 10) {
56+
badges.push({cls: 'rocket', icon: '🚀', title: 'Acceleration: Explosive Growth (>10x)'})
57+
} else if (a > 2) {
58+
badges.push({cls: 'trend-up', icon: '📈', title: 'Acceleration: Rising Star (>2x)'})
59+
}
60+
61+
// 3. Consistency (c)
62+
if (c > 10) {
63+
badges.push({cls: 'pillar', icon: '🏛️', title: 'Consistency: Community Pillar (>10y)'})
64+
} else if (c > 5) {
65+
badges.push({cls: 'shield', icon: '🛡️', title: 'Consistency: Veteran (>5y)'})
66+
}
67+
68+
// Zero State
69+
if (badges.length === 0 && c <= 1) {
70+
badges.push({cls: 'seedling', icon: '🌱', title: 'New Contributor'})
71+
}
72+
73+
// Map badges to fixed nodes
74+
nodes.forEach((node, index) => {
75+
let badge = badges[index];
76+
77+
if (badge) {
78+
node.cls = ['devindex-badge', badge.cls];
79+
node.title = badge.title;
80+
node.html = badge.icon; // Using html for emoji chars is fine, but text is safer? Emoji IS text.
81+
node.style = null // Remove visibility: hidden
82+
} else {
83+
node.style = {visibility: 'hidden'}
84+
}
85+
});
86+
} else {
87+
// Hide all if no data
88+
nodes.forEach(node => {
89+
node.style = {visibility: 'hidden'}
90+
})
91+
}
92+
93+
me.update()
94+
}
95+
}
96+
97+
export default Neo.setupClass(Heuristics);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.devindex-heuristics {
2+
align-items: center;
3+
contain : layout paint style;
4+
display : flex;
5+
gap : 4px;
6+
height : 100%;
7+
8+
.devindex-badge {
9+
align-items : center;
10+
border-radius : 4px;
11+
display : flex;
12+
font-size : 14px;
13+
justify-content: center;
14+
width : 20px;
15+
16+
&.seedling {color: #4caf50;} /* Green */
17+
&.fire {color: #f44336;} /* Red */
18+
&.bolt {color: #ff9800;} /* Orange */
19+
&.rocket {color: #9c27b0;} /* Purple */
20+
&.trend-up {color: #2196f3;} /* Blue */
21+
&.pillar {color: #ffd700;} /* Gold */
22+
&.shield {color: #607d8b;} /* Blue Grey */
23+
}
24+
}

0 commit comments

Comments
 (0)