Skip to content

Commit e82ed6f

Browse files
authored
Merge pull request #310 from setchy/feature/177-moved-in-out
feature: add optional support for moved in / out blips
2 parents 2b2fd1b + 9891656 commit e82ed6f

File tree

17 files changed

+281
-14
lines changed

17 files changed

+281
-14
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ Create a Google Sheet. Give it at least the below column headers, and put in the
2929
| Apache Kylin | assess | platforms | TRUE | Apache Kylin is an open source analytics solution ... |
3030
| JSF | hold | languages & frameworks | FALSE | We continue to see teams run into trouble using JSF ... |
3131

32+
### Want to show blip movement information?
33+
34+
If you want to show movement of blips, add the optional column `status` to your dataset.
35+
36+
This column accepts the following case-insensitive values :
37+
38+
- `New` - appearing on the radar for the first time
39+
- `Moved In` - moving towards the center of the radar
40+
- `Moved Out` - moving towards the edge of the radar
41+
- `No Change` - no change in position
42+
3243
### Sharing the sheet
3344

3445
- In Google Sheets, click on "Share".

spec/graphing/blips-spec.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,77 @@ describe('Blips', function () {
187187
blipText: () => '12 New Blips',
188188
name: 'blip1',
189189
isNew: () => true,
190+
status: () => null,
190191
}
191192

192193
const actual = blipAssistiveText(blip)
193194
expect(actual).toEqual('`ring1 ring, group of 12 New Blips')
194195
})
195196

197+
it('should return correct assistive text for new blip', function () {
198+
const blip = {
199+
isGroup: () => false,
200+
ring: () => {
201+
return {
202+
name: () => 'Trial',
203+
}
204+
},
205+
name: () => 'Some cool tech',
206+
status: () => 'New',
207+
}
208+
209+
const actual = blipAssistiveText(blip)
210+
expect(actual).toEqual('Trial ring, Some cool tech, New.')
211+
})
212+
213+
it('should return correct assistive text for existing blip', function () {
214+
const blip = {
215+
isGroup: () => false,
216+
ring: () => {
217+
return {
218+
name: () => 'Trial',
219+
}
220+
},
221+
name: () => 'Some cool tech',
222+
status: () => 'No change',
223+
}
224+
225+
const actual = blipAssistiveText(blip)
226+
expect(actual).toEqual('Trial ring, Some cool tech, No change.')
227+
})
228+
229+
it('should return correct assistive text for moved in blip', function () {
230+
const blip = {
231+
isGroup: () => false,
232+
ring: () => {
233+
return {
234+
name: () => 'Trial',
235+
}
236+
},
237+
name: () => 'Some cool tech',
238+
status: () => 'Moved in',
239+
}
240+
241+
const actual = blipAssistiveText(blip)
242+
expect(actual).toEqual('Trial ring, Some cool tech, Moved in.')
243+
})
244+
245+
it('should return correct assistive text for moved out blip', function () {
246+
const blip = {
247+
isGroup: () => false,
248+
ring: () => {
249+
return {
250+
name: () => 'Trial',
251+
}
252+
},
253+
name: () => 'Some cool tech',
254+
status: () => 'Moved out',
255+
}
256+
257+
const actual = blipAssistiveText(blip)
258+
expect(actual).toEqual('Trial ring, Some cool tech, Moved out.')
259+
})
260+
196261
it('should return group blip with appropriate values', function () {
197262
const ringBlips = mockRingBlips(20)
198263
const groupBlip = createGroupBlip(ringBlips, 'New', { name: () => 'ring1' }, 'first')

spec/models/blip-spec.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('Blip', function () {
1414
})
1515

1616
it('has a topic', function () {
17-
blip = new Blip('My Blip', new Ring('My Ring'), true, 'topic', 'description')
17+
blip = new Blip('My Blip', new Ring('My Ring'), true, null, 'topic', 'description')
1818

1919
expect(blip.topic()).toEqual('topic')
2020
})
@@ -24,7 +24,7 @@ describe('Blip', function () {
2424
})
2525

2626
it('has a description', function () {
27-
blip = new Blip('My Blip', new Ring('My Ring'), true, 'topic', 'description')
27+
blip = new Blip('My Blip', new Ring('My Ring'), true, null, 'topic', 'description')
2828

2929
expect(blip.description()).toEqual('description')
3030
})
@@ -56,17 +56,41 @@ describe('Blip', function () {
5656
})
5757

5858
it('is new', function () {
59-
blip = new Blip('My Blip', new Ring('My Ring'), true)
59+
blip = new Blip('My Blip', new Ring('My Ring'), true, null, 'My Topic', 'My Description')
6060

6161
expect(blip.isNew()).toBe(true)
6262
})
6363

6464
it('is not new', function () {
65-
blip = new Blip('My Blip', new Ring('My Ring'), false)
65+
blip = new Blip('My Blip', new Ring('My Ring'), false, null, 'My Topic', 'My Description')
6666

6767
expect(blip.isNew()).toBe(false)
6868
})
6969

70+
it('status is new', function () {
71+
blip = new Blip('My Blip', new Ring('My Ring'), null, 'new', 'My Topic', 'My Description')
72+
73+
expect(blip.isNew()).toBe(true)
74+
})
75+
76+
it('status has moved in', function () {
77+
blip = new Blip('My Blip', new Ring('My Ring'), null, 'Moved In', 'My Topic', 'My Description')
78+
79+
expect(blip.hasMovedIn()).toBe(true)
80+
})
81+
82+
it('status has moved out', function () {
83+
blip = new Blip('My Blip', new Ring('My Ring'), null, 'Moved Out', 'My Topic', 'My Description')
84+
85+
expect(blip.hasMovedOut()).toBe(true)
86+
})
87+
88+
it('status has no change', function () {
89+
blip = new Blip('My Blip', new Ring('My Ring'), null, 'No Change', 'My Topic', 'My Description')
90+
91+
expect(blip.hasNoChange()).toBe(true)
92+
})
93+
7094
it('has false as default value for isGroup', function () {
7195
expect(blip.isGroup()).toEqual(false)
7296
})

spec/util/inputSanitizer-spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ describe('Input Santizer for Protected sheet', function () {
107107
ring: '',
108108
quadrant: '',
109109
isNew: '',
110+
status: '',
110111
})
111112
})
112113
})

src/common.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ require('./images/search-logo-2x.svg')
66
require('./images/banner-image-mobile.jpg')
77
require('./images/banner-image-desktop.jpg')
88
require('./images/new.svg')
9+
require('./images/moved.svg')
910
require('./images/existing.svg')
11+
require('./images/no-change.svg')
1012
require('./images/arrow-icon.svg')
1113
require('./images/first-quadrant-btn-bg.svg')
1214
require('./images/second-quadrant-btn-bg.svg')

src/graphing/blips.js

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function findBlipCoordinates(blip, minRadius, maxRadius, startAngle, allBlipCoor
106106
function blipAssistiveText(blip) {
107107
return blip.isGroup()
108108
? `\`${blip.ring().name()} ring, group of ${blip.blipText()}`
109-
: `${blip.ring().name()} ring, ${blip.name()}, ${blip.isNew() ? 'new' : 'existing'} blip.`
109+
: `${blip.ring().name()} ring, ${blip.name()}, ${blip.status()}.`
110110
}
111111
function addOuterCircle(parentSvg, order, scale = 1) {
112112
parentSvg
@@ -120,6 +120,66 @@ function addOuterCircle(parentSvg, order, scale = 1) {
120120
.style('transform', `scale(${scale})`)
121121
}
122122

123+
function addMovedInLine(parentSvg, order, scale = 1) {
124+
let path
125+
126+
switch (order) {
127+
case 'first':
128+
path =
129+
'M16.5 34.44c0-.86.7-1.56 1.56-1.56c8.16 0 14.8-6.64 14.8-14.8c0-.86.7-1.56 1.56-1.56c.86 0 1.56.7 1.56 1.56C36 27.96 27.96 36 18.07 36C17.2 36 16.5 35.3 16.5 34.44z'
130+
break
131+
case 'second':
132+
path =
133+
'M16.5 1.56c0 .86.7 1.56 1.56 1.56c8.16 0 14.8 6.64 14.8 14.8c0 .86.7 1.56 1.56 1.56c.86 0 1.56-.7 1.56-1.56C36 8.04 27.96 0 18.07 0C17.2 0 16.5.7 16.5 1.56z'
134+
break
135+
case 'third':
136+
path =
137+
'M19.5 34.44c0-.86-.7-1.56-1.56-1.56c-8.16 0-14.8-6.64-14.8-14.8c0-.86-.7-1.56-1.56-1.56S0 17.2 0 18.07C0 27.96 8.04 36 17.93 36C18.8 36 19.5 35.3 19.5 34.44z'
138+
break
139+
case 'fourth':
140+
path =
141+
'M19.5 1.56c0 0.86-0.7 1.56-1.56 1.56c-8.16 0-14.8 6.64-14.8 14.8c0 0.86-0.7 1.56-1.56 1.56S0 18.8 0 17.93C0 8.04 8.04 0 17.93 0C18.8 0 19.5 0.7 19.5 1.56z'
142+
break
143+
}
144+
145+
parentSvg
146+
.append('path')
147+
.attr('opacity', '1')
148+
.attr('class', order)
149+
.attr('d', path)
150+
.style('transform', `scale(${scale})`)
151+
}
152+
153+
function addMovedOutLine(parentSvg, order, scale = 1) {
154+
let path
155+
156+
switch (order) {
157+
case 'first':
158+
path =
159+
'M19.5 1.56c0 0.86-0.7 1.56-1.56 1.56c-8.16 0-14.8 6.64-14.8 14.8c0 0.86-0.7 1.56-1.56 1.56S0 18.8 0 17.93C0 8.04 8.04 0 17.93 0C18.8 0 19.5 0.7 19.5 1.56z'
160+
break
161+
case 'second':
162+
path =
163+
'M19.5 34.44c0-.86-.7-1.56-1.56-1.56c-8.16 0-14.8-6.64-14.8-14.8c0-.86-.7-1.56-1.56-1.56S0 17.2 0 18.07C0 27.96 8.04 36 17.93 36C18.8 36 19.5 35.3 19.5 34.44z'
164+
break
165+
case 'third':
166+
path =
167+
'M16.5 1.56c0 .86.7 1.56 1.56 1.56c8.16 0 14.8 6.64 14.8 14.8c0 .86.7 1.56 1.56 1.56c.86 0 1.56-.7 1.56-1.56C36 8.04 27.96 0 18.07 0C17.2 0 16.5.7 16.5 1.56z'
168+
break
169+
case 'fourth':
170+
path =
171+
'M16.5 34.44c0-.86.7-1.56 1.56-1.56c8.16 0 14.8-6.64 14.8-14.8c0-.86.7-1.56 1.56-1.56c.86 0 1.56.7 1.56 1.56C36 27.96 27.96 36 18.07 36C17.2 36 16.5 35.3 16.5 34.44z'
172+
break
173+
}
174+
175+
parentSvg
176+
.append('path')
177+
.attr('opacity', '1')
178+
.attr('class', order)
179+
.attr('d', path)
180+
.style('transform', `scale(${scale})`)
181+
}
182+
123183
function drawBlipCircle(group, blip, xValue, yValue, order) {
124184
group
125185
.attr('transform', `scale(1) translate(${xValue - 16}, ${yValue - 16})`)
@@ -138,6 +198,16 @@ function newBlip(blip, xValue, yValue, order, group) {
138198
addOuterCircle(group, order, blip.scale)
139199
}
140200

201+
function movedInBlip(blip, xValue, yValue, order, group) {
202+
drawBlipCircle(group, blip, xValue, yValue, order)
203+
addMovedInLine(group, order, blip.scale)
204+
}
205+
206+
function movedOutBlip(blip, xValue, yValue, order, group) {
207+
drawBlipCircle(group, blip, xValue, yValue, order)
208+
addMovedOutLine(group, order, blip.scale)
209+
}
210+
141211
function existingBlip(blip, xValue, yValue, order, group) {
142212
drawBlipCircle(group, blip, xValue, yValue, order)
143213
}
@@ -175,6 +245,10 @@ function drawBlipInCoordinates(blip, coordinates, order, quadrantGroup) {
175245
groupBlip(blip, x, y, order, group)
176246
} else if (blip.isNew()) {
177247
newBlip(blip, x, y, order, group)
248+
} else if (blip.hasMovedIn()) {
249+
movedInBlip(blip, x, y, order, group)
250+
} else if (blip.hasMovedOut()) {
251+
movedOutBlip(blip, x, y, order, group)
178252
} else {
179253
existingBlip(blip, x, y, order, group)
180254
}

src/graphing/components/quadrants.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ function renderRadarQuadrants(size, svg, quadrant, rings, ringCalculator, tip) {
390390
return quadrantGroup
391391
}
392392

393-
function renderRadarLegends(radarElement) {
393+
function renderRadarLegends(radarElement, hasMovements) {
394394
const legendsContainer = radarElement.append('div').classed('radar-legends', true)
395395

396396
const newImage = legendsContainer
@@ -401,6 +401,14 @@ function renderRadarLegends(radarElement) {
401401
.attr('alt', 'new blip legend icon')
402402
.node().outerHTML
403403

404+
const movedImage = legendsContainer
405+
.append('img')
406+
.attr('src', '/images/moved.svg')
407+
.attr('width', '37px')
408+
.attr('height', '37px')
409+
.attr('alt', `moved in or out blip legend icon`)
410+
.node().outerHTML
411+
404412
const existingImage = legendsContainer
405413
.append('img')
406414
.attr('src', '/images/existing.svg')
@@ -409,7 +417,19 @@ function renderRadarLegends(radarElement) {
409417
.attr('alt', 'existing blip legend icon')
410418
.node().outerHTML
411419

412-
legendsContainer.html(`${newImage} New ${existingImage} Existing`)
420+
const noChangeImage = legendsContainer
421+
.append('img')
422+
.attr('src', '/images/no-change.svg')
423+
.attr('width', '37px')
424+
.attr('height', '37px')
425+
.attr('alt', 'no change blip legend icon')
426+
.node().outerHTML
427+
428+
if (hasMovements) {
429+
legendsContainer.html(`${newImage} New ${movedImage} Moved in/out ${noChangeImage} No change`)
430+
} else {
431+
legendsContainer.html(`${newImage} New ${existingImage} Existing`)
432+
}
413433
}
414434

415435
function renderMobileView(quadrant) {

src/graphing/radar.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,12 +828,26 @@ const Radar = function (size, radar) {
828828
})
829829

830830
if (featureToggles.UIRefresh2022) {
831-
renderRadarLegends(radarElement)
831+
renderRadarLegends(radarElement, hasMovementData(quadrants))
832832
hideTooltipOnScroll(tip)
833833
addRadarLinkInPdfView()
834834
}
835835
}
836836

837+
function hasMovementData(quadrants) {
838+
for (var quadrantWrapper of quadrants) {
839+
let quadrant = quadrantWrapper.quadrant
840+
841+
for (var blip of quadrant.blips()) {
842+
if (blip.status() !== '') {
843+
return true
844+
}
845+
}
846+
}
847+
848+
return false
849+
}
850+
837851
return self
838852
}
839853

src/images/moved.svg

Lines changed: 9 additions & 0 deletions
Loading

src/images/no-change.svg

Lines changed: 9 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)