Skip to content

Commit 4969764

Browse files
authored
Add color picker for number widgets (#40)
* Added support for choosing a color in the 1x1 widget * Add background color option to the number widgets
1 parent b2f598c commit 4969764

9 files changed

+139
-74
lines changed

vss-extension-dev.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifestVersion": 1,
33
"id": "GHAzDoWidget-DEV",
4-
"version": "0.2.371",
4+
"version": "0.2.397",
55
"public": false,
66
"name": "Advanced Security dashboard Widgets [DEV]",
77
"description": "[DEV] GitHub Advanced Security for Azure DevOps dashboard widgets",

vss-extension.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifestVersion": 1,
33
"id": "GHAzDoWidget",
4-
"version": "0.0.1.11",
4+
"version": "0.0.1.14",
55
"public": true,
66
"name": "Advanced Security dashboard Widgets",
77
"description": "GitHub Advanced Security for Azure DevOps dashboard widgets",

widgets/styles.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
}
1010

1111
.GHAzDo-widget {
12-
background-color: rgb(104, 33, 122);
12+
background-color: #68217a;
1313
color: white;
1414
text-align: center;
1515
font-size: 30px;

widgets/widgets/widget_1x1/configuration_1x1.html

+26-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
VSS.register("GHAzDoWidget.Configuration_1x1", async function () {
1717
var $repoDropdown = $("#repo-dropdown");
1818
var $repoAlertType = $("#repo-alert-type");
19+
var $colorPicker = $("#color-picker");
1920
const repos = await getRepos(VSS, Service, GitWebApi);
2021
const projects = await getProjects(VSS, Service, RestClient);
2122

@@ -32,7 +33,8 @@
3233
data: JSON.stringify({
3334
repo: $repoDropdown.val(),
3435
repoId: repo?.id,
35-
repoAlertType: $repoAlertType.val()
36+
repoAlertType: $repoAlertType.val(),
37+
color: $colorPicker.val()
3638
})
3739
};
3840
var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
@@ -60,6 +62,11 @@
6062
$repoAlertType.val(settings.repoAlertType);
6163
}
6264

65+
if (settings && settings.color) {
66+
// select the color that was saved in the settings
67+
$colorPicker.val(settings.color);
68+
}
69+
6370
// register a change event handler for the dropdowns
6471
$repoDropdown.on("change", async function () {
6572
await reloadWidget(widgetConfigurationContext);
@@ -69,6 +76,10 @@
6976
await reloadWidget(widgetConfigurationContext);
7077
});
7178

79+
$colorPicker.on("change", async function () {
80+
await reloadWidget(widgetConfigurationContext);
81+
});
82+
7283
return WidgetHelpers.WidgetStatusHelper.Success();
7384
},
7485
onSave: async function() {
@@ -81,7 +92,8 @@
8192
data: JSON.stringify({
8293
repo: $repoDropdown.val(),
8394
repoId: repo?.id,
84-
repoAlertType: $repoAlertType.val()
95+
repoAlertType: $repoAlertType.val(),
96+
color: $colorPicker.val()
8597
})
8698
};
8799
consoleLog(`Saving the 1x1 settings with ${JSON.stringify(customSettings)}`)
@@ -99,6 +111,10 @@
99111
margin-top: 10px;
100112
min-width: 150px;
101113
}
114+
115+
td {
116+
padding: 5px;
117+
}
102118
</style>
103119
<div class="container">
104120
<table>
@@ -122,6 +138,14 @@
122138
</select>
123139
</td>
124140
</tr>
141+
<tr>
142+
<td>
143+
<label class="label">Background color: </label>
144+
</td>
145+
<td>
146+
<input type="color" id="color-picker" value="#68217a">
147+
</td>
148+
</tr>
125149
</table>
126150
</div>
127151
</body>

widgets/widgets/widget_1x1/widget_1x1.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
</head>
5858
<body>
59-
<div class="widget GHAzDo-widget">
59+
<div class="widget GHAzDo-widget" id="GHAzDo-widget">
6060
<h2 class="ghazdo-title" title="">GitHub Advanced Security Alerts</h2>
6161
<div id="query-info-container" class="column-container">
6262

widgets/widgets/widget_1x1/widget_1x1.js

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ async function loadWidget(widgetSettings, organization, projectName, VSS, Servic
5252
title.attr('title', repoName);
5353
consoleLog(`title set to [${repoName}]`);
5454

55+
// set the color
56+
const color = data.color ? data.color : '#68217a'; // default to purple
57+
const widget = document.getElementById('GHAzDo-widget');
58+
widget.style.backgroundColor = `${color}`;
59+
5560
// GHAS is only available on the SaaS version, so we can hardcode the domain
5661
linkBase = `https://dev.azure.com/${organization}/${projectName}/_git/${repoName}/alerts`;
5762
}

widgets/widgets/widget_2x1/configuration_2x1.html

+48-17
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,29 @@
1414
VSS.require(["VSS/Service", "TFS/Dashboards/WidgetHelpers", "VSS/Context", "TFS/VersionControl/GitRestClient"],
1515
function (Service, WidgetHelpers, context, GitWebApi) {
1616
VSS.register("GHAzDoWidget.Configuration", async function () {
17-
var $repoDropdown = $("#repo-dropdown");
17+
var $repoDropdown = $("#repo-dropdown")
18+
var $colorPicker = $("#color-picker")
1819
// get a repos in this project
1920
const repos = await getRepos(VSS, Service, GitWebApi);
2021

22+
async function reloadWidget(widgetConfigurationContext) {
23+
let repo;
24+
if (repos) {
25+
// find the repo with this name
26+
repo = repos.find(r => r.name === $repoDropdown.val());
27+
}
28+
var customSettings = {
29+
data: JSON.stringify({
30+
repo: $repoDropdown.val(),
31+
repoId: repo.id,
32+
color: $colorPicker.val()
33+
})
34+
};
35+
var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
36+
var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
37+
widgetConfigurationContext.notify(eventName, eventArgs);
38+
}
39+
2140
return {
2241
load: async function (widgetSettings, widgetConfigurationContext) {
2342
var settings = logWidgetSettings(widgetSettings, VSS, "2x1");
@@ -38,22 +57,17 @@
3857
$repoDropdown.val(settings.repo);
3958
}
4059

41-
$repoDropdown.on("change", function () {
42-
let repo;
43-
if (repos) {
44-
// find the repo with this name
45-
repo = repos.find(r => r.name === $repoDropdown.val());
46-
}
60+
if (settings && settings.color) {
61+
// select the color that was saved in the settings
62+
$colorPicker.val(settings.color);
63+
}
4764

48-
var customSettings = {
49-
data: JSON.stringify({
50-
repo: $repoDropdown.val(),
51-
repoId: repo.id
52-
})
53-
};
54-
var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
55-
var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
56-
widgetConfigurationContext.notify(eventName, eventArgs);
65+
$colorPicker.on("change", async function () {
66+
await reloadWidget(widgetConfigurationContext);
67+
});
68+
69+
$repoDropdown.on("change", async function () {
70+
await reloadWidget(widgetConfigurationContext);
5771
});
5872

5973
return WidgetHelpers.WidgetStatusHelper.Success();
@@ -68,7 +82,8 @@
6882
var customSettings = {
6983
data: JSON.stringify({
7084
repo: $repoDropdown.val(),
71-
repoId: repo.id
85+
repoId: repo.id,
86+
color: $colorPicker.val()
7287
})
7388
};
7489
console.log(`Saving the settings with ${JSON.stringify(customSettings)}`)
@@ -81,6 +96,12 @@
8196
</script>
8297
</head>
8398
<body>
99+
<style>
100+
td {
101+
padding: 5px;
102+
}
103+
</style>
104+
84105
<div class="container">
85106
<fieldset>
86107
<label class="label">Repository: </label>
@@ -89,5 +110,15 @@
89110
</select>
90111
</fieldset>
91112
</div>
113+
<table>
114+
<tr>
115+
<td>
116+
<label class="label">Background color: </label>
117+
</td>
118+
<td>
119+
<input type="color" id="color-picker" value="#68217a">
120+
</td>
121+
</tr>
122+
</table>
92123
</body>
93124
</html>

widgets/widgets/widget_2x1/widget_2x1.html

+18-18
Original file line numberDiff line numberDiff line change
@@ -10,46 +10,46 @@
1010
VSS.init({
1111
explicitNotifyLoaded: true,
1212
usePlatformStyles: true
13-
});
13+
})
1414

1515
VSS.require(
1616
["TFS/Dashboards/WidgetHelpers", "VSS/Context"],
1717
async function (WidgetHelpers, context)
1818
{
1919
WidgetHelpers.IncludeWidgetStyles();
2020
VSS.register("GHAzDoWidget", function () {
21-
const webContext = VSS.getWebContext();
22-
const project = webContext.project;
23-
const organization = webContext.account.name;
24-
const projectId = project.id;
21+
const webContext = VSS.getWebContext()
22+
const project = webContext.project
23+
const organization = webContext.account.name
24+
const projectId = project.id
2525
// convert project.name to url encoding
26-
const projectName = project.name.replace(/ /g, "%20").replace(/&/g, "%26");
26+
const projectName = project.name.replace(/ /g, "%20").replace(/&/g, "%26")
2727

28-
consoleLog('project id: ' + projectId);
29-
consoleLog('project name: ' + projectName);
30-
consoleLog('organization name: ' + organization);
28+
consoleLog('project id: ' + projectId)
29+
consoleLog('project name: ' + projectName)
30+
consoleLog('organization name: ' + organization)
3131

3232
return {
3333
load: async function (widgetSettings) {
34-
await loadWidget(widgetSettings, organization, projectName);
34+
await loadWidget(widgetSettings, organization, projectName)
3535

36-
return WidgetHelpers.WidgetStatusHelper.Success();
36+
return WidgetHelpers.WidgetStatusHelper.Success()
3737
},
3838
reload: async function (widgetSettings) {
39-
consoleLog('reload with widgetSettings: ' + JSON.stringify(widgetSettings));
40-
await loadWidget(widgetSettings, organization, projectName);
41-
return;
39+
consoleLog('reload with widgetSettings: ' + JSON.stringify(widgetSettings))
40+
await loadWidget(widgetSettings, organization, projectName)
41+
return
4242
}
4343
}
44-
});
45-
VSS.notifyLoadSucceeded();
44+
})
45+
VSS.notifyLoadSucceeded()
4646
}
47-
);
47+
)
4848
</script>
4949

5050
</head>
5151
<body>
52-
<div class="widget GHAzDo-widget">
52+
<div class="widget GHAzDo-widget" id="GHAzDo-widget">
5353
<h2 class="ghazdo-title">GitHub Advanced Security Alerts</h2>
5454
<div id="query-info-container" class="column-container">
5555

+38-33
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,61 @@
11
async function loadWidget(widgetSettings, organization, projectName) {
2-
consoleLog(`WidgetSettings inside loadWidget: ${JSON.stringify(widgetSettings)}`);
3-
consoleLog(`Running for organization [${organization}], projectName [${projectName}]`);
2+
consoleLog(`WidgetSettings inside loadWidget: ${JSON.stringify(widgetSettings)}`)
3+
consoleLog(`Running for organization [${organization}], projectName [${projectName}]`)
44

55
// data contains a stringified json object, so we need to make a json object from it
6-
const data = JSON.parse(widgetSettings.customSettings.data);
6+
const data = JSON.parse(widgetSettings.customSettings.data)
77

88
// init with default values
99
let alerts = {
1010
dependencyAlerts: 0,
1111
secretAlerts: 0,
1212
codeAlerts: 0
13-
};
14-
let linkBase = 'https://dev.azure.com';
13+
}
14+
let linkBase = 'https://dev.azure.com'
1515

1616
if (data && data.repo) {
17-
const repoName = data.repo;
18-
const repoId = data.repoId;
19-
consoleLog('loaded repoName from widgetSettings: ' + repoName);
17+
const repoName = data.repo
18+
const repoId = data.repoId
19+
consoleLog('loaded repoName from widgetSettings: ' + repoName)
2020

2121
// set the tile
22-
var title = $('h2.ghazdo-title');
23-
title.text(`Security Alerts for ${repoName}`);
24-
title.attr('title', repoName);
25-
alerts = (await getAlerts(organization, projectName, repoId)).values;
26-
consoleLog('alerts: ' + JSON.stringify(alerts));
22+
var title = $('h2.ghazdo-title')
23+
title.text(`Security Alerts for ${repoName}`)
24+
title.attr('title', repoName)
25+
alerts = (await getAlerts(organization, projectName, repoId)).values
26+
consoleLog('alerts: ' + JSON.stringify(alerts))
2727

2828
// GHAS is only available on the SaaS version, so we can hardcode the domain
29-
linkBase = `https://dev.azure.com/${organization}/${projectName}/_git/${repoName}/alerts`;
29+
linkBase = `https://dev.azure.com/${organization}/${projectName}/_git/${repoName}/alerts`
30+
31+
// set the color
32+
const color = data.color ? data.color : '#68217a' // default to purple
33+
const widget = document.getElementById('GHAzDo-widget')
34+
widget.style.backgroundColor = `${color}`
3035
}
3136
else {
3237
consoleLog('configuration is needed first, opening with empty values');
3338
// set the tile to indicate config is needed
34-
var title = $('h2.ghazdo-title');
35-
title.text(`Configure the widget to get Security Alerts`);
39+
var title = $('h2.ghazdo-title')
40+
title.text(`Configure the widget to get Security Alerts`)
3641
}
3742

3843
// set the alert counts
39-
var dependencyAlertCount = $('p.dependencyAlertCount');
40-
dependencyAlertCount.text(alerts.dependencyAlerts);
41-
const dependencyLinkValue = `${linkBase}?_t=dependencies`;
42-
const dependencyLink = $('a.dependency-link');
43-
dependencyLink.attr('href', dependencyLinkValue);
44-
45-
var secretAlertCount = $('p.secretAlertCount');
46-
secretAlertCount.text(alerts.secretAlerts);
47-
const secretLinkValue = `${linkBase}?_t=secrets`;
48-
const secretLink = $('a.secret-link');
49-
secretLink.attr('href', secretLinkValue);
50-
51-
var codeAlertCount = $('p.codeAlertCount');
52-
codeAlertCount.text(alerts.codeAlerts);
53-
const codeLinkValue = `${linkBase}?_t=codescanning`;
54-
const codeLink = $('a.code-link');
55-
codeLink.attr('href', codeLinkValue);
44+
var dependencyAlertCount = $('p.dependencyAlertCount')
45+
dependencyAlertCount.text(alerts.dependencyAlerts)
46+
const dependencyLinkValue = `${linkBase}?_t=dependencies`
47+
const dependencyLink = $('a.dependency-link')
48+
dependencyLink.attr('href', dependencyLinkValue)
49+
50+
var secretAlertCount = $('p.secretAlertCount')
51+
secretAlertCount.text(alerts.secretAlerts)
52+
const secretLinkValue = `${linkBase}?_t=secrets`
53+
const secretLink = $('a.secret-link')
54+
secretLink.attr('href', secretLinkValue)
55+
56+
var codeAlertCount = $('p.codeAlertCount')
57+
codeAlertCount.text(alerts.codeAlerts)
58+
const codeLinkValue = `${linkBase}?_t=codescanning`
59+
const codeLink = $('a.code-link')
60+
codeLink.attr('href', codeLinkValue)
5661
}

0 commit comments

Comments
 (0)