Skip to content

Commit

Permalink
Fixes major bug with disabled fields in jsonforms. Adds final report, c…
Browse files Browse the repository at this point in the history
…loses #4.
  • Loading branch information
davetaz committed May 22, 2024
1 parent e84ccd0 commit d870765
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 134 deletions.
3 changes: 2 additions & 1 deletion controllers/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ async function addRiskScoreToProject(project) {
unintendedConsequence.riskScore = null;
}
}
return project;
}


Expand Down Expand Up @@ -241,4 +242,4 @@ async function getCompletionState(projectId, schema) {
}
}

module.exports = { getUserProjects, getCompletionState };
module.exports = { getUserProjects, getCompletionState, getUserProjectMetrics, addRiskScoreToProject };
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "care.theodi.org",
"version": "2.2.0",
"version": "2.3.0",
"description": "The ODI Care tool (AI enabled)",
"main": "index.js",
"scripts": {
Expand Down
13 changes: 11 additions & 2 deletions public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ li {
overflow-x: hidden;
height: 175px;
}
.top-risks tbody tr:nth-child(2n) {
.top-risks tr:nth-child(2n) {
color: white;
}
#unintendedConsequences tr:nth-child(2n) {
color: white;
}
.top-risks tbody tr:nth-child(2n) a {
Expand Down Expand Up @@ -286,7 +289,10 @@ fieldset .form-group {
overflow-y: auto; /* Scrollable contents if sidebar is long */
z-index: 1000; /* Ensures sidebar is above other content */
}
.sidebar li {
.result ul {
line-height: 2rem;
}
.sidebar li, .result li {
margin: 0;
padding: 4px 0 6px 21px;
list-style: none;
Expand All @@ -295,6 +301,9 @@ fieldset .form-group {
background-position: left center;
background-size: 25px;
}
.result li {
padding-left: 2rem;
}
.sidebar ul li a {
display: block;
padding: 10px;
Expand Down
24 changes: 10 additions & 14 deletions public/data/forms/actionPlanning.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,32 @@
"items": [
{
"key": "unintendedConsequences[].consequence",
"fieldHtmlClass": "input inputText",
"fieldHtmlClass": "input inputText disabled",
"placeholder": "Unintended consequence",
"prepend": "<h2 class='draggable'>Unintended consequence</h2>",
"notitle": true,
"disabled": true
"notitle": true
},
{
"key": "unintendedConsequences[].outcome",
"fieldHtmlClass": "input",
"fieldHtmlClass": "input disabled",
"prepend": "<h3>Outcome</h3>",
"notitle": true,
"disabled": true
"notitle": true
},
{
"type": "fieldset",
"title": "Risk evaluation",
"items": [
{
"key": "unintendedConsequences[].impact",
"fieldHtmlClass": "input",
"fieldHtmlClass": "input disabled",
"prepend": "<h3>Impact</h3>",
"notitle": true,
"disabled": true
"notitle": true
},
{
"key": "unintendedConsequences[].likelihood",
"fieldHtmlClass": "input",
"fieldHtmlClass": "input disabled",
"prepend": "<h3>Likelihood</h3>",
"notitle": true,
"disabled": true
"notitle": true
}
]
},
Expand Down Expand Up @@ -88,7 +84,7 @@
"type": "submit",
"title": "View risk register",
"htmlClass": "submitButton",
"next": "riskRegister",
"quickNav": "true"
"next": "",
"quickNav": "false"
}
]
10 changes: 4 additions & 6 deletions public/data/forms/riskEvaluation.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@
"items": [
{
"key": "unintendedConsequences[].consequence",
"fieldHtmlClass": "input inputText",
"fieldHtmlClass": "input inputText disabled",
"placeholder": "Unintended consequence",
"prepend": "<h2 class='draggable'>Unintended consequence</h2>",
"notitle": true,
"disabled": true
"notitle": true
},
{
"key": "unintendedConsequences[].outcome",
"fieldHtmlClass": "input",
"fieldHtmlClass": "input disabled",
"prepend": "<h3>Outcome</h3>",
"notitle": true,
"disabled": true
"notitle": true
},
{
"type": "fieldset",
Expand Down
136 changes: 136 additions & 0 deletions public/js/dashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
function addRiskDonut(riskCounts) {
const ctx = document.getElementById('riskChart').getContext('2d');
new Chart(ctx, {
type: 'doughnut',
data: {
labels: Object.keys(riskCounts),
datasets: [{
label: 'Risk count',
data: Object.values(riskCounts),
backgroundColor: [
'rgba(200, 200, 200, 0.5)',
'rgba(255, 99, 132, 0.5)',
'rgba(255, 206, 86, 0.5)',
'rgba(54, 162, 235, 0.5)'

],
borderColor: [
'rgba(200, 200, 200, 1)',
'rgba(255, 99, 132, 1)',
'rgba(255, 206, 86, 1)',
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}]
},
options: {
aspectRatio: 2,
responsive: true,
plugins: {
legend: {
position: 'right',
},
title: {
display: false,
text: 'Risk Counts'
}
}
}
});
}
function addAverages(averageScores) {
const likelihoodBar = document.getElementById('likelihood-bar');
likelihoodBar.style.width = (averageScores.likelihood / 3 * 100) + '%';
likelihoodBar.innerText = averageScores.likelihood;
likelihoodBar.style.backgroundColor = getColorForScore(averageScores.likelihood);

const impactBar = document.getElementById('impact-bar');
impactBar.style.width = (averageScores.impact / 3 * 100) + '%';
impactBar.innerText = averageScores.impact;
impactBar.style.backgroundColor = getColorForScore(averageScores.impact);

const riskBar = document.getElementById('risk-bar');
riskBar.style.width = (averageScores.riskScore / 9 * 100) + '%';
riskBar.innerText = averageScores.riskScore;
riskBar.style.backgroundColor = getColorForScore(averageScores.riskScore / 3);
}

function addTopRisks(topRisks) {
const tableBody = document.getElementById('topRisksTableBody');
tableBody.innerHTML = ''; // Clear existing rows

topRisks.forEach(risk => {
const row = tableBody.insertRow();
const scoreText = getScoreText(risk.score/3);
const scoreColor = getColorForScore(risk.score/3);

row.innerHTML = `
<td>${risk.consequence}</td>
<td style="color: ${scoreColor}">${scoreText}</td>
<td><a href="/project/${risk.projectId}/actionPlanning">View</a></td>
`;
});
}

function getScoreText(score) {
if (score < 1) {
return 'Low';
} else if (score < 2) {
return 'Medium';
} else {
return 'High';
}
}

function getColorForScore(score) {
if (score > 2) {
return 'rgba(255, 99, 132, 0.75)';
} else if (score >= 1 && score <= 2) {
return 'rgba(255, 206, 86, 0.75)';
} else {
return 'rgba(54, 162, 235, 0.75)';
}
}

async function addRiskScoreToProject(project) {
for (const unintendedConsequence of project.unintendedConsequences) {
// Check if both impact and likelihood are defined
if (unintendedConsequence.likelihood && unintendedConsequence.impact) {
// Calculate risk score for the unintended consequence
let riskScore = 1; // Default risk score
switch (unintendedConsequence.likelihood) {
case 'High':
riskScore *= 3;
break;
case 'Medium':
riskScore *= 2;
break;
case 'Low':
riskScore *= 1;
break;
default:
// Handle unknown likelihood
break;
}
switch (unintendedConsequence.impact) {
case 'High':
riskScore *= 3;
break;
case 'Medium':
riskScore *= 2;
break;
case 'Low':
riskScore *= 1;
break;
default:
// Handle unknown impact
break;
}
// Add risk score to the unintended consequence
unintendedConsequence.riskScore = riskScore;
} else {
unintendedConsequence.riskScore = null;
}
}
return project;
}
50 changes: 43 additions & 7 deletions routes/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,25 @@ router.get('/:id/completeAssessment', ensureAuthenticated, checkProjectAccess, l
next(error); // Pass error to error handling middleware
}
});
// GET route to retrieve a project by ID
router.get('/:id/riskSummary', ensureAuthenticated, checkProjectAccess, loadProject, async (req, res, next) => {
try {
// Find the project by ID
let project = res.locals.project;
project = await projectController.addRiskScoreToProject(project);
const userProjects = [];
userProjects.push(project);
let metrics = await projectController.getUserProjectMetrics(userProjects);

return res.json(metrics);

} catch (error) {
next(error); // Pass error to error handling middleware
}
});

// GET route to retrieve a project by ID
router.get('/:id/:page?', ensureAuthenticated, checkProjectAccess, loadProject, async (req, res, next) => {
router.get('/:id/:page', ensureAuthenticated, checkProjectAccess, loadProject, async (req, res, next) => {
try {
// Find the project by ID
const project = res.locals.project;
Expand All @@ -44,14 +60,9 @@ router.get('/:id/:page?', ensureAuthenticated, checkProjectAccess, loadProject,
const acceptHeader = req.get('Accept');

if (acceptHeader === 'application/json') {
// Respond with JSON
// Respond with JSON (filter it according to the schema?)
return res.json(project);
} else {
// Respond with HTML (rendering scan.ejs)
let page = {
link: "projectDetails",
title: "Project details"
};
// Check if the page parameter is provided
const pages = require('../pages.json');
const pageParam = req.params.page;
Expand All @@ -71,6 +82,31 @@ router.get('/:id/:page?', ensureAuthenticated, checkProjectAccess, loadProject,
}
});

// GET route to retrieve a project by ID
router.get('/:id', ensureAuthenticated, checkProjectAccess, loadProject, async (req, res, next) => {
try {
// Find the project by ID
const project = res.locals.project;

// Content negotiation based on request Accept header
const acceptHeader = req.get('Accept');

if (acceptHeader === 'application/json') {
// Respond with JSON (filter it according to the schema?)
return res.json(project);
} else {
let page = {
link: "/finalReport",
title: "Project evaluation"
};
res.locals.page = page;
res.render('pages/project', { project: project });
}
} catch (error) {
next(error); // Pass error to error handling middleware
}
});

// POST route to create a new project
router.post('/', ensureAuthenticated, async (req, res) => {
try {
Expand Down
Loading

0 comments on commit d870765

Please sign in to comment.