Skip to content

Commit

Permalink
Add homepage - first iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
bill-moj committed Jan 9, 2025
1 parent b45fcbd commit 4479328
Show file tree
Hide file tree
Showing 32 changed files with 441 additions and 31 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ COMPONENT_API_TIMEOUT_DEADLINE=5000
COMMON_COMPONENTS_ENABLED=true
DPS_HOME_PAGE_URL=https://digital-dev.prison.service.justice.gov.uk
PRISONER_PROFILE_URL=https://prisoner-dev.digital.prison.service.justice.gov.uk
LEGACY_KEY_WORKERS_UI_URL=https://dev.manage-key-workers.service.justice.gov.uk

# Credentials for allowing user access
AUTH_CODE_CLIENT_ID=hmpps-typescript-template
Expand Down
11 changes: 11 additions & 0 deletions assets/js/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
function Card(container) {
this.container = container

if (this.container.querySelector('a') !== null) {
this.container.addEventListener('click', () => {
this.container.querySelector('a').click()
})
}
}

export default Card
7 changes: 7 additions & 0 deletions assets/js/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as govukFrontend from 'govuk-frontend'
import * as mojFrontend from '@ministryofjustice/frontend'
import Card from './card'
import { nodeListForEach } from './utils'

govukFrontend.initAll()
mojFrontend.initAll()

var $cards = document.querySelectorAll('.card--clickable')
nodeListForEach($cards, function ($card) {
new Card($card)
})
10 changes: 10 additions & 0 deletions assets/js/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function nodeListForEach(nodes, callback) {
if (window.NodeList.prototype.forEach) {
return nodes.forEach(callback)
}
for (var i = 0; i < nodes.length; i++) {
callback.call(window, nodes[i], i, nodes)
}
}

export { nodeListForEach }
3 changes: 2 additions & 1 deletion assets/scss/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ $govuk-page-width: $moj-page-width;
@import 'node_modules/@ministryofjustice/hmpps-connect-dps-components/dist/assets/footer';
@import 'node_modules/@ministryofjustice/hmpps-connect-dps-components/dist/assets/header-bar';

@import './components/card';
@import './components/header-bar';
@import './local';
@import './local';
98 changes: 98 additions & 0 deletions assets/scss/components/_card.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* ==========================================================================
COMPONENTS / #CARD
========================================================================== */

$card-border-width: 1px;
$card-border-bottom-width: govuk-spacing(1);
$card-border-hover-color: $govuk-border-colour;
$card-border-color: lighten($card-border-hover-color, 15%);

.card {
margin-bottom: govuk-spacing(7);
background: $govuk-body-background-colour;
border: $card-border-width solid $card-border-color;
position: relative;
width: 100%;
padding: govuk-spacing(5);

&__heading {
margin-top: 0;
margin-bottom: govuk-spacing(3);
}

&__description {
margin-bottom: 0;
}

/* Clickable card
========================================================================== */
&--clickable {
border-bottom-width: $card-border-bottom-width;

&:hover,
&:active {
cursor: pointer;

.card__heading a,
.card__link {
color: $govuk-link-hover-colour;
text-decoration: none;

&:focus {
@include govuk-focused-text;
}
}
}

&:hover {
border-color: $card-border-hover-color;
}

&:active {
border-color: $card-border-hover-color;
bottom: -$card-border-width;
}
}
}

/* Card group
========================================================================== */

/**
* A card group allows you to have a row of cards.
* Flexbox is used to make each card in a row the same height.
*/

.card-group {
display: flex;
flex-wrap: wrap;
margin-bottom: govuk-spacing(3);
padding: 0;

@include govuk-media-query($until: desktop) {
margin-bottom: govuk-spacing(6);
}

&__item {
display: flex;
list-style-type: none;
margin-bottom: 0;

@include govuk-media-query($until: desktop) {
flex: 0 0 100%;
}
.card {
margin-bottom: govuk-spacing(5);
}

@include govuk-media-query($until: desktop) {
.card {
margin-bottom: govuk-spacing(3);
}

&:last-child .card {
margin-bottom: 0;
}
}
}
}
19 changes: 19 additions & 0 deletions assets/scss/local.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
.govuk-main-wrapper {
min-height: 600px;
}

.homepage-content-container {
width: 300%;
margin-left: -100%;
padding: 30px 0;
background: #f0f4f5;
height: auto;
display: flex;
justify-content: center;
}

.homepage-content {
max-width: 100vw;
}

.dropshadow {
border: 1px solid govuk-colour('dark-grey');
box-shadow: 0 5px govuk-colour('mid-grey');
}
8 changes: 6 additions & 2 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ export default defineConfig({
})
},
baseUrl: 'http://localhost:3007',
excludeSpecPattern: '**/!(*.cy).ts',
specPattern: 'integration_tests/e2e/**/*.cy.{js,jsx,ts,tsx}',
excludeSpecPattern: ['dist', '**/!(*.cy).ts'],
specPattern: '**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'integration_tests/support/index.ts',
experimentalRunAllSpecs: true,
retries: {
runMode: 2,
},
},
})
14 changes: 11 additions & 3 deletions esbuild/esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ const buildConfig = {
from: path.join(cwd, 'server/views/**/*'),
to: path.join(cwd, 'dist/server/views'),
},
{
from: path.join(cwd, 'server/routes/journeys/**/*'),
to: path.join(cwd, 'dist/server/routes/journeys'),
},
{
from: path.join(cwd, 'server/routes/**/*'),
to: path.join(cwd, 'dist/server/routes'),
},
],
},

Expand Down Expand Up @@ -60,14 +68,14 @@ const main = () => {

if (args.includes('--dev-server')) {
let serverProcess = null
chokidar.watch(['dist']).on('all', () => {
chokidar.watch(['dist'], { ignored: ['**/*.cy.ts'] }).on('all', () => {
if (serverProcess) serverProcess.kill()
serverProcess = spawn('node', ['--env-file=.env', 'dist/server.js'], { stdio: 'inherit' })
})
}
if (args.includes('--dev-test-server')) {
let serverProcess = null
chokidar.watch(['dist']).on('all', () => {
chokidar.watch(['dist'], { ignored: ['**/*.cy.ts'] }).on('all', () => {
if (serverProcess) serverProcess.kill()
serverProcess = spawn('node', ['--env-file=feature.env', 'dist/server.js'], { stdio: 'inherit' })
})
Expand All @@ -82,7 +90,7 @@ const main = () => {

// App
chokidar
.watch(['server/**/*'], { ...chokidarOptions, ignored: ['**/*.test.ts'] })
.watch(['server/**/*'], { ...chokidarOptions, ignored: ['**/*.test.ts', '**/*.cy.ts'] })
.on('all', () => buildApp(buildConfig).catch(e => process.stderr.write(`${e}\n`)))
}
}
Expand Down
5 changes: 4 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import hmppsConfig from '@ministryofjustice/eslint-config-hmpps'

export default [
...hmppsConfig(),
...hmppsConfig({
extraIgnorePaths: ['assets'],
}),
{
rules: {
'dot-notation': 'off',
'import/prefer-default-export': 0,
},
},
]
1 change: 1 addition & 0 deletions feature.env
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ KEYWORKER_API_URL=http://localhost:9091/keyworker-api
PRISON_API_URL=http://localhost:9091/prison-api
COMPONENT_API_URL=http://localhost:9091/components
COMMON_COMPONENTS_ENABLED=true
LEGACY_KEY_WORKERS_UI_URL=https://legacy.key-workers.url
1 change: 1 addition & 0 deletions helm_deploy/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ generic-service:
PRISONER_PROFILE_URL: "https://prisoner-dev.digital.prison.service.justice.gov.uk"
PRISON_API_URL: "https://prison-api-dev.prison.service.justice.gov.uk"
KEYWORKER_API_URL: "https://keyworker-api-dev.prison.service.justice.gov.uk"
LEGACY_KEY_WORKERS_UI_URL: "https://dev.manage-key-workers.service.justice.gov.uk"
ENVIRONMENT_NAME: DEV
AUDIT_ENABLED: "false"
SENTRY_ENVIRONMENT: DEV
Expand Down
1 change: 1 addition & 0 deletions helm_deploy/values-preprod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ generic-service:
PRISONER_PROFILE_URL: "https://prisoner-preprod.digital.prison.service.justice.gov.uk"
PRISON_API_URL: "https://prison-api-preprod.prison.service.justice.gov.uk"
KEYWORKER_API_URL: "https://keyworker-api-preprod.prison.service.justice.gov.uk"
LEGACY_KEY_WORKERS_UI_URL: "https://preprod.manage-key-workers.service.justice.gov.uk"
ENVIRONMENT_NAME: PRE-PRODUCTION
AUDIT_ENABLED: "false"
SENTRY_ENVIRONMENT: PRE-PRODUCTION
Expand Down
1 change: 1 addition & 0 deletions helm_deploy/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ generic-service:
PRISONER_PROFILE_URL: "https://prisoner.digital.prison.service.justice.gov.uk"
KEYWORKER_API_URL: "https://keyworker-api.prison.service.justice.gov.uk"
PRISON_API_URL: "https://prison-api.prison.service.justice.gov.uk"
LEGACY_KEY_WORKERS_UI_URL: "https://manage-key-workers.service.justice.gov.uk"
AUDIT_ENABLED: "false"
SENTRY_ENVIRONMENT: PRODUCTION

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import { v4 as uuidV4 } from 'uuid'

context('test errorHandler', () => {
const uuid = uuidV4()

beforeEach(() => {
cy.task('reset')
cy.task('stubSignIn')
cy.task('stubComponents')
})

it('should go to the custom error page when an API 500s', () => {
cy.task('stubGetPrisoner500')
cy.task('stubGetPrisonerImage')
// TODO: add test for API error handling
it.skip('should go to the custom error page when an API 500s', () => {
cy.task('stubAPI500Error')
cy.signIn()
cy.visit(`${uuid}/prisoners/A1111AA/referral/start`, { failOnStatusCode: false })
cy.visit(`/path-that-requires-API-call`, { failOnStatusCode: false })
cy.findByText(/sorry, there is a problem with the service/i).should('be.visible')
})

it('should say page not found when 404', () => {
cy.signIn()
cy.visit(`${uuid}/foobar`, { failOnStatusCode: false })
cy.visit(`/foobar`, { failOnStatusCode: false })
cy.findByRole('heading', { name: /Page not found/i }).should('be.visible')
})
})
4 changes: 1 addition & 3 deletions integration_tests/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import Page, { PageElement } from './page'

export default class IndexPage extends Page {
constructor() {
super('This site is under construction...')
super('Key workers')
}

headerUserName = (): PageElement => cy.get('[data-qa=header-user-name]')

headerPhaseBanner = (): PageElement => cy.get('[data-qa=header-phase-banner]')
}
1 change: 1 addition & 0 deletions integration_tests/support/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import './commands'
import '@testing-library/cypress/add-commands'
11 changes: 11 additions & 0 deletions integration_tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"noEmit": true,
"lib": ["es5", "dom", "es2015.promise"],
"types": ["cypress", "express", "express-session", "@testing-library/cypress"],
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["**/*.ts"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"start-feature:dev": "concurrently -k -p \"[{name}]\" -n \"ESBuild,Node\" -c \"yellow.bold,cyan.bold\" \"node esbuild/esbuild.config.js --build --watch \" \"node esbuild/esbuild.config.js --dev-test-server\"",
"lint": "eslint . --cache --max-warnings 0",
"lint-fix": "eslint . --cache --max-warnings 0 --fix",
"typecheck": "tsc",
"typecheck": "tsc && tsc -p integration_tests && tsc -p server/routes",
"test": "jest",
"test:ci": "jest --runInBand",
"security_audit": "npx audit-ci --config audit-ci.json",
Expand Down
1 change: 1 addition & 0 deletions server/@types/express/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export declare global {
csrfToken: ReturnType<CsrfTokenGenerator>
user: HmppsUser
digitalPrisonServicesUrl: string
legacyKeyWorkersUiUrl: string
breadcrumbs: Breadcrumbs
prisoner?: PrisonerSummary
buildNumber?: string
Expand Down
3 changes: 2 additions & 1 deletion server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import routes from './routes'
import type { Services } from './services'
import checkPopulateUserCaseloads from './middleware/checkPopulateUserCaseloads'
import populateClientToken from './middleware/populateSystemClientToken'
import breadcrumbs from './middleware/breadcrumbs'

export default function createApp(services: Services): express.Application {
const app = express()
Expand Down Expand Up @@ -62,7 +63,7 @@ export default function createApp(services: Services): express.Application {
res.notFound = () => res.status(404).render('pages/not-found')
next()
})

app.use(breadcrumbs())
app.use(checkPopulateUserCaseloads(services.prisonApiService))
app.use(routes(services))

Expand Down
1 change: 1 addition & 0 deletions server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export default {
serviceUrls: {
digitalPrison: get('DPS_HOME_PAGE_URL', 'http://localhost:3001', requiredInProduction),
prisonerProfile: get('PRISONER_PROFILE_URL', 'http://localhost:3001', requiredInProduction),
legacyKeyWorkersUI: get('LEGACY_KEY_WORKERS_UI_URL', 'http://localhost:3001', requiredInProduction),
},
sqs: {
audit: auditConfig(),
Expand Down
2 changes: 1 addition & 1 deletion server/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module.exports = {
'.*.cy.ts',
],
testMatch: ['<rootDir>/(server|job)/**/?(*.)(test).{ts,js,jsx,mjs}'],
testPathIgnorePatterns: ['<rootDir>/server/routes/journeys', '<rootDir>/server/routes/csip-records', 'node_modules'],
testPathIgnorePatterns: ['<rootDir>/server/routes/journeys', 'node_modules'],
testEnvironment: 'node',
rootDir: '../',
moduleFileExtensions: ['web.js', 'js', 'json', 'node', 'ts'],
Expand Down
Loading

0 comments on commit 4479328

Please sign in to comment.