-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from rajbos/chart
Adding trend line chart for the AdvSec alerts
- Loading branch information
Showing
7 changed files
with
416 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<script src="../lib/VSS.SDK.min.js"></script> | ||
<script src="../library.js"></script> | ||
<link rel="stylesheet" href="../styles.css" /> | ||
</head> | ||
<body> | ||
<script lang=""> | ||
VSS.init({ | ||
explicitNotifyLoaded: true, | ||
usePlatformStyles: true | ||
}); | ||
|
||
VSS.require([ | ||
"TFS/Dashboards/WidgetHelpers", | ||
"Charts/Services", | ||
"VSS/Context", | ||
"VSS/Authentication/Services" | ||
], | ||
function (WidgetHelpers, Services, context) { | ||
WidgetHelpers.IncludeWidgetStyles(); | ||
VSS.register("GHAzDoWidget.Chart", function () { | ||
return { | ||
load: async function(widgetSettings) { | ||
return Services.ChartsService.getService().then(async function(chartService){ | ||
consoleLog("Starting to create chart"); | ||
var $container = $('#Chart-Container'); | ||
var $title = $('h2.title'); | ||
|
||
const webContext = VSS.getWebContext(); | ||
const project = webContext.project; | ||
const organization = webContext.account.name; | ||
const projectId = project.id; | ||
// convert project.name to url encoding | ||
const projectName = project.name.replace(/ /g, "%20").replace(/&/g, "%26"); | ||
|
||
consoleLog('project id: ' + projectId); | ||
consoleLog('project name: ' + projectName); | ||
consoleLog('organization name: ' + organization); | ||
|
||
consoleLog(`WidgetSettings inside loadChartWidget_2x2: ${JSON.stringify(widgetSettings)}`); | ||
|
||
// data contains a stringified json object, so we need to make a json object from it | ||
const data = JSON.parse(widgetSettings.customSettings.data); | ||
|
||
let repoName | ||
let repoId | ||
if (data && data.repo) { | ||
repoName = data.repo; | ||
repoId = data.repoId; | ||
consoleLog('loaded repoName from widgetSettings: ' + repoName); | ||
|
||
$title.text(`Advanced Security Alerts Trend`) | ||
$container.text(`${data.repo}`) | ||
|
||
// load the alerts for the selected repo | ||
try { | ||
alerts = await getAlerts(organization, projectName, repoId); | ||
consoleLog('alerts: ' + JSON.stringify(alerts)); | ||
} | ||
catch (err) { | ||
consoleLog(`Error loading the grouped alerts: ${err}`); | ||
} | ||
} | ||
else { | ||
consoleLog('configuration is needed first, opening with empty values'); | ||
// set the tile to indicate config is needed | ||
$title.text(`Configure the widget to get Advanced Security alerts trend information`); | ||
} | ||
|
||
// init empty object first | ||
let alertTrendLines = {secretAlertTrend: [], dependencyAlertTrend: [], codeAlertsTrend: []}; | ||
try { | ||
// get the trend data for alerts first | ||
alertTrendLines = await getAlertsTrendLines(organization, projectName, repoId) | ||
consoleLog('Dependencies AlertTrend: ' + JSON.stringify(alertTrendLines.dependencyAlertsTrend)); | ||
consoleLog('Code scanning AlertTrend: ' + JSON.stringify(alertTrendLines.codeAlertsTrend)); | ||
consoleLog('Secrets AlertTrend: ' + JSON.stringify(alertTrendLines.secretAlertsTrend)); | ||
} | ||
catch (err) { | ||
consoleLog(`Error loading the alerts trend: ${err}`); | ||
} | ||
|
||
const datePoints = getDatePoints(); | ||
var chartOptions = { | ||
"hostOptions": { | ||
"height": "290", | ||
"width": "300" | ||
}, | ||
"chartType": "line", | ||
"series": | ||
[ | ||
{ | ||
"name": "Dependencies", | ||
"data": alertTrendLines.dependencyAlertsTrend | ||
}, | ||
{ | ||
"name": "Code scanning", | ||
"data": alertTrendLines.codeAlertsTrend | ||
}, | ||
{ | ||
"name": "Secrets", | ||
"data": alertTrendLines.secretAlertsTrend | ||
} | ||
], | ||
"xAxis": { | ||
"labelValues": datePoints, | ||
"labelFormatMode": "dateTime", // format is 2023-09-17 | ||
}, | ||
"specializedOptions": { | ||
"includeMarkers": "true" | ||
} | ||
}; | ||
|
||
try { | ||
chartService.createChart($container, chartOptions); | ||
} | ||
catch (err) { | ||
console.log(`Error creating chart: ${err}`); | ||
} | ||
return WidgetHelpers.WidgetStatusHelper.Success(); | ||
}); | ||
} | ||
} | ||
}); | ||
VSS.notifyLoadSucceeded(); | ||
}); | ||
|
||
function consoleLog(message) { | ||
console.log(message); | ||
} | ||
</script> | ||
|
||
<div class="widget"> | ||
<h2 class="title">Chart Widget</h2> | ||
<div id="Chart-Container"></div> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<!DOCTYPE html> | ||
<html xmlns="http://www.w3.org/1999/xhtml"> | ||
<head> | ||
<script src="../lib/VSS.SDK.min.js"></script> | ||
<link rel="stylesheet" href="../styles.css" /> | ||
|
||
<script type="text/javascript"> | ||
VSS.init({ | ||
explicitNotifyLoaded: true, | ||
usePlatformStyles: true | ||
}); | ||
|
||
VSS.require(["VSS/Service", "TFS/Dashboards/WidgetHelpers", "VSS/Context", "TFS/VersionControl/GitRestClient"], | ||
function (Service, WidgetHelpers, context, GitWebApi) { | ||
VSS.register("GHAzDoWidget.Chart.Configuration", function () { | ||
var $repoDropdown = $("#repo-dropdown"); | ||
|
||
async function getRepos() { | ||
try { | ||
const webContext = VSS.getWebContext(); | ||
const project = webContext.project; | ||
|
||
// todo: load the available repos in this project | ||
const gitClient = Service.getClient(GitWebApi.GitHttpClient); | ||
repos = await gitClient.getRepositories(project.name); | ||
console.log(`Found these repos: ${JSON.stringify(repos)}`); | ||
return repos; | ||
} | ||
catch (err) { | ||
console.log(`Error loading the available repos: ${err}`); | ||
return []; | ||
} | ||
} | ||
|
||
return { | ||
load: async function (widgetSettings, widgetConfigurationContext) { | ||
var settings = JSON.parse(widgetSettings.customSettings.data); | ||
console.log(`Loading the Chart.2x2 settings with ${JSON.stringify(settings)}`) | ||
|
||
const repos = await getRepos(); | ||
// add all repos as selection options to the dropdown | ||
if (repos) { | ||
// sort the repo alphabetically | ||
repos.sort((a, b) => a.name.localeCompare(b.name)); | ||
repos.forEach(r => { | ||
$repoDropdown.append(`<option value=${r.name}>${r.name}</option>`); | ||
}); | ||
} | ||
|
||
if (settings && settings.repo) { | ||
// select the repo that was saved in the settings | ||
$repoDropdown.val(settings.repo); | ||
} | ||
|
||
$repoDropdown.on("change", function () { | ||
let repo; | ||
if (repos) { | ||
// find the repo with this name | ||
repo = repos.find(r => r.name === $repoDropdown.val()); | ||
} | ||
|
||
var customSettings = { | ||
data: JSON.stringify({ | ||
repo: $repoDropdown.val(), | ||
repoId: repo.id | ||
}) | ||
}; | ||
var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange; | ||
var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings); | ||
widgetConfigurationContext.notify(eventName, eventArgs); | ||
}); | ||
|
||
return WidgetHelpers.WidgetStatusHelper.Success(); | ||
}, | ||
onSave: async function() { | ||
const repos = await getRepos(); | ||
let repo; | ||
if (repos) { | ||
// find the repo with this name | ||
repo = repos.find(r => r.name === $repoDropdown.val()); | ||
} | ||
var customSettings = { | ||
data: JSON.stringify({ | ||
repo: $repoDropdown.val(), | ||
repoId: repo.id | ||
}) | ||
}; | ||
console.log(`Saving the Chart.2x2 settings with ${JSON.stringify(customSettings)}`) | ||
return WidgetHelpers.WidgetConfigurationSave.Valid(customSettings); | ||
} | ||
} | ||
}); | ||
VSS.notifyLoadSucceeded(); | ||
}); | ||
</script> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<fieldset> | ||
<label class="label">Repository: </label> | ||
<select id="repo-dropdown" style="margin-top:10px"> | ||
<!-- todo: dynamically load the available repos in this project--> | ||
</select> | ||
</fieldset> | ||
</div> | ||
</body> | ||
</html> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.