Skip to content

Commit

Permalink
Merge pull request #192 from digital-land/staging
Browse files Browse the repository at this point in the history
LPA dashboard increment
  • Loading branch information
GeorgeGoodall authored Aug 1, 2024
2 parents 1ea04d4 + 7eb9136 commit fd5a0fd
Show file tree
Hide file tree
Showing 29 changed files with 719 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
74 changes: 74 additions & 0 deletions src/controllers/LpaOverviewController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import performanceDbApi from '../services/performanceDbApi.js' // Assume you have an API service module
import logger from '../utils/logger.js'
import { dataSubjects } from '../utils/utils.js'

// get a list of available datasets
const availableDatasets = Object.values(dataSubjects)
.flatMap(dataSubject =>
dataSubject.dataSets
.filter(dataset => dataset.available)
.map(dataset => dataset.value)
)

const LpaOverviewController = {
/**
* Get LPA overview data and render the overview page
* @param {Request} req - Express request object
* @param {Response} res - Express response object
* @param {NextFunction} next - Express next function
* @returns {Promise<void>} - Returns a promise that resolves when the overview page is rendered
*/
async getOverview (req, res, next) {
try {
const lpa = req.params.lpa

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

// restructure datasets to usable format
const datasets = Object.entries(lpaOverview.datasets).map(([key, value]) => {
return {
slug: key,
...value
}
})

// add in any of the missing key 8 datasets
const keys = Object.keys(lpaOverview.datasets)
availableDatasets.forEach(dataset => {
if (!keys.includes(dataset)) {
datasets.push({
slug: dataset,
endpoint: null
})
}
})

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: lpaOverview.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
43 changes: 43 additions & 0 deletions src/filters/makeDatasetSlugToReadableNameFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import logger from '../utils/logger.js'

/**
* 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}`)
// ToDo: work out what to do here? potentially update it with data from datasette
logger.warning(`can't find a name for ${slug}`)
return 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,6 +3,7 @@ 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'
import privacy from '../routes/privacy.js'
import cookies from '../routes/cookies.js'

Expand All @@ -12,6 +13,7 @@ export function setupRoutes (app) {
app.use('/accessibility', accessibility)
app.use('/api', polling)
app.use('/health', health)
app.use('/manage', manage)
app.use('/privacy-notice', privacy)
app.use('/cookies', cookies)
}
File renamed without changes.
19 changes: 19 additions & 0 deletions src/services/datasette.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from 'axios'
import logger from '../utils/logger.js'

const datasetteUrl = 'https://datasette.planning.data.gov.uk'
const database = 'digital-land'

export default {
runQuery: async (query) => {
const encodedQuery = encodeURIComponent(query)
const url = `${datasetteUrl}/${database}.json?sql=${encodedQuery}`
try {
const response = await axios.get(url)
return response.data
} catch (error) {
logger.warn(error)
throw error
}
}
}
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit fd5a0fd

Please sign in to comment.