Skip to content

Commit

Permalink
Merge pull request #115 from digital-land/feat/dashboard
Browse files Browse the repository at this point in the history
Feat/dashboard
  • Loading branch information
GeorgeGoodall authored Jul 12, 2024
2 parents 71b1e8d + 18434e5 commit 33caf79
Show file tree
Hide file tree
Showing 28 changed files with 585 additions and 44 deletions.
60 changes: 59 additions & 1 deletion src/assets/scss/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,62 @@ $govuk-global-styles: true;
.app-map {
height: 500px;
@include govuk-responsive-margin(6, $direction: "bottom");
}
}

.task-div {
margin-bottom: 10px;
padding: 10px;
}

.dataset-summary-grid {
display: flex;
flex-wrap: wrap;
column-gap: govuk-spacing(3);
row-gap: govuk-spacing(6);
align-items: stretch;
}

.dataset-summary-grid .govuk-summary-card {
width: calc((100% / 3) - govuk-spacing(3));
}

.dataset-summary-grid .govuk-summary-card__title-wrapper {
align-items: flex-start;
}

.dataset-status {
margin-bottom: govuk-spacing(6);

display: flex;
column-gap: govuk-spacing(6);
}

.dataset-status--item {
background-color: $govuk-brand-colour;
color: govuk-colour("white");

padding: govuk-spacing(2) govuk-spacing(3);
flex-grow: 1;
flex-basis: 0;

@include govuk-font($size: 24, $weight: bold);
}

.big-number {
@include govuk-font($size: 80, $weight: bold);
display: block;
}

.planning-data-actions {
list-style: none;
margin: 0;
padding: 0;

display: flex;
column-gap: govuk-spacing(2);
}

code,
code * {
font-family: monospace;
}
2 changes: 1 addition & 1 deletion src/controllers/CheckAnswersController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PageController from './pageController.js'
import notifyClient from '../utils/mailClient.js'
import notifyClient from '../services/mailClient.js'
import config from '../../config/index.js'

const dataManagementEmail = process.env.DATA_MANAGEMENT_EMAIL || config.email.dataManagementEmail
Expand Down
42 changes: 42 additions & 0 deletions src/controllers/LpaOverviewController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import performanceDbApi from '../services/performanceDbApi.js' // Assume you have an API service module
import logger from '../utils/logger.js'

const LpaOverviewController = {
async getOverview (req, res, next) {
try {
const lpa = req.params.lpa

const response = await performanceDbApi.getLpaOverview(lpa) // Make API request
const data = response.data

const datasets = Object.entries(data.datasets).map(([key, value]) => {
return { ...value, slug: key }
})
const totalDatasets = datasets.length
const [datasetsWithEndpoints, datasetsWithIssues, datasetsWithErrors] = datasets.reduce((accumulator, dataset) => {
if (dataset.endpoint !== null) accumulator[0]++
if (dataset.issue) accumulator[1]++
if (dataset.error) accumulator[2]++
return accumulator
}, [0, 0, 0])

const params = {
organisation: {
name: data.name
},
datasets,
totalDatasets,
datasetsWithEndpoints,
datasetsWithIssues,
datasetsWithErrors
}

res.render('manage/lpa-overview.html', params)
} catch (error) {
logger.error(error)
next(error)
}
}
}

export default LpaOverviewController
2 changes: 1 addition & 1 deletion src/controllers/lpaDetailsController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PageController from './pageController.js'
import { fetchLocalAuthorities } from '../utils/fetchLocalAuthorities.js'
import { fetchLocalAuthorities } from '../services/fetchLocalAuthorities.js'

class LpaDetailsController extends PageController {
async locals (req, res, next) {
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/resultsController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PageController from './pageController.js'
import { getRequestData } from '../utils/asyncRequestApi.js'
import { getRequestData } from '../services/asyncRequestApi.js'

const failedFileRequestTemplate = 'results/failedFileRequest'
const failedUrlRequestTemplate = 'results/failedUrlRequest'
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/statusController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import PageController from './pageController.js'
import { getRequestData } from '../utils/asyncRequestApi.js'
import { getRequestData } from '../services/asyncRequestApi.js'
import { finishedProcessingStatuses } from '../utils/utils.js'

class StatusController extends PageController {
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/submitUrlController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import UploadController from './uploadController.js'
import { postUrlRequest } from '../utils/asyncRequestApi.js'
import { postUrlRequest } from '../services/asyncRequestApi.js'
import { URL } from 'url'
import logger from '../utils/logger.js'
import axios from 'axios'
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/uploadFileController.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import multer from 'multer'
import { promises as fs, createReadStream } from 'fs'
import config from '../../config/index.js'
import logger from '../utils/logger.js'
import { postFileRequest } from '../utils/asyncRequestApi.js'
import { postFileRequest } from '../services/asyncRequestApi.js'
import { allowedFileTypes } from '../utils/utils.js'

AWS.config.update({
Expand Down
25 changes: 3 additions & 22 deletions src/filters/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,14 @@ import validationMessageLookup from './validationMessageLookup.js'
import toErrorList from './toErrorList.js'
import prettifyColumnName from './prettifyColumnName.js'
import getFullServiceName from './getFullServiceName.js'
import { makeDatasetSlugToReadableNameFilter, createDatasetMapping } from './makeDatasetSlugToReadableNameFilter.js'

const { govukMarkdown } = xGovFilters

/**
*
* @param {*} dataSubjects
* @returns {Map<string,string>}
*/
function createDatasetMapping (dataSubjects) {
const mapping = new Map()
for (const data of Object.values(dataSubjects)) {
for (const dataset of data.dataSets) {
mapping.set(dataset.value, dataset.text)
}
}
return mapping
}

const addFilters = (nunjucksEnv, { dataSubjects }) => {
const datasetNameMapping = createDatasetMapping(dataSubjects)
nunjucksEnv.addFilter('datasetSlugToReadableName', function (slug) {
const name = datasetNameMapping.get(slug)
if (!name) {
throw new Error(`Can't find a name for ${slug}`)
}
return name
})
const datasetSlugToReadableName = makeDatasetSlugToReadableNameFilter(datasetNameMapping)
nunjucksEnv.addFilter('datasetSlugToReadableName', datasetSlugToReadableName)

nunjucksEnv.addFilter('govukMarkdown', govukMarkdown)
nunjucksEnv.addFilter('getkeys', getkeys)
Expand Down
38 changes: 38 additions & 0 deletions src/filters/makeDatasetSlugToReadableNameFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Creates a filter function that takes a dataset slug as input and returns its corresponding readable name.
* The filter function uses a provided dataset name mapping to look up the readable name.
*
* @param {Map<string, string>} datasetNameMapping - A map of dataset slugs to their corresponding readable names.
* @returns {(slug: string) => string} - A filter function that takes a dataset slug as input and returns its corresponding readable name.
*/
export const makeDatasetSlugToReadableNameFilter = (datasetNameMapping) => {
/**
* A filter function that takes a dataset slug as input and returns its corresponding readable name.
*
* @param {string} slug - The dataset slug to look up.
* @returns {string} - The readable name corresponding to the provided slug.
* @throws {Error} - If the provided slug is not found in the dataset name mapping.
*/
return (slug) => {
const name = datasetNameMapping.get(slug)
if (!name) {
throw new Error(`Can't find a name for ${slug}`)
}
return name
}
}

/**
*
* @param {*} dataSubjects
* @returns {Map<string,string>}
*/
export const createDatasetMapping = (dataSubjects) => {
const mapping = new Map()
for (const data of Object.values(dataSubjects)) {
for (const dataset of data.dataSets) {
mapping.set(dataset.value, dataset.text)
}
}
return mapping
}
2 changes: 1 addition & 1 deletion src/routes/api.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express'
import { getRequestData } from '../utils/asyncRequestApi.js'
import { getRequestData } from '../services/asyncRequestApi.js'

const router = express.Router()

Expand Down
8 changes: 8 additions & 0 deletions src/routes/manage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import express from 'express'
import LpaOverviewController from '../controllers/LpaOverviewController.js'

const router = express.Router()

router.get('/:lpa/overview', LpaOverviewController.getOverview)

export default router
2 changes: 2 additions & 0 deletions src/serverSetup/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import endpointSubmissionFormFormWisard from '../routes/form-wizard/endpoint-sub
import accessibility from '../routes/accessibility.js'
import polling from '../routes/api.js'
import health from '../routes/health.js'
import manage from '../routes/manage.js'

export function setupRoutes (app) {
app.use('/', checkFormWizard)
app.use('/submit', endpointSubmissionFormFormWisard)
app.use('/accessibility', accessibility)
app.use('/api', polling)
app.use('/health', health)
app.use('/manage', manage)
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
47 changes: 47 additions & 0 deletions src/services/performanceDbApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export default {
getLpaOverview: async (lpa) => {
return {
data: {
name: 'Borechester City Council',
datasets: {
'article-4-direction': {
endpoint: null
},
'article-4-direction-area': {
endpoint: null
},
'conservation-area': {
endpoint: 'http://conservation-area.json',
error: null,
issue: 'Endpoint has not been updated since 21 May 2023'
},
'conservation-area-document': {
endpoint: 'http://conservation-area-document.json',
error: null,
issue: null
},
'listed-building-outline': {
endpoint: 'http://listed-building-outline.json',
error: null,
issue: null
},
tree: {
endpoint: 'http://tree.json',
error: null,
issue: 'There are 20 issues in this dataset'
},
'tree-preservation-order': {
endpoint: 'http://tree-preservation-order.json',
error: 'Error connecting to endpoint',
issue: null
},
'tree-preservation-zone': {
endpoint: 'http://tree-preservation-zone.json',
error: 'Error connecting to endpoint',
issue: null
}
}
}
}
}
}
Loading

0 comments on commit 33caf79

Please sign in to comment.