5 Commits
Author SHA1 Message Date
Robert Bond 4cbc674788 Merged PR 2068: Set portal to readonly
Related work items: #21227
2026-01-30 10:24:07 +00:00
robbond 46bc5d1006 pass showlogin vars to pages and components 2026-01-28 13:31:19 +00:00
robbond b790facf56 redirect login attempts to status page 2026-01-28 13:30:27 +00:00
robbond c8f43710d3 service banner annpouncement and display logic 2026-01-28 13:30:05 +00:00
robbond c40d2df1e9 announcement page 2026-01-28 13:29:26 +00:00
474 changed files with 26018 additions and 67030 deletions
-176
View File
@@ -1,176 +0,0 @@
# Contributing with AI (Refactor Branch — PEDW FrontEnd)
## Purpose
This guide defines how engineers and AI agents should work safely and efficiently in this refactor branch.
This branch focuses on **safe, behaviour-preserving refactor of the new appeal flow**.
---
## Start Here (Required Order)
1. Read `.clinerules/refactor-branch-rules.md`
2. Read `GUARDRAILS.md`
3. Read core context:
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
- `context/architecture.md`
- `context/domain-flows.md`
Only read additional files when directly relevant.
Do **not** load all context, templates, or memory-bank files by default.
---
## Core Principle
This is a **refactor branch**, not a feature branch.
- Preserve current live S78 behaviour
- Do not introduce business-rule changes unless explicitly requested
- Prefer small, safe, reversible changes
- Focus on structure, not behaviour
---
## Standard AI-Assisted Workflow
### 1. Scope
- Define requirement
- Confirm non-goals
- Identify impacted flow areas
- Identify risk level
### 2. Plan
- Keep plan small and incremental
- Identify safe boundaries
- Avoid mixing refactor + feature work
### 3. Implement
- Make the smallest viable change
- Prefer extraction over rewrite
- Preserve interfaces and payload shapes
### 4. Validate
Minimum required:
- `npm run lint`
- targeted manual checks
- EN/CY parity checks (if user-facing)
- negative-path checks for sensitive flows
### 5. Document (only when needed)
- update `memory-bank/change-log.md` for non-trivial work
- record decisions or pitfalls if useful
---
## Templates (Use Only When Needed)
Templates are optional tools, not default context.
Use **only one** template if needed:
- feature implementation
- bug fix
- refactor
- debugging
- code review
Do not load all templates.
Do not treat templates as baseline context.
---
## Context Loading Rule (Critical)
Always use the **minimum required context**.
### Default context for this branch:
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
- `context/architecture.md`
- `context/domain-flows.md`
### Only load additional files when:
- working with integrations → `integration-map.md`
- reviewing test gaps → `test-coverage-map.md`
- performing release work → `runbook.md`
- working on specific planned sequence → `context/plans/*`
Never load:
- all context files
- all templates
- onboarding or overview docs
---
## Branching Protocol
This repository currently uses different branch rules depending on the work type.
### For BAU / normal delivery work
- create work branches from `SIPS-Development`
### For new appeal refactor work
- use the `refactor` branch as the base branch
- do refactor implementation either:
- directly on `refactor`, if that is the agreed working model, or
- on a short-lived feature branch created from `refactor`
Do not perform refactor implementation directly on `SIPS-Development`.
If unsure which branch model applies, stop and confirm before making changes.
---
## No-Break Rules (Always Enforce)
- Do not weaken auth/session behaviour
- Do not weaken security headers/CSP
- Keep EN/CY behaviour aligned
- Do not expose secrets or personal data
- Protect save/resume/upload/submit journeys
---
## PR Minimum (AI-Assisted)
Every change must include:
- Scope summary
- Files changed
- Risk notes (auth/data/i18n/a11y)
- Validation evidence
- Rollback plan
---
## Handling Unknowns
If unsure:
1. Choose the safer option
2. Do not change behaviour
3. call out assumptions clearly
4. log open questions if needed
---
## Summary Rule
If in doubt:
> Preserve behaviour, reduce risk, keep changes small.
-95
View File
@@ -1,95 +0,0 @@
# Default Rules (Reference Only)
## Important
This file is **not the active rule set for this refactor branch**.
Active working rules are defined in:
- `.clinerules/refactor-branch-rules.md`
- `context/refactor-branch-charter.md`
- `context/newappeal-refactor-guardrails.md`
Do not load this file by default.
---
## Purpose
This file provides general repository-wide guidance and may be referenced when needed for broader context.
---
## Repository Mission
Deliver safe, accessible, bilingual (EN/CY), and reliable public-service functionality without regressing core journeys.
---
## General Priorities
1. Safety and security of user data
2. Stability of public-facing journeys
3. Accessibility and bilingual parity
4. Maintainability of code
5. Controlled, safe delivery
---
## General Coding Guidance
- Follow existing repo patterns
- Keep page-level logic thin
- Move reusable logic into `components/`, `actions/`, or `lib/`
- Avoid broad refactors in feature or bugfix work
- Prefer small, focused changes
---
## Architecture Guardrails (General)
- Do not bypass auth/session handling
- Do not weaken security controls
- Preserve relay request integrity
- Maintain EN/CY route parity
- Keep Redux hydration/persistence stable
---
## Validation Expectations (General)
- linting must pass
- user-facing changes must be verified
- accessibility and EN/CY checks required
- sensitive flows require negative-path checks
---
## When To Use This File
Only reference this file when:
- broader repository rules are required
- behaviour conflicts are unclear
- no branch-specific guidance exists
---
## Summary
This file is background guidance only.
For this refactor branch:
- follow branch-specific rules first
- prioritise behaviour preservation
- keep context minimal and focused
## Branching Guidance (Reference)
Branching depends on work type:
- BAU work typically branches from `SIPS-Development`
- refactor-stream work for the new appeal flow uses `refactor` as the base branch
Follow branch-specific rules first.
-234
View File
@@ -1,234 +0,0 @@
# Refactor Branch Rules (Active)
## Purpose
This file defines the active working rules for the **refactor branch**.
This branch is focused on **safe, behaviour-preserving refactor of portal journeys**, including:
- New Appeal Flow (completed baseline)
- Representations Flow (active refactor stream)
---
## Core Rule (Highest Priority)
Do not change live behaviour unless explicitly instructed.
Refactor = improve structure, not behaviour.
---
## Primary Objectives
1. Make core portal journeys easier to understand and maintain
2. Reduce risk when making future changes
3. Improve separation of concerns (UI, workflow, data, integrations)
4. Prepare flows for future extensibility (e.g. multiple appeal types, additional journey types)
---
## Active Refactor Streams
### Completed
- New Appeal Flow (S78)
### Active
- Representations Flow
Each stream must follow **slice-based, behaviour-preserving refactor discipline**.
---
## Non-Negotiable Rules
- Preserve all current user journeys:
### Appeals
- start appeal
- save and exit
- resume appeal
- upload documents
- check answers
- submit appeal
- confirmation
### Representations
- start from case summary CTA
- select capacity
- select representation type
- enter content / upload files
- check answers
- submit representation
- completion
---
Do not:
- change payload structures
- change validation rules
- change business logic
- change route/query behaviour
- change navigation or side-effect sequencing
- introduce EN/CY drift
- mix refactor with feature work
---
## Refactor Approach
Always:
1. Understand current behaviour first
2. Identify smallest safe change
3. Prefer extraction over rewrite
4. Keep public interfaces stable
5. Make changes easy to review and revert
---
## Change Size Guidance
- Prefer small PRs (<400 LOC where possible)
- Avoid large multi-concern changes
- Split work into safe slices
- One slice = one branch = one commit
---
## Branch Model (Critical)
### Branch Roles
- `SIPS-Development`
- BAU branch
- ongoing feature and bugfix work
- must remain stable
- `refactor`
- integration branch for refactor work
- all refactor slices merge here first
- feature branches (short-lived)
- created from `refactor`
- one per slice
- merged back into `refactor`
---
### Flow
SIPS-Development
refactor
feature/slice-x
refactor
↓ (when stable & validated)
SIPS-Development
---
## Context Usage Rules (Critical for Efficiency)
### Default context (only load these):
- `context/refactor-branch-charter.md`
- `context/architecture.md`
- `context/domain-flows.md`
### Only load when needed:
- appeal work → `newappeal-refactor-guardrails.md`
- representation work → `representations-refactor-guardrails.md`
- plans → `context/plans/*`
### Never load by default:
- all context files
- onboarding docs
- all templates
---
## Templates Usage
- Use only ONE template when needed
- Do not load all templates
- Do not treat templates as baseline context
---
## Safety Rules
- Do not weaken authentication or session logic
- Do not weaken security headers or middleware
- Do not expose secrets or personal data
- Preserve EN/CY parity
- Maintain accessibility standards
---
## Regression Safety Rule (Critical)
This is a live system. All refactor work must prove behaviour is unchanged.
Before completing any slice:
### Appeals
- start appeal
- save and exit
- resume
- upload
- check answers
- submit
- confirmation
### Representations
- navigate from case summary → make representation
- complete full journey
- submit successfully
- confirmation shown
Also:
- verify EN/CY parity
- verify no navigation or state regressions
If regression cannot be ruled out:
→ do not proceed
---
## When Unsure
1. Choose the safest option
2. Do not change behaviour
3. Call out assumptions
4. Keep the change minimal
---
## Definition of Success
A successful change:
- preserves behaviour
- reduces complexity
- improves clarity
- is small and safe to merge
- introduces no regression risk
---
## One-Line Rule
> Keep behaviour the same, reduce risk, and make the smallest safe change.
-15
View File
@@ -1,15 +0,0 @@
# Bugfix Workflow
1. Clarify the bug symptoms and expected behavior.
2. Inspect the relevant files and execution path.
3. Identify the most likely root cause.
4. Implement the smallest safe fix.
5. Check for:
- side effects
- regression risk
- validation gaps
- missing error handling
6. Summarize:
- root cause
- fix
- preventive improvements worth noting
-17
View File
@@ -1,17 +0,0 @@
# Code Review Workflow
Review the relevant code or changes for:
- correctness
- edge cases
- data integrity
- security concerns
- performance concerns
- maintainability
- readability
- consistency with repo conventions
Return:
1. key findings
2. impact / severity where useful
3. suggested improvements
4. strengths worth preserving
@@ -1,18 +0,0 @@
# Database Migration Workflow
1. Understand the desired schema or data change.
2. Inspect current data model, queries, and dependent code.
3. Identify:
- forward migration steps
- backward compatibility concerns
- rollback considerations
4. Implement or propose the minimal safe migration path.
5. Review for:
- data integrity
- ordering issues
- application compatibility
- deployment timing risk
6. Summarize:
- schema/data changes
- impacted code paths
- rollout / rollback notes
-17
View File
@@ -1,17 +0,0 @@
# Debugging Workflow
1. Capture the symptom, error, or incorrect behavior.
2. Inspect the relevant path and recent changes.
3. Form the most likely hypotheses.
4. Narrow the cause using the smallest practical evidence checks.
5. Propose or implement the minimal safe fix.
6. Review for:
- hidden assumptions
- unhandled states
- logging or observability gaps
- regression risk
7. Summarize:
- symptom
- cause
- fix
- prevention ideas
@@ -1,10 +0,0 @@
# Documentation Update Workflow
1. Identify what changed in the code or workflow.
2. Inspect the affected docs and support files.
3. Update only the relevant sections.
4. Keep the docs concise, factual, and current.
5. Summarize:
- what changed
- which docs were updated
- anything still uncertain
@@ -1,16 +0,0 @@
# Feature Implementation Workflow
1. Understand the requirement and desired outcome.
2. Inspect the relevant files, patterns, and data flows.
3. Propose a short implementation plan for non-trivial work.
4. Implement the smallest maintainable change that satisfies the requirement.
5. Review for:
- correctness
- edge cases
- error handling
- compatibility with existing behavior
- maintainability
6. Summarize:
- what changed
- why
- any follow-up considerations
-13
View File
@@ -1,13 +0,0 @@
# Planning Workflow
1. Clarify the objective.
2. Inspect the relevant code areas and constraints.
3. Identify implementation options.
4. Compare trade-offs.
5. Recommend the most practical path.
6. Return:
- objective summary
- proposed plan
- risks
- dependencies
- suggested execution order
-16
View File
@@ -1,16 +0,0 @@
# PR Review Workflow
Review the pull request or change set for:
- correctness
- scope discipline
- regression risk
- compatibility impact
- tests or validation gaps
- security and performance concerns
- maintainability
Return:
1. summary of change intent
2. key risks
3. requested changes
4. optional improvements
-16
View File
@@ -1,16 +0,0 @@
# Refactor Workflow
1. Understand the current behavior that must be preserved.
2. Inspect the relevant modules and dependencies.
3. Identify safe refactor boundaries.
4. Propose a scoped plan.
5. Refactor incrementally.
6. Review for:
- preserved behavior
- reduced complexity
- improved readability
- regression risk
7. Summarize:
- what was simplified
- what was preserved
- remaining debt
@@ -1,15 +0,0 @@
# Release Readiness Workflow
1. Review the scope of changes.
2. Check:
- build readiness
- environment assumptions
- configuration changes
- database implications
- CI/CD impact
- rollback expectations
3. Identify release risks and missing checks.
4. Summarize:
- release blockers
- risks
- final recommended checks
+27 -125
View File
@@ -19,7 +19,6 @@ RELAY_ROOT = https://ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net/ar-hc-lz-pe
RELAYURI = "ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net" RELAYURI = "ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net"
RELAYPATH = "ar-hc-lz-pedw-dev-uks-01" RELAYPATH = "ar-hc-lz-pedw-dev-uks-01"
CRMURL = "devcrm2016.llcdt.gov.wales/DVPINS" CRMURL = "devcrm2016.llcdt.gov.wales/DVPINS"
CRMURL_VERSION = "v8.2"
# //New Test # //New Test
CLIENT_ID = d40b9373-96c2-4b04-8bd8-c2a2fe6444c1 CLIENT_ID = d40b9373-96c2-4b04-8bd8-c2a2fe6444c1
@@ -27,24 +26,18 @@ CLIENT_SECRET = 6hT8Q~glL~jloWpGmvXw3UY37QFwjUE0r._jobEM
RELAY_ROOT = https://ar-ns-lz-pedw-test-uks-01.servicebus.windows.net/ar-hc-lz-pedw-test-uks-01/ RELAY_ROOT = https://ar-ns-lz-pedw-test-uks-01.servicebus.windows.net/ar-hc-lz-pedw-test-uks-01/
RELAYURI = "ar-ns-lz-pedw-test-uks-01.servicebus.windows.net" RELAYURI = "ar-ns-lz-pedw-test-uks-01.servicebus.windows.net"
RELAYPATH = "ar-hc-lz-pedw-test-uks-01" RELAYPATH = "ar-hc-lz-pedw-test-uks-01"
# CRMURL = "tscrm2016.llcdt.gov.wales/UATPINS" CRMURL = "tscrm2016.llcdt.gov.wales/UATPINS"
# CRMURL_VERSION = "v8.2"
CRMURL = "ts-pedw.crm11.dynamics.com"
CRMURL_VERSION = "v9.2"
# //New PreProd # # //New PreProd
# CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a # CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a
# CLIENT_SECRET = VWY8Q~9EtRzGXpd8Xs~5OS1fej2IyVJ8JgTMncw3 # CLIENT_SECRET = V288Q~P1lFMvvX9Xnkx2pLixK~GOREH983Owqc1E
# RELAY_ROOT = https://ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-uks-01/ # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-uks-01/
# RELAYURI = "ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net" # RELAYURI = "ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-ppe-uks-01" # RELAYPATH = "ar-hc-lz-pedw-ppe-uks-01"
# # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-ukw-01/ # # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-ukw-01/
# # RELAYURI = "ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net" # # RELAYURI = "ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net"
# # RELAYPATH = "ar-hc-lz-pedw-ppe-ukw-01" # # RELAYPATH = "ar-hc-lz-pedw-ppe-ukw-01"
# # CRMURL = "ppcrm2016.llcdt.gov.wales/PPPINSWales" # CRMURL = "ppcrm2016.llcdt.gov.wales/PPPINSWales"
# # CRMURL_VERSION = "v8.2"
# CRMURL = "wg-pp-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
# //Prod Oauth WGO # //Prod Oauth WGO
@@ -56,77 +49,28 @@ CRMURL_VERSION = "v9.2"
# CRMURL = "crm2016.llc.gov.wales/PEDW" # CRMURL = "crm2016.llc.gov.wales/PEDW"
# //New Prod # //New Prod
# CLIENT_ID = 3e4141a3-1fbd-454e-98f0-7f3a4f14a3cc CLIENT_ID = 3e4141a3-1fbd-454e-98f0-7f3a4f14a3cc
# CLIENT_SECRET = ULC8Q~fZiXm0.teVLlZ_7LjxBOj2vIsWSApu2bAq CLIENT_SECRET = tFk8Q~E.R-HFjROTu1sRKqwb_ONzy05uPYoF6awR
# RELAY_ROOT = https://ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net/ar-hc-lz-pedw-prod-uks-01/ RELAY_ROOT = https://ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net/ar-hc-lz-pedw-prod-uks-01/
# RELAYURI = "ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net" RELAYURI = "ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-prod-uks-01" RELAYPATH = "ar-hc-lz-pedw-prod-uks-01"
# # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-prod-ukw-01/ # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-prod-ukw-01/
# # RELAYURI = "ar-ns-lz-pedw-prod-ukw-01.servicebus.windows.net" # RELAYURI = "ar-ns-lz-pedw-prod-ukw-01.servicebus.windows.net"
# # RELAYPATH = "ar-hc-lz-pedw-prod-ukw-01" # RELAYPATH = "ar-hc-lz-pedw-prod-ukw-01"
# CRMURL = "crm2016.llc.gov.wales/PEDW" CRMURL = "crm2016.llcdt.gov.wales/PEDW"
# CRMURL_VERSION = "v8.2"
# D365 cnr WGO
# CLIENT_ID = 3125ac03-91ac-46a7-a166-0086f0ed90b3
# CLIENT_SECRET = bFq8Q~9VX5Ra3lKnGGIXsB.G6-ZGMx7LqyqXjdr4
# RELAY_ROOT = https://ar-ns-lz-pedw-d365cnr-uks-01.servicebus.windows.net/ar-hc-lz-pedw-d365cnr-uks-01/
# RELAYURI = "ar-ns-lz-pedw-d365cnr-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-d365cnr-uks-01"
# CRMURL = "dv-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
# D365 Dev WGO
# CLIENT_ID = 9b834097-03d7-409b-b038-ecfec31a394a
# CLIENT_SECRET = .Jf8Q~tKMObCJjhh_hy3J5AIctFrBalU4FS~tdxk
# RELAY_ROOT = https://ar-ns-lz-pedw-d365dev-uks-01.servicebus.windows.net/ar-hc-lz-pedw-d365dev-uks-01/
# RELAYURI = "ar-ns-lz-pedw-d365dev-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-d365dev-uks-01"
# CRMURL = "dv-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
# D365 Test WGO
# CLIENT_ID = d40b9373-96c2-4b04-8bd8-c2a2fe6444c1
# CLIENT_SECRET = 6hT8Q~glL~jloWpGmvXw3UY37QFwjUE0r._jobEM
# RELAY_ROOT = https://ar-ns-lz-pedw-d365test-uks-01.servicebus.windows.net/ar-hc-lz-pedw-d365test-uks-01/
# RELAYURI = "ar-ns-lz-pedw-d365test-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-d365test-uks-01"
# CRMURL = "ts-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
# D365 PP WGO
# CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a
# CLIENT_SECRET = V288Q~P1lFMvvX9Xnkx2pLixK~GOREH983Owqc1E
# RELAY_ROOT = https://ar-ns-lz-pedw-d365ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-d365ppe-uks-01/
# RELAYURI = "ar-ns-lz-pedw-d365ppe-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-d365ppe-uks-01"
# CRMURL = "wg-pp-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
# D365 Prod WGO
# CLIENT_ID = 3e4141a3-1fbd-454e-98f0-7f3a4f14a3cc
# CLIENT_SECRET = ULC8Q~fZiXm0.teVLlZ_7LjxBOj2vIsWSApu2bAq
# RELAY_ROOT = https://ar-ns-lz-pedw-d365prod-uks-01.servicebus.windows.net/ar-hc-lz-pedw-d365prod-uks-01/
# RELAYURI = "ar-ns-lz-pedw-d365prod-uks-01.servicebus.windows.net"
# RELAYPATH = "ar-hc-lz-pedw-d365prod-uks-01"
# CRMURL = "wg-prod-pedw.crm11.dynamics.com"
# CRMURL_VERSION = "v9.2"
//GOOGLE_TAG_MANAGER = GTM-T78CBC3 //GOOGLE_TAG_MANAGER = GTM-T78CBC3
GOOGLE_TAG_MANAGER = G-GTWW3JT03Z GOOGLE_TAG_MANAGER = G-GTWW3JT03Z
SHOWLOGIN = true SHOWLOGIN = true
SHOWREPRESENTATIONS = true SHOWREPRESENTATIONS = true
SHOWFILEUPLOAD = "false" SHOWFILEUPLOAD = "false"
SHOWMAPS = true SHOWMAPS = false
API_ROOT = "http://localhost:3000" API_ROOT = "http://localhost:3000"
CY_API_ROOT = "http://cymru.local:3000" CY_API_ROOT = "http://cymru.local:3000"
I18N_DOMAIN = "cymru.local" I18N_DOMAIN = "cymru.local"
# DOCAPI_OFFLINE = "07:00:00,16:00:00" # DOCAPI_OFFLINE = "12:00:00,14:00:00"
DOCAPI_OFFLINE = "01:00:00,04:00:00" DOCAPI_OFFLINE = "02:00:00,04:00:00"
SHOWFILTERDOCS = true SHOWFILTERDOCS = true
@@ -136,14 +80,16 @@ NEXTAUTH_URL_INTERNAL = $API_ROOT
NEXTAUTH_SECRET = SuperSecret NEXTAUTH_SECRET = SuperSecret
// CNR sql server // CNR sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-cnr-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword DATABASE_URL = sqlserver://sql-srv-plt-pedw-cnr-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// dev test sql server // dev test sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-dev-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword # DATABASE_URL = sqlserver://pedw-dev-test-sql-svr.database.windows.net:1433;database=PEDWDev;user=RobBondSQL;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// DATABASE_URL = sqlserver://sql-srv-plt-pedw-dev-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// test sql server // test sql server
DATABASE_URL = sqlserver://sql-srv-plt-pedw-test-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword DATABASE_URL = sqlserver://sql-srv-plt-pedw-test-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// Pre prod sql server // Pre prod sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-ppe-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustservercertificate=true;hostnameincertificate=*.database.windows.net;logintimeout=30;authentication=SqlPassword # DATABASE_URL = sqlserver://sql-srv-plt-pedw-ppe-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustservercertificate=true;hostnameincertificate=*.database.windows.net;logintimeout=30;authentication=SqlPassword
@@ -151,24 +97,7 @@ NEXTAUTH_SECRET = SuperSecret
# DATABASE_URL = sqlserver://pp-pedw-sql.database.windows.net:1433;database=PEDWPreProd;user=RobBondSQL;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword # DATABASE_URL = sqlserver://pp-pedw-sql.database.windows.net:1433;database=PEDWPreProd;user=RobBondSQL;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// Prod sql server // Prod sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-prod-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword DATABASE_URL = sqlserver://sql-srv-plt-pedw-prod-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// D365 CNR sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-d365cnr-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// D365 Dev sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-d365dev-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// D365 Test sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-d365test-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// D365 PPE sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-d365ppe-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
// D365 Prod sql server
# DATABASE_URL = sqlserver://sql-srv-plt-pedw-d365prod-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword
SECRET = SuperSecret SECRET = SuperSecret
@@ -191,7 +120,6 @@ AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwdevuks.blob.core.windows.net
// New test key // New test key
AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwtestuks" AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwtestuks"
# AZURE_STORAGE_ACCOUNT_KEY = 5NdDO9GGlbTFLHFOXZRw8H2C0Ow5bFTvHwUHEbStyzg2mbd1uwHSeBSvM/dkN+HfdwrFzqAkwL5P+AStdO6cig==
AZURE_STORAGE_ACCOUNT_KEY = bqJAz5pYQVGee8dnVhlsqW+xHwinNTjgY2AmojNyB+d4uAotMR20WcO4Op13yB+9dFaXAkkjtIA4+AStHT/IYg== AZURE_STORAGE_ACCOUNT_KEY = bqJAz5pYQVGee8dnVhlsqW+xHwinNTjgY2AmojNyB+d4uAotMR20WcO4Op13yB+9dFaXAkkjtIA4+AStHT/IYg==
AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwtestuks.blob.core.windows.net AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwtestuks.blob.core.windows.net
@@ -201,40 +129,15 @@ AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwtestuks.blob.core.windows.net
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwppeuks.blob.core.windows.net # AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwppeuks.blob.core.windows.net
# PROD key // PROD key
# AZURE_STORAGE_ACCOUNT_NAME = "pedwprod" # AZURE_STORAGE_ACCOUNT_NAME = "pedwprod"
# AZURE_STORAGE_ACCOUNT_KEY = koZ46STRqapSa2Dod8MLL6aju1eYLhhyJ6DXpCLMTnFLJvbDT6CHUv/jwr5U/Ta8a60MWzwToHQy+AStADO7sg== # AZURE_STORAGE_ACCOUNT_KEY = koZ46STRqapSa2Dod8MLL6aju1eYLhhyJ6DXpCLMTnFLJvbDT6CHUv/jwr5U/Ta8a60MWzwToHQy+AStADO7sg==
# AZURE_PEDW_STORAGE_ENDPOINT = https://pedwprod.blob.core.windows.net # AZURE_PEDW_STORAGE_ENDPOINT = https://pedwprod.blob.core.windows.net
# New PROD key # // New PROD key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwproduks" AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwproduks"
# AZURE_STORAGE_ACCOUNT_KEY = OfV9MFqXcLLPam9GhEdMWadIOwIzhc5hd5TUqzIuQoswFdtV4ybaemjatSv+Kht0Ny1qQKjLplwY+AStUTZJrg== AZURE_STORAGE_ACCOUNT_KEY = OfV9MFqXcLLPam9GhEdMWadIOwIzhc5hd5TUqzIuQoswFdtV4ybaemjatSv+Kht0Ny1qQKjLplwY+AStUTZJrg==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwproduks.blob.core.windows.net AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwproduks.blob.core.windows.net
# D365 CNR key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwd365cnruks"
# AZURE_STORAGE_ACCOUNT_KEY = nEwCp+4FuVf/9a4DOyKuQO2yRRV4Ypigg20ch1YaiL09YmEhWMEO5pNLpYtI3WnQCkIqeu1CUqwM+AStCLW01g==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwd365cnruks.blob.core.windows.net
# D365 DEV key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwd365devuks"
# AZURE_STORAGE_ACCOUNT_KEY = XzwQxuZXSwYrVgemDUD2ymTpYTIfWqhypbmEALw1ZEEP0M4D3b3Gh28clSymxwFu7Gu9mhwkW4/V+AStZ6RF8Q==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwd365devuks.blob.core.windows.net
# D365 TEST key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwd365testuks"
# AZURE_STORAGE_ACCOUNT_KEY = 5NdDO9GGlbTFLHFOXZRw8H2C0Ow5bFTvHwUHEbStyzg2mbd1uwHSeBSvM/dkN+HfdwrFzqAkwL5P+AStdO6cig==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwd365testuks.blob.core.windows.net
# D365 PP key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwd365ppeuks"
# AZURE_STORAGE_ACCOUNT_KEY = xQz4FWDnQDE09uPOCj1t7axRiquvZG9vbxL88ywzVsJnTsAgewrHnuAGkxGPBCp2xGE53ffYOme6+AStSr8OoQ==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwd365ppeuks.blob.core.windows.net
# D365 Prod key
# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwd365produks"
# AZURE_STORAGE_ACCOUNT_KEY = DvKcWhDpFKMFdVXFF2SqDG0sYQ3AkNCmJUBG0cvgzi5NBHS4Ahd2hPAlfA3hGi2EbohUag3vCucK+ASt1IdBhA==
# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwd365produks.blob.core.windows.net
AZURE_PEDW_CONTAINER = "pedwapplications" AZURE_PEDW_CONTAINER = "pedwapplications"
@@ -255,7 +158,7 @@ APPLICATIONINSIGHTS_CONNECTIONSTRING = InstrumentationKey=7a06e24a-793c-47bc-898
// Test Connection string // Test Connection string
NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=cc60e8e7-5b30-4c2b-a176-8b96b21b12df;IngestionEndpoint=https://ukwest-0.in.applicationinsights.azure.com/;LiveEndpoint=https://ukwest.livediagnostics.monitor.azure.com/;ApplicationId=2a4094be-6fd1-46ab-a67d-5f241692b129 //NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=cc60e8e7-5b30-4c2b-a176-8b96b21b12df;IngestionEndpoint=https://ukwest-0.in.applicationinsights.azure.com/;LiveEndpoint=https://ukwest.livediagnostics.monitor.azure.com/;ApplicationId=2a4094be-6fd1-46ab-a67d-5f241692b129
// Preprod Connection string // Preprod Connection string
//NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=7370f0f9-834d-4c7a-b3c4-9951fcad5ad2;IngestionEndpoint=https://ukwest-0.in.applicationinsights.azure.com/;LiveEndpoint=https://ukwest.livediagnostics.monitor.azure.com/;ApplicationId=04362cb7-6dfc-469e-8274-12243e8be851 //NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=7370f0f9-834d-4c7a-b3c4-9951fcad5ad2;IngestionEndpoint=https://ukwest-0.in.applicationinsights.azure.com/;LiveEndpoint=https://ukwest.livediagnostics.monitor.azure.com/;ApplicationId=04362cb7-6dfc-469e-8274-12243e8be851
@@ -271,4 +174,3 @@ HIDEERRORLOGS = false
SHOWSIPS = true SHOWSIPS = true
ALLOWED_IPS=::1,203.0.113.42,198.51.100.17 ALLOWED_IPS=::1,203.0.113.42,198.51.100.17
UPLOAD_BATCH_COUNT = 5
-8
View File
@@ -48,11 +48,3 @@ gitclean.sh
pages/admin/logcheck.js pages/admin/logcheck.js
pages/admin/logchecker.js pages/admin/logchecker.js
pages/baracuda.html pages/baracuda.html
pages/holding-min.html
pages/holding.html
# Cline / AI-assistant governance artifacts (keep local-only)
ai-prompts/
pages/baracuda.min.html
+1 -2
View File
@@ -1,6 +1,5 @@
{ {
"tabWidth": 4, "tabWidth": 4,
"useTabs": false, "useTabs": false,
"quoteProps": "preserve", "quoteProps":"preserve"
"trailingComma": "none"
} }
+1 -1
View File
@@ -11,7 +11,7 @@
"command": "npm run dev" "command": "npm run dev"
}, },
{"name": "Launch Chrome against localhost", {"name": "Launch Chrome against localhost",
"type": "chrome", "type": "pwa-chrome",
"request": "launch", "request": "launch",
"url": "http://localhost:3000", "url": "http://localhost:3000",
"webRoot": "${workspaceFolder}" "webRoot": "${workspaceFolder}"
-46
View File
@@ -1,46 +0,0 @@
# AI Context — PEDW FrontEnd
## Overview
PEDW FrontEnd is a Next.js 14 (Pages Router) bilingual (EN/CY) public-service portal for planning case search, case detail/document viewing, and authenticated portal workflows (appeals, representations, watchlists, dashboard views).
## Architecture
- Monorepo-style Next.js app with UI routes in `pages/` and API handlers in `pages/api/**`.
- Redux (`next-redux-wrapper` + `redux-persist`) for shared client/server state.
- `next-auth` for auth/session with Prisma adapter.
- Integration-heavy BFF pattern: API routes proxy to relay/CRM and storage/notify services.
## Key components
- `components/breadcrumbs.js`: central breadcrumb/back-link behavior.
- `components/case/summary.js`: case-detail tabs, representation eligibility logic, watch/email actions.
- `actions/index.js`: shared API utilities, token/header/hash helpers, many side-effect wrappers.
- `pages/api/endpoint/**`: relay-backed business-data APIs.
- `pages/api/file/**`: blob/document/PDF/upload endpoints.
## Data model boundaries
- Prisma (`prisma/schema.prisma`) stores auth/session entities only (`User`, `Account`, `Session`, `VerificationToken`) on SQL Server.
- Business/case data is external (Dynamics/relay path), not persisted as Prisma domain models here.
## API/integration patterns
- Many endpoint handlers compute HMAC hash query params (`hash`) for relay-bound requests.
- Token acquisition + OData headers are reused across proxy handlers.
- File endpoints often validate request hash for sensitive blob actions.
- GOV.UK Notify used for email, including language-specific template selection in some flows.
## Infrastructure/tooling
- Scripts: `npm run dev`, `npm run build`, `npm start`, `npm run lint`.
- CI/CD artifacts present: `azure-pipelines.yml`, `Jenkinsfile`, `Dockerfile` (active production source-of-truth not explicit in repo).
- Security controls: `middleware.js` CSP/runtime headers + `next.config.js` security headers.
## Development constraints
- Preserve auth/session behavior in `pages/api/auth/[...nextauth].js`.
- Do not weaken CSP/security headers in `middleware.js` or `next.config.js`.
- Keep EN/CY parity across routes and locale resources (`i18n.js`, `locales/**`, rewrites).
- Treat relay hash behavior as security-sensitive; keep path/hash compatibility stable.
- Avoid logging secrets/personal data in auth/email/file/account flows.
-25
View File
@@ -1,25 +0,0 @@
# Use official Node.js 20 LTS image
FROM node:20-alpine
# Set working directory
WORKDIR /app
# Install dependencies first (better caching)
COPY package*.json ./
RUN npm ci --production
# Copy source files (including .next build output if pre-built)
COPY . .
# If you want to build inside container, uncomment:
# RUN npm run build
# Use non-root user (optional, but recommended)
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# Expose port your app listens on
EXPOSE 3000
# Start your Next.js app (adjust if using custom server)
CMD ["npm", "start"]
-83
View File
@@ -1,83 +0,0 @@
# PEDW FrontEnd Guardrails
## Purpose
This document is a fast pre-flight checklist to reduce regressions in high-risk areas. Use it before coding, before opening a PR, and before merge.
## Non-Negotiable Guardrails
1. **Auth/session integrity**
- Do not bypass `next-auth` flow in `pages/api/auth/[...nextauth].js`.
- Preserve secure redirect behavior and cookie/session settings.
2. **Security headers and CSP**
- Do not weaken `middleware.js` CSP/header behavior or `next.config.js` security headers without explicit rationale.
3. **Data model safety**
- Treat `prisma/schema.prisma` as source-of-truth for auth/account persistence.
4. **Bilingual parity (EN/CY)**
- Any user-facing route/content change must validate both locales.
- Keep `i18n.js`, `locales/`, and `next.config.js` rewrites aligned.
5. **Public-service reliability**
- Avoid breaking core flows: search, case, account, myportal, admin.
## Sensitive Flow Protection
Apply extra checks for:
- `pages/api/auth/**`
- `pages/api/file/**`
- `pages/api/email/**`
- `pages/api/endpoint/*_api.js` handling account/user data
## Relay Hash Integrity Rules (CRM-bound APIs)
Apply when changing relay-bound portal endpoints and helpers (notably `pages/api/endpoint/**` and `actions/index.js`):
1. Keep relay endpoint configuration sourced from `API_ROOT`.
2. Preserve path-hash generation behavior:
- hash input must be request path/query (excluding domain),
- appended hash parameter must remain compatible with relay expectations.
3. Do not change hash algorithm/key usage contract without coordinated relay change.
4. Treat hash validation failures as security-relevant negative paths; verify graceful rejection handling.
5. Never log hash key material or sensitive request payloads.
Required for sensitive changes:
- Negative-path validation (unauthorized, invalid input, malformed payload).
- Safe logging (no secrets/tokens/personal data in cleartext).
- Explicit rollback steps.
## Relay Policy Change Guardrail (timeouts/retries/logging)
When changing shared relay forwarding policy (for example in `pages/api/middleware/relayForwarding.js`), treat this as an operationally sensitive change even if endpoint contracts are unchanged.
Minimum required before merge:
1. Complete the relay governance gate in `context/runbook.md` (Relay Hardening Rollout Playbook).
2. Attach non-prod smoke evidence for:
- deterministic non-retry classes (`400`, `401`, `403`, `404`)
- transient retry classes (`429`, `503`, timeout/network-transient)
3. Confirm structured redacted logging and duplicate-log suppression behavior.
4. Provide fast mitigation + rollback path (`RELAY_RETRY_MAX=0` and commit-revert path).
## Pre-PR Quick Checklist
- [ ] Ran `npm run lint` (or documented why unavailable)
- [ ] Verified changed routes/APIs manually
- [ ] Verified EN + CY behavior for impacted user-facing flow
- [ ] Performed accessibility smoke checks (keyboard, focus, labels, headings)
- [ ] Added risk notes (auth/data/i18n/a11y)
- [ ] Updated `memory-bank/change-log.md` for non-trivial changes
## If Assumptions Are Unclear
1. Record assumptions in PR notes.
2. Add unresolved items to `memory-bank/open-questions.md`.
3. Choose the safer behavior and clearly mark as temporary.
## Related Docs
- `.clinerules`
- `CONTRIBUTING_AI.md`
- `context/runbook.md`
- `context/integration-map.md`
- `memory-bank/README.md`
Vendored
-50
View File
@@ -1,50 +0,0 @@
pipeline {
agent {
docker {
image 'node:20' // ✅ Node.js 20 with npm included
}
}
environment {
IMAGE = "pedw-app"
}
stages {
stage('Install & Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Build Docker Image') {
steps {
sh "docker build -t $REGISTRY/$IMAGE:latest ."
}
}
stage('Push Docker Image') {
steps {
withCredentials([usernamePassword(credentialsId: 'dockerhub-credentials', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
sh "echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin"
sh "docker push $REGISTRY/$IMAGE:latest"
}
}
}
stage('Deploy to Plesk') {
steps {
sshagent(['plesk-ssh-key']) {
sh """
ssh root@your-plesk-domain.com '
docker pull $REGISTRY/$IMAGE:latest &&
docker stop nextjs-app || true &&
docker rm nextjs-app || true &&
docker run -d --restart=always --name nextjs-app -p 3000:3000 $REGISTRY/$IMAGE:latest
'
"""
}
}
}
}
}
+182 -241
View File
@@ -11,7 +11,7 @@ const {
ContainerSASPermissions, ContainerSASPermissions,
generateBlobSASQueryParameters, generateBlobSASQueryParameters,
SASProtocol SASProtocol,
} = require("@azure/storage-blob"); } = require("@azure/storage-blob");
const { const {
QueueServiceClient, QueueServiceClient,
@@ -23,7 +23,7 @@ const {
generateAccountSASQueryParameters, generateAccountSASQueryParameters,
generateQueueSASQueryParameters, generateQueueSASQueryParameters,
StorageSharedKeyCredential, StorageSharedKeyCredential,
QueueClient QueueClient,
} = require("@azure/storage-queue"); } = require("@azure/storage-queue");
const STORAGE_PATH = process.env.AZURE_PEDW_STORAGE_ENDPOINT; const STORAGE_PATH = process.env.AZURE_PEDW_STORAGE_ENDPOINT;
const STORAGE_CONTAINER = process.env.AZURE_PEDW_CONTAINER; const STORAGE_CONTAINER = process.env.AZURE_PEDW_CONTAINER;
@@ -31,88 +31,6 @@ const QUEUE_PATH = process.env.AZURE_PEDW_QUEUE_ENDPOINT;
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME; const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const buildDownloadBlobQueryPath = ({
containerName,
casefolderID,
blobname,
encodeCasefolderID = true,
encodeBlobname = true
}) => {
const casefolderPart = encodeCasefolderID
? encodeURIComponent(casefolderID)
: casefolderID;
const blobPart = encodeBlobname ? encodeURIComponent(blobname) : blobname;
return (
"/api/file/downloadblob?container=" +
containerName +
"&casefolderID=" +
casefolderPart +
"&blobname=" +
blobPart
);
};
const buildDeleteBlobQueryPath = ({
containerName,
casefolderID,
blobname,
encodeCasefolderID = true,
encodeBlobname = true
}) => {
const casefolderPart = encodeCasefolderID
? encodeURIComponent(casefolderID)
: casefolderID;
const blobPart = encodeBlobname ? encodeURIComponent(blobname) : blobname;
return (
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
casefolderPart +
"&blobname=" +
blobPart
);
};
const buildGetBlobListQueryPath = ({ containerName, casefolderID }) => {
return (
"/api/file/getbloblist?container=" +
containerName +
"&casefolderID=" +
casefolderID
);
};
const buildCaseObjectPath = (casefolderID) => {
return casefolderID + "/" + casefolderID + "_case.json";
};
const buildHashMetadataPaths = ({ containerName, casefolderID, blobname }) => {
return {
"hashedfilepath": hashAPIPath(
buildDownloadBlobQueryPath({
containerName,
casefolderID,
blobname
})
),
"hasheddeletepath": hashAPIPath(
buildDeleteBlobQueryPath({
containerName,
casefolderID,
blobname
})
),
"hashgetblobs": hashAPIPath(
buildGetBlobListQueryPath({
containerName,
casefolderID
})
)
};
};
export const createContainerSas = async (containerName) => { export const createContainerSas = async (containerName) => {
// Get environment variables // Get environment variables
@@ -149,7 +67,7 @@ export const createContainerSas = async (containerName) => {
permissions: ContainerSASPermissions.parse(containerPermissions), permissions: ContainerSASPermissions.parse(containerPermissions),
protocol: SASProtocol.HttpsAndHttp, protocol: SASProtocol.HttpsAndHttp,
startsOn: TEN_MINUTES_BEFORE_NOW, startsOn: TEN_MINUTES_BEFORE_NOW,
expiresOn: TEN_MINUTES_AFTER_NOW expiresOn: TEN_MINUTES_AFTER_NOW,
}; };
// console.log( // console.log(
@@ -208,7 +126,7 @@ export const createBlobSas = async (containerName, blobName) => {
permissions: BlobSASPermissions.parse(blobPermissionsForAnonymousUser), permissions: BlobSASPermissions.parse(blobPermissionsForAnonymousUser),
protocol: SASProtocol.HttpsAndHttp, protocol: SASProtocol.HttpsAndHttp,
startsOn: TEN_MINUTES_BEFORE_NOW, startsOn: TEN_MINUTES_BEFORE_NOW,
expiresOn: TEN_MINUTES_AFTER_NOW expiresOn: TEN_MINUTES_AFTER_NOW,
}; };
const sasToken = generateBlobSASQueryParameters( const sasToken = generateBlobSASQueryParameters(
@@ -269,38 +187,61 @@ export const getBlobs = async (containerName, casefolderID) => {
const blobObj = []; const blobObj = [];
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: casefolderID + "/files/" prefix: casefolderID + "/files/",
})) { })) {
const blobPathParts = blob.name.split("/"); let blobDocumentType = blob.name
const fileName = blobPathParts[2]; .split("/")[2]
const contentLength = blob.properties.contentLength; .slice(0, blob.name.split("/")[2].indexOf("_"));
blobObj.push({ blobObj.push({
"name": fileName, "name": blob.name.split("/")[2],
"path": blob.name, "path": blob.name,
"documentType": getDocumentTypeFromFilename(fileName), "documentType": getDocumentTypeFromFilename(
blob.name.split("/")[2]
),
"versionId": blob.versionId, "versionId": blob.versionId,
"caseObj": buildCaseObjectPath(casefolderID), "caseObj": casefolderID + "/" + casefolderID + "_case.json",
"isCurrentVersion": blob.isCurrentVersion, "isCurrentVersion": blob.isCurrentVersion,
"contentLength": contentLength, "contentLength": blob.properties.contentLength,
"size": contentLength, "size": blob.properties.contentLength,
"contentType": blob.contentType, "contentType": blob.contentType,
"lastModified": blob.properties.lastModified, "lastModified": blob.properties.lastModified,
"filepath": buildDownloadBlobQueryPath({ "filepath":
containerName, "/api/file/downloadblob?container=" +
casefolderID, containerName +
blobname: blob.name "&casefolderID=" +
}), encodeURIComponent(casefolderID) +
...buildHashMetadataPaths({ "&blobname=" +
containerName, encodeURIComponent(blob.name),
casefolderID, "hashedfilepath": hashAPIPath(
blobname: fileName "/api/file/downloadblob?container=" +
}), containerName +
"deletepath": buildDeleteBlobQueryPath({ "&casefolderID=" +
containerName, encodeURIComponent(casefolderID) +
casefolderID, "&blobname=" +
blobname: fileName encodeURIComponent(blob.name.split("/")[2])
}) ),
"deletepath":
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
encodeURIComponent(casefolderID) +
"&blobname=" +
encodeURIComponent(blob.name.split("/")[2]),
"hasheddeletepath": hashAPIPath(
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
encodeURIComponent(casefolderID) +
"&blobname=" +
encodeURIComponent(blob.name.split("/")[2])
),
"hashgetblobs": hashAPIPath(
"/api/file/getbloblist?container=" +
containerName +
"&casefolderID=" +
casefolderID
),
}); });
} }
//console.log("blobObj:", blobObj); //console.log("blobObj:", blobObj);
@@ -336,7 +277,7 @@ export const createBlob = async (formContent, containerName, caseref) => {
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: caseID, caseID: caseID,
blobType: "Appeal" blobType: "Appeal",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -368,8 +309,8 @@ export const createRepBlob = async (formContent, containerName, caseref) => {
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: formContent.ticketnumber || formContent.caseRef, caseID: formContent.ticketnumber,
blobType: "Representation" blobType: "Representation",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -415,14 +356,12 @@ export const createAppealPDFBlob = async (
const uploadOptions = { const uploadOptions = {
blockSize: 4 * 1024 * 1024, // 4 MiB max block size blockSize: 4 * 1024 * 1024, // 4 MiB max block size
concurrency: 2, // maximum number of parallel transfer workers concurrency: 2, // maximum number of parallel transfer workers
maxSingleShotSize: 8 * 1024 * 1024 // 8 MiB initial transfer size maxSingleShotSize: 8 * 1024 * 1024, // 8 MiB initial transfer size
}; };
console.log("blobName:", blobName); console.log("blobName:", blobName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName); const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = Buffer.isBuffer(content) const uploadBlobResponse = await blockBlobClient.uploadStream(content);
? await blockBlobClient.uploadData(content)
: await blockBlobClient.uploadStream(content);
console.log(uploadBlobResponse); console.log(uploadBlobResponse);
let whichLocation = "846040000"; // Default value let whichLocation = "846040000"; // Default value
@@ -432,7 +371,7 @@ export const createAppealPDFBlob = async (
caseID: caseID, caseID: caseID,
blobType: "Appeal PDF", blobType: "Appeal PDF",
ishareLocation: whichLocation, ishareLocation: whichLocation,
documentLocationId: whichLocation documentLocationId: whichLocation,
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -466,15 +405,13 @@ export const createRepPDFBlob = async (
const uploadOptions = { const uploadOptions = {
blockSize: 4 * 1024 * 1024, // 4 MiB max block size blockSize: 4 * 1024 * 1024, // 4 MiB max block size
concurrency: 2, // maximum number of parallel transfer workers concurrency: 2, // maximum number of parallel transfer workers
maxSingleShotSize: 8 * 1024 * 1024 // 8 MiB initial transfer size maxSingleShotSize: 8 * 1024 * 1024, // 8 MiB initial transfer size
}; };
console.log("blobName:", blobName); console.log("blobName:", blobName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName); const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = Buffer.isBuffer(content) const uploadBlobResponse = await blockBlobClient.uploadStream(content);
? await blockBlobClient.uploadData(content)
: await blockBlobClient.uploadStream(content);
let whichLocation = let whichLocation =
repName.indexOf("_IP_") > 0 repName.indexOf("_IP_") > 0
@@ -486,9 +423,7 @@ export const createRepPDFBlob = async (
: repName.indexOf("_Comments") > 0 : repName.indexOf("_Comments") > 0
? "846040003" ? "846040003"
: repName.indexOf("_Impact") > 0 : repName.indexOf("_Impact") > 0
? "846040029" ? "846040001"
: repName.indexOf("_Consultation_Response_") > 0
? "846040036"
: "846040002"; : "846040002";
const tags = { const tags = {
@@ -496,7 +431,7 @@ export const createRepPDFBlob = async (
caseID: caseID, caseID: caseID,
blobType: "Representation PDF", blobType: "Representation PDF",
ishareLocation: whichLocation, ishareLocation: whichLocation,
documentLocationId: whichLocation documentLocationId: whichLocation,
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -510,7 +445,7 @@ export const deleteBlob = async (containerName, blobName) => {
const creds = new DefaultAzureCredential(); const creds = new DefaultAzureCredential();
const options = { const options = {
deleteSnapshots: "include" // or 'only' deleteSnapshots: "include", // or 'only'
}; };
const containerToken = await createContainerSas(containerName); const containerToken = await createContainerSas(containerName);
@@ -530,7 +465,7 @@ export const deleteBlobCase = async (containerName, blobName) => {
const creds = new DefaultAzureCredential(); const creds = new DefaultAzureCredential();
const options = { const options = {
deleteSnapshots: "include" // or 'only' deleteSnapshots: "include", // or 'only'
}; };
const containerToken = await createContainerSas(containerName); const containerToken = await createContainerSas(containerName);
@@ -542,7 +477,7 @@ export const deleteBlobCase = async (containerName, blobName) => {
console.log("blob to delete:", blobName); console.log("blob to delete:", blobName);
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: blobName prefix: blobName,
})) { })) {
console.log(" ------ :", blob.name); console.log(" ------ :", blob.name);
containerClient.deleteBlob(blob.name); containerClient.deleteBlob(blob.name);
@@ -560,7 +495,7 @@ export const deleteBlobRep = async (containerName, blobName) => {
const creds = new DefaultAzureCredential(); const creds = new DefaultAzureCredential();
const options = { const options = {
deleteSnapshots: "include" // or 'only' deleteSnapshots: "include", // or 'only'
}; };
const containerToken = await createContainerSas(containerName); const containerToken = await createContainerSas(containerName);
@@ -570,7 +505,7 @@ export const deleteBlobRep = async (containerName, blobName) => {
console.log("blob to delete:", blobName); console.log("blob to delete:", blobName);
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: blobName prefix: blobName,
})) { })) {
console.log("------ :", blob.name); console.log("------ :", blob.name);
const blockBlobClient = containerClient.getBlockBlobClient(blob.name); const blockBlobClient = containerClient.getBlockBlobClient(blob.name);
@@ -668,20 +603,13 @@ export const uploadFile = async (formContent, containerName, foldername) => {
? "846040005" ? "846040005"
: files[prop][0].fieldName.indexOf("_Statement_") > 0 : files[prop][0].fieldName.indexOf("_Statement_") > 0
? "846040002" ? "846040002"
: files[prop][0].fieldName.indexOf( : files[prop][0].fieldName.indexOf("_Questionnaire_") >
"_Questionnaire_"
) > 0
? "846040001"
: files[prop][0].fieldName.indexOf("_Comments_") >
0 0
? "846040001"
: files[prop][0].fieldName.indexOf("_Comments_") > 0
? "846040003" ? "846040003"
: files[prop][0].fieldName.indexOf("_Impact_") > : files[prop][0].fieldName.indexOf("_Impact_") > 0
0
? "846040001" ? "846040001"
: files[prop][0].fieldName.indexOf(
"_Consultation_Response_"
) > 0
? "846040036"
: "846040000"; : "846040000";
const tags = { const tags = {
@@ -690,7 +618,7 @@ export const uploadFile = async (formContent, containerName, foldername) => {
documentType: files[prop][0].fieldName.split(".")[1], documentType: files[prop][0].fieldName.split(".")[1],
blobType: "RepresentationFile", blobType: "RepresentationFile",
ishareLocation: whichLocation, ishareLocation: whichLocation,
documentLocationId: whichLocation documentLocationId: whichLocation,
}; };
const withTags = blockBlobClient.setTags(tags); const withTags = blockBlobClient.setTags(tags);
const withMeta = blockBlobClient.setMetadata(tags); const withMeta = blockBlobClient.setMetadata(tags);
@@ -801,14 +729,13 @@ export const uploadSingleFile = async (
{ {
pattern: pattern:
/_Statement_of_Case|_-_Statement_of_Case|_-_Application_Form|_-_Site_Ownership_Certificate|_-_Decision_Notice|_-_Site_Location_Plan|_-_Plans_Drawing_Documents|_-_Additional_Plans_Drawings_Documents|_-_Design_and_Access_Statement|_-_NSB_LPA_Additional_Documents|_-_LPA_Correspondence|_-_LPA_Original_Permission|_-_LPA's_Registration_Letter|_-_Environmental_Statement|_-_Cost_of_Application|_-_Other_Relevant_Material|_-_S106_Agreement_or_Unilateral_Undertaking/, /_Statement_of_Case|_-_Statement_of_Case|_-_Application_Form|_-_Site_Ownership_Certificate|_-_Decision_Notice|_-_Site_Location_Plan|_-_Plans_Drawing_Documents|_-_Additional_Plans_Drawings_Documents|_-_Design_and_Access_Statement|_-_NSB_LPA_Additional_Documents|_-_LPA_Correspondence|_-_LPA_Original_Permission|_-_LPA's_Registration_Letter|_-_Environmental_Statement|_-_Cost_of_Application|_-_Other_Relevant_Material|_-_S106_Agreement_or_Unilateral_Undertaking/,
value: "846040000" value: "846040000",
}, },
{ pattern: /_IP_/, value: "846040005" }, { pattern: /_IP_/, value: "846040005" },
{ pattern: /_Statement_/, value: "846040002" }, { pattern: /_Statement_/, value: "846040002" },
{ pattern: /_Questionnaire_/, value: "846040001" }, { pattern: /_Questionnaire_/, value: "846040001" },
{ pattern: /_Comments_/, value: "846040003" }, { pattern: /_Comments_/, value: "846040003" },
{ pattern: /_Impact_/, value: "846040001" }, { pattern: /_Impact_/, value: "846040001" },
{ pattern: /_Consultation_Response_/, value: "846040036" }
]; ];
// Find a matching pattern or fallback to default // Find a matching pattern or fallback to default
@@ -829,7 +756,7 @@ export const uploadSingleFile = async (
documentType: files[prop][0].fieldName.split(".")[1], documentType: files[prop][0].fieldName.split(".")[1],
blobType: "RepresentationFile", blobType: "RepresentationFile",
ishareLocation: whichLocation, ishareLocation: whichLocation,
documentLocationId: whichLocation documentLocationId: whichLocation,
}; };
const withTags = await blockBlobClient.setTags(tags); const withTags = await blockBlobClient.setTags(tags);
const withMeta = await blockBlobClient.setMetadata(tags); const withMeta = await blockBlobClient.setMetadata(tags);
@@ -866,7 +793,7 @@ export const uploadRepFiles = async (
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: formContent.split("tmp/")[0], caseID: formContent.split("tmp/")[0],
documentType: "Rep docs" documentType: "Rep docs",
}; };
console.log(tags); console.log(tags);
const withTags = await blockBlobClient.setTags(tags); const withTags = await blockBlobClient.setTags(tags);
@@ -911,7 +838,7 @@ export const uploadPDFRepFiles = async (
containerid: containerName, containerid: containerName,
caseID: foldername.split("/")[0], caseID: foldername.split("/")[0],
documentType: repType, documentType: repType,
blobType: "RepresentationPDF" blobType: "RepresentationPDF",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -964,7 +891,7 @@ export const uploadPDFAppealFiles = async (
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: foldername.split("/")[0], caseID: foldername.split("/")[0],
blobType: "AppealPDF" blobType: "AppealPDF",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -1003,7 +930,7 @@ export const uploadPDFCaseFiles = async (
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: foldername.split("/")[0], caseID: foldername.split("/")[0],
blobType: "AppealPDF" blobType: "AppealPDF",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -1209,7 +1136,7 @@ export const downloadAllRepsFiles = async (containerName, repsBlobObj) => {
return { return {
"@odata.count": blobCount, "@odata.count": blobCount,
"value": downloaded "value": downloaded,
}; };
}; };
@@ -1248,7 +1175,7 @@ export const getCaseBlob = async (
const tags = { const tags = {
containerid: containerName, containerid: containerName,
caseID: caseReference, caseID: caseReference,
blobType: "Case" blobType: "Case",
}; };
//console.log("the tags:", tags); //console.log("the tags:", tags);
@@ -1279,7 +1206,7 @@ export const getProgressBlobs = async (containerName, caseReference) => {
let blobCount = 0; let blobCount = 0;
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: caseReference prefix: caseReference,
})) { })) {
blobCount++; blobCount++;
} }
@@ -1292,34 +1219,47 @@ export const getProgressBlobs = async (containerName, caseReference) => {
let blobObj = []; let blobObj = [];
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: caseReference + "/" + caseReference + "_appeal.json" prefix: caseReference + "/" + caseReference + "_appeal.json",
})) { })) {
const blobPathParts = blob.name.split("/"); console.log("getProgressBlobs in here", blob.name.split("/"));
const appealBlobName = blobPathParts[1];
const contentLength = blob.properties.contentLength;
//consoleLogger("getProgressBlobs in here", blobPathParts);
blobObj.push({ blobObj.push({
"name": appealBlobName, "name": blob.name.split("/")[1],
"path": blob.name, "path": blob.name,
"versionId": blob.versionId, "versionId": blob.versionId,
"caseObj": buildCaseObjectPath(caseReference), "caseObj": caseReference + "/" + caseReference + "_case.json",
"isCurrentVersion": blob.isCurrentVersion, "isCurrentVersion": blob.isCurrentVersion,
"contentLength": contentLength, "contentLength": blob.properties.contentLength,
"contentType": blob.contentType, "contentType": blob.contentType,
"lastModified": blob.properties.lastModified, "lastModified": blob.properties.lastModified,
...buildHashMetadataPaths({ "hashedfilepath": hashAPIPath(
containerName, "/api/file/downloadblob?container=" +
casefolderID: caseReference, containerName +
blobname: appealBlobName "&casefolderID=" +
}) encodeURIComponent(caseReference) +
"&blobname=" +
encodeURIComponent(blob.name.split("/")[1])
),
"hasheddeletepath": hashAPIPath(
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
encodeURIComponent(caseReference) +
"&blobname=" +
encodeURIComponent(blob.name.split("/")[1])
),
"hashgetblobs": hashAPIPath(
"/api/file/getbloblist?container=" +
containerName +
"&casefolderID=" +
caseReference
),
}); });
} }
blobObj = _.sortBy(blobObj, [ blobObj = _.sortBy(blobObj, [
function (o) { function (o) {
return o.lastModified; return o.lastModified;
} },
]).reverse()[0]; ]).reverse()[0];
return blobObj; return blobObj;
@@ -1338,24 +1278,8 @@ export const getAllProgressBlobs = async (containerName) => {
for await (const blob of containerClient.findBlobsByTags( for await (const blob of containerClient.findBlobsByTags(
"blobType='Appeal'" "blobType='Appeal'"
)) { )) {
const namePart = blob.name.split("/")[1] ?? ""; blob.name.split("/")[1].indexOf("_appeal.json") > 0 &&
blob.name.split("/")[1].indexOf("undefined") < 0 &&
// keep your existing name filters
if (
namePart.indexOf("_appeal.json") <= 0 ||
namePart.indexOf("undefined") >= 0
)
continue;
// existence check (filters out soft-deleted / stale index hits)
const blobClient = containerClient.getBlobClient(blob.name);
try {
await blobClient.getProperties();
} catch (e) {
// errors usually expose statusCode
if (e?.statusCode === 404) continue;
throw e;
}
blobObj.push({ blobObj.push({
"name": blob.name.split("/")[1], "name": blob.name.split("/")[1],
"path": blob.name, "path": blob.name,
@@ -1364,7 +1288,7 @@ export const getAllProgressBlobs = async (containerName) => {
blob.name.split("/")[0] + blob.name.split("/")[0] +
"/" + "/" +
blob.name.split("/")[0] + blob.name.split("/")[0] +
"_case.json" "_case.json",
// "isCurrentVersion": blob.isCurrentVersion, // "isCurrentVersion": blob.isCurrentVersion,
// "contentLength": blob.properties.contentLength, // "contentLength": blob.properties.contentLength,
// "contentType": blob.contentType, // "contentType": blob.contentType,
@@ -1421,7 +1345,7 @@ export const getRepsBlobs = async (containerName) => {
includeMetadata: true, includeMetadata: true,
includeSnapshots: false, includeSnapshots: false,
includeTags: true, includeTags: true,
includeVersions: true includeVersions: true,
}; };
let blobObj = []; let blobObj = [];
@@ -1430,27 +1354,14 @@ export const getRepsBlobs = async (containerName) => {
listOptions listOptions
)) { )) {
const blobClient = containerClient.getBlobClient(blob.name); const blobClient = containerClient.getBlobClient(blob.name);
//console.log("getreps blob:", blob);
// Filter out soft-deleted/stale tag entries and malformed names. blob.name.split("/")[2].indexOf("_rep.json") > 0 &&
const namePart = blob.name.split("/")[2] ?? ""; blob.name.split("/")[2].indexOf("undefined") < 0 &&
if (
namePart.indexOf("_rep.json") <= 0 ||
namePart.indexOf("undefined") >= 0
)
continue;
try {
const properties = await blobClient.getProperties();
blobObj.push({ blobObj.push({
"name": namePart, "name": blob.name.split("/")[2],
"path": blob.name, "path": blob.name,
"size": properties.contentLength "size": blobClient.getProperties().contentLength,
}); });
} catch (error) {
if (error?.statusCode === 404) continue;
throw error;
}
} }
//console.log("blobObjwwwww:", blobObj); //console.log("blobObjwwwww:", blobObj);
@@ -1473,43 +1384,73 @@ export const getRepsFilesBlobs = async (
const blobObj = []; const blobObj = [];
for await (const blob of containerClient.listBlobsFlat({ for await (const blob of containerClient.listBlobsFlat({
prefix: casefolderID + "/" + filenamePrefix + "/files/" prefix: casefolderID + "/" + filenamePrefix + "/files/",
})) { })) {
const blobPathParts = blob.name.split("/"); let blobDocumentType = blob.name
const casefolderPath = blobPathParts[0] + "/" + blobPathParts[1]; .split("/")[2]
const repFileName = blobPathParts[3]; .slice(0, blob.name.split("/")[2].indexOf("_"));
const contentLength = blob.properties.contentLength;
//consoleLogger(blob.name); console.log(blob.name);
blobObj.push({ blobObj.push({
"name": repFileName, "name": blob.name.split("/")[3],
"path": blob.name, "path": blob.name,
"documentType": getDocumentTypeFromFilename(repFileName), "documentType": getDocumentTypeFromFilename(
blob.name.split("/")[3]
),
"versionId": blob.versionId, "versionId": blob.versionId,
"isCurrentVersion": blob.isCurrentVersion, "isCurrentVersion": blob.isCurrentVersion,
"contentLength": contentLength, "contentLength": blob.properties.contentLength,
"filenameprefix": filenamePrefix, "filenameprefix": filenamePrefix,
"filepath": buildDownloadBlobQueryPath({ "filepath":
containerName, "/api/file/downloadblob?container=" +
casefolderID: casefolderPath, containerName +
blobname: repFileName "&casefolderID=" +
}), encodeURIComponent(
...buildHashMetadataPaths({ blob.name.split("/")[0] + "/" + blob.name.split("/")[1]
containerName, ) +
casefolderID: casefolderPath, "&blobname=" +
blobname: repFileName encodeURIComponent(blob.name.split("/")[3]),
}), "hashedfilepath": hashAPIPath(
"deletepath": buildDeleteBlobQueryPath({ "/api/file/downloadblob?container=" +
containerName, containerName +
casefolderID: casefolderPath, "&casefolderID=" +
blobname: repFileName, encodeURIComponent(
encodeCasefolderID: false, blob.name.split("/")[0] + "/" + blob.name.split("/")[1]
encodeBlobname: false ) +
}) "&blobname=" +
encodeURIComponent(blob.name.split("/")[3])
),
"deletepath":
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
blob.name.split("/")[0] +
"/" +
blob.name.split("/")[1] +
"&blobname=" +
blob.name.split("/")[3],
"hasheddeletepath": hashAPIPath(
"/api/file/deleteblob?container=" +
containerName +
"&casefolderID=" +
encodeURIComponent(
blob.name.split("/")[0] + "/" + blob.name.split("/")[1]
) +
"&blobname=" +
encodeURIComponent(blob.name.split("/")[3])
),
"hashgetblobs": hashAPIPath(
"/api/file/getbloblist?container=" +
containerName +
"&casefolderID=" +
blob.name.split("/")[0] +
"/" +
blob.name.split("/")[1]
),
}); });
} }
//consoleLogger("blobObj:", blobObj); console.log("blobObj:", blobObj);
return blobObj; return blobObj;
}; };
@@ -1549,7 +1490,7 @@ export const createQueueSas = async (queueName) => {
var sas_signature_val = { var sas_signature_val = {
expiresOn: TEN_MINUTES_AFTER_NOW, expiresOn: TEN_MINUTES_AFTER_NOW,
permissions: permission, permissions: permission,
queueName: queueName queueName: queueName,
}; };
const sasToken = generateQueueSASQueryParameters( const sasToken = generateQueueSASQueryParameters(
@@ -1593,7 +1534,7 @@ export const createCaseCompleteMessage = async (
caseReference + caseReference +
"_case.json", "_case.json",
filespath: filespath:
endpointURL + "/" + containerName + "/" + caseReference + "/files" endpointURL + "/" + containerName + "/" + caseReference + "/files",
// uploadUrl: fileRecord.uploadUrl, // uploadUrl: fileRecord.uploadUrl,
// filename: fileRecord.file.name, // filename: fileRecord.file.name,
@@ -1654,7 +1595,7 @@ export const createRepCompleteMessage = async (
caseReference + caseReference +
"/" + "/" +
filename + filename +
"/files" "/files",
}; };
console.log("======================", message, "====================="); console.log("======================", message, "=====================");
@@ -1680,7 +1621,7 @@ export const listContainers = async (
includeDeleted: false, includeDeleted: false,
includeMetadata: true, includeMetadata: true,
includeSystem: true, includeSystem: true,
prefix: containerNamePrefix prefix: containerNamePrefix,
}; };
console.log( console.log(
"\n\n\n=================================================\n", "\n\n\n=================================================\n",
@@ -1723,7 +1664,7 @@ export const listBlobHierarchical = async (
includeTags: true, // include indexable tags includeTags: true, // include indexable tags
includeUncommitedBlobs: false, // include uncommitted blobs includeUncommitedBlobs: false, // include uncommitted blobs
includeVersions: false, // include all blob version includeVersions: false, // include all blob version
prefix: "" // filter by blob name prefix prefix: "", // filter by blob name prefix
}; };
let i = 1; let i = 1;
@@ -1809,7 +1750,7 @@ export async function listBlobHierarchicalForUser(containerClient) {
? lastModifiedDate.toISOString() ? lastModifiedDate.toISOString()
: null, : null,
createdOn: createdOnDate ? createdOnDate.toISOString() : null, createdOn: createdOnDate ? createdOnDate.toISOString() : null,
displayDate displayDate,
}); });
} }
return blobNames; return blobNames;
@@ -1824,7 +1765,7 @@ export async function listContainersForUser(
includeDeleted: false, includeDeleted: false,
includeMetadata: true, includeMetadata: true,
includeSystem: true, includeSystem: true,
prefix: containerNamePrefix prefix: containerNamePrefix,
}; };
const results = []; const results = [];
@@ -1842,7 +1783,7 @@ export async function listContainersForUser(
if (blobNames && blobNames.length > 0) { if (blobNames && blobNames.length > 0) {
results.push({ results.push({
container: containerItem.name, container: containerItem.name,
blobs: blobNames blobs: blobNames,
}); });
} }
} }
-18
View File
@@ -1,18 +0,0 @@
# Actions Clients
This folder contains extracted client wrappers from `actions/index.js` as part of the Priority 1 refactor plan.
Current extracted clients:
- `relayClient` (shared hash-signing helper used by account/portal/document direct services)
- `endpointClient` (shared JSON request helpers for GET and generic axios config requests)
Current usage includes:
- relay hash-signing helper reuse across account/portal/document direct services
- shared endpoint JSON request helpers reused by admin/notify/integration/reference-data direct services
Notes:
- Core helper extraction and compatibility barrel support remain in place.
- Additional client extraction (`fileClient`, `notifyClient`) can be layered in incrementally without changing public exports from `actions/index.js`.
-11
View File
@@ -1,11 +0,0 @@
import axios from "axios";
export const getJson = async (url, config) => {
const response = await axios.get(url, config);
return response.data;
};
export const requestJson = async (config) => {
const response = await axios(config);
return response.data;
};
-22
View File
@@ -1,22 +0,0 @@
import { getJson, requestJson } from "./endpointClient";
import { getSignedJson, postSignedJson } from "./signedRequestClient";
export const getFileJson = (url) => {
return getJson(url);
};
export const getSignedFileJson = async (queryUrl) => {
return getSignedJson(queryUrl);
};
export const downloadFileBlob = (url) => {
return requestJson({
method: "get",
url,
responseType: "blob"
});
};
export const postSignedFileJson = async (queryUrl, data, config = {}) => {
return postSignedJson(queryUrl, data, config);
};
-37
View File
@@ -1,37 +0,0 @@
const encodeRouteParam = (value) => encodeURIComponent(String(value));
export const buildFileQuery = (path, params = {}, options = {}) => {
const { encode = false } = options;
const entries = Object.entries(params).filter(([, value]) => {
return value !== undefined && value !== null;
});
if (entries.length === 0) {
return path;
}
const query = entries
.map(([key, value]) => {
if (!encode) {
return `${key}=${String(value)}`;
}
return `${encodeRouteParam(key)}=${encodeRouteParam(value)}`;
})
.join("&");
return `${path}?${query}`;
};
export const withBaseUrl = (baseUrl, route) => {
return `${baseUrl}${route}`;
};
export const appendQuerySuffix = (route, suffix = "") => {
return `${route}${suffix}`;
};
export const appendHashSuffix = (route, hashBuilder) => {
return appendQuerySuffix(route, hashBuilder(route));
};
-5
View File
@@ -1,5 +0,0 @@
export * from "./relayClient";
export * from "./endpointClient";
export * from "./fileClient";
export * from "./fileRouteBuilder";
export * from "./signedRequestClient";
-22
View File
@@ -1,22 +0,0 @@
import axios from "axios";
import { hashAPIPath } from "../core/hash";
export const buildHashedQueryUrl = async (queryUrl) => {
try {
const signRes = await axios.get(
"/api/endpoint/gethash_api?path=" + encodeURIComponent(queryUrl)
);
if (!signRes?.data?.hash) {
throw new Error("Hash signature unavailable");
}
return queryUrl + signRes.data.hash;
} catch (error) {
if (typeof window === "undefined" && process.env.HASHKEY) {
return queryUrl + hashAPIPath(queryUrl);
}
throw error;
}
};
-45
View File
@@ -1,45 +0,0 @@
import { requestJson } from "./endpointClient";
import { buildHashedQueryUrl } from "./relayClient";
export const buildSignedUrl = async (queryUrl, config = {}) => {
const { baseUrl = "" } = config;
return `${baseUrl}${await buildHashedQueryUrl(queryUrl)}`;
};
const signedRequestJson = async ({ method, queryUrl, data, config = {} }) => {
const { baseUrl, ...requestConfig } = config;
const signedUrl = await buildSignedUrl(queryUrl, { baseUrl });
return requestJson({
method,
url: signedUrl,
data,
...requestConfig
});
};
export const getSignedJson = (queryUrl, config = {}) => {
return signedRequestJson({
method: "get",
queryUrl,
config
});
};
export const postSignedJson = (queryUrl, data, config = {}) => {
return signedRequestJson({
method: "post",
queryUrl,
data,
config
});
};
export const deleteSignedJson = (queryUrl, config = {}) => {
return signedRequestJson({
method: "delete",
queryUrl,
config
});
};
-15
View File
@@ -1,15 +0,0 @@
const port = parseInt(process.env.PORT, 10) || 3000;
export const BASE_URL =
typeof window !== "undefined"
? window.apiRoot
: process.env.API_ROOT || `http://localhost:${port}`;
export const API_PATH = "/api/data/v8.2/";
export const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export const ACCESS_TOKEN_ENDPOINT = process.env.ACCESS_TOKEN_ENDPOINT;
export const TENANT_ID = process.env.TENANT;
-11
View File
@@ -1,11 +0,0 @@
export const isNonEmptyString = (value) => {
return typeof value === "string" && value.trim().length > 0;
};
export const sanitizeString = (value) => {
return typeof value === "string" ? value.trim() : "";
};
export const escapeODataString = (value) => {
return sanitizeString(value).replace(/'/g, "''");
};
-22
View File
@@ -1,22 +0,0 @@
import CryptoJS from "crypto-js";
const WORDKEY = process.env.HASHKEY;
export const hashAPIPath = (queryPath) => {
var hashlink = CryptoJS.HmacSHA256(
queryPath,
CryptoJS.enc.Hex.parse(WORDKEY)
);
hashlink = hashlink.toString(CryptoJS.enc.Hex);
return (queryPath.indexOf("?") > -1 ? "&hash=" : "?hash=") + hashlink;
};
export const hashString = (stringToHash) => {
let hashedStr = CryptoJS.AES.encrypt(stringToHash, "pedw");
return hashedStr.toString();
};
export const dehashString = (stringToDeHash) => {
let dehashedStr = CryptoJS.AES.decrypt(decodeURI(stringToDeHash), "pedw");
return dehashedStr.toString(CryptoJS.enc.Utf8);
};
-50
View File
@@ -1,50 +0,0 @@
export const azureHeaders = (access_token) => {
return {
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json;odata.metadata=none",
"Prefer": 'odata.include-annotations="*",return=representation',
"Content-Type": "application/json",
"Authorization": "Bearer " + access_token
}
};
};
export const azureHeadersNoOdata = (access_token) => {
return {
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + access_token
}
};
};
export const azureHeadersPaged = (access_token) => {
return {
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json;odata.metadata=none",
"Prefer":
'odata.include-annotations="*",return=representation, odata.maxpagesize=10',
"Content-Type": "application/json",
"Authorization": "Bearer " + access_token
}
};
};
export const azureHeadersPagedCustom = (access_token, showNumberOfRecords) => {
return {
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json;odata.metadata=none",
"Prefer":
'odata.include-annotations="*",return=representation, odata.maxpagesize=' +
showNumberOfRecords,
"Content-Type": "application/json",
"Authorization": "Bearer " + access_token
}
};
};
-106
View File
@@ -1,106 +0,0 @@
import _ from "lodash";
const MASK = "[REDACTED]";
const redactString = (value) => {
if (typeof value !== "string") return value;
return value
.replace(
/([a-zA-Z0-9._%+-]{1,})@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g,
`${MASK}@${MASK}`
)
.replace(/Bearer\s+[A-Za-z0-9._\-]+/gi, `Bearer ${MASK}`)
.replace(/("client_secret"\s*:\s*")[^"]+("?)/gi, `$1${MASK}$2`)
.replace(/("access_token"\s*:\s*")[^"]+("?)/gi, `$1${MASK}$2`);
};
export const redactSensitive = (value) => {
if (value == null) return value;
if (typeof value === "string") {
return redactString(value);
}
try {
const json = JSON.stringify(value);
return redactString(json);
} catch (_error) {
return MASK;
}
};
export const getIP = (req) => {
const forwarded = req.headers["x-forwarded-for"];
const ip =
typeof forwarded === "string"
? forwarded.split(/, /)[0]
: req.socket.remoteAddress;
console.info(
"\n====================\n Client IP address: " + ip,
"\n=====================\n"
);
};
export const consoleLogger = (err) => {
console.log(
"\n\n/////////////////////////////////////////////////\nRaw Error " +
redactSensitive(err) +
"\n\n/////////////////////////////////////////////////\n"
);
var errStr =
"\n\n/////////////////////////////////////////////////\nServer Error " +
"\n" +
(_.has(err, "name") ? "Name: " + err.name + "\n" : "") +
(_.has(err, "code") ? "Code: " + err.code + "\n" : "") +
(_.has(err, "query") ? "Query: " + err.query + "\n" : "") +
(_.has(err, "message") ? "Message: " + err.message + "\n" : "") +
(_.has(err, "request.url")
? "request.url: " + err.request.url + "\n"
: "") +
(_.has(err, "response.status") ? "Status: " + err.code + "\n" : "") +
(_.has(err, "response.statusText")
? "\nStatusText: " + err.response.status + "\n"
: "") +
(_.has(err, "response.request.socket.remoteAddress")
? "\nRequest IP: " +
err.response.request.socket.remoteAddress +
"\n"
: "") +
(_.has(err, "response.data.error.message")
? "\nMessage: " +
redactSensitive(err.response.data.error.message) +
"\n"
: "") +
(_.has(err, "response.config.url")
? "\nRequest URL: " + redactSensitive(err.config.url) + "\n"
: "") +
(_.has(err, "response.headers.date")
? "\nRequest Time: " + err.response.headers.date + "\n"
: "") +
(_.has(err, "config.url")
? "\nAxios config url: " + redactSensitive(err.config.url) + "\n"
: "") +
(_.has(err, "config.url")
? "\nAxios message url: " + redactSensitive(err.message) + "\n"
: "") +
(_.has(err, "config.data")
? "\nRequest payload: " + redactSensitive(err.config.data) + "\n"
: "") +
"\n/////////////////////////////////////////////////\n";
console.log(errStr);
};
export const conLog = (err) => {
var errStr =
"\n\n/////////////////////////////////////////////////\nResponse: " +
"\n" +
err +
"\n/////////////////////////////////////////////////\n\n";
console.log(errStr);
return errStr;
};
-41
View File
@@ -1,41 +0,0 @@
import { requestJson } from "../clients/endpointClient";
import { ACCESS_TOKEN_ENDPOINT, TENANT_ID } from "./env";
import { consoleLogger } from "./logger";
const cache = {};
const tokenBody =
"grant_type=" +
process.env.GRANT_TYPE +
"&client_id=" +
process.env.CLIENT_ID +
"&client_secret=" +
process.env.CLIENT_SECRET +
"&scope=" +
"https://" +
process.env.RELAYURI +
"/.default";
const tokenConfig = {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache"
}
};
export const getToken = async () => {
try {
const data = await requestJson({
method: "post",
url: `${ACCESS_TOKEN_ENDPOINT}${TENANT_ID}/oauth2/v2.0/token`,
data: tokenBody,
...tokenConfig
});
cache.tokenResponse = data;
return data;
} catch (error) {
consoleLogger(error);
return error;
}
};
+2196 -8
View File
File diff suppressed because it is too large Load Diff
+21 -32
View File
@@ -1,58 +1,53 @@
export const getSelectQuery = (appealTypeName) => { export const getSelectQuery = (appealTypeName) => {
switch (appealTypeName) { switch (appealTypeName) {
case "pinswg_advertses": case "pinswg_advertses":
return "&$select=pinswg_detailedeiascreeningrequired,pinswg_speacialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_procedure,pinswg_questionnaireduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_startdate,pinswg_otherpartiesstatement,pinswg_finalcommentsduedate,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_speacialistcaseprocess,pinswg_statementduedate"; return "&$select=pinswg_speacialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_procedure,pinswg_questionnaireduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_startdate,pinswg_otherpartiesstatement,pinswg_finalcommentsduedate,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_speacialistcaseprocess,pinswg_statementduedate";
break; break;
case "pinswg_callinss77s": case "pinswg_callinss77s":
return "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_startdate,statuscode,pinswg_dateexportedtoiss,pinswg_startdateofevent,pinswg_typeofevent,pinswg_statementsduedate,pinswg_otherpartiesstatement"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_startdate,statuscode,pinswg_dateexportedtoiss,pinswg_startdateofevent,pinswg_typeofevent,pinswg_statementsduedate,pinswg_otherpartiesstatement";
break; break;
case "pinswg_commonlands": case "pinswg_commonlands":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_starttimeoftheevent,pinswg_typeofevent,pinswg_statementsduedate"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_starttimeoftheevent,pinswg_typeofevent,pinswg_statementsduedate";
break; break;
case "pinswg_environmentalpermittings": case "pinswg_environmentalpermittings":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateofevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateofevent,pinswg_typeofevent";
break; break;
case "pinswg_hedgeshedgerowstreepreservationreplacems": case "pinswg_hedgeshedgerowstreepreservationreplacems":
return "&$select=pinswg_detailedeiascreening,pinswg_specialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate,pinswg_specialistcaseprocess"; return "&$select=pinswg_specialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate,pinswg_specialistcaseprocess";
break; break;
case "pinswg_miscellaneouscaseworks": case "pinswg_miscellaneouscaseworks":
return "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate";
break;
case "pinswg_wayleaves": case "pinswg_wayleaves":
return "&$select=pinswg_detailedeiascreening,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate";
break; break;
case "pinswg_communityinfrastructurelevys117118119s": case "pinswg_communityinfrastructurelevys117118119s":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_questionnaireduedate,pinswg_statementduedate"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_questionnaireduedate,pinswg_statementduedate";
break; break;
case "pinswg_compulsorypurchaseorderses": case "pinswg_compulsorypurchaseorderses":
return "&$select=pinswg_detailedeiascreening,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddresscounty,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate";
break; break;
case "pinswg_dnses": case "pinswg_dnses":
return "&$select=pinswg_eiarequired,pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_addresscounty,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_choiceofprocedure,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofdecision,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectdescription,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_suspensionenddates,pinswg_suspensionstartdates,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_casestage,_pinswg_dnsids_value,pinswg_startdateofevent,pinswg_typeofevent"; return "&$select=pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_addresscounty,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_choiceofprocedure,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofdecision,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectdescription,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_suspensionenddates,pinswg_suspensionstartdates,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_casestage,_pinswg_dnsids_value,pinswg_startdateofevent,pinswg_typeofevent";
break; break;
case "pinswg_electricityacts": case "pinswg_electricityacts":
return "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_startdateofevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_startdateofevent,pinswg_typeofevent";
break;
case "pinswg_harbourrevisionorders":
return "&$select=pinswg_eiarequired,pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_addresscounty,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_choiceofprocedure,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofdecision,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectdiscription,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_suspensionenddates,pinswg_suspensionstartdate,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_casestage,pinswg_startdateofevent,pinswg_typeofevent";
break; break;
case "pinswg_householderappealhases": case "pinswg_householderappealhases":
return "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstmt,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstmt,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode";
break; break;
case "pinswg_enforcementnoticeappeals174s": case "pinswg_enforcementnoticeappeals174s":
return "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent";
break; break;
case "pinswg_enforcementlistedbuildingconservationaps": case "pinswg_enforcementlistedbuildingconservationaps":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdates,pinswg_statementduedate,statuscode,pinswg_startdateofevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdates,pinswg_statementduedate,statuscode,pinswg_startdateofevent,pinswg_typeofevent";
break; break;
case "pinswg_maintenanceoflands217s": case "pinswg_maintenanceoflands217s":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdates,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdates,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent";
break; break;
case "pinswg_lawfuldevelopmentcertificates": case "pinswg_lawfuldevelopmentcertificates":
return "&$select=pinswg_detailedeiascreeningrequiered,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent";
break; break;
case "pinswg_listedbuildingandconservationareaconsens": case "pinswg_listedbuildingandconservationareaconsens":
return "&$select=pinswg_detailedeiascreeningrequiered,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_sitepostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_starttimeofevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_sitepostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_starttimeofevent,pinswg_typeofevent";
break; break;
case "pinswg_planningappeals78s": case "pinswg_planningappeals78s":
//console.log( //console.log(
@@ -60,17 +55,17 @@ export const getSelectQuery = (appealTypeName) => {
// process.env.RELAYPATH == "test-pedw-hc" // process.env.RELAYPATH == "test-pedw-hc"
// ); // );
return process.env.RELAYPATH == "dev-pedw-hc" return process.env.RELAYPATH == "dev-pedw-hc"
? "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,pinswg_siteaddresscounty,_pinswg_localplanningauthority_value,pinswg_casedecisiondate,pinswg_dicision,pinswg_dateeventrequested,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdatetimeiftheevent,pinswg_representation_period_end_date,pinswg_extend_representation_date,pinswg_typeofevent" ? "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_localplanningauthority_value,pinswg_casedecisiondate,pinswg_dicision,pinswg_dateeventrequested,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdatetimeiftheevent,pinswg_representation_period_end_date,pinswg_extend_representation_date,pinswg_typeofevent"
: "&$select=pinswg_eiarequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,pinswg_siteaddresscounty,_pinswg_localplanningauthority_value,pinswg_casedecisiondate,pinswg_dicision,pinswg_dateeventrequested,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdatetimeiftheevent,pinswg_typeofevent,pinswg_developmentdescription,pinswg_whyisinspectorneededonsite,pinswg_outlinehealthandsafetyissuesonsite,pinswg_additionalappealsmadedetails,pinswg_chosenprocedureexplanation,pinswg_dateofapplication,pinswg_lpaapplicationreference,pinswg_caseworkreason,pinswg_dateoflpadecision,pinswg_areaofsiteinhectaresdec,pinswg_floorspaceinsquaremeters,pinswg_ownershipcertificate,pinswg_siteviewablefromroad,pinswg_costappliedforindicator,pinswg_s106unilateralsubmitted"; : "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_localplanningauthority_value,pinswg_casedecisiondate,pinswg_dicision,pinswg_dateeventrequested,pinswg_finalcommentsduedate,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdatetimeiftheevent,pinswg_typeofevent";
break; break;
case "pinswg_planningconditionss73s79s": case "pinswg_planningconditionss73s79s":
return "&$select=pinswg_detailedeiascreeningrequiered,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateofevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateofevent,pinswg_typeofevent";
break; break;
case "pinswg_planningobligationappeals106s": case "pinswg_planningobligationappeals106s":
return "&$select=pinswg_detailedeiascreeningrequired,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatements,pinswg_procedure,pinswg_questionnaireduedate,pinswg_startdate,pinswg_statementduedate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent";
break; break;
case "pinswg_rows": case "pinswg_rows":
return "&$select=pinswg_detailedeiascreeningrequired,pinswg_specialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate,pinswg_specialistcaseprocess"; return "&$select=pinswg_specialistcaseprocess,modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,pinswg_casedecisiondate,pinswg_dateeventrequested,pinswg_decision,pinswg_finalcommentsduedate,pinswg_otherpartiesstatement,pinswg_procedure,pinswg_proofsofevidencewrittenstatementsofeviden,pinswg_questionnaireduedate,pinswg_relevantauthorityname,pinswg_startdate,statuscode,pinswg_startdateoftheevent,pinswg_typeofevent,pinswg_statementduedate,pinswg_specialistcaseprocess";
break; break;
case "pinswg_ldps": case "pinswg_ldps":
return "&$select=modifiedon,pinswg_name"; return "&$select=modifiedon,pinswg_name";
@@ -78,12 +73,6 @@ export const getSelectQuery = (appealTypeName) => {
case "pinswg_nonvalidations": case "pinswg_nonvalidations":
return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,statuscode"; return "&$select=modifiedon,_pinswg_appellant_value,pinswg_name,pinswg_siteaddressline1,pinswg_siteaddressline2,pinswg_siteaddresspostcode,pinswg_siteaddresstown,_pinswg_associatedlpa_value,statuscode";
break; break;
case "pinswg_transportandworkacts":
return "&$select=pinswg_eiarequired,pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_addresscounty,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_choiceofprocedure,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofdecision,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectdescription,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_suspensionenddates,pinswg_suspensionstartdate,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_casestage,pinswg_startdateofevent,pinswg_typeofevent";
case "pinswg_sipses":
// return "&$select=pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,_pinswg_appellant_value,pinswg_name,pinswg_addressline1,pinswg_addressline2,pinswg_postcode,pinswg_addresstown,_pinswg_associatedlpa_value,pinswg_addresscounty,pinswg_applicationacceptedasvalid,pinswg_applicationrejectedasinvalid,pinswg_choiceofprocedure,pinswg_confirmrequesttovaryapplication,pinswg_dateeventrequested,pinswg_dateofdecision,pinswg_dateofrequesttovarytheapplication,pinswg_dateofsubmissionofapplication,pinswg_dateprojectpublishedonwebsite,pinswg_deadlineforsubmissionofapplication,pinswg_decision,pinswg_endofrepresentationperiod,pinswg_inspectorreportsubmittedtowelshgovernment,pinswg_procedureconfirmed,pinswg_projectdescription,pinswg_projectlocation,pinswg_recommendation,pinswg_rejectrequesttovaryapplication,pinswg_reportdueby,pinswg_suspensiondates,pinswg_suspensionenddates,pinswg_suspensionstartdates,pinswg_validnoticeofintentiontosubmitanapplicati,pinswg_webaddress,pinswg_withdrawndate,pinswg_writtenacceptanceofnotification,statuscode,pinswg_casestage,_pinswg_dnsids_value,pinswg_startdateofevent,pinswg_typeofevent";
return "&$select=_pinswg_projecttype_value,pinswg_eiarequired,pinswg_anticipatedgridrefeasting,pinswg_anticipatedgridrefnorthing,_pinswg_appellant_value,pinswg_name,_pinswg_associatedlpa_value,pinswg_choiceofprocedure,pinswg_decision,pinswg_projectdescription,pinswg_projectlocation,pinswg_recommendation,statuscode,pinswg_casestage,_pinswg_sipscase_value,pinswg_writtenacceptanceofnotification,pinswg_validnoticeofintentiontosubmit,pinswg_deadlineforsubmissionofapplication,pinswg_screeningstartdate,pinswg_eiatargetdate,pinswg_targetextended,pinswg_directionissueddate,pinswg_eiarequired,pinswg_scopingstartdate,pinswg_scopingtargetdate,pinswg_scopingtargetextended,pinswg_scopingoutcomeissueddate,pinswg_essubmitted,pinswg_deemedmarinelicenseappliedfor,pinswg_validationdeadlineextension,pinswg_casesuspensionstartdate,pinswg_casesuspensionenddate,pinswg_consultationopen,pinswg_consultationclose,pinswg_reportissuedtowelshministers,pinswg_decisionissuedtoapplicant,pinswg_decisionoutcome,pinswg_redetermination,pinswg_redeterminationconsultationdeadline";
break;
default: default:
return ""; return "";
break; break;
-108
View File
@@ -1,108 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { getJson, requestJson } from "../clients/endpointClient";
import { getSignedJson } from "../clients/signedRequestClient";
export const getPersonalAccount = (contactid) => {
return getJson(
BASE_URL + "/api/endpoint/getpersonalaccount_api?contactid=" + contactid
).catch((error) => {
consoleLogger(error);
});
};
export const getLogin = (emailAddress, pwd) => {
return getJson(
"/api/endpoint/getlogin_api?emailAddress=" +
emailAddress +
"&pwd=" +
pwd
).catch((error) => {
consoleLogger(error);
});
};
export const updatePassword = (contactId, newpassword) => {
var queryUrl = "/api/endpoint/updateaccount_api?contactId=" + contactId;
var data = { "pinswg_custom_password": newpassword };
var config = {
method: "post",
url: queryUrl,
data: data
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const updateAccount = async (contactId, updateBody, ssr) => {
var queryUrl =
(ssr ? BASE_URL : "") +
"/api/endpoint/updateaccount_api?contactId=" +
contactId;
var data = updateBody;
var config = {
method: "post",
url: queryUrl,
data: data
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const createAccount = (formValues) => {
var data = formValues;
var queryUrl = "/api/endpoint/createaccount_api";
var config = {
method: "post",
url: queryUrl,
data: data
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const getEmailAccountCheck = (emailAddress) => {
return getJson(
"/api/endpoint/getemailaccountcheck_api?emailAddress=" + emailAddress
).catch((error) => {
consoleLogger(error);
});
};
export const getPortalLogin = async (emailAddress) => {
var queryUrl =
"/api/endpoint/getportallogin_api?emailAddress=" + emailAddress;
return getSignedJson(queryUrl, { baseUrl: BASE_URL }).catch((error) => {
consoleLogger(error);
return JSON.stringify(error);
});
};
export const getPortalLoginProxy = async (emailAddress) => {
var queryUrl =
"/api/endpoint/getportalloginproxy_api?emailAddress=" + emailAddress;
return getJson(queryUrl).catch((error) => {
consoleLogger(error);
return JSON.stringify(error);
});
};
export const getPreferredLanguage = async (email) => {
return getJson(
BASE_URL +
"/api/endpoint/getpreferredlanguage_api?emailAddress=" +
email
).catch((error) => {
consoleLogger(error);
return error.response;
});
};
-23
View File
@@ -1,23 +0,0 @@
import {
getPersonalAccount,
getLogin,
updatePassword,
updateAccount,
createAccount,
getEmailAccountCheck,
getPortalLogin,
getPortalLoginProxy,
getPreferredLanguage
} from "./accountDirectService";
export {
getPersonalAccount,
getLogin,
updatePassword,
updateAccount,
createAccount,
getEmailAccountCheck,
getPortalLogin,
getPortalLoginProxy,
getPreferredLanguage
};
-67
View File
@@ -1,67 +0,0 @@
import { BASE_URL } from "../core/env";
import { logAndReturnResponse } from "./httpServiceUtils";
import { getJson } from "../clients/endpointClient";
export const getNewAppeals = async (searchString) => {
try {
return await getJson(BASE_URL + "/api/admin/getnewappeals_api");
} catch (error) {
return logAndReturnResponse(error);
}
};
export const getNewAppealsPage = async (
searchString,
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords
) => {
try {
return await getJson(
"/api/admin/getnewappeals_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
);
} catch (error) {
return logAndReturnResponse(error);
}
};
export const getNewDocumentsPaged = async (
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords,
documentType,
documentOrigin,
selectedWeeks
) => {
try {
return await getJson(
"/api/admin/getlatestdocuments_api?pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords +
"&documentType=" +
documentType +
"&numberWeeks=" +
selectedWeeks +
"&documentOrigin=" +
documentOrigin
);
} catch (error) {
return logAndReturnResponse(error);
}
};
-7
View File
@@ -1,7 +0,0 @@
import {
getNewAppeals,
getNewAppealsPage,
getNewDocumentsPaged
} from "./adminDirectService";
export { getNewAppeals, getNewAppealsPage, getNewDocumentsPaged };
-276
View File
@@ -1,276 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { logAndReturnResponse } from "./httpServiceUtils";
import { getJson, requestJson } from "../clients/endpointClient";
import { buildFileQuery, withBaseUrl } from "../clients/fileRouteBuilder";
export const getCaseMessage = (searchString) => {
const route = buildFileQuery("/api/endpoint/getcasemessage_api", {
id: searchString
});
return getJson(withBaseUrl(BASE_URL, route)).catch(logAndReturnResponse);
};
export const getIncidentbyID = (searchString) => {
const route = buildFileQuery("/api/endpoint/getincidentbyid_api", {
searchString
});
return getJson(withBaseUrl(BASE_URL, route)).catch(logAndReturnResponse);
};
export const getIsPublishedbyID = (searchString) => {
const route = buildFileQuery("/api/endpoint/getispublishedbyid_api", {
searchString
});
return getJson(route).catch(logAndReturnResponse);
};
export const getPartSavedAppeal = (searchString) => {
const route = buildFileQuery("/api/endpoint/getpartsavedappeal_api", {
searchString
});
return getJson(withBaseUrl(BASE_URL, route)).catch(logAndReturnResponse);
};
export const getSIPSEvents = async (caseid) => {
const route = buildFileQuery("/api/endpoint/getsipsevents_api", {
caseid
});
return getJson(withBaseUrl(BASE_URL, route)).catch(logAndReturnResponse);
};
export const getSIPSMedia = async (caseid) => {
const route = buildFileQuery("/api/endpoint/getsipsmedia_api", {
caseid
});
return getJson(withBaseUrl(BASE_URL, route)).catch(logAndReturnResponse);
};
export const getAppealID = (
caseReference,
updateFormCollection,
primaryAttribute
) => {
const route = buildFileQuery("/api/endpoint/getappealid_api", {
updateFormCollection,
primaryAttribute,
caseReference
});
return getJson(route)
.then((data) => {
const result = Object.entries(data.value[0]).filter(
([key]) => !key.startsWith("_")
)[0][1];
var appealID = result;
return appealID;
})
.catch((error) => {
consoleLogger(error);
});
};
export const createNewCase = (
appealTypeId,
lpaID,
contactid,
createBody,
containerName
) => {
appealTypeId = parseInt(appealTypeId);
var data = createBody;
var queryUrl = buildFileQuery("/api/endpoint/createcase_api", {
appealTypeId,
lpaID,
contactid,
containername: containerName
});
var config = {
method: "post",
url: withBaseUrl(BASE_URL, queryUrl),
data: data
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const createNewCaseBlob = (
appealTypeId,
lpaID,
contactid,
createBody,
containerName,
lpaName
) => {
appealTypeId = parseInt(appealTypeId);
var data = createBody;
data.pinswg_lpaname = lpaName;
data.createdon = new Date();
var queryUrl = buildFileQuery("/api/file/createcase_api", {
appealTypeId,
lpaID,
contactid,
containername: containerName
});
var config = {
method: "post",
url: queryUrl,
data: data
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const updateCase = async (
incidentId,
updateBody,
updateFormCollection,
primaryAttribute,
caseReference
) => {
var data = updateBody;
var appealObj = await getAppealID(
caseReference,
updateFormCollection,
primaryAttribute
);
var queryUrl = buildFileQuery("/api/endpoint/updatecase_api", {
updateFormCollection,
appealObj
});
var config = {
method: "post",
url: queryUrl,
data: updateBody
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const updateCaseBlob = async (
incidentId,
updateBody,
updateFormCollection,
primaryAttribute,
caseReference
) => {
var data = updateBody;
var appealObj = await getAppealID(
caseReference,
updateFormCollection,
primaryAttribute
);
var queryUrl = buildFileQuery("/api/file/updatecase_api", {
updateFormCollection,
appealObj
});
var config = {
method: "post",
url: queryUrl,
data: updateBody
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const patchCase = async (incidentid) => {
var queryUrl = buildFileQuery("/api/endpoint/patchcase_api", {
incidentid
});
return getJson(queryUrl).catch((error) => {
//console.log("this error:", error);
});
};
export const getCase = (incidentID) => {
const route = buildFileQuery("/api/endpoint/getcase_api", {
incidentID
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getCaseByID = (incidentID) => {
const route = buildFileQuery("/api/endpoint/getcasebyid_api", {
incidentID
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getAppealPDFDocs = (incidentID) => {
const route = buildFileQuery("/api/endpoint/getappealpdfdocuments_api", {
incidentid: incidentID
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getAppealPDFDocument = async (incidentid) => {
const route = buildFileQuery("/api/endpoint/getappealpdfdocuments_api", {
incidentid
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
return error.response;
});
};
export const getPortalModuleDetails = async (appealType, caseReference) => {
const route = buildFileQuery("/api/endpoint/getportalmoduledetails_api", {
appealType,
caseReference: encodeURI(caseReference)
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getPortalModuleDetailsProxy = (appealType, caseReference) => {
const route = buildFileQuery(
"/api/endpoint/getportalmoduledetailsproxy_api",
{
appealType,
caseReference: caseReference.replace(/\'/g, "''")
}
);
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
-41
View File
@@ -1,41 +0,0 @@
import {
getCaseMessage,
getIncidentbyID,
getSIPSEvents,
getSIPSMedia,
getAppealID,
createNewCase,
createNewCaseBlob,
updateCase,
updateCaseBlob,
patchCase,
getCase,
getCaseByID,
getAppealPDFDocs,
getAppealPDFDocument,
getPartSavedAppeal,
getIsPublishedbyID,
getPortalModuleDetails,
getPortalModuleDetailsProxy
} from "./caseDirectService";
export {
getCaseMessage,
getIncidentbyID,
getSIPSEvents,
getSIPSMedia,
getAppealID,
createNewCase,
createNewCaseBlob,
updateCase,
updateCaseBlob,
patchCase,
getCase,
getCaseByID,
getAppealPDFDocs,
getAppealPDFDocument,
getPartSavedAppeal,
getIsPublishedbyID,
getPortalModuleDetails,
getPortalModuleDetailsProxy
};
-394
View File
@@ -1,394 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { hashAPIPath } from "../core/hash";
import {
buildFileQuery,
withBaseUrl,
appendQuerySuffix,
appendHashSuffix
} from "../clients/fileRouteBuilder";
import {
getFileJson,
getSignedFileJson,
downloadFileBlob,
postSignedFileJson
} from "../clients/fileClient";
const MAX_FILES_PER_UPLOAD_BATCH = 10;
export const getAwaitingSubmissionFromBlob = (containerName) => {
const route = buildFileQuery("/api/file/getawaitingsubmissionfromblob", {
container: containerName
});
return getFileJson(
withBaseUrl(BASE_URL, appendHashSuffix(route, hashAPIPath))
).catch((error) => {
consoleLogger(error);
});
};
export const getRepsFromBlob = (containerName) => {
const route = buildFileQuery("/api/file/getrepsblob", {
container: containerName
});
return getFileJson(
withBaseUrl(BASE_URL, appendHashSuffix(route, hashAPIPath))
).catch((error) => {
consoleLogger(error);
});
};
export const getRepsFromBlobProxy = async (containerName) => {
const route = buildFileQuery("/api/file/getrepsblobproxy", {
container: containerName
});
return getFileJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getAwaitingSubmissionFromBlobProxy = async (containerName) => {
const route = buildFileQuery(
"/api/file/getawaitingsubmissionfromblobproxy",
{
container: containerName
}
);
return getFileJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getFilesFromBlobproxy = (containerName, casefolderID) => {
const route = buildFileQuery("/api/file/getbloblistproxy", {
container: containerName,
casefolderID
});
return getFileJson(route).catch((error) => {
consoleLogger(error);
});
};
export const deleteAwaitingSubmissionsFromBlob = (
containerID,
casefolderID
) => {
var queryUrl = buildFileQuery("/api/file/deleteblobcase", {
container: containerID,
casefolderID
});
return getSignedFileJson(queryUrl).catch((error) => {
consoleLogger(error);
});
};
export const deleteMyRepresentationsFromBlob = (
containerID,
casefolderID,
repfile
) => {
var queryUrl = buildFileQuery("/api/file/deleteblobrep", {
container: containerID,
casefolderID,
repfile
});
return getSignedFileJson(queryUrl).catch((error) => {
consoleLogger(error);
});
};
export const uploadFiles = async (
formValues,
filesObj,
containerID,
casefolderID
) => {
let files = filesObj;
var formData = new FormData();
formData.append("appealData", JSON.stringify(formValues));
formData.append("containerID", containerID);
formData.append("casefolderID", casefolderID);
for (let i = 0; i < files.length; i++) {
for (let j = 0; j < files[i].length; j++) {
formData.append(files[i][j].name, files[i][j]);
}
}
var queryUrl = "/api/file/upload";
try {
return await postSignedFileJson(queryUrl, formData);
} catch (error) {
consoleLogger(error);
}
};
export const uploadSingleFile = async (
filesObj,
containerID,
casefolderID,
options = {}
) => {
let files = filesObj;
try {
const queryUrl = "/api/file/uploadsinglefile";
const uploadResponse = {
data: [],
invalidFiles: []
};
let cumulativeUploaded = 0;
let cumulativeInvalid = 0;
const totalFiles = files.length;
const totalChunks = Math.ceil(totalFiles / MAX_FILES_PER_UPLOAD_BATCH);
for (
let index = 0;
index < files.length;
index += MAX_FILES_PER_UPLOAD_BATCH
) {
const chunkIndex =
Math.floor(index / MAX_FILES_PER_UPLOAD_BATCH) + 1;
const fileChunk = files.slice(
index,
index + MAX_FILES_PER_UPLOAD_BATCH
);
const formData = new FormData();
formData.append("containerID", containerID);
formData.append("casefolderID", casefolderID);
for (let i = 0; i < fileChunk.length; i++) {
formData.append(fileChunk[i].name, fileChunk[i]);
}
const chunkResult = await postSignedFileJson(queryUrl, formData);
if (Array.isArray(chunkResult?.data)) {
uploadResponse.data.push(...chunkResult.data);
cumulativeUploaded += chunkResult.data.length;
}
if (Array.isArray(chunkResult?.invalidFiles)) {
uploadResponse.invalidFiles.push(...chunkResult.invalidFiles);
cumulativeInvalid += chunkResult.invalidFiles.length;
}
if (typeof options.onChunkComplete === "function") {
options.onChunkComplete({
chunkIndex,
totalChunks,
totalFiles,
cumulativeUploaded,
cumulativeInvalid,
processedFiles: cumulativeUploaded + cumulativeInvalid
});
}
}
return uploadResponse;
} catch (error) {
consoleLogger(error);
}
};
export const uploadRepFiles = async (
formValues,
filesObj,
containerID,
casefolderID
) => {
var formData = new FormData();
formData.append("appealData", JSON.stringify(formValues));
formData.append("containerID", containerID);
formData.append("casefolderID", casefolderID);
formData.append("repOrAppeal", true);
var queryUrl = "/api/file/upload";
try {
return await postSignedFileJson(queryUrl, formData);
} catch (error) {
consoleLogger(error);
}
};
export const generateRepPDF = async (
formValues,
containerID,
casefolderID,
options = {}
) => {
var queryUrl =
"/api/file/generatepdf" + (options.download ? "?download=true" : "");
formValues.containerID = containerID;
try {
return await postSignedFileJson(queryUrl, formValues, {
...(options.download ? { responseType: "blob" } : {})
});
} catch (error) {
consoleLogger(error);
}
};
export const generateAppealPDF = async (
formValues,
containerID,
casefolderID,
appealType,
fileList,
options = {}
) => {
Object.assign(formValues, {
"filesList": fileList
});
var queryUrl =
"/api/file/generateappealpdf?appealType=" +
appealType +
(options.download ? "&download=true" : "");
try {
return await postSignedFileJson(queryUrl, formValues, {
...(options.download ? { responseType: "blob" } : {})
});
} catch (error) {
consoleLogger(error);
}
};
export const getFilesFromBlob = (containerName, casefolderID) => {
const route = buildFileQuery("/api/file/getbloblist", {
container: containerName,
casefolderID
});
return getFileJson(
withBaseUrl(BASE_URL, appendHashSuffix(route, hashAPIPath))
).catch((error) => {
consoleLogger(error);
});
};
export const getFilesFromBlobHashed = (
containerName,
getblobshash,
casefolderID
) => {
const route = buildFileQuery("/api/file/getbloblist", {
container: containerName,
casefolderID
});
return getFileJson(appendQuerySuffix(route, getblobshash)).catch(
(error) => {
consoleLogger(error);
}
);
};
export const deleteBlob = async (
containerName,
blobName,
deleteblobhash,
casefolderID
) => {
const route = buildFileQuery(
"/api/file/deleteblob",
{
container: containerName,
casefolderID,
blobname: blobName
},
{
encode: true
}
);
return getFileJson(appendQuerySuffix(route, deleteblobhash)).catch(
(error) => {
consoleLogger(error);
}
);
};
export const deleteRepBlob = async (
containerName,
blobName,
deleteblobhash,
casefolderID,
filenamePrefix
) => {
const route = buildFileQuery(
"/api/file/deleteblob",
{
container: containerName,
casefolderID: casefolderID + "/" + filenamePrefix,
blobname: blobName
},
{
encode: true
}
);
return getFileJson(appendQuerySuffix(route, deleteblobhash)).catch(
(error) => {
consoleLogger(error);
}
);
};
export const downloadBlob = (containerName, blobName) => {
const queryUrl = withBaseUrl(
BASE_URL,
buildFileQuery("/api/file/downloadblob", {
container: containerName.toLowerCase(),
blobname: blobName
})
);
return downloadFileBlob(queryUrl).catch((error) => {
consoleLogger(error);
});
};
export const getProgressFromBlob = async (containerName, casereference) => {
const route = buildFileQuery(
"/api/file/getprogressobjblob",
{
container: containerName,
casefolderID: casereference
},
{
encode: true
}
);
return getFileJson(
withBaseUrl(BASE_URL, appendHashSuffix(route, hashAPIPath))
).catch((error) => {
consoleLogger(error);
});
};
export const createContainerProxy = (containerName) => {
var route = buildFileQuery("/api/file/setupcontainer", {
ident: containerName
});
var queryUrl = appendHashSuffix(route, hashAPIPath);
return getFileJson(withBaseUrl(BASE_URL, queryUrl)).catch((error) => {
consoleLogger(error);
return JSON.stringify(error);
});
};
-43
View File
@@ -1,43 +0,0 @@
import {
getAwaitingSubmissionFromBlob,
getRepsFromBlob,
getRepsFromBlobProxy,
getAwaitingSubmissionFromBlobProxy,
deleteAwaitingSubmissionsFromBlob,
deleteMyRepresentationsFromBlob,
uploadFiles,
uploadSingleFile,
uploadRepFiles,
generateRepPDF,
generateAppealPDF,
getFilesFromBlob,
getFilesFromBlobproxy,
getFilesFromBlobHashed,
deleteBlob,
deleteRepBlob,
downloadBlob,
getProgressFromBlob,
createContainerProxy
} from "./documentDirectService";
export {
getAwaitingSubmissionFromBlob,
getRepsFromBlob,
getRepsFromBlobProxy,
getAwaitingSubmissionFromBlobProxy,
deleteAwaitingSubmissionsFromBlob,
deleteMyRepresentationsFromBlob,
uploadFiles,
uploadSingleFile,
uploadRepFiles,
generateRepPDF,
generateAppealPDF,
getFilesFromBlob,
getFilesFromBlobproxy,
getFilesFromBlobHashed,
deleteBlob,
deleteRepBlob,
downloadBlob,
getProgressFromBlob,
createContainerProxy
};
-19
View File
@@ -1,19 +0,0 @@
import { consoleLogger } from "../core/logger";
export const buildEmptyValueErrorResponse = (error) => {
return {
value: [],
errorCode: error.response.status,
errorMsg: error.response.statusText
};
};
export const logAndReturnResponse = (error) => {
consoleLogger(error);
return error.response;
};
export const logAndReturnEmptyValueErrorResponse = (error) => {
consoleLogger(error);
return buildEmptyValueErrorResponse(error);
};
-9
View File
@@ -1,9 +0,0 @@
export * from "./searchService";
export * from "./caseService";
export * from "./accountService";
export * from "./portalService";
export * from "./documentService";
export * from "./referenceDataService";
export * from "./notifyService";
export * from "./adminService";
export * from "./integrationService";
@@ -1,19 +0,0 @@
import { consoleLogger } from "../core/logger";
import { requestJson } from "../clients/endpointClient";
export const createCRMTask = async (formValues) => {
var queryUrl = "/api/endpoint/createcrmtask_api";
var data = formValues;
var config = {
method: "post",
url: queryUrl,
data: data
};
try {
return await requestJson(config);
} catch (error) {
consoleLogger(error);
}
};
-3
View File
@@ -1,3 +0,0 @@
import { createCRMTask } from "./integrationDirectService";
export { createCRMTask };
-27
View File
@@ -1,27 +0,0 @@
import { consoleLogger } from "../core/logger";
import { requestJson } from "../clients/endpointClient";
export const sendEmail = async (
templateId,
emailAddress,
personalisation,
reference
) => {
var mailData = {
"templateId": templateId,
"emailAddress": emailAddress,
"reference": reference,
"personalisation": personalisation
};
try {
return await requestJson({
method: "post",
url: "/api/email/notify",
data: mailData
});
} catch (error) {
consoleLogger(error);
throw error;
}
};
-3
View File
@@ -1,3 +0,0 @@
import { sendEmail } from "./notifyDirectService";
export { sendEmail };
-309
View File
@@ -1,309 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { getJson, requestJson } from "../clients/endpointClient";
import {
deleteSignedJson,
buildSignedUrl
} from "../clients/signedRequestClient";
import {
buildFileQuery,
withBaseUrl,
appendQuerySuffix
} from "../clients/fileRouteBuilder";
export const getMyCases = (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getmycases_api", {
loggedInUserId
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getMyInvolvements = async (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getmyinvolvements_api", {
loggedInUserId
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getMyLPACases = (lpaid) => {
const route = buildFileQuery("/api/endpoint/getmylpacases_api", {
lpaid
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getMyRepresentations = (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getmyrepresentations_api", {
loggedInUserId
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getMyRepresentationsProxy = (loggedInUserId) => {
const route = buildFileQuery(
"/api/endpoint/getmyrepresentationsproxy_api",
{
loggedInUserId
}
);
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getRepresentations = (incidentID) => {
const route = buildFileQuery("/api/endpoint/getrepresentations_api", {
incidentID
});
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getRepresentationsProxy = (incidentID) => {
const route = buildFileQuery("/api/endpoint/getrepresentationsproxy_api", {
incidentID
});
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getWatchedCases = (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getwatchedcases_api", {
loggedInUserId
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const getWatchedCasesProxy = (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getwatchedcasesproxy_api", {
loggedInUserId
});
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getAwaitingSubmissionProxy = (loggedInUserId) => {
const route = buildFileQuery(
"/api/endpoint/getawaitingsubmissionproxy_api",
{
loggedInUserId
}
);
return getJson(route).catch((error) => {
consoleLogger(error);
});
};
export const getAwaitingSubmission = (loggedInUserId) => {
const route = buildFileQuery("/api/endpoint/getawaitingsubmission_api", {
loggedInUserId
});
return getJson(withBaseUrl(BASE_URL, route)).catch((error) => {
consoleLogger(error);
});
};
export const createWatchedCases = async (formValues) => {
var data = formValues;
var queryUrl = buildFileQuery("/api/endpoint/createwatchedcases_api");
var config = {
method: "post",
url: queryUrl,
data: data
};
try {
return await requestJson(config);
} catch (error) {
consoleLogger(error);
}
};
export const deleteMyRepresentations = (myRepresentationsID) => {
var queryUrl = buildFileQuery("/api/endpoint/deletemyrepresentations_api", {
myRepresentationsID
});
return deleteSignedJson(queryUrl, {
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json;odata.metadata=none",
"Prefer": 'odata.include-annotations="*",return=representation',
"Content-Type": "application/json"
}
}).catch((error) => {
consoleLogger(error);
});
};
export const deleteAwaitingSubmissions = (incidentID) => {
var queryUrl = buildFileQuery(
"/api/endpoint/deleteawaitingsubmissions_api",
{
incidentID
}
);
var config = {
method: "delete",
url: queryUrl
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const deleteWatchedCases = async (watchedCaseID) => {
var queryUrl = buildFileQuery("/api/endpoint/deletewatchedcases_api", {
watchedCaseID
});
return deleteSignedJson(queryUrl).catch((error) => {
consoleLogger(error);
});
};
export const sendCaseCompleteMessage = async (
containerID,
caseReference,
inv
) => {
var hashQueryPath = buildFileQuery(
"/api/file/createappealcompletemessage_api",
{
container: containerID,
tempcaseref: caseReference
}
);
var queryUrl = buildFileQuery("/api/file/createappealcompletemessage_api", {
container: containerID,
tempcaseref: caseReference,
inv
});
var signedQueryUrl = await buildSignedUrl(hashQueryPath);
queryUrl = appendQuerySuffix(
queryUrl,
signedQueryUrl.replace(hashQueryPath, "")
);
var config = {
method: "get",
url: queryUrl
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const sendCaseCompleteMessageProxy = async (
containerID,
caseReference
) => {
var queryUrl = buildFileQuery(
"/api/file/createappealcompletemessageproxy_api",
{
container: containerID,
tempcaseref: caseReference
}
);
var config = {
method: "get",
url: queryUrl
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const sendRepCompleteMessage = async (
containerID,
caseReference,
fileName
) => {
var hashQueryPath = buildFileQuery(
"/api/file/createrepcompletemessage_api",
{
container: containerID,
tempcaseref: caseReference,
repid: fileName
}
);
var queryUrl = await buildSignedUrl(hashQueryPath);
var config = {
method: "get",
url: queryUrl
};
return requestJson(config).catch((error) => {
consoleLogger(error);
});
};
export const setRepInvolvment = async (caseid, contactid) => {
var queryUrl = buildFileQuery("/api/file/createrepinvolvement_api");
var data = { "incidentid": caseid, "contactid": contactid };
var config = {
method: "post",
url: queryUrl,
data: data
};
try {
return await requestJson(config);
} catch (error) {
consoleLogger(error);
}
};
export const setCaseInvolvment = async (caseid, contactid) => {
var queryUrl = buildFileQuery("/api/file/createrepinvolvement_api");
var data = { "incidentid": caseid, "contactid": contactid };
var config = {
method: "post",
url: queryUrl,
data: data
};
try {
return await requestJson(config);
} catch (error) {
consoleLogger(error);
}
};
-45
View File
@@ -1,45 +0,0 @@
import {
getMyCases,
getMyInvolvements,
getMyLPACases,
getMyRepresentations,
getMyRepresentationsProxy,
getRepresentations,
getRepresentationsProxy,
getWatchedCases,
getWatchedCasesProxy,
getAwaitingSubmission,
getAwaitingSubmissionProxy,
createWatchedCases,
deleteWatchedCases,
deleteMyRepresentations,
deleteAwaitingSubmissions,
sendCaseCompleteMessage,
sendCaseCompleteMessageProxy,
sendRepCompleteMessage,
setRepInvolvment,
setCaseInvolvment
} from "./portalDirectService";
export {
getMyCases,
getMyInvolvements,
getMyLPACases,
getMyRepresentations,
getMyRepresentationsProxy,
getRepresentations,
getRepresentationsProxy,
getWatchedCases,
getWatchedCasesProxy,
getAwaitingSubmission,
getAwaitingSubmissionProxy,
createWatchedCases,
deleteWatchedCases,
deleteMyRepresentations,
deleteAwaitingSubmissions,
sendCaseCompleteMessage,
sendCaseCompleteMessageProxy,
sendRepCompleteMessage,
setRepInvolvment,
setCaseInvolvment
};
@@ -1,58 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { logAndReturnEmptyValueErrorResponse } from "./httpServiceUtils";
import { getJson } from "../clients/endpointClient";
export const getAppealsTypes = () => {
return getJson(BASE_URL + "/api/endpoint/getappealtypes_api").catch(
logAndReturnEmptyValueErrorResponse
);
};
export const getProjectTypes = () => {
return getJson(BASE_URL + "/api/endpoint/getprojecttypes_api").catch(
logAndReturnEmptyValueErrorResponse
);
};
export const getAppealsTypesForNewAppeal = () => {
return getJson(
BASE_URL + "/api/endpoint/getappealtypesfornewappeal_api"
).catch(logAndReturnEmptyValueErrorResponse);
};
export const getLPA = () => {
return getJson(BASE_URL + "/api/endpoint/getlpa_api").catch(
logAndReturnEmptyValueErrorResponse
);
};
export const getFormData = (whichForm) => {
return getJson(
BASE_URL + "/api/endpoint/getformdata_api?whichForm=" + whichForm
).catch((error) => {
consoleLogger(error);
});
};
export const getMandatoryFields = (whichForm) => {
return getJson(
BASE_URL + "/api/endpoint/getmandatoryfields_api?whichForm=" + whichForm
).catch((error) => {
consoleLogger(error);
});
};
export const getPickLists = (whichForm) => {
return getJson(
BASE_URL + "/api/endpoint/getpicklists_api?whichForm=" + whichForm
).catch((error) => {
consoleLogger(error);
});
};
export const getNotice = () => {
return getJson(BASE_URL + "/api/notices").catch((error) => {
consoleLogger(error);
});
};
-21
View File
@@ -1,21 +0,0 @@
import {
getAppealsTypes,
getProjectTypes,
getAppealsTypesForNewAppeal,
getLPA,
getFormData,
getMandatoryFields,
getPickLists,
getNotice
} from "./referenceDataDirectService";
export {
getAppealsTypes,
getProjectTypes,
getAppealsTypesForNewAppeal,
getLPA,
getFormData,
getMandatoryFields,
getPickLists,
getNotice
};
-261
View File
@@ -1,261 +0,0 @@
import { BASE_URL } from "../core/env";
import { consoleLogger } from "../core/logger";
import { getJson } from "../clients/endpointClient";
import {
logAndReturnResponse,
logAndReturnEmptyValueErrorResponse
} from "./httpServiceUtils";
export const getBasicSearch = (searchString) => {
return getJson(
BASE_URL +
"/api/endpoint/getbasicsearch_api?searchString=" +
searchString
).catch(logAndReturnResponse);
};
export const getBasicDNSURLSearch = (searchString) => {
return getJson(
BASE_URL +
"/api/endpoint/getbasicdnsurlsearch_api?searchString=" +
searchString
).catch(logAndReturnResponse);
};
export const getAddressSearchPaged = (
searchString,
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords
) => {
return getJson(
"/api/endpoint/getbasicsearch_by_address_paged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getBasicSearchPaged = (
searchString,
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords
) => {
return getJson(
"/api/endpoint/getbasicsearchpaged_api?searchString=" +
searchString +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getDNSCoords = () => {
return getJson(BASE_URL + "/api/endpoint/getdnscoords_api").catch(
logAndReturnEmptyValueErrorResponse
);
};
export const getDNSList = (searchString) => {
return getJson(BASE_URL + "/api/endpoint/getdnslist_api").catch(
logAndReturnResponse
);
};
export const getBasicDNSSearch = (searchString) => {
return getJson(BASE_URL + "/api/endpoint/getbasicdnssearch_api").catch(
logAndReturnResponse
);
};
export const getBasicDNSSearchPaged = (
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords
) => {
return getJson(
"/api/endpoint/getbasicdnssearchpaged_api?pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnResponse);
};
export const getAdvancedSearch = (searchString) => {
return getJson(
BASE_URL +
"/api/endpoint/getadvancedsearch_api?searchstring=" +
JSON.stringify(searchString)
).catch(logAndReturnEmptyValueErrorResponse);
};
export const getAdvancedSearchPaged = (
searchString,
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords
) => {
return getJson(
"/api/endpoint/getadvancedsearchpaged_api?searchstring=" +
JSON.stringify(searchString) +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords
).catch(logAndReturnEmptyValueErrorResponse);
};
export const getBasicSearchDetails = async (
appealTypeName,
caseReference,
primaryIdAttribute,
incidentID
) => {
return getJson(
BASE_URL +
"/api/endpoint/getbasicsearchdetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getBasicPartSavedDetails = (
appealTypeName,
caseReference,
primaryIdAttribute,
incidentID
) => {
return getJson(
BASE_URL +
"/api/endpoint/getbasicpartsaveddetails_api?appealTypeName=" +
appealTypeName +
"&primaryIdAttribute=" +
primaryIdAttribute +
"&incidentID=" +
incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getBasicSearchDetailsPaged = async (
appealTypeName,
caseReference,
primaryIdAttribute,
incidentIDs
) => {
if (!incidentIDs || incidentIDs.length === 0) return [];
const filter = incidentIDs
.map((id) => {
const suffix =
primaryIdAttribute === "pinswg_sipscase"
? `_${primaryIdAttribute}_value`
: `_${primaryIdAttribute}s_value`;
return `${suffix} eq ${id}`;
})
.join(" or ");
const url = `/api/endpoint/getbasicsearchdetailspaged_api?appealTypeName=${appealTypeName}&primaryIdAttribute=${primaryIdAttribute}&incidentID=${encodeURIComponent(
filter
)}`;
try {
const data = await getJson(url);
return data.value || [];
} catch (error) {
consoleLogger(error);
return [];
}
};
export const getSearchDocumentDetails = (incidentID) => {
return getJson(
"/api/endpoint/getsearchdocumentdetails_api?incidentid=" + incidentID
).catch((error) => {
consoleLogger(error);
throw error;
});
};
export const getSearchDocumentTypes = (incidentID) => {
return getJson(
"/api/endpoint/getsearchdocumentTypes_api?incidentid=" + incidentID
).catch((error) => {
consoleLogger(error);
});
};
export const getSearchDocumentDetailsPaged = (
incidentID,
pageNumber,
orderBy,
fieldSort,
showNumberOfRecords,
documentType
) => {
return getJson(
"/api/endpoint/getsearchdocumentdetailspaged_api?incidentid=" +
incidentID +
"&pageNumber=" +
pageNumber +
"&orderby=" +
orderBy +
"&fieldSort=" +
fieldSort +
"&showNumberOfRecords=" +
showNumberOfRecords +
"&documentType=" +
documentType
).catch((error) => {
consoleLogger(error);
});
};
export const getLinkedCases = (parentIncidentid) => {
return getJson(
"/api/endpoint/getlinkedcases_api?parentincidentid=" + parentIncidentid
).catch((error) => {
consoleLogger(error);
});
};
export const getAddressSearch = async (searchString) => {
const params = new URLSearchParams(searchString);
const str = params.toString();
var queryUrl =
BASE_URL + "/api/endpoint/getbasicsearch_by_address_api?" + str;
return getJson(queryUrl).catch(logAndReturnEmptyValueErrorResponse);
};
-41
View File
@@ -1,41 +0,0 @@
import {
getBasicSearch,
getAddressSearch,
getAddressSearchPaged,
getBasicSearchPaged,
getAdvancedSearch,
getAdvancedSearchPaged,
getBasicDNSURLSearch,
getBasicDNSSearch,
getBasicDNSSearchPaged,
getDNSCoords,
getDNSList,
getBasicSearchDetails,
getBasicSearchDetailsPaged,
getBasicPartSavedDetails,
getSearchDocumentDetails,
getSearchDocumentTypes,
getSearchDocumentDetailsPaged,
getLinkedCases
} from "./searchDirectService";
export {
getBasicSearch,
getAddressSearch,
getAddressSearchPaged,
getBasicSearchPaged,
getAdvancedSearch,
getAdvancedSearchPaged,
getBasicDNSURLSearch,
getBasicDNSSearch,
getBasicDNSSearchPaged,
getDNSCoords,
getDNSList,
getBasicSearchDetails,
getBasicSearchDetailsPaged,
getBasicPartSavedDetails,
getSearchDocumentDetails,
getSearchDocumentTypes,
getSearchDocumentDetailsPaged,
getLinkedCases
};
-57
View File
@@ -1,57 +0,0 @@
# Refactor Session Handoff (Usable Prompt)
## Purpose
Copy/paste this directly into a new chat session to continue the current PEDW refactor stream with the right context and next-step planning.
## Copy/Paste Prompt
```
You are continuing an in-flight refactor stream in the PEDW FrontEnd repository.
Before any analysis or code changes:
1) Ask for the Azure DevOps work item ID (required).
2) Create a new branch from `origin/SIPS-Development` prefixed with that ID (e.g. `US12345-progress-update` or `TASK67890-progress-update`).
3) Confirm branch name, then continue.
Follow this order before implementing:
1) Read `.clinerules/default-rules.md` and `.clinerules/CONTRIBUTING_AI.md`
2) Read `GUARDRAILS.md`
3) Read current-state docs:
- `context/architecture.md`
- `context/current-state-scorecard.md`
- `context/next-work-plan-sequence-b.md`
- `context/test-coverage-map.md`
4) Read memory context:
- `memory-bank/change-log.md` (latest entries)
- `memory-bank/debt-list.md`
- `memory-bank/architect-review.md`
- `memory-bank/decisions.md`
- `memory-bank/open-questions.md`
Then provide (based on what you read):
1. Current state summary (what is done, what remains)
2. Recommended next slice from this exact shortlist (pick one):
- Slice B1.1: create shared signed-request helper(s) in `actions/clients/` and migrate one pilot path in `actions/services/portalDirectService.js`
- Slice B1.2: migrate remaining signed flows in `actions/services/documentDirectService.js` to the shared signed helper(s)
- Slice B2.1: auth logging hardening in `pages/api/auth/[...nextauth].js` (redacted structured logs, no behavior change)
- Slice B2.2: file/email logging hardening in selected `pages/api/file/**` and `pages/api/email/**`
3. Exact files to change
4. Validation plan (lint + targeted tests + EN/CY parity + negative-path checks)
5. Rollback plan
Constraints:
- Preserve behavior unless explicitly requested otherwise
- Do not weaken auth/session/CSP/security flows
- Keep EN/CY parity
- Keep scope to one bounded slice per commit
- Update `memory-bank/change-log.md` for non-trivial changes
After proposing the slice, wait for approval before editing files.
```
## Best use
- Start-of-day continuation
- Branch handover between engineers/agents
- Recovery after interrupted context window
-183
View File
@@ -1,183 +0,0 @@
# Refactor Slice Execution (Usable Prompts)
## Purpose
Copy/paste one of these prompts directly to execute a specific next slice (not just a template).
## Prompt A — Slice B1.1 (signed-request helper + pilot migration)
```
Act as a senior architect + senior software engineer working in PEDW FrontEnd.
Before any analysis or code changes:
1) Ask for the Azure DevOps work item ID (required).
2) Create a new branch from `origin/SIPS-Development` prefixed with that ID (e.g. `US12345-signed-helper-pilot`).
3) Confirm branch name and only then proceed.
Goal:
Implement Slice B1.1 only: introduce shared signed-request helper(s) and migrate one pilot signed path in portal service.
Exact scope:
- Add shared signed-request helper(s) in `actions/clients/` for signed GET/POST/DELETE execution.
- Migrate one pilot signed flow in `actions/services/portalDirectService.js` to use the helper.
- Do not migrate additional modules in this slice.
Mandatory context to read before coding:
- `.clinerules/default-rules.md`
- `GUARDRAILS.md`
- `context/architecture.md`
- `context/current-state-scorecard.md`
- `context/next-work-plan-sequence-b.md`
- `memory-bank/debt-list.md`
- latest relevant `memory-bank/change-log.md` entries
Required output before edits:
1. Scope and non-goals
2. Risks and how they are contained
3. Files to touch
4. Acceptance criteria
5. Validation checklist
Implementation constraints:
- Smallest viable diff
- Preserve API/route/public behavior
- Preserve auth/session/security and EN/CY parity
- No dependency churn unless required by scope
- No unrelated cleanup
Validation minimum:
- `npm run lint`
- `node tests/phase22/index.test.cjs`
- `node tests/phase7/service-behaviour.test.cjs`
- explicit negative-path verification for sensitive flows
Completion output:
1. Files changed
2. Behavior parity statement
3. Validation evidence (commands + pass/fail)
4. Rollback steps
5. `memory-bank/change-log.md` entry content
```
## Prompt B — Slice B1.2 (document signed-flow migration)
```
Act as a senior architect + senior software engineer working in PEDW FrontEnd.
Before any analysis or code changes:
1) Ask for the Azure DevOps work item ID (required).
2) Create a new branch from `origin/SIPS-Development` prefixed with that ID (e.g. `TASK67890-document-signed-migration`).
3) Confirm branch name and only then proceed.
Goal:
Implement Slice B1.2 only: migrate remaining signed flows in `documentDirectService` to shared signed-request helper(s) with no behavior change.
Exact scope:
- Update `actions/services/documentDirectService.js` signed GET/POST/DELETE paths to use shared signed helper(s).
- Preserve hash generation, headers, methods, and catch-path behavior.
- Do not modify unrelated services.
Mandatory context to read before coding:
- `.clinerules/default-rules.md`
- `GUARDRAILS.md`
- `context/architecture.md`
- `context/current-state-scorecard.md`
- `context/next-work-plan-sequence-b.md`
- `context/test-coverage-map.md`
- latest relevant `memory-bank/change-log.md` entries
Required output before edits:
1. Scope and non-goals
2. Risks and containment
3. Files to touch
4. Acceptance criteria
5. Validation checklist
Validation minimum:
- `npm run lint`
- `node tests/phase22/index.test.cjs`
- `node tests/phase7/service-behaviour.test.cjs`
Completion output:
1. Files changed
2. Behavior parity statement
3. Validation evidence
4. Rollback steps
5. `memory-bank/change-log.md` entry
```
## Prompt C — Slice B2.1 (auth logging hardening)
```
Act as a senior architect + senior software engineer working in PEDW FrontEnd.
Before any analysis or code changes:
1) Ask for the Azure DevOps work item ID (required).
2) Create a new branch from `origin/SIPS-Development` prefixed with that ID (e.g. `US12345-auth-logging-hardening`).
3) Confirm branch name and only then proceed.
Goal:
Implement Slice B2.1 only: harden logging in `pages/api/auth/[...nextauth].js` using redacted structured logging with no behavior change.
Exact scope:
- Replace sensitive/verbose direct logs in auth route with structured logger usage.
- Do not alter auth/session/redirect functional behavior.
Mandatory context to read before coding:
- `.clinerules/default-rules.md`
- `GUARDRAILS.md`
- `context/architecture.md`
- `context/next-work-plan-sequence-b.md`
- `memory-bank/open-questions.md` (Q-001)
Validation minimum:
- `npm run lint`
- `node tests/phase22/auth-redirect-safety.test.cjs`
- targeted manual negative-path check for auth error logging paths
Completion output must include:
1. Redaction policy applied (fields excluded)
2. Files changed
3. Behavior parity statement
4. Validation evidence
5. Rollback plan
6. `memory-bank/change-log.md` update text
```
## Prompt D — Slice B2.2 (file/email logging hardening cluster)
```
Act as a senior architect + senior software engineer working in PEDW FrontEnd.
Before any analysis or code changes:
1) Ask for the Azure DevOps work item ID (required).
2) Create a new branch from `origin/SIPS-Development` prefixed with that ID (e.g. `TASK67890-file-email-logging-hardening`).
3) Confirm branch name and only then proceed.
Goal:
Implement Slice B2.2 only: harden logging in one bounded file/email route cluster using redacted structured logs.
Exact scope:
- Choose a small cluster in `pages/api/file/**` and/or `pages/api/email/**`.
- Replace risky direct logs with structured redacted logging.
- Preserve endpoint contracts and negative-path semantics.
Validation minimum:
- `npm run lint`
- targeted tests for changed handlers
- explicit negative-path check(s) for unauthorized/invalid input behavior
Completion output:
1. Cluster chosen and why
2. Files changed
3. Redaction fields/policy applied
4. Validation evidence
5. Rollback steps
6. `memory-bank/change-log.md` update text
```
## Best use
- Run Sequence B slices as independent, reviewable commits
- Start a fresh chat and execute one prompt at a time
- Keep each slice bounded with explicit rollback
+5 -5
View File
@@ -4,7 +4,7 @@ import { useRouter } from "next/router";
import React, { useState } from "react"; import React, { useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { Field, formValueSelector, reduxForm } from "redux-form"; import { Field, formValueSelector, reduxForm } from "redux-form";
import { updatePassword } from "../../actions/services/accountService"; import { updatePassword } from "../../actions";
const RenderTextfield = ({ const RenderTextfield = ({
id, id,
@@ -60,7 +60,7 @@ const ChangePassword = (props) => {
handleSubmit, handleSubmit,
value, value,
setPasswordUpdated, setPasswordUpdated,
passwordUpdated passwordUpdated,
} = props; } = props;
let { t, lang } = useTranslation(); let { t, lang } = useTranslation();
@@ -158,7 +158,7 @@ const mapStateToProps = (state) => {
searchResultsObj: state.searchResultsObj, searchResultsObj: state.searchResultsObj,
formData: state.formData, formData: state.formData,
appealType: state.appealType, appealType: state.appealType,
accountDetails: state.accountDetails accountDetails: state.accountDetails,
//form: state.form, //form: state.form,
}; };
}; };
@@ -167,7 +167,7 @@ const mapDispatchToProps = (dispatch) => {
return { return {
setCurrentSection: (currentSection) => { setCurrentSection: (currentSection) => {
dispatch(setCurrentSection(currentSection)); dispatch(setCurrentSection(currentSection));
} },
}; };
}; };
@@ -179,6 +179,6 @@ export default connect(
)( )(
reduxForm({ reduxForm({
form: "changepasswordForm", form: "changepasswordForm",
destroyOnUnmount: false destroyOnUnmount: false,
})(ChangePassword) })(ChangePassword)
); );
+5 -16
View File
@@ -246,7 +246,6 @@ let PersonalDetails = (props) => {
return ( return (
<> <>
<div className="govuk-form-group">
{props.accountUpdatedComplete == false ? ( {props.accountUpdatedComplete == false ? (
props.personalDetailsComplete == false ? ( props.personalDetailsComplete == false ? (
<form onSubmit={handleSubmit(onHandleSubmit)}> <form onSubmit={handleSubmit(onHandleSubmit)}>
@@ -287,9 +286,7 @@ let PersonalDetails = (props) => {
type="text" type="text"
className="govuk-input govuk-input--width-20" className="govuk-input govuk-input--width-20"
validate={[required]} validate={[required]}
label={t( label={t("account:account-first-name-label")}
"account:account-first-name-label"
)}
errorMsg={t("account:is-required-label")} errorMsg={t("account:is-required-label")}
/> />
<Field <Field
@@ -309,9 +306,7 @@ let PersonalDetails = (props) => {
type="email" type="email"
className="govuk-input govuk-input--width-20" className="govuk-input govuk-input--width-20"
validate={[required, email]} validate={[required, email]}
label={t( label={t("account:account-email-address-label")}
"account:account-email-address-label"
)}
disabled disabled
/> />
<Field <Field
@@ -329,18 +324,14 @@ let PersonalDetails = (props) => {
component={RenderTextfield} component={RenderTextfield}
type="text" type="text"
className="govuk-input govuk-input--width-20" className="govuk-input govuk-input--width-20"
label={t( label={t("account:account-company-group-label")}
"account:account-company-group-label"
)}
errorMsg={t("account:is-required-label")} errorMsg={t("account:is-required-label")}
/> />
</fieldset> </fieldset>
<fieldset className="govuk-fieldset"> <fieldset className="govuk-fieldset">
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m"> <legend className="govuk-fieldset__legend govuk-fieldset__legend--m">
<h2 className="govuk-fieldset__heading"> <h2 className="govuk-fieldset__heading">
{t( {t("account:account-your-address-label")}
"account:account-your-address-label"
)}
</h2> </h2>
</legend> </legend>
@@ -408,8 +399,7 @@ let PersonalDetails = (props) => {
<Link <Link
href={ href={
"/myportal?q=" + "/myportal?q=" +
props.props.accountDetails props.props.accountDetails.loggedinUserId
.loggedinUserId
} }
className="govuk-link" className="govuk-link"
> >
@@ -433,7 +423,6 @@ let PersonalDetails = (props) => {
) : ( ) : (
<PersonalDetailsComplete props={props} /> <PersonalDetailsComplete props={props} />
)} )}
</div>
</> </>
); );
}; };
+12 -39
View File
@@ -3,54 +3,28 @@ import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { updateAccount } from "../../actions/services/accountService"; import { updateAccount } from "../../actions";
import { setCookie } from "nookies";
const PersonalDetailsComplete = (props) => { const PersonalDetailsComplete = (props) => {
const { const {
handleSubmit, handleSubmit,
value, value,
setRegisterFormComplete, setRegisterFormComplete,
setAccountCreatedComplete setAccountCreatedComplete,
} = props; } = props;
let { t, lang } = useTranslation(); let { t, lang } = useTranslation();
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
// let contactid = props.accountDetails.loggedinUserId;
// let updateBody = props.props.props.form.personalDetailsForm.values;
// let prefLang =
// props.props.props.form.personalDetailsForm.values
// .pinswg_preferredlanguage;
const { loggedinUserId } = props.accountDetails || {};
const formValues = props.props?.props?.form?.personalDetailsForm?.values;
const prefLang = formValues?.pinswg_preferredlanguage;
const userLang = prefLang === "846040000" ? "cy" : "en"; // Move this outside useEffect
useEffect(() => { useEffect(() => {
// let contactid = props.accountDetails.loggedinUserId; let contactid = props.accountDetails.loggedinUserId;
// let updateBody = props.props.props.form.personalDetailsForm.values; let updateBody = props.props.props.form.personalDetailsForm.values;
// let prefLang = updateAccount(contactid, updateBody);
// props.props.props.form.personalDetailsForm.values }, [
// .pinswg_preferredlanguage; props.accountDetails.loggedinUserId,
if (!loggedinUserId || !formValues) return; props.props.props.form.personalDetailsForm.values,
]);
console.log("=============== pref lang", prefLang);
setCookie(null, "pedw_locale", userLang, {
path: "/"
});
console.log("Set cookie to:", userLang);
async function doUpdate() {
const response = await updateAccount(loggedinUserId, formValues);
}
doUpdate();
}, [loggedinUserId, formValues, prefLang]);
return ( return (
<> <>
@@ -60,8 +34,7 @@ const PersonalDetailsComplete = (props) => {
<p className="govuk-body"> <p className="govuk-body">
<Link <Link
locale={userLang} href={"/myportal?q=" + props.accountDetails.loggedinUserId}
href={userLang === "cy" ? "/cy/fymhorth" : "/myportal"}
className="govuk-link" className="govuk-link"
> >
{" "} {" "}
@@ -78,7 +51,7 @@ const mapStateToProps = (state) => {
searchResultsObj: state.searchResultsObj, searchResultsObj: state.searchResultsObj,
formData: state.formData, formData: state.formData,
appealType: state.appealType, appealType: state.appealType,
accountDetails: state.accountDetails accountDetails: state.accountDetails,
//form: state.form, //form: state.form,
}; };
}; };
@@ -87,7 +60,7 @@ const mapDispatchToProps = (dispatch) => {
return { return {
setCurrentSection: (currentSection) => { setCurrentSection: (currentSection) => {
dispatch(setCurrentSection(currentSection)); dispatch(setCurrentSection(currentSection));
} },
}; };
}; };
+7 -10
View File
@@ -8,10 +8,7 @@ import { connect } from "react-redux";
import { setAccCr, setLogout } from "../../store/accountDetails/action"; import { setAccCr, setLogout } from "../../store/accountDetails/action";
import { import { createAccount, getEmailAccountCheck } from "../../actions";
createAccount,
getEmailAccountCheck
} from "../../actions/services/accountService";
const RegisterComplete = (props) => { const RegisterComplete = (props) => {
const { const {
@@ -21,7 +18,7 @@ const RegisterComplete = (props) => {
value, value,
setRegisterFormComplete, setRegisterFormComplete,
setAccountCreatedComplete, setAccountCreatedComplete,
setAccCr setAccCr,
} = props; } = props;
let { t, lang } = useTranslation(); let { t, lang } = useTranslation();
@@ -37,7 +34,7 @@ const RegisterComplete = (props) => {
// was an appellant "pinswg_typeofinvolvement": 846040001, // was an appellant "pinswg_typeofinvolvement": 846040001,
Object.assign(accountBody, { Object.assign(accountBody, {
"pinswg_typeofinvolvement": 846040061 "pinswg_typeofinvolvement": 846040061,
}); });
accountBody = _.omit(accountBody, ["custom_password_check"]); accountBody = _.omit(accountBody, ["custom_password_check"]);
@@ -108,9 +105,9 @@ const RegisterComplete = (props) => {
<p className="govuk-body"> <p className="govuk-body">
<a <a
onClick={() => { onClick={() => {
(setRegisterFormComplete(false), setRegisterFormComplete(false),
setAccountCreatedComplete(false), setAccountCreatedComplete(false),
setAccCr(false)); setAccCr(false);
}} }}
className="govuk-link" className="govuk-link"
> >
@@ -133,7 +130,7 @@ const mapStateToProps = (state) => {
searchResultsObj: state.searchResultsObj, searchResultsObj: state.searchResultsObj,
formData: state.formData, formData: state.formData,
appealType: state.appealType, appealType: state.appealType,
accountDetails: state.accountDetails accountDetails: state.accountDetails,
//form: state.form, //form: state.form,
}; };
}; };
@@ -145,7 +142,7 @@ const mapDispatchToProps = (dispatch) => {
}, },
setLogout: () => { setLogout: () => {
dispatch(setLogout()); dispatch(setLogout());
} },
}; };
}; };
-4
View File
@@ -137,8 +137,6 @@ const RegisterForm = (props) => {
{props.accountCreatedComplete != true ? ( {props.accountCreatedComplete != true ? (
props.registerFormComplete == false ? ( props.registerFormComplete == false ? (
<form onSubmit={handleSubmit(onHandleSubmit)}> <form onSubmit={handleSubmit(onHandleSubmit)}>
<div className="card" id="personalDetailsCard">
<div className="card-body">
<fieldset className="govuk-fieldset"> <fieldset className="govuk-fieldset">
<legend className="govuk-fieldset__legend govuk-fieldset__legend--m"> <legend className="govuk-fieldset__legend govuk-fieldset__legend--m">
<h2 className="govuk-fieldset__heading"> <h2 className="govuk-fieldset__heading">
@@ -283,8 +281,6 @@ const RegisterForm = (props) => {
{t("common:continue-button")} {t("common:continue-button")}
</button> </button>
</div> </div>
</div>
</div>
</form> </form>
) : ( ) : (
<RegisterFormCheck <RegisterFormCheck
+14 -15
View File
@@ -9,15 +9,14 @@ import { connect } from "react-redux";
import { import {
setSearchResults, setSearchResults,
setSearchDetails setSearchDetails,
} from "../../../store/searchOutput/action"; } from "../../../store/searchOutput/action";
import { getDetailsProxy, getSearchDetailsPaged } from "../../utils"; import { getDetailsProxy, getSearchDetailsPaged } from "../../utils";
import { getAdvancedSearchPaged } from "../../../actions/services/searchService"; import { getAdvancedSearchPaged, getNewAppealsPage } from "../../../actions";
import { getNewAppealsPage } from "../../../actions/services/adminService";
import { import {
setCurrentPage, setCurrentPage,
setCurrentReference setCurrentReference,
} from "../../../store/currentView/action"; } from "../../../store/currentView/action";
function AppealsTab(props) { function AppealsTab(props) {
@@ -87,7 +86,7 @@ function AppealsTab(props) {
searchString, searchString,
selectedOption, selectedOption,
props.setSearchDetails, props.setSearchDetails,
props.setSearchResults props.setSearchResults,
] ]
); );
@@ -106,7 +105,7 @@ function AppealsTab(props) {
orderByState, orderByState,
searchLoaded, searchLoaded,
getSearchPageResults, getSearchPageResults,
router.query router.query,
]); ]);
const ResultsView = (resultsArr) => { const ResultsView = (resultsArr) => {
@@ -226,7 +225,7 @@ function AppealsTab(props) {
item.ticketnumber + item.ticketnumber +
'")]', '")]',
json: searchDetailsObj, json: searchDetailsObj,
eval: true eval: true,
}); });
detailsObj = detailsObj[0] || {}; detailsObj = detailsObj[0] || {};
@@ -276,7 +275,7 @@ function AppealsTab(props) {
"pinswg_specialistcaseprocess" "pinswg_specialistcaseprocess"
) )
? detailsObj.pinswg_specialistcaseprocess ? detailsObj.pinswg_specialistcaseprocess
: "" : "",
}); });
}} }}
> >
@@ -397,7 +396,7 @@ function AppealsTab(props) {
" " + " " +
item.pinswg_appellantlastname item.pinswg_appellantlastname
: _.has(detailsObj, [ : _.has(detailsObj, [
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue" "_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue",
]) ])
? detailsObj[ ? detailsObj[
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue" "_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue"
@@ -412,7 +411,7 @@ function AppealsTab(props) {
: :
</span> </span>
{_.has(item, [ {_.has(item, [
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue",
]) ])
? router.locale == "cy" ? router.locale == "cy"
? jsonpath({ ? jsonpath({
@@ -423,7 +422,7 @@ function AppealsTab(props) {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item[ : item[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
@@ -446,7 +445,7 @@ function AppealsTab(props) {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item[ : item[
"pinswg_appealcasetype@OData.Community.Display.V1.FormattedValue" "pinswg_appealcasetype@OData.Community.Display.V1.FormattedValue"
@@ -469,7 +468,7 @@ function AppealsTab(props) {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item[ : item[
"statuscode@OData.Community.Display.V1.FormattedValue" "statuscode@OData.Community.Display.V1.FormattedValue"
@@ -556,13 +555,13 @@ const mapDispatchToProps = (dispatch) => {
}, },
setCurrentPage: (currentPage) => { setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage)); dispatch(setCurrentPage(currentPage));
} },
}; };
}; };
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
searchResultsObj: state.searchResultsObj searchResultsObj: state.searchResultsObj,
}; };
}; };
+89 -59
View File
@@ -5,7 +5,7 @@ import { useRouter } from "next/router";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import transLookup from "../../../data/lookuptranslations.json"; import transLookup from "../../../data/lookuptranslations.json";
import { formatDates, getDocLink } from "../../utils"; import { formatDates } from "../../utils";
import PaginationControl from "../../../components/case/pagination"; import PaginationControl from "../../../components/case/pagination";
import DocumentLink from "../../utils/downloads"; import DocumentLink from "../../utils/downloads";
import { useDownloadQueue } from "../../utils/downloadmanager"; import { useDownloadQueue } from "../../utils/downloadmanager";
@@ -15,177 +15,177 @@ import { sendGAEvent } from "@next/third-parties/google";
import { import {
getSearchDocumentDetails, getSearchDocumentDetails,
getSearchDocumentDetailsPaged, getSearchDocumentDetailsPaged,
getSearchDocumentTypes getSearchDocumentTypes,
} from "../../../actions/services/searchService"; getNewDocumentsPaged,
import { getNewDocumentsPaged } from "../../../actions/services/adminService"; } from "../../../actions";
import { setCurrentPage } from "../../../store/currentView/action"; import { setCurrentPage } from "../../../store/currentView/action";
import { setDocumentDetails } from "../../../store/searchOutput/action"; import { setDocumentDetails } from "../../../store/searchOutput/action";
const getDocumentTypes = [ const getDocumentTypes = [
{ {
"Value": 846040009, "Value": 846040009,
"Label": "Main Party - Pre-Submission Docs" "Label": "Main Party - Pre-Submission Docs",
}, },
{ {
"Value": 846040000, "Value": 846040000,
"Label": "Main Party - Submission Document" "Label": "Main Party - Submission Document",
}, },
{ {
"Value": 846040001, "Value": 846040001,
"Label": "Main Party - Questionnaire" "Label": "Main Party - Questionnaire",
}, },
{ {
"Value": 846040002, "Value": 846040002,
"Label": "Main Party - Statements" "Label": "Main Party - Statements",
}, },
{ {
"Value": 846040003, "Value": 846040003,
"Label": "Main Party - Comments" "Label": "Main Party - Comments",
}, },
{ {
"Value": 846040004, "Value": 846040004,
"Label": "Main Party - Written Statements of Evidence" "Label": "Main Party - Written Statements of Evidence",
}, },
{ {
"Value": 846040010, "Value": 846040010,
"Label": "Main Party - Environmental Statements" "Label": "Main Party - Environmental Statements",
}, },
{ {
"Value": 846040005, "Value": 846040005,
"Label": "Interested Party Representations" "Label": "Interested Party Representations",
}, },
{ {
"Value": 846040006, "Value": 846040006,
"Label": "Correspondence" "Label": "Correspondence",
}, },
{ {
"Value": 846040008, "Value": 846040008,
"Label": "Inspector Notes" "Label": "Inspector Notes",
}, },
{ {
"Value": 846040007, "Value": 846040007,
"Label": "Final Decision/Report" "Label": "Final Decision/Report",
}, },
{ {
"Value": 846040011, "Value": 846040011,
"Label": "Post Decision Correspondence" "Label": "Post Decision Correspondence",
}, },
{ {
"Value": 846040012, "Value": 846040012,
"Label": "High Court Challenge Correspondence" "Label": "High Court Challenge Correspondence",
}, },
{ {
"Value": 846040013, "Value": 846040013,
"Label": "Event - Correspondence" "Label": "Event - Correspondence",
}, },
{ {
"Value": 846040014, "Value": 846040014,
"Label": "Event - Documents" "Label": "Event - Documents",
}, },
{ {
"Value": 846040015, "Value": 846040015,
"Label": "Pre-Application - General" "Label": "Pre-Application - General",
}, },
{ {
"Value": 846040016, "Value": 846040016,
"Label": "Pre-Application - EIA Screening" "Label": "Pre-Application - EIA Screening",
}, },
{ {
"Value": 846040017, "Value": 846040017,
"Label": "Pre-Application - EIA Scoping" "Label": "Pre-Application - EIA Scoping",
}, },
{ {
"Value": 846040018, "Value": 846040018,
"Label": "EIA Screening" "Label": "EIA Screening",
}, },
{ {
"Value": 846040019, "Value": 846040019,
"Label": "EIA Scoping" "Label": "EIA Scoping",
}, },
{ {
"Value": 846040020, "Value": 846040020,
"Label": "Pre-Application Services Documents" "Label": "Pre-Application Services Documents",
}, },
{ {
"Value": 846040021, "Value": 846040021,
"Label": "Notification" "Label": "Notification",
}, },
{ {
"Value": 846040022, "Value": 846040022,
"Label": "Label":
"Submission - Environmental Statement - written statement and NTS" "Submission - Environmental Statement - written statement and NTS",
}, },
{ {
"Value": 846040023, "Value": 846040023,
"Label": "Submission - Environmental Statement - Appendices" "Label": "Submission - Environmental Statement - Appendices",
}, },
{ {
"Value": 846040024, "Value": 846040024,
"Label": "Submission - Environmental Statement - Figures" "Label": "Submission - Environmental Statement - Figures",
}, },
{ {
"Value": 846040025, "Value": 846040025,
"Label": "Submission - Draft Infrastructure Consent Orders" "Label": "Submission - Draft Infrastructure Consent Orders",
}, },
{ {
"Value": 846040026, "Value": 846040026,
"Label": "Submission - Compulsory Acquisition Information" "Label": "Submission - Compulsory Acquisition Information",
}, },
{ {
"Value": 846040027, "Value": 846040027,
"Label": "Submission - Application Documents" "Label": "Submission - Application Documents",
}, },
{ {
"Value": 846040028, "Value": 846040028,
"Label": "Examination Notices" "Label": "Examination Notices",
}, },
{ {
"Value": 846040029, "Value": 846040029,
"Label": "Local/Marine Impact Reports" "Label": "Local/Marine Impact Reports",
}, },
{ {
"Value": 846040030, "Value": 846040030,
"Label": "Submission - Further Information" "Label": "Submission - Further Information",
}, },
{ {
"Value": 846040031, "Value": 846040031,
"Label": "Formal Variation requests" "Label": "Formal Variation requests",
}, },
{ {
"Value": 846040032, "Value": 846040032,
"Label": "Further Information - Interested Party Representations" "Label": "Further Information - Interested Party Representations",
}, },
{ {
"Value": 846040033, "Value": 846040033,
"Label": "Hearing Statements" "Label": "Hearing Statements",
}, },
{ {
"Value": 846040034, "Value": 846040034,
"Label": "Events - Recordings" "Label": "Events - Recordings",
}, },
{ {
"Value": 846040035, "Value": 846040035,
"Label": "Internal Correspondence" "Label": "Internal Correspondence",
}, },
{ {
"Value": 846040036, "Value": 846040036,
"Label": "Consultation Response" "Label": "Consultation Response",
} },
]; ];
const getOrigin = [ const getOrigin = [
{ {
"Value": 846040000, "Value": 846040000,
"Label": "MDU" "Label": "MDU",
}, },
{ {
"Value": 846040001, "Value": 846040001,
"Label": "Portal" "Label": "Portal",
}, },
{ {
"Value": 846040002, "Value": 846040002,
"Label": "Manual" "Label": "Manual",
} },
]; ];
const DocumentsTab = (props) => { const DocumentsTab = (props) => {
@@ -200,7 +200,7 @@ const DocumentsTab = (props) => {
setDocumentDetails, setDocumentDetails,
setCurrentPage, setCurrentPage,
docsOffline, docsOffline,
showFilteredDocs showFilteredDocs,
} = props; } = props;
const router = useRouter(); const router = useRouter();
@@ -236,7 +236,7 @@ const DocumentsTab = (props) => {
setCheckedItems((prev) => ({ setCheckedItems((prev) => ({
...prev, ...prev,
[name]: checked [name]: checked,
})); }));
setSelectAll(false); setSelectAll(false);
}; };
@@ -246,7 +246,7 @@ const DocumentsTab = (props) => {
setCheckedOriginItems((prev) => ({ setCheckedOriginItems((prev) => ({
...prev, ...prev,
[name]: checked [name]: checked,
})); }));
setSelectOriginAll(false); setSelectOriginAll(false);
}; };
@@ -305,7 +305,37 @@ const DocumentsTab = (props) => {
setSelectedDocumentOrigin("all") setSelectedDocumentOrigin("all")
); );
}; };
let ShowDocLinks = getDocLink(docsOffline); let ShowDocLinks = false;
let checkShowDocLinks = docsOffline != false ? true : false;
const getDocLink = (docsOffline) => {
var startTime = docsOffline.split(",")[0];
var endTime = docsOffline.split(",")[1];
// console.log(startTime);
// console.log(endTime);
var currentDate = new Date();
var startDate = new Date(currentDate.getTime());
startDate.setHours(startTime.split(":")[0]);
startDate.setMinutes(startTime.split(":")[1]);
startDate.setSeconds(startTime.split(":")[2]);
var endDate = new Date(currentDate.getTime());
endDate.setHours(endTime.split(":")[0]);
endDate.setMinutes(endTime.split(":")[1]);
endDate.setSeconds(endTime.split(":")[2]);
// console.log(startDate);
// console.log(endDate);
// console.log(currentDate);
var valid = startDate < currentDate && endDate > currentDate;
ShowDocLinks = valid;
};
checkShowDocLinks && getDocLink(docsOffline);
const FilteredDocumentView = (documentDetailsArr) => { const FilteredDocumentView = (documentDetailsArr) => {
documentDetailsArr = documentDetailsArr.value; documentDetailsArr = documentDetailsArr.value;
@@ -404,7 +434,7 @@ const DocumentsTab = (props) => {
item.Label + item.Label +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item.Label || : item.Label ||
t( t(
@@ -477,7 +507,7 @@ const DocumentsTab = (props) => {
item.Label + item.Label +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item.Label || : item.Label ||
t( t(
@@ -496,7 +526,7 @@ const DocumentsTab = (props) => {
const checkedValues = [ const checkedValues = [
...document.querySelectorAll( ...document.querySelectorAll(
".govuk-checkboxes__input:checked" ".govuk-checkboxes__input:checked"
) ),
].map((e) => e.value); ].map((e) => e.value);
const origins = checkedValues const origins = checkedValues
@@ -697,7 +727,7 @@ const DocumentsTab = (props) => {
incidentid + incidentid +
"')]", "')]",
json: item, json: item,
eval: true eval: true,
}); });
detailsObj = item; detailsObj = item;
return ( return (
@@ -831,7 +861,7 @@ const DocumentsTab = (props) => {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: detailsObj[ : detailsObj[
"pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue" "pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue"
@@ -946,7 +976,7 @@ const DocumentsTab = (props) => {
selectedDocumentType, selectedDocumentType,
selectedWeeks, selectedWeeks,
selectedDocumentOrigin, selectedDocumentOrigin,
props.setDocumentDetails props.setDocumentDetails,
] ]
); );
@@ -1081,7 +1111,7 @@ const DocumentsTab = (props) => {
getOrigin, getOrigin,
getDocumentResults, getDocumentResults,
lang, lang,
selectedWeeks selectedWeeks,
]); ]);
function countFieldValue(obj, field, targetValue) { function countFieldValue(obj, field, targetValue) {
@@ -1166,7 +1196,7 @@ const DocumentsTab = (props) => {
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
...state ...state,
}; };
}; };
@@ -1177,7 +1207,7 @@ const mapDispatchToProps = (dispatch) => {
}, },
setCurrentPage: (currentPage) => { setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage)); dispatch(setCurrentPage(currentPage));
} },
}; };
}; };
+8 -8
View File
@@ -4,9 +4,9 @@ import Link from "next/link";
import { bytesToSize } from "../../../components/utils"; import { bytesToSize } from "../../../components/utils";
import { import {
deleteMyRepresentationsFromBlob, deleteMyRepresentationsFromBlob,
deleteAwaitingSubmissionsFromBlob deleteAwaitingSubmissionsFromBlob,
} from "../../../actions/services/documentService"; sendRepCompleteMessage,
import { sendRepCompleteMessage } from "../../../actions/services/portalService"; } from "../../../actions";
import { formatBlobDates } from "../utils/adminHelper"; import { formatBlobDates } from "../utils/adminHelper";
@@ -150,7 +150,7 @@ export default function StorageTab({ data, repCompleteCount }) {
headers: headers:
{ {
"Content-Type": "Content-Type":
"application/json" "application/json",
}, },
body: JSON.stringify( body: JSON.stringify(
{ {
@@ -159,18 +159,18 @@ export default function StorageTab({ data, repCompleteCount }) {
blobName: blobName:
folder folder
.repJsonBlob .repJsonBlob
.name .name,
} }
) ),
} }
); );
const result = const result =
await response.json(); await response.json();
if (response.ok) { if (response.ok) {
(alert( alert(
"repComplete removed!" "repComplete removed!"
), ),
window.location.reload()); window.location.reload();
// Optionally refresh the page or update UI state here // Optionally refresh the page or update UI state here
} else { } else {
alert( alert(
+9 -17
View File
@@ -5,9 +5,9 @@ import { PrismaClient } from "@prisma/client";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import { getUpToLastSlash, streamToString } from "../utils/adminHelper"; import { getUpToLastSlash, streamToString } from "../utils/adminHelper";
import { listContainersForUser } from "../../../actions/azurestorage"; import { listContainersForUser } from "../../../actions/azurestorage";
import pLimit from "p-limit";
const prisma = global.prisma || new PrismaClient(); const prisma = global.prisma || new PrismaClient();
const WORDKEY = process.env.HASHKEY;
/** /**
* Generate HMAC hash for blob API link. * Generate HMAC hash for blob API link.
*/ */
@@ -34,10 +34,8 @@ export async function fetchAdminStorageData() {
const users = await prisma.user.findMany(); const users = await prisma.user.findMany();
const limit = pLimit(5);
let data = await Promise.all( let data = await Promise.all(
users.map(async (user) => { users.map(async (user) => {
limit(async () => {
const containers = await listContainersForUser( const containers = await listContainersForUser(
blobServiceClient, blobServiceClient,
`${user.id}`, `${user.id}`,
@@ -56,9 +54,7 @@ export async function fetchAdminStorageData() {
`/api/file/downloadblob?container=${ `/api/file/downloadblob?container=${
container.container container.container
}&casefolderID=${folderPath}&blobname=${blob.name }&casefolderID=${folderPath}&blobname=${blob.name
.substring( .substring(blob.name.lastIndexOf("/") + 1)
blob.name.lastIndexOf("/") + 1
)
.trim()}`, .trim()}`,
process.env.HASHKEY process.env.HASHKEY
); );
@@ -66,13 +62,12 @@ export async function fetchAdminStorageData() {
const fileNameOnly = blob.name.substring( const fileNameOnly = blob.name.substring(
blob.name.lastIndexOf("/") + 1 blob.name.lastIndexOf("/") + 1
); );
const isTmpFile = const isTmpFile = fileNameOnly.startsWith("TMP-");
fileNameOnly.startsWith("TMP-");
const blobWithHash = { const blobWithHash = {
...blob, ...blob,
hashedfilepath, hashedfilepath,
isTmpFile isTmpFile,
}; };
let folderGroup = acc.find( let folderGroup = acc.find(
@@ -85,7 +80,7 @@ export async function fetchAdminStorageData() {
hasRepJson: false, hasRepJson: false,
repJsonBlob: null, repJsonBlob: null,
repComplete: false, repComplete: false,
hasTmpFile: false hasTmpFile: false,
}; };
acc.push(folderGroup); acc.push(folderGroup);
} }
@@ -97,9 +92,7 @@ export async function fetchAdminStorageData() {
} }
// rep.json handling // rep.json handling
if ( if (blob.name.toLowerCase().endsWith("rep.json")) {
blob.name.toLowerCase().endsWith("rep.json")
) {
folderGroup.hasRepJson = true; folderGroup.hasRepJson = true;
folderGroup.repJsonBlob = blobWithHash; folderGroup.repJsonBlob = blobWithHash;
@@ -144,10 +137,9 @@ export async function fetchAdminStorageData() {
? { ? {
id: user.id, id: user.id,
email: user.email, email: user.email,
containers: containersWithHashes containers: containersWithHashes,
} }
: null; : null;
});
}) })
); );
@@ -158,7 +150,7 @@ export async function fetchAdminStorageData() {
.map((user) => ({ .map((user) => ({
id: user.id, id: user.id,
email: user.email, email: user.email,
created: user.emailVerified?.toLocaleString("en-GB") || "" created: user.emailVerified?.toLocaleString("en-GB") || "",
})); }));
let repCompleteCount = 0; let repCompleteCount = 0;
+1133 -274
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -42,8 +42,6 @@ const Case = (props) => {
documentDetailsObj={props.documentDetailsObj} documentDetailsObj={props.documentDetailsObj}
showFilteredDocs={props.showFilteredDocs} showFilteredDocs={props.showFilteredDocs}
showLoginCheck={props.showLoginCheck} showLoginCheck={props.showLoginCheck}
eventsObj={props.eventsObj}
mediaObj={props.mediaObj}
/> />
{showRepresentations == true && ( {showRepresentations == true && (
<RepresentationList <RepresentationList
+7 -29
View File
@@ -15,22 +15,12 @@ export default function CaseNoticeBanner(props) {
const bannerOpenCookie = typeof cookie.get("pedwNotice") == "undefined"; const bannerOpenCookie = typeof cookie.get("pedwNotice") == "undefined";
let messagesObjArr = messagesObj.value; let messagesObjArr = messagesObj.value;
let todaysDate = new Date();
return ( return (
<> <>
{messagesObjArr.map((message, index) => ( {messagesObjArr.map((message, index) => (
<div key={index}> <div className="govuk-warning-text noticebanner" key={index}>
{todaysDate.toISOString() >= message.scheduledstart &&
todaysDate.toISOString() <= message.scheduledend && (
<div
className="govuk-warning-text noticebanner"
key={index}
>
<strong className="govuk-warning-text__text"> <strong className="govuk-warning-text__text">
<span className="govuk-visually-hidden"> <span className="govuk-visually-hidden">Warning</span>
{t("case:notice-label")}
</span>
</strong> </strong>
<div> <div>
<div className=" govuk-body-s"> <div className=" govuk-body-s">
@@ -59,9 +49,7 @@ export default function CaseNoticeBanner(props) {
: message.subject : message.subject
.split("Banner ")[1] .split("Banner ")[1]
.split(";")[0] .split(";")[0]
: message.subject.split( : message.subject.split("Banner ")[1]}
"Banner "
)[1]}
</h2> </h2>
</div> </div>
<div className="govuk-body-s"> <div className="govuk-body-s">
@@ -71,24 +59,16 @@ export default function CaseNoticeBanner(props) {
) || [] ) || []
).length > 0 ).length > 0
? router.locale == "cy" ? router.locale == "cy"
? message.description.split( ? message.description.split(">>>")[1]
">>>" : message.description.split(">>>")[0]
)[1]
: message.description.split(
">>>"
)[0]
: ( : (
message.description.match( message.description.match(
new RegExp(";", "g") new RegExp(";", "g")
) || [] ) || []
).length > 0 ).length > 0
? router.locale == "cy" ? router.locale == "cy"
? message.description.split( ? message.description.split(";")[1]
";" : message.description.split(";")[0]
)[1]
: message.description.split(
";"
)[0]
: message.description} : message.description}
</div> </div>
<div className="govuk-body-xs govuk-!-margin-bottom-0 "> <div className="govuk-body-xs govuk-!-margin-bottom-0 ">
@@ -97,8 +77,6 @@ export default function CaseNoticeBanner(props) {
</div> </div>
</div> </div>
</div> </div>
)}
</div>
))} ))}
</> </>
); );
+51 -21
View File
@@ -5,15 +5,15 @@ import { useRouter } from "next/router";
import { useCallback, useEffect, useRef, useState } from "react"; import { useCallback, useEffect, useRef, useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import transLookup from "../../data/lookuptranslations.json"; import transLookup from "../../data/lookuptranslations.json";
import { formatDates, getDocLink } from "../utils"; import { formatDates } from "../utils";
import PaginationControl from "./pagination"; import PaginationControl from "./pagination";
import { sendGAEvent } from "@next/third-parties/google"; import { sendGAEvent } from "@next/third-parties/google";
import { import {
getSearchDocumentDetails, getSearchDocumentDetails,
getSearchDocumentDetailsPaged, getSearchDocumentDetailsPaged,
getSearchDocumentTypes getSearchDocumentTypes,
} from "../../actions/services/searchService"; } from "../../actions";
import { setCurrentPage } from "../../store/currentView/action"; import { setCurrentPage } from "../../store/currentView/action";
import { setDocumentDetails } from "../../store/searchOutput/action"; import { setDocumentDetails } from "../../store/searchOutput/action";
@@ -32,7 +32,7 @@ const DocumentDetails = (props) => {
setDocumentDetails, setDocumentDetails,
setCurrentPage, setCurrentPage,
docsOffline, docsOffline,
showFilteredDocs showFilteredDocs,
} = props; } = props;
const router = useRouter(); const router = useRouter();
@@ -57,7 +57,7 @@ const DocumentDetails = (props) => {
setCheckedItems((prev) => ({ setCheckedItems((prev) => ({
...prev, ...prev,
[name]: checked [name]: checked,
})); }));
setSelectAll(false); setSelectAll(false);
}; };
@@ -90,7 +90,37 @@ const DocumentDetails = (props) => {
setCurrentPage(1) setCurrentPage(1)
); );
}; };
let ShowDocLinks = getDocLink(docsOffline); let ShowDocLinks = false;
let checkShowDocLinks = docsOffline != false ? true : false;
const getDocLink = (docsOffline) => {
var startTime = docsOffline.split(",")[0];
var endTime = docsOffline.split(",")[1];
// console.log(startTime);
// console.log(endTime);
var currentDate = new Date();
var startDate = new Date(currentDate.getTime());
startDate.setHours(startTime.split(":")[0]);
startDate.setMinutes(startTime.split(":")[1]);
startDate.setSeconds(startTime.split(":")[2]);
var endDate = new Date(currentDate.getTime());
endDate.setHours(endTime.split(":")[0]);
endDate.setMinutes(endTime.split(":")[1]);
endDate.setSeconds(endTime.split(":")[2]);
// console.log(startDate);
// console.log(endDate);
// console.log(currentDate);
var valid = startDate < currentDate && endDate > currentDate;
ShowDocLinks = valid;
};
checkShowDocLinks && getDocLink(docsOffline);
const DocumentView = (documentDetailsArr) => { const DocumentView = (documentDetailsArr) => {
documentDetailsArr = documentDetailsArr.value; documentDetailsArr = documentDetailsArr.value;
@@ -132,7 +162,7 @@ const DocumentDetails = (props) => {
? jsonpath({ ? jsonpath({
path: '$..[?(@ && @.value=="All")].value_cy', path: '$..[?(@ && @.value=="All")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: "All"} : "All"}
</option> </option>
@@ -151,7 +181,7 @@ const DocumentDetails = (props) => {
item.pinswg_isharedocumentlocationsLabel + item.pinswg_isharedocumentlocationsLabel +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item.pinswg_isharedocumentlocationsLabel || : item.pinswg_isharedocumentlocationsLabel ||
t( t(
@@ -298,7 +328,7 @@ const DocumentDetails = (props) => {
incidentid + incidentid +
"')]", "')]",
json: item, json: item,
sanbox: {} sanbox: {},
}); });
detailsObj = item; detailsObj = item;
return ( return (
@@ -330,7 +360,7 @@ const DocumentDetails = (props) => {
} }
key={key} key={key}
onClick={() => { onClick={() => {
(toggleDownLoadLink(key), toggleDownLoadLink(key),
sendGAEvent( sendGAEvent(
"event", "event",
"DownloadedFile", "DownloadedFile",
@@ -338,9 +368,9 @@ const DocumentDetails = (props) => {
caseReference: caseReference:
props.caseReference, props.caseReference,
filename: filename:
detailsObj.pinswg_name detailsObj.pinswg_name,
} }
)); );
}} }}
> >
<span className="results-visually-hidden"> <span className="results-visually-hidden">
@@ -388,7 +418,7 @@ const DocumentDetails = (props) => {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: detailsObj[ : detailsObj[
"pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue" "pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue"
@@ -554,7 +584,7 @@ const DocumentDetails = (props) => {
item.pinswg_isharedocumentlocationsLabel + item.pinswg_isharedocumentlocationsLabel +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: item.pinswg_isharedocumentlocationsLabel || : item.pinswg_isharedocumentlocationsLabel ||
t( t(
@@ -574,7 +604,7 @@ const DocumentDetails = (props) => {
const data = [ const data = [
...document.querySelectorAll( ...document.querySelectorAll(
".govuk-checkboxes__input:checked" ".govuk-checkboxes__input:checked"
) ),
].map((e) => e.value); ].map((e) => e.value);
setSelectedDocumentType(data); setSelectedDocumentType(data);
setCurrentPage(1); setCurrentPage(1);
@@ -710,7 +740,7 @@ const DocumentDetails = (props) => {
incidentid + incidentid +
"')]", "')]",
json: item, json: item,
eval: true eval: true,
}); });
detailsObj = item; detailsObj = item;
return ( return (
@@ -827,7 +857,7 @@ const DocumentDetails = (props) => {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
eval: true eval: true,
}) })
: detailsObj[ : detailsObj[
"pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue" "pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue"
@@ -905,7 +935,7 @@ const DocumentDetails = (props) => {
props.incidentid, props.incidentid,
selectedOption, selectedOption,
selectedDocumentType, selectedDocumentType,
setDocumentDetails setDocumentDetails,
] ]
); );
@@ -1029,7 +1059,7 @@ const DocumentDetails = (props) => {
orderByState, orderByState,
getDocumentTypes, getDocumentTypes,
getDocumentResults, getDocumentResults,
lang lang,
]); ]);
return ( return (
<div className="govuk-grid-row"> <div className="govuk-grid-row">
@@ -1059,7 +1089,7 @@ const DocumentDetails = (props) => {
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
...state ...state,
}; };
}; };
@@ -1070,7 +1100,7 @@ const mapDispatchToProps = (dispatch) => {
}, },
setCurrentPage: (currentPage) => { setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage)); dispatch(setCurrentPage(currentPage));
} },
}; };
}; };
-221
View File
@@ -1,221 +0,0 @@
import { setEventDetails } from "../../store/searchOutput/action";
import { setCurrentPage } from "../../store/currentView/action";
import { connect } from "react-redux";
import useTranslation from "next-translate/useTranslation";
import { formatDates } from "../utils";
const EIADetails = (props) => {
let { t } = useTranslation();
const EventView = (eventsArr) => {
eventsArr = eventsArr.value;
return eventsArr.map((item, key) => {
<div>{item.pinswg_name}</div>;
});
};
const eventsArr = props.eventsObj?.value || [];
// event publishiing flag set to true displa
function hasOwnPropertyAndNotNull(obj, property) {
return obj.hasOwnProperty(property) && obj[property] !== null;
}
//console.log(eventsArr.length > 0);
return (
eventsArr.length > 0 && (
<div className="govuk-grid-row">
<div className="card">
<div className="card-body">
<h2 className="govuk-heading-m ">
{t("case:event-title")}
</h2>
{eventsArr.map(
(item, key) =>
item.pinswg_eventpublishflag && (
<>
{" "}
<div className="eventContainer">
<div className="eventColumn">
<div>
<b>
{" "}
{t(
"case:event-name-label"
)}
</b>
: {item.pinswg_name}
</div>
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventname"
) && (
<div>
<b>
{t(
"case:event-event-name-label"
)}
</b>
:{" "}
{item.pinswg_eventname}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline1"
) && (
<>
<div>
<b>
{t(
"case:event-address-label"
)}
</b>
:
</div>
<div>
{
item.pinswg_eventaddressline1
}
</div>
</>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline2"
) && (
<div>
{
item.pinswg_eventaddressline2
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresstown"
) && (
<div>
{
item.pinswg_eventaddresstown
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresscounty
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresspostcode
}
</div>
)}
</div>
{/* type of event
start date date of event - end date of event
if virtual event no address showNoOfRecords
show event address */}
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_dateeventrequested"
) && (
<div>
<b>
{t(
"case:event-start-date-label"
)}
</b>
:{" "}
{formatDates(
item.pinswg_dateeventrequested
)}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_enddateoftheevent"
) && (
<div>
<b>
{t(
"case:event-end-date-label"
)}
</b>
:{" "}
{item.pinswg_enddateoftheevent !=
null &&
formatDates(
item.pinswg_enddateoftheevent
)}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue",
]
) && (
<div>
<b>
{t(
"case:event-type-of-event-label"
)}
</b>
:{" "}
{
item[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue"
]
}
</div>
)}
</div>
</div>
</>
)
)}{" "}
</div>
</div>
</div>
)
);
};
const mapStateToProps = (state) => {
return {
...state,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setEventDetails: (eventsObj) => {
dispatch(setEventDetails(eventsObj));
},
setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(EIADetails);
-221
View File
@@ -1,221 +0,0 @@
import { setEventDetails } from "../../store/searchOutput/action";
import { setCurrentPage } from "../../store/currentView/action";
import { connect } from "react-redux";
import useTranslation from "next-translate/useTranslation";
import { formatDates } from "../utils";
const EventsDetails = (props) => {
let { t } = useTranslation();
const EventView = (eventsArr) => {
eventsArr = eventsArr.value;
return eventsArr.map((item, key) => {
<div>{item.pinswg_name}</div>;
});
};
const eventsArr = props.eventsObj?.value || [];
// event publishiing flag set to true displa
function hasOwnPropertyAndNotNull(obj, property) {
return obj.hasOwnProperty(property) && obj[property] !== null;
}
//console.log(eventsArr.length > 0);
return (
eventsArr.length > 0 && (
<div className="govuk-grid-row">
<div className="card">
<div className="card-body">
<h2 className="govuk-heading-m ">
{t("case:event-title")}
</h2>
{eventsArr.map(
(item, key) =>
item.pinswg_eventpublishflag && (
<>
{" "}
<div className="eventContainer">
<div className="eventColumn">
<div>
<b>
{" "}
{t(
"case:event-name-label"
)}
</b>
: {item.pinswg_name}
</div>
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventname"
) && (
<div>
<b>
{t(
"case:event-event-name-label"
)}
</b>
:{" "}
{item.pinswg_eventname}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline1"
) && (
<>
<div>
<b>
{t(
"case:event-address-label"
)}
</b>
:
</div>
<div>
{
item.pinswg_eventaddressline1
}
</div>
</>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline2"
) && (
<div>
{
item.pinswg_eventaddressline2
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresstown"
) && (
<div>
{
item.pinswg_eventaddresstown
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresscounty
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresspostcode
}
</div>
)}
</div>
{/* type of event
start date date of event - end date of event
if virtual event no address showNoOfRecords
show event address */}
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_dateeventrequested"
) && (
<div>
<b>
{t(
"case:event-start-date-label"
)}
</b>
:{" "}
{formatDates(
item.pinswg_dateeventrequested
)}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_enddateoftheevent"
) && (
<div>
<b>
{t(
"case:event-end-date-label"
)}
</b>
:{" "}
{item.pinswg_enddateoftheevent !=
null &&
formatDates(
item.pinswg_enddateoftheevent
)}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue",
]
) && (
<div>
<b>
{t(
"case:event-type-of-event-label"
)}
</b>
:{" "}
{
item[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue"
]
}
</div>
)}
</div>
</div>
</>
)
)}{" "}
</div>
</div>
</div>
)
);
};
const mapStateToProps = (state) => {
return {
...state,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setEventDetails: (eventsObj) => {
dispatch(setEventDetails(eventsObj));
},
setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(EventsDetails);
-646
View File
@@ -1,646 +0,0 @@
// // import { setEventDetails } from "../../store/searchOutput/action";
// // import { setCurrentPage } from "../../store/currentView/action";
// // import { connect } from "react-redux";
// // import useTranslation from "next-translate/useTranslation";
// // import { formatDates } from "../utils";
// // const MediaDetails = (props) => {
// // let { t } = useTranslation();
// // const MediaView = (mediaArr) => {
// // mediaArr = mediaArr.value;
// // return mediaArr.map((item, key) => {
// // <div>{item.pinswg_name}</div>;
// // });
// // };
// // const mediaArr = props.mediaObj?.value || [];
// // // event publishiing flag set to true displa
// // function hasOwnPropertyAndNotNull(obj, property) {
// // return obj.hasOwnProperty(property) && obj[property] !== null;
// // }
// // //console.log(eventsArr.length > 0);
// // return (
// // mediaArr.length > 0 && (
// // <div className="govuk-grid-row">
// // <div className="card">
// // <div className="card-body">
// // <h2 className="govuk-heading-m ">
// // {t("case:event-title")}Media
// // </h2>
// // {mediaArr.map(
// // (item, key) =>
// // item.pinswg_publishtoweb && (
// // <>
// // {" "}
// // <div className="">
// // <div className="">
// // <div>
// // <b>
// // {" "}
// // {t(
// // "case:event-name-label",
// // )}
// // </b>
// // : {item.pinswg_name}
// // </div>
// // {hasOwnPropertyAndNotNull(
// // item,
// // "pinswg_description",
// // ) && (
// // <div>
// // <b>
// // {t(
// // "case:event-event-name-label",
// // )}
// // </b>
// // :{" "}
// // {
// // item.pinswg_description
// // }
// // </div>
// // )}
// // </div>
// // </div>
// // </>
// // ),
// // )}{" "}
// // </div>
// // </div>
// // </div>
// // )
// // );
// // };
// // const mapStateToProps = (state) => {
// // return {
// // ...state,
// // };
// // };
// // const mapDispatchToProps = (dispatch) => {
// // return {
// // setEventDetails: (mediaObj) => {
// // dispatch(setEventDetails(mediaObj));
// // },
// // setCurrentPage: (currentPage) => {
// // dispatch(setCurrentPage(currentPage));
// // },
// // };
// // };
// // export default connect(mapStateToProps, mapDispatchToProps)(MediaDetails);
// import { useEffect, useMemo, useState } from "react";
// import { connect } from "react-redux";
// import useTranslation from "next-translate/useTranslation";
// import { useRouter } from "next/router";
// const extractYouTubeId = (input) => {
// if (!input) return null;
// if (/^[a-zA-Z0-9_-]{11}$/.test(input)) return input;
// try {
// const url = new URL(input);
// if (url.hostname.includes("youtu.be"))
// return url.pathname.slice(1) || null;
// const v = url.searchParams.get("v");
// if (v) return v;
// const embedMatch = url.pathname.match(/\/embed\/([^/]+)/);
// if (embedMatch?.[1]) return embedMatch[1];
// const shortsMatch = url.pathname.match(/\/shorts\/([^/]+)/);
// if (shortsMatch?.[1]) return shortsMatch[1];
// return null;
// } catch {
// return null;
// }
// };
// export default function MediaDetails({ mediaObj, whichTab }) {
// const router = useRouter();
// const mediaArr = mediaObj?.value || [];
// const videoItems = useMemo(() => {
// const isWelsh = router.locale === "cy";
// return (mediaArr || [])
// .filter((x) => x?.pinswg_publishtoweb)
// .map((item) => {
// const url = isWelsh
// ? item.pinswg_mediaLinkCY
// : item.pinswg_mediaLinkEN;
// const videoId = extractYouTubeId(url);
// if (!videoId) return null;
// return {
// key:
// item.pinswg_documentid ||
// `${item.pinswg_name}-${videoId}`,
// videoId,
// name: item.pinswg_name || "Video",
// description: item.pinswg_description || "",
// thumbnail: `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`,
// };
// })
// .filter(Boolean);
// }, [mediaArr, router.locale]);
// const [watchedIds, setWatchedIds] = useState(new Set());
// const [selectedIndex, setSelectedIndex] = useState(0);
// // Forces a fresh iframe instance whenever we need to hard-stop playback
// const [playerInstance, setPlayerInstance] = useState(0);
// const isActive = whichTab === "case-media";
// const selected = videoItems[selectedIndex] || null;
// // When leaving the media tab, hard-stop playback by unmounting (and bumping instance)
// useEffect(() => {
// if (!isActive) {
// setPlayerInstance((n) => n + 1);
// }
// }, [isActive]);
// // When list/locale changes, reset to first (no autoplay)
// useEffect(() => {
// setSelectedIndex(0);
// setPlayerInstance((n) => n + 1);
// }, [videoItems.length, router.locale]);
// if (!videoItems.length) return null;
// const embedBase = "https://www.youtube-nocookie.com/embed";
// // IMPORTANT:
// // - autoplay=0 for initial load
// // - autoplay=1 only when user clicks an item
// const [autoplay, setAutoplay] = useState(false);
// useEffect(() => {
// // whenever we leave tab or reset player, don't autoplay next time
// if (!isActive) setAutoplay(false);
// }, [isActive]);
// const embedSrc = selected
// ? `${embedBase}/${selected.videoId}?rel=0&modestbranding=1&playsinline=1&autoplay=${autoplay ? "1" : "0"}`
// : "";
// return (
// <div className="govuk-grid-row">
// <div className="card">
// <div className="card-body">
// <h2 className="govuk-heading-m">Media</h2>
// {/* Player: only render when tab is active */}
// {isActive && (
// <div className="videoWrapper govuk-!-margin-bottom-4">
// <iframe
// key={`${selected?.videoId}-${playerInstance}`}
// src={embedSrc}
// title={selected?.name || "YouTube video"}
// frameBorder="0"
// allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
// allowFullScreen
// />
// </div>
// )}
// <h3 className="govuk-heading-s">Videos</h3>
// <ul className="govuk-list govuk-list--spaced">
// {videoItems.map((v, idx) => {
// const isSelected = idx === selectedIndex;
// return (
// <li key={v.key}>
// <button
// type="button"
// className={`videoTabButton ${isSelected ? "active" : ""}`}
// onClick={() => {
// setSelectedIndex(idx);
// setAutoplay(true); // play only on user action
// setPlayerInstance((n) => n + 1); // ensure clean switch / stop previous
// setWatchedIds((prev) =>
// new Set(prev).add(v.videoId),
// );
// }}
// >
// <div className="videoTabContent">
// <div className="thumbnailWrapper">
// <img
// src={v.thumbnail}
// alt=""
// className="videoThumbnail"
// loading="lazy"
// />
// <span
// className="playIcon"
// aria-hidden="true"
// >
// ▶
// </span>
// {/* Duration badge (see section 2) */}
// {v.duration && (
// <span className="durationBadge">
// {v.duration}
// </span>
// )}
// {/* Watched indicator (see section 3) */}
// {watchedIds.has(v.videoId) && (
// <span className="watchedBadge">
// Watched
// </span>
// )}
// </div>
// <span className="videoTitle">
// {v.name}
// </span>
// </div>
// </button>
// </li>
// );
// })}
// </ul>
// </div>
// </div>
// <style jsx>{`
// .videoWrapper {
// position: relative;
// padding-bottom: 56.25%;
// height: 0;
// overflow: hidden;
// border: 1px solid #b1b4b6;
// border-radius: 4px;
// }
// .videoWrapper iframe {
// position: absolute;
// top: 0;
// left: 0;
// width: 100%;
// height: 100%;
// }
// .videoTabButton {
// width: 100%;
// text-align: left;
// background: transparent;
// border: 1px solid #b1b4b6;
// border-radius: 4px;
// padding: 10px 12px;
// cursor: pointer;
// }
// .videoTabButton:hover {
// background: #f3f2f1;
// }
// .videoTabButton.active {
// border-color: #1d70b8;
// box-shadow: inset 0 0 0 1px #1d70b8;
// background: #eef4ff;
// }
// .videoTabContent {
// display: flex;
// gap: 12px;
// align-items: center;
// }
// .videoThumbnail {
// width: 120px;
// aspect-ratio: 16 / 9;
// object-fit: cover;
// border-radius: 4px;
// border: 1px solid #b1b4b6;
// background: #000;
// }
// .videoTitle {
// font-weight: 600;
// }
// @media (max-width: 40.0625em) {
// .videoThumbnail {
// width: 90px;
// }
// }
// .thumbnailWrapper {
// position: relative;
// width: 120px;
// flex-shrink: 0;
// }
// .videoThumbnail {
// width: 100%;
// aspect-ratio: 16 / 9;
// object-fit: cover;
// border-radius: 4px;
// border: 1px solid #b1b4b6;
// background: #000;
// }
// /* ▶ Play icon */
// .playIcon {
// position: absolute;
// inset: 0;
// display: flex;
// align-items: center;
// justify-content: center;
// font-size: 32px;
// color: white;
// text-shadow: 0 0 6px rgba(0, 0, 0, 0.7);
// pointer-events: none;
// }
// /* ⏱ Duration badge */
// .durationBadge {
// position: absolute;
// bottom: 6px;
// right: 6px;
// background: rgba(0, 0, 0, 0.8);
// color: white;
// font-size: 12px;
// padding: 2px 6px;
// border-radius: 3px;
// }
// /* 👁 Watched badge */
// .watchedBadge {
// position: absolute;
// top: 6px;
// left: 6px;
// background: #00703c; /* GOV green */
// color: white;
// font-size: 11px;
// padding: 2px 6px;
// border-radius: 3px;
// }
// .videoTabContent {
// display: flex;
// gap: 12px;
// align-items: center;
// }
// .videoTitle {
// font-weight: 600;
// }
// `}</style>
// </div>
// );
// }
import { useEffect, useMemo, useState } from "react";
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
/**
* MediaDetails
* - Renders a YouTube player + a list of videos from mediaObj.value
* - Loads first item by default (no autoplay)
* - Plays only when user selects an item
* - Stops playback when leaving the "case-media" parent tab (pass whichTab)
* - Shows thumbnail with play overlay
* - Optional duration badge (if you supply v.duration)
* - "Watched" badge once a video has been played (session only)
*/
const extractYouTubeId = (input) => {
if (!input) return null;
// Already looks like a YouTube ID?
if (/^[a-zA-Z0-9_-]{11}$/.test(input)) return input;
try {
const url = new URL(input);
// youtu.be/<id>
if (url.hostname.includes("youtu.be")) {
return url.pathname.replace("/", "") || null;
}
// youtube.com/watch?v=<id>
const v = url.searchParams.get("v");
if (v) return v;
// youtube.com/embed/<id>
const embedMatch = url.pathname.match(/\/embed\/([^/]+)/);
if (embedMatch?.[1]) return embedMatch[1];
// youtube.com/shorts/<id>
const shortsMatch = url.pathname.match(/\/shorts\/([^/]+)/);
if (shortsMatch?.[1]) return shortsMatch[1];
return null;
} catch {
return null;
}
};
const MediaDetails = ({ mediaObj, whichTab, title, useNoCookie = true }) => {
const { t } = useTranslation();
const router = useRouter();
const mediaArr = mediaObj?.value || [];
const isActive = whichTab ? whichTab === "case-media" : true;
// Build list of playable items (publishable only)
const videoItems = useMemo(() => {
const isWelsh = router.locale === "cy";
return (mediaArr || [])
.filter((x) => x?.pinswg_publishtoweb)
.map((item) => {
const link = isWelsh
? item.pinswg_mediaLinkCY
: item.pinswg_mediaLinkEN;
const videoId = extractYouTubeId(link);
if (!videoId) return null;
return {
key:
item.pinswg_documentid ||
item.pinswg_mediaid ||
`${item.pinswg_name}-${videoId}`,
videoId,
name: item.pinswg_name || "Video",
description: item.pinswg_description || "",
// If you later store duration in CRM, map it here (e.g. "03:42")
duration: item.pinswg_duration || null,
thumbnailHQ: `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`,
thumbnailMax: `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`,
raw: item,
};
})
.filter(Boolean);
}, [mediaArr, router.locale]);
const [selectedIndex, setSelectedIndex] = useState(0);
// Default false so first item loads but does not play.
const [autoplay, setAutoplay] = useState(false);
// Bump this to force iframe remount (hard stop playback).
const [playerInstance, setPlayerInstance] = useState(0);
// Track which videos have been played (session only).
const [watchedIds, setWatchedIds] = useState(() => new Set());
// When list or locale changes: reset selection and do not autoplay
useEffect(() => {
setSelectedIndex(0);
setAutoplay(false);
setPlayerInstance((n) => n + 1);
}, [videoItems.length, router.locale]);
// When leaving the media tab: hard stop playback
useEffect(() => {
if (!isActive) {
setAutoplay(false);
setPlayerInstance((n) => n + 1);
}
}, [isActive]);
const selected = videoItems[selectedIndex] || null;
const domain = useNoCookie
? "https://www.youtube-nocookie.com"
: "https://www.youtube.com";
const embedSrc = selected
? `${domain}/embed/${selected.videoId}?rel=0&modestbranding=1&playsinline=1&autoplay=${
autoplay ? "1" : "0"
}`
: "";
if (!videoItems.length) return null;
return (
<div className="govuk-grid-row">
<div className="card">
<div className="card-body">
<h2 className="govuk-heading-m">{t("case:media-title")}</h2>
{/* Player: unmount when not active (guarantees playback stops) */}
{isActive && (
<div className="videoWrapper govuk-!-margin-bottom-4">
<iframe
key={`${selected?.videoId}-${playerInstance}`}
src={embedSrc}
title={selected?.name || "YouTube video"}
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
)}
{/* Selected info */}
{selected && (
<div className="govuk-!-margin-bottom-4">
<div className="govuk-body">
<b>{t("case:event-name-label")}</b>:{" "}
{selected.name}
</div>
{!!selected.description && (
<div className="govuk-body">
<b>{t("case:event-event-name-label")}</b>:{" "}
{selected.description}
</div>
)}
</div>
)}
{/* Video list */}
<h3 className="govuk-heading-s">
{t("case:video-heading")}
</h3>
<ul className="govuk-list govuk-list--spaced">
{videoItems.map((v, idx) => {
const isSelected = idx === selectedIndex;
return (
<li key={v.key}>
<button
type="button"
className={`videoTabButton ${
isSelected ? "active" : ""
}`}
aria-current={
isSelected ? "true" : undefined
}
onClick={() => {
setSelectedIndex(idx);
// Start playback only when user selects
setAutoplay(true);
// Force remount to stop previous + start clean
setPlayerInstance((n) => n + 1);
// Mark watched
setWatchedIds((prev) => {
const next = new Set(prev);
next.add(v.videoId);
return next;
});
}}
>
<div className="videoTabContent">
<div className="thumbnailWrapper">
<img
src={v.thumbnailMax}
onError={(e) => {
// fallback for videos without maxres
e.currentTarget.src =
v.thumbnailHQ;
}}
alt=""
className="videoThumbnail"
loading="lazy"
/>
<span
className="playIcon"
aria-hidden="true"
>
</span>
{!!v.duration && (
<span className="durationBadge">
{v.duration}
</span>
)}
{watchedIds.has(v.videoId) && (
<span className="watchedBadge">
Watched
</span>
)}
</div>
<span className="videoTitle">
{v.name}
</span>
</div>
</button>
</li>
);
})}
</ul>
</div>
</div>
</div>
);
};
export default MediaDetails;
+12 -13
View File
@@ -13,7 +13,7 @@ const PaginationControl = (props) => {
currentPage, currentPage,
spinnerState, spinnerState,
getDocumentResults, getDocumentResults,
setCurrentPage setCurrentPage,
} = props; } = props;
let { t } = useTranslation(); let { t } = useTranslation();
@@ -45,7 +45,7 @@ const PaginationControl = (props) => {
const range = { const range = {
start: Math.round(currentPage - delta / 2), start: Math.round(currentPage - delta / 2),
end: Math.round(currentPage + delta / 2) end: Math.round(currentPage + delta / 2),
}; };
if (range.start - 1 === 1 || range.end + 1 === pageCount) { if (range.start - 1 === 1 || range.end + 1 === pageCount) {
@@ -89,7 +89,7 @@ const PaginationControl = (props) => {
<span <span
className="govuk-body govuk-link govuk-!-font-weight-bold govuk-link--no-underline activePaginationItem leftTextButton" className="govuk-body govuk-link govuk-!-font-weight-bold govuk-link--no-underline activePaginationItem leftTextButton"
onClick={() => { onClick={() => {
(spinnerState(), spinnerState(),
setCurrentPage( setCurrentPage(
props.currentView.currentPage - props.currentView.currentPage -
1 1
@@ -99,7 +99,7 @@ const PaginationControl = (props) => {
1, 1,
orderBy, orderBy,
fieldSort fieldSort
)); );
}} }}
> >
{t("common:previous-link-button")} {t("common:previous-link-button")}
@@ -132,12 +132,12 @@ const PaginationControl = (props) => {
key={i} key={i}
onClick={() => { onClick={() => {
spinnerState(); spinnerState();
(setCurrentPage(e), setCurrentPage(e),
getDocumentResults( getDocumentResults(
e, e,
orderBy, orderBy,
fieldSort fieldSort
)); );
}} }}
> >
{e} {e}
@@ -150,7 +150,7 @@ const PaginationControl = (props) => {
<span <span
className="govuk-body govuk-link govuk-!-font-weight-bold govuk-link--no-underline activePaginationItem rightTextButton" className="govuk-body govuk-link govuk-!-font-weight-bold govuk-link--no-underline activePaginationItem rightTextButton"
onClick={() => { onClick={() => {
(spinnerState(), spinnerState(),
setCurrentPage( setCurrentPage(
props.currentView.currentPage + props.currentView.currentPage +
1 1
@@ -160,7 +160,7 @@ const PaginationControl = (props) => {
1, 1,
orderBy, orderBy,
fieldSort fieldSort
)); );
}} }}
> >
{t("common:next-link-button")} {t("common:next-link-button")}
@@ -174,9 +174,8 @@ const PaginationControl = (props) => {
</div> </div>
</div> </div>
<div className="govuk-body-s mobilePageCount"> <div className="govuk-body-s mobilePageCount">
{t("common:pages-label")}{" "} {t("common:pages-label")} {currentPage}{" "}
{props.currentView.currentPage} {t("common:of-label")}{" "} {t("common:of-label")} {pagesCount}
{pagesCount}
</div> </div>
</div> </div>
)} )}
@@ -186,7 +185,7 @@ const PaginationControl = (props) => {
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
currentView: state.currentView currentView: state.currentView,
}; };
}; };
@@ -194,7 +193,7 @@ const mapDispatchToProps = (dispatch) => {
return { return {
setCurrentPage: (currentPage) => { setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage)); dispatch(setCurrentPage(currentPage));
} },
}; };
}; };
@@ -1,364 +0,0 @@
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import { connect } from "react-redux";
import { Field, change, reduxForm } from "redux-form";
import { useState } from "react";
import { bytesToSize, getThumbnailIconByExtension } from "../../utils";
import {
FileUploadField,
RenderCondtionalRadioList,
RenderPickList,
RenderRichMultiline,
shouldDisableButton,
} from "./representationElements";
import { useDropzone } from "react-dropzone";
import {
setRepresentationCapacity,
setRepresentationSubmit,
setFilesForRepresentations,
} from "../../../store/currentView/action";
const ConsultationAgent = (props) => {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const {
formObj,
appellantApplicantRepresentationArr,
setRepresentationCapacity,
setRepresentationSubmit,
currentView,
setRepFileName,
updateRepresentation,
setSavingStatus,
savingStatus,
setFilesForRepresentations,
} = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
if (JSON.stringify(formObj) != "{}") {
setRepFileName(formObj.representationForm.values);
let filterFilesList = props.currentView.caseReference.hasOwnProperty(
"repDetails"
)
? props.currentView.caseReference.repDetails.hasOwnProperty(
"filesList"
)
? props.currentView.caseReference.repDetails.filesList.filter(
function (el) {
return el != null;
}
)
: []
: [];
const files = acceptedFiles.map((file) => (
<li key={file.path}>
{file.path} - {file.size} bytes
</li>
));
const required = (value) => (value ? undefined : "Required");
return (
<>
<div className="govuk-grid-row">
<div className="govuk-form-group">
{typeof formObj.representationForm.values
.representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:consultation-from-an-agent-heading"
)}
</h2>
<label
className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{t(
"myrepresentations:kind-of-consultation-label"
)}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
optionsArr={
appellantApplicantRepresentationArr
}
/>
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values
.representationType != "undefined") && (
<>
<div className="govuk-grid-row">
<div className="govuk-form-group">
<Field
name="representationOnBehalfOf"
datafieldname="representationOnBehalfOf"
// label={t("myrepresentations:capacity-select-what-capacity-label")}
options={["Yes", "No"]}
id="representationOnBehalfOf"
className="govuk-radios__input"
errorMsg={t(
"myrepresentations:select-an-option-label"
)}
component={RenderCondtionalRadioList}
validate={[required]}
legend={t("case:representation-onbehalfof")}
hint={t(
"myrepresentations:representation-onbehalfof-hint"
)}
/>
</div>
</div>
<div className="govuk-grid-row">
<div className="govuk-form-group">
<p className="govuk-body">
{formObj.representationForm.values
.representationType ==
"Consultation Response"
? t(
"myrepresentations:enter-comment-label"
)
: t(
"myrepresentations:consultation-comment-label"
)}
</p>
<fieldset
className="govuk-fieldset"
aria-describedby="commentBox-hint"
>
{formObj.representationForm.values
.representationType ==
"Consultation Response" && (
<div className="govuk-form-group">
<Field
name="representationComments"
id="representationComments"
component={RenderRichMultiline}
type="text"
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={
props.name + "-hint"
}
/>
{formObj.representationForm.values
.appealType == "846040004" ? (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
) : (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
)}
</div>
)}
<div className="govuk-form-group govuk-!-margin-bottom-9">
<FileUploadField
name={"representationDocuments"}
id={"representationDocuments"}
label={t(
"myrepresentations:add-files-label"
)}
ticketnumber={
props.props.caseReference
}
hint={"sdsd"}
fileList={
props.currentView.fileList
// props.currentView.caseReference.hasOwnProperty(
// "repDetails"
// )
// ? props.currentView.caseReference.repDetails.hasOwnProperty(
// "filesList"
// ) &&
// props.currentView
// .caseReference
// .repDetails.filesList
// .length > 0
// ? props.currentView
// .caseReference
// .repDetails
// .filesList
// : []
// : []
}
setFilesForRepresentations={
setFilesForRepresentations
}
containerID={
props.props.props.accountDetails
.containerID
}
filenamePrefix={props.formObj}
props={props.props.props}
setCurrentReference={
props.setCurrentReference
}
/>
</div>
</fieldset>
</div>{" "}
</div>
</>
)}
{typeof formObj.representationForm.values.representationType !=
"undefined" && (
<div className="govuk-grid-row">
<div className="govuk-button-group">
<button
type="submit"
className="govuk-button"
data-module="govuk-button"
disabled={shouldDisableButton({
props,
formObj,
})}
>
{t("common:continue-button")}
</button>
{/* {router.query.state != "edit" && (
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationCapacity",
""
);
}}
className="govuk-link"
>
{t("common:back-link")}
</a>
)} */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/>
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)}
</>
);
}
};
const mapDispatchToProps = (dispatch) => ({
updateField: (form, field, newValue) =>
dispatch(change(form, field, newValue)),
setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList));
},
});
export default connect(
null,
mapDispatchToProps
)(
reduxForm({
form: "representationForm",
enableReinitialize: true,
destroyOnUnmount: false,
})(ConsultationAgent)
);
@@ -1,337 +0,0 @@
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import { connect } from "react-redux";
import { Field, change, reduxForm } from "redux-form";
import { useState } from "react";
import { bytesToSize, getThumbnailIconByExtension } from "../../utils";
import {
FileUploadField,
RenderPickList,
RenderRichMultiline,
shouldDisableButton,
} from "./representationElements";
import { useDropzone } from "react-dropzone";
import {
setRepresentationCapacity,
setRepresentationSubmit,
setFilesForRepresentations,
} from "../../../store/currentView/action";
const ConsultationAppellant = (props) => {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const {
formObj,
appellantApplicantRepresentationArr,
setRepresentationCapacity,
setRepresentationSubmit,
currentView,
setRepFileName,
updateRepresentation,
setSavingStatus,
savingStatus,
setFilesForRepresentations,
} = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
console.log(JSON.stringify(formObj) == "{}" ? "empty" : "value");
if (JSON.stringify(formObj) != "{}") {
setRepFileName(formObj.representationForm.values);
let filterFilesList = props.currentView.caseReference.hasOwnProperty(
"repDetails"
)
? props.currentView.caseReference.repDetails.hasOwnProperty(
"filesList"
)
? props.currentView.caseReference.repDetails.filesList.filter(
function (el) {
return el != null;
}
)
: []
: [];
filterFilesList = filterFilesList.filter(
(value, index, self) =>
index === self.findIndex((t) => t.name === value.name)
);
return (
<>
<div className="govuk-grid-row">
<div className="govuk-form-group">
{typeof formObj.representationForm.values
.representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:consultation-from-an-appellant-heading"
)}
</h2>
<label
className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{t(
"myrepresentations:kind-of-consultation-label"
)}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
optionsArr={
appellantApplicantRepresentationArr
}
/>
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values
.representationType != "undefined") && (
<div className="govuk-grid-row">
<div className="govuk-form-group">
<p className="govuk-body">
{formObj.representationForm.values
.representationType ==
"Consultation Response"
? t("myrepresentations:enter-comment-label")
: t(
"myrepresentations:consultation-comment-label"
)}
</p>
<fieldset
className="govuk-fieldset"
aria-describedby="commentBox-hint"
>
{formObj.representationForm.values
.representationType ==
"Consultation Response" && (
<div className="govuk-form-group">
<Field
name="representationComments"
id="representationComments"
component={RenderRichMultiline}
type="text"
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={
props.name + "-hint"
}
/>
{formObj.representationForm.values
.appealType == "846040004" ? (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
) : (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
)}
</div>
)}
<div className="govuk-form-group govuk-!-margin-bottom-9">
<FileUploadField
name={"representationDocuments"}
id={"representationDocuments"}
label={t(
"myrepresentations:add-files-label"
)}
ticketnumber={props.props.caseReference}
hint={"sdsd"}
fileList={
props.currentView.fileList
// props.currentView.caseReference.hasOwnProperty(
// "repDetails"
// )
// ? props.currentView.caseReference.repDetails.hasOwnProperty(
// "filesList"
// ) &&
// props.currentView
// .caseReference.repDetails
// .filesList.length > 0
// ? props.currentView
// .caseReference
// .repDetails.filesList
// : []
// : []
}
setFilesForRepresentations={
setFilesForRepresentations
}
containerID={
props.props.props.accountDetails
.containerID
}
filenamePrefix={props.formObj}
props={props.props.props}
setCurrentReference={
props.setCurrentReference
}
/>
</div>
</fieldset>
</div>{" "}
</div>
)}
{typeof formObj.representationForm.values.representationType !=
"undefined" && (
<div className="govuk-grid-row">
<div className="govuk-button-group">
<button
type="submit"
className="govuk-button"
data-module="govuk-button"
disabled={shouldDisableButton({
props,
formObj,
})}
>
{t("common:continue-button")}
</button>
{/* {router.query.state != "edit" && (
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationType",
""
);
}}
className="govuk-link"
>
{t("common:back-link")}
</a>
)} */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/>
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)}
</>
);
}
};
//const mapStateToProps = (state, props) => {};
const mapDispatchToProps = (dispatch) => {
return {
updateField: (form, field, newValue) =>
dispatch(change(form, field, newValue)),
setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList));
},
};
};
export default connect(
null,
mapDispatchToProps
)(
reduxForm({
form: "representationForm",
enableReinitialize: true,
destroyOnUnmount: false,
})(ConsultationAppellant)
);
@@ -1,378 +0,0 @@
import useTranslation from "next-translate/useTranslation";
import { useRouter } from "next/router";
import { connect } from "react-redux";
import { Field, change, reduxForm } from "redux-form";
import { useState } from "react";
import { bytesToSize, getThumbnailIconByExtension } from "../../utils";
import {
FileUploadField,
RenderCondtionalRadioList,
RenderPickList,
RenderRichMultiline,
shouldDisableButton,
} from "./representationElements";
import { useDropzone } from "react-dropzone";
import {
setRepresentationCapacity,
setRepresentationSubmit,
setFilesForRepresentations,
} from "../../../store/currentView/action";
const ConsultationInterestedPartyPerson = (props) => {
let { t } = useTranslation();
const router = useRouter();
const { locale } = router;
const {
formObj,
interestedPersonRepresentationArr,
setRepresentationCapacity,
setRepresentationSubmit,
setRepFileName,
updateRepresentation,
setSavingStatus,
savingStatus,
setFilesForRepresentations,
} = props;
const required = (value) => (value ? undefined : "Required");
const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
if (JSON.stringify(formObj) != "{}") {
setRepFileName(formObj.representationForm.values);
let filterFilesList = props.currentView.caseReference.hasOwnProperty(
"repDetails"
)
? props.currentView.caseReference.repDetails.hasOwnProperty(
"filesList"
)
? props.currentView.caseReference.repDetails.filesList.filter(
function (el) {
return el != null;
}
)
: []
: [];
const files = acceptedFiles.map((file) => (
<li key={file.path}>
{file.path} - {file.size} bytes
</li>
));
return (
<>
<div className="govuk-grid-row">
<div className="govuk-form-group">
{typeof formObj.representationForm.values
.representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:consultation-from-an-interested-person-heading"
)}
</h2>
<label
className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{t(
"myrepresentations:kind-of-consultation-label"
)}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
validate={[required]}
optionsArr={
interestedPersonRepresentationArr
}
errorMsg={t(
"myrepresentations:select-an-option-label"
)}
/>
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values
.representationType != "undefined") && (
<>
<div className="govuk-grid-row">
<div className="govuk-form-group">
<Field
name="representationOnBehalfOf"
datafieldname="representationOnBehalfOf"
// label="In what capacity do you wish to make representations on this case?"
options={[
t(
"myrepresentations:questionnaire-yes"
),
t("myrepresentations:questionnaire-no"),
]}
id="representationOnBehalfOf"
className="govuk-radios__input"
errorMsg={t(
"myrepresentations:select-an-option-label"
)}
component={RenderCondtionalRadioList}
validate={[required]}
legend={t("case:representation-onbehalfof")}
hint={t(
"myrepresentations:representation-onbehalfof-hint"
)}
/>
</div>
</div>
<div className="govuk-grid-row">
<div className="govuk-form-group">
<p className="govuk-body">
{formObj.representationForm.values
.representationType ==
"Consultation Response"
? t(
"myrepresentations:enter-comment-label"
)
: t(
"myrepresentations:consultation-comment-label"
)}
</p>
<fieldset
className="govuk-fieldset"
aria-describedby="commentBox-hint"
>
{" "}
{formObj.representationForm.values
.representationType ==
"Consultation Response" && (
<div className="govuk-form-group">
<Field
name="representationComments"
id="representationComments"
component={RenderRichMultiline}
type="text"
rows="5"
className="govuk-textarea govuk-input--width-30"
aria-describedby={
props.name + "-hint"
}
/>
{formObj.representationForm.values
.appealType == "846040004" ? (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
) : (
<p className="govuk-hint govuk-!-font-size-14 govuk-!-margin-top-5">
{t(
"myrepresentations:publish-policy-label"
)}{" "}
<a
href={t(
"myrepresentations:publish-policy-link"
)}
>
{t(
"myrepresentations:publish-policy-link-label"
)}
</a>{" "}
{t(
"myrepresentations:publish-policy-label-two"
)}
</p>
)}
</div>
)}
<div className="govuk-form-group govuk-!-margin-bottom-9">
<FileUploadField
name={"representationDocuments"}
id={"representationDocuments"}
label={t(
"myrepresentations:add-files-label"
)}
ticketnumber={
props.props.caseReference
}
hint={"sdsd"}
fileList={
props.currentView.fileList
// props.currentView.caseReference.hasOwnProperty(
// "repDetails"
// )
// ? props.currentView.caseReference.repDetails.hasOwnProperty(
// "filesList"
// ) &&
// props.currentView
// .caseReference
// .repDetails.filesList
// .length > 0
// ? props.currentView
// .caseReference
// .repDetails
// .filesList
// : []
// : []
}
setFilesForRepresentations={
setFilesForRepresentations
}
containerID={
props.props.props.accountDetails
.containerID
}
filenamePrefix={props.formObj}
props={props.props.props}
setCurrentReference={
props.setCurrentReference
}
/>
</div>
</fieldset>
</div>{" "}
</div>
</>
)}
{typeof formObj.representationForm.values.representationType !=
"undefined" && (
<div className="govuk-grid-row">
<div className="govuk-button-group">
<button
type="submit"
className="govuk-button"
data-module="govuk-button"
disabled={shouldDisableButton({
props,
formObj,
})}
>
{t("common:continue-button")}
</button>
{/*
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationCapacity",
""
);
props.updateField(
"representationForm",
"representationType",
""
);
}}
className="govuk-link"
>
{t("case:summary-back-button-label")}
</a> */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/>
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)}
</>
);
}
};
//const mapStateToProps = (state, props) => {};
const mapDispatchToProps = (dispatch) => ({
updateField: (form, field, newValue) =>
dispatch(change(form, field, newValue)),
setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList));
},
});
export default connect(
null,
mapDispatchToProps
)(
reduxForm({
form: "representationForm",
enableReinitialize: true,
destroyOnUnmount: false,
})(ConsultationInterestedPartyPerson)
);
@@ -1,42 +0,0 @@
const RepresentationActionButtons = ({
t,
locale,
isSaving,
isContinueDisabled,
onSaveExit
}) => {
return (
<div className="govuk-grid-row">
<div className="govuk-button-group">
<button
type="submit"
className="govuk-button"
data-module="govuk-button"
disabled={isContinueDisabled}
>
{t("common:continue-button")}
</button>
{isSaving ? (
<span className=" progress-save-active">
{locale == "cy" ? "Nôl data" : "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={locale == "cy" ? "Nôl data" : "Saving data"}
/>
</span>
) : (
<button
className="govuk-button progress-save "
onClick={onSaveExit}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
);
};
export default RepresentationActionButtons;
@@ -1,49 +0,0 @@
import { Field } from "redux-form";
import { RenderPickList } from "../representationElements";
const RepresentationTypeSelectorBlock = ({
t,
headingText,
kindLabelText,
isTypeSelected,
selectedTypeDisplay,
optionsArr,
validate,
errorMsg
}) => {
return (
<div className="govuk-grid-row">
<div className="govuk-form-group">
{!isTypeSelected ? (
<>
<h2 className="govuk-heading-m ">{headingText}</h2>
<label
className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{kindLabelText}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
validate={validate}
optionsArr={optionsArr}
errorMsg={errorMsg}
/>
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{selectedTypeDisplay}
</label>
)}
</div>
</div>
);
};
export default RepresentationTypeSelectorBlock;
File diff suppressed because it is too large Load Diff
@@ -8,17 +8,15 @@ import { bytesToSize, getThumbnailIconByExtension } from "../../utils";
import { import {
FileUploadField, FileUploadField,
RenderCondtionalRadioList, RenderCondtionalRadioList,
RenderPickList,
RenderRichMultiline, RenderRichMultiline,
shouldDisableButton
} from "./representationElements"; } from "./representationElements";
import RepresentationActionButtons from "./elements/RepresentationActionButtons";
import RepresentationTypeSelectorBlock from "./elements/RepresentationTypeSelectorBlock";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { import {
setRepresentationCapacity, setRepresentationCapacity,
setRepresentationSubmit, setRepresentationSubmit,
setFilesForRepresentations setFilesForRepresentations,
} from "../../../store/currentView/action"; } from "../../../store/currentView/action";
const RepAgent = (props) => { const RepAgent = (props) => {
@@ -36,7 +34,7 @@ const RepAgent = (props) => {
updateRepresentation, updateRepresentation,
setSavingStatus, setSavingStatus,
savingStatus, savingStatus,
setFilesForRepresentations setFilesForRepresentations,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
@@ -64,44 +62,58 @@ const RepAgent = (props) => {
)); ));
const required = (value) => (value ? undefined : "Required"); const required = (value) => (value ? undefined : "Required");
const hasTypeSelectionInline =
typeof formObj.representationForm.values.representationType ==
"undefined" && props.representationType != "Select...";
const selectedRepresentationTypeDisplay =
router.locale == "cy"
? formObj.representationForm.values.representationType ==
"Questionnaire"
? "Holiadur"
: formObj.representationForm.values.representationType ==
"Statement"
? "Datganiad"
: formObj.representationForm.values.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values.representationType
: formObj.representationForm.values.representationType;
const handleSaveExit = () => {
let valuesObj = props.props.props.form[props.form].values || {};
delete valuesObj["_pinswg_appellant_value"];
updateRepresentation(valuesObj, false, true);
};
return ( return (
<> <>
<RepresentationTypeSelectorBlock <div className="govuk-grid-row">
t={t} <div className="govuk-form-group">
headingText={t( {typeof formObj.representationForm.values
.representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:representation-from-an-agent-heading" "myrepresentations:representation-from-an-agent-heading"
)} )}
kindLabelText={t("myrepresentations:kind-of-rep-label")} </h2>
isTypeSelected={!hasTypeSelectionInline}
selectedTypeDisplay={selectedRepresentationTypeDisplay} <label
optionsArr={appellantApplicantRepresentationArr} className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{t("myrepresentations:kind-of-rep-label")}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
optionsArr={
appellantApplicantRepresentationArr
}
/> />
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" || {(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values typeof formObj.representationForm.values
.representationType != "undefined") && ( .representationType != "undefined") && (
@@ -229,16 +241,72 @@ const RepAgent = (props) => {
)} )}
{typeof formObj.representationForm.values.representationType != {typeof formObj.representationForm.values.representationType !=
"undefined" && ( "undefined" && (
<RepresentationActionButtons <div className="govuk-grid-row">
t={t} <div className="govuk-button-group">
locale={router.locale} <button
isSaving={savingStatus} type="submit"
isContinueDisabled={shouldDisableButton({ className="govuk-button"
props, data-module="govuk-button"
formObj >
})} {t("common:continue-button")}
onSaveExit={handleSaveExit} </button>
{/* {router.query.state != "edit" && (
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationCapacity",
""
);
}}
className="govuk-link"
>
{t("common:back-link")}
</a>
)} */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/> />
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)} )}
</> </>
); );
@@ -251,7 +319,7 @@ const mapDispatchToProps = (dispatch) => ({
setFilesForRepresentations: (fileList) => { setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList)); dispatch(setFilesForRepresentations(fileList));
} },
}); });
export default connect( export default connect(
@@ -261,6 +329,6 @@ export default connect(
reduxForm({ reduxForm({
form: "representationForm", form: "representationForm",
enableReinitialize: true, enableReinitialize: true,
destroyOnUnmount: false destroyOnUnmount: false,
})(RepAgent) })(RepAgent)
); );
@@ -9,16 +9,13 @@ import {
FileUploadField, FileUploadField,
RenderPickList, RenderPickList,
RenderRichMultiline, RenderRichMultiline,
shouldDisableButton
} from "./representationElements"; } from "./representationElements";
import RepresentationActionButtons from "./elements/RepresentationActionButtons";
import RepresentationTypeSelectorBlock from "./elements/RepresentationTypeSelectorBlock";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { import {
setRepresentationCapacity, setRepresentationCapacity,
setRepresentationSubmit, setRepresentationSubmit,
setFilesForRepresentations setFilesForRepresentations,
} from "../../../store/currentView/action"; } from "../../../store/currentView/action";
const RepAppellant = (props) => { const RepAppellant = (props) => {
@@ -36,7 +33,7 @@ const RepAppellant = (props) => {
updateRepresentation, updateRepresentation,
setSavingStatus, setSavingStatus,
savingStatus, savingStatus,
setFilesForRepresentations setFilesForRepresentations,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
@@ -64,44 +61,56 @@ const RepAppellant = (props) => {
index === self.findIndex((t) => t.name === value.name) index === self.findIndex((t) => t.name === value.name)
); );
const hasTypeSelectionInline =
typeof formObj.representationForm.values.representationType ==
"undefined" && props.representationType != "Select...";
const selectedRepresentationTypeDisplay =
router.locale == "cy"
? formObj.representationForm.values.representationType ==
"Questionnaire"
? "Holiadur"
: formObj.representationForm.values.representationType ==
"Statement"
? "Datganiad"
: formObj.representationForm.values.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values.representationType
: formObj.representationForm.values.representationType;
const handleSaveExit = () => {
let valuesObj = props.props.props.form[props.form].values || {};
delete valuesObj["_pinswg_appellant_value"];
updateRepresentation(valuesObj, false, true);
};
return ( return (
<> <>
<RepresentationTypeSelectorBlock <div className="govuk-grid-row">
t={t} <div className="govuk-form-group">
headingText={t( {typeof formObj.representationForm.values
.representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:representation-from-an-appellant-heading" "myrepresentations:representation-from-an-appellant-heading"
)} )}
kindLabelText={t("myrepresentations:kind-of-rep-label")} </h2>
isTypeSelected={!hasTypeSelectionInline} <label
selectedTypeDisplay={selectedRepresentationTypeDisplay} className="govuk-label govuk-body-m"
optionsArr={appellantApplicantRepresentationArr} htmlFor="representationType"
>
{t("myrepresentations:kind-of-rep-label")}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
optionsArr={
appellantApplicantRepresentationArr
}
/> />
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" || {(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values typeof formObj.representationForm.values
.representationType != "undefined") && ( .representationType != "undefined") && (
@@ -219,19 +228,75 @@ const RepAppellant = (props) => {
</div>{" "} </div>{" "}
</div> </div>
)} )}
{typeof formObj.representationForm.values.representationType != {typeof formObj.representationForm.values.representationType !=
"undefined" && ( "undefined" && (
<RepresentationActionButtons <div className="govuk-grid-row">
t={t} <div className="govuk-button-group">
locale={router.locale} <button
isSaving={savingStatus} type="submit"
isContinueDisabled={shouldDisableButton({ className="govuk-button"
props, data-module="govuk-button"
formObj >
})} {t("common:continue-button")}
onSaveExit={handleSaveExit} </button>
{/* {router.query.state != "edit" && (
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationType",
""
);
}}
className="govuk-link"
>
{t("common:back-link")}
</a>
)} */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/> />
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)} )}
</> </>
); );
@@ -247,7 +312,7 @@ const mapDispatchToProps = (dispatch) => {
setFilesForRepresentations: (fileList) => { setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList)); dispatch(setFilesForRepresentations(fileList));
} },
}; };
}; };
@@ -258,6 +323,6 @@ export default connect(
reduxForm({ reduxForm({
form: "representationForm", form: "representationForm",
enableReinitialize: true, enableReinitialize: true,
destroyOnUnmount: false destroyOnUnmount: false,
})(RepAppellant) })(RepAppellant)
); );
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { Field } from "redux-form"; import { Field } from "redux-form";
import RepDetails from "./representationDetails"; import RepDetails from "./representationDetails";
import { RenderRadioList } from "./representationElements"; import { RenderRadioListWithText } from "./representationElements";
let RepCapacitySelection = (props) => { let RepCapacitySelection = (props) => {
let { t } = useTranslation(); let { t } = useTranslation();
@@ -17,7 +17,7 @@ let RepCapacitySelection = (props) => {
casesObj, casesObj,
validate, validate,
handleSubmit, handleSubmit,
setCurrentReference setCurrentReference,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
const files = acceptedFiles.map((file) => ( const files = acceptedFiles.map((file) => (
@@ -27,7 +27,6 @@ let RepCapacitySelection = (props) => {
)); ));
const required = (value) => (value ? undefined : "Required"); const required = (value) => (value ? undefined : "Required");
const appealType = props.props.currentView.caseReference.appealType;
return ( return (
<> <>
@@ -43,7 +42,6 @@ let RepCapacitySelection = (props) => {
myRepresentations={props.props.myRepresentations} myRepresentations={props.props.myRepresentations}
props={props} props={props}
setCurrentReference={setCurrentReference} setCurrentReference={setCurrentReference}
appealType={appealType}
/>{" "} />{" "}
<div id="rep-details" className=""> <div id="rep-details" className="">
<div className="govuk-grid-column-full"> <div className="govuk-grid-column-full">
@@ -52,27 +50,21 @@ let RepCapacitySelection = (props) => {
{t( {t(
"myrepresentations:capacity-select-your-details" "myrepresentations:capacity-select-your-details"
)}{" "} )}{" "}
- {props.firstValue}{" "} - {props.firstValue}
</h2> </h2>
<Field <Field
name="representationCapacity" name="representationCapacity"
datafieldname="representationCapacity" datafieldname="representationCapacity"
label={ label={t(
appealType != 846040002
? t(
"myrepresentations:capacity-select-what-capacity-label" "myrepresentations:capacity-select-what-capacity-label"
) )}
: t(
"myrepresentations:sips-capacity-select-what-capacity-label"
)
}
options={capacityOptionsArr} options={capacityOptionsArr}
id="representationCapacity" id="representationCapacity"
className="govuk-radios__input" className="govuk-radios__input"
errorMsg={t( errorMsg={t(
"myrepresentations:select-an-option-label" "myrepresentations:select-an-option-label"
)} )}
component={RenderRadioList} component={RenderRadioListWithText}
validate={[required]} validate={[required]}
/> />
</div> </div>
@@ -7,10 +7,10 @@ import { connect } from "react-redux";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { import {
createWatchedCases, createWatchedCases,
sendEmail,
sendRepCompleteMessage, sendRepCompleteMessage,
setRepInvolvment setRepInvolvment,
} from "../../../actions/services/portalService"; } from "../../../actions";
import { sendEmail } from "../../../actions/services/notifyService";
import { setRepresentationReset } from "../../../store/currentView/action"; import { setRepresentationReset } from "../../../store/currentView/action";
const RepComplete = (props) => { const RepComplete = (props) => {
@@ -27,7 +27,7 @@ const RepComplete = (props) => {
setSubmitBack, setSubmitBack,
setRepresentationSubmitConfirmation, setRepresentationSubmitConfirmation,
setRepresentationMessageSent, setRepresentationMessageSent,
repFormData repFormData,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
const files = acceptedFiles.map((file) => ( const files = acceptedFiles.map((file) => (
@@ -40,16 +40,11 @@ const RepComplete = (props) => {
props.props.currentView.caseReference.appealType === 846040002; props.props.currentView.caseReference.appealType === 846040002;
useEffect(() => { useEffect(() => {
const isWelsh = router.locale === "cy";
const reference = isSIPS const reference = isSIPS
? "PEDW-CONSULTATION-COMPLETE" + isWelsh && "-CY" ? "PEDW-CONSULTATION-COMPLETE"
: "PEDW-REPRESENTATION-COMPLETE" + isWelsh && "-CY"; : "PEDW-REPRESENTATION-COMPLETE";
const templateId = isSIPS const templateId = isSIPS
? isWelsh ? "c3f373ca-df9d-4967-bea0-3ad3a57f8dcc"
? "7d27b968-6f63-4334-b1c4-2e4a69554212"
: "c3f373ca-df9d-4967-bea0-3ad3a57f8dcc"
: isWelsh
? "6e2f0111-b352-4074-91a2-760403cd185b"
: "c49785e7-3217-40b6-b33f-dffc4e58d5c1"; : "c49785e7-3217-40b6-b33f-dffc4e58d5c1";
const emailAddress = const emailAddress =
@@ -60,10 +55,10 @@ const RepComplete = (props) => {
"emailAddress": "emailAddress":
props.props.props.props.accountDetails.accountDetails props.props.props.props.accountDetails.accountDetails
.emailaddress1, .emailaddress1,
"linkExpiry": 10 * 60 "linkExpiry": 10 * 60,
}; };
(props.props.currentView.representationMessageSent != true && props.props.currentView.representationMessageSent != true &&
(setRepInvolvment( (setRepInvolvment(
props.props.currentView.caseReference.incidentid, props.props.currentView.caseReference.incidentid,
props.props.props.props.accountDetails.accountDetails.contactid props.props.props.props.accountDetails.accountDetails.contactid
@@ -94,10 +89,10 @@ const RepComplete = (props) => {
? props.props.currentView.caseReference.repDetails ? props.props.currentView.caseReference.repDetails
.representationType .representationType
: props.props.currentView.caseReference : props.props.currentView.caseReference
.representationType .representationType,
}), }),
setRepresentationMessageSent(true)), setRepresentationMessageSent(true)),
window.scrollTo({ top: 0, behavior: "smooth" })); window.scrollTo({ top: 0, behavior: "smooth" });
}); });
return ( return (
<div id="rep-appellant"> <div id="rep-appellant">
@@ -109,7 +104,6 @@ const RepComplete = (props) => {
<p>{t("myrepresentations:rep-complete-para-one")}</p> <p>{t("myrepresentations:rep-complete-para-one")}</p>
<p>{t("myrepresentations:rep-complete-para-two")}</p> <p>{t("myrepresentations:rep-complete-para-two")}</p>
<p> {t("myrepresentations:rep-complete-para-three")}</p> <p> {t("myrepresentations:rep-complete-para-three")}</p>
<p> {t("myrepresentations:rep-complete-para-four")}</p>
</div> </div>
<div className="govuk-grid-row"> <div className="govuk-grid-row">
<div className="govuk-button-group"> <div className="govuk-button-group">
@@ -136,7 +130,7 @@ const mapStateToProps = (state) => {
currentView: state.currentView, currentView: state.currentView,
myRepresentations: state.myRepresentations, myRepresentations: state.myRepresentations,
initialValues: state.currentView.caseReference.repDetails, initialValues: state.currentView.caseReference.repDetails,
accountDetails: state.accountDetails accountDetails: state.accountDetails,
//form: state.form, //form: state.form,
}; };
}; };
@@ -4,7 +4,6 @@ import { useRouter } from "next/router";
import { useState } from "react"; import { useState } from "react";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { generateRepPDF } from "../../../actions/services/documentService";
import RepComplete from "./representationComplete"; import RepComplete from "./representationComplete";
import RepLPAQuestionnaireCheck_enforcement from "./representationQuestionnairesCheck/representationLPAQuestionnaireCheck_enforcement"; import RepLPAQuestionnaireCheck_enforcement from "./representationQuestionnairesCheck/representationLPAQuestionnaireCheck_enforcement";
import RepLPAQuestionnaireCheck_s78 from "./representationQuestionnairesCheck/representationLPAQuestionnaireCheck_s78"; import RepLPAQuestionnaireCheck_s78 from "./representationQuestionnairesCheck/representationLPAQuestionnaireCheck_s78";
@@ -14,19 +13,16 @@ import {
getThumbnailIconByExtension, getThumbnailIconByExtension,
formatDates, formatDates,
updateLinks, updateLinks,
getDocLink
} from "../../utils"; } from "../../utils";
import { import {
setCurrentReference, setCurrentReference,
setCurrentView setCurrentView,
} from "../../../store/currentView/action"; } from "../../../store/currentView/action";
const RepCompleteSubmit = (props) => { const RepCompleteSubmit = (props) => {
let { t } = useTranslation(); let { t } = useTranslation();
const [confirmSections, setConfirmSections] = useState(false); const [confirmSections, setConfirmSections] = useState(false);
const [downloadQuestionnaire, setDownloadQuestionnaire] = useState(false);
const [downloadInProgress, setDownloadInProgress] = useState(false);
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
@@ -45,11 +41,7 @@ const RepCompleteSubmit = (props) => {
questionnaireCount, questionnaireCount,
finaliseAppealProcess, finaliseAppealProcess,
setCurrentReference, setCurrentReference,
docsOffline
} = props; } = props;
let ShowDocLinks = getDocLink(docsOffline);
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
const files = acceptedFiles.map((file) => ( const files = acceptedFiles.map((file) => (
<li key={file.path}> <li key={file.path}>
@@ -61,13 +53,6 @@ const RepCompleteSubmit = (props) => {
repFormData = updateLinks(repFormData); repFormData = updateLinks(repFormData);
const representationOnBehalfOfDisplay =
repFormData.representationOnBehalfOf === "Yes"
? t("myrepresentations:questionnaire-yes")
: repFormData.representationOnBehalfOf === "No"
? t("myrepresentations:questionnaire-no")
: repFormData.representationOnBehalfOf;
//const repDate = new Date(); //const repDate = new Date();
// let day = repDate.getDate(); // let day = repDate.getDate();
@@ -179,7 +164,7 @@ const RepCompleteSubmit = (props) => {
typeof filesUploadObj[key].name != "undefined" && typeof filesUploadObj[key].name != "undefined" &&
buildAppealFilesArray.push({ buildAppealFilesArray.push({
"name": filesUploadObj[key].name, "name": filesUploadObj[key].name,
"size": filesUploadObj[key].contentLength "size": filesUploadObj[key].contentLength,
}); });
} }
@@ -195,7 +180,7 @@ const RepCompleteSubmit = (props) => {
// : []; // : [];
let arrUniq = [ let arrUniq = [
...new Map(buildAppealFilesArray.map((v) => [v.name, v])).values() ...new Map(buildAppealFilesArray.map((v) => [v.name, v])).values(),
]; ];
buildAppealFilesArray = buildAppealFilesArray.filter(function (el) { buildAppealFilesArray = buildAppealFilesArray.filter(function (el) {
@@ -227,7 +212,7 @@ const RepCompleteSubmit = (props) => {
arrUniq = removeEmptyObjects(arrUniq); arrUniq = removeEmptyObjects(arrUniq);
Object.assign(formObj.representationForm.values, { Object.assign(formObj.representationForm.values, {
"filesList": arrUniq "filesList": arrUniq,
}); });
let filterFiles = []; let filterFiles = [];
@@ -264,64 +249,6 @@ const RepCompleteSubmit = (props) => {
} }
}; };
const triggerQuestionnaireDownload = async () => {
if (
repFormData.representationType !== "Questionnaire" ||
!downloadQuestionnaire
) {
return;
}
if (downloadInProgress) {
return;
}
try {
setDownloadInProgress(true);
const containerID =
props.accountDetails?.containerID ||
props.props?.accountDetails?.containerID ||
props.props?.props?.accountDetails?.containerID;
const caseRef =
currentView?.caseReference?.ticketnumber ||
repFormData?.caseRef ||
repFormData?.ticketnumber;
if (!containerID || !caseRef) {
console.error(
"Questionnaire download skipped: missing containerID or case reference",
{ containerID, caseRef }
);
return;
}
repFormData.locale = router.locale == "cy" ? "cy" : "en";
const pdfBlob = await generateRepPDF(
repFormData,
containerID,
caseRef,
{ download: true }
);
if (pdfBlob) {
const blobUrl = window.URL.createObjectURL(pdfBlob);
const anchor = document.createElement("a");
anchor.href = blobUrl;
anchor.download = `${repFormData.repfile_name || "questionnaire"}.pdf`;
document.body.appendChild(anchor);
anchor.click();
anchor.remove();
window.URL.revokeObjectURL(blobUrl);
}
} catch (error) {
console.error("Questionnaire download failed", error);
} finally {
setDownloadInProgress(false);
}
};
return ( return (
<> <>
{currentView.representationSubmitConfirmation == true ? ( {currentView.representationSubmitConfirmation == true ? (
@@ -337,31 +264,19 @@ const RepCompleteSubmit = (props) => {
<div className="govuk-grid-row govuk-body"> <div className="govuk-grid-row govuk-body">
<h1 className="govuk-heading-m "> <h1 className="govuk-heading-m ">
{" "} {" "}
{repFormData.appealType == 846040002 {t(
? t(
"myrepresentations:consultation-check-submit-heading"
)
: t(
"myrepresentations:rep-check-submit-heading" "myrepresentations:rep-check-submit-heading"
)} )}
</h1> </h1>
<dl className="govuk-summary-list "> <dl className="govuk-summary-list ">
<h2 className="govuk-heading-m govuk-!-margin-top-9"> <h2 className="govuk-heading-m govuk-!-margin-top-9">
{repFormData.appealType == 846040002 {t(
? t(
"myrepresentations:consultation-check-your-rep-heading"
)
: t(
"myrepresentations:rep-check-your-rep-heading" "myrepresentations:rep-check-your-rep-heading"
)} )}
</h2> </h2>
<div className="govuk-summary-list__row"> <div className="govuk-summary-list__row">
<dt className="govuk-summary-list__key"> <dt className="govuk-summary-list__key">
{repFormData.appealType == 846040002 {t(
? t(
"case:consultation-representation-type"
)
: t(
"case:representation-representation-type" "case:representation-representation-type"
)} )}
</dt> </dt>
@@ -413,7 +328,7 @@ const RepCompleteSubmit = (props) => {
<dd className="govuk-summary-list__value"> <dd className="govuk-summary-list__value">
{ {
representationOnBehalfOfDisplay repFormData.representationOnBehalfOf
} }
</dd> </dd>
@@ -435,7 +350,7 @@ const RepCompleteSubmit = (props) => {
"appealType": "appealType":
repFormData.appealType, repFormData.appealType,
"repDetails": "repDetails":
repFormData repFormData,
}); });
setRepresentationSubmit( setRepresentationSubmit(
false false
@@ -488,7 +403,7 @@ const RepCompleteSubmit = (props) => {
"appealType": "appealType":
repFormData.appealType, repFormData.appealType,
"repDetails": "repDetails":
repFormData repFormData,
} }
); );
setRepresentationSubmit( setRepresentationSubmit(
@@ -512,20 +427,17 @@ const RepCompleteSubmit = (props) => {
</> </>
)} )}
{repFormData.representationType != {repFormData.representationType !=
"Questionnaire" && "Questionnaire" && (
repFormData.appealType != 846040002 && (
<div className="govuk-summary-list__row"> <div className="govuk-summary-list__row">
<dt className="govuk-summary-list__key"> <dt className="govuk-summary-list__key">
{t( {t("case:representation-comments")}
"case:representation-comments"
)}
</dt> </dt>
<dd className="govuk-summary-list__value"> <dd className="govuk-summary-list__value">
<span <span
className="multiline-elipsis" className="multiline-elipsis"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: repFormData.representationComments __html: repFormData.representationComments,
}} }}
/> />
</dd> </dd>
@@ -549,16 +461,14 @@ const RepCompleteSubmit = (props) => {
"appealType": "appealType":
repFormData.appealType, repFormData.appealType,
"repDetails": "repDetails":
repFormData repFormData,
}); });
setRepresentationSubmit( setRepresentationSubmit(
false false
); );
}} }}
> >
{t( {t("common:change-link-label")}
"common:change-link-label"
)}
<span className="govuk-visually-hidden"> <span className="govuk-visually-hidden">
{" "} {" "}
{/* {FieldsTranslations( {/* {FieldsTranslations(
@@ -629,7 +539,7 @@ const RepCompleteSubmit = (props) => {
"appealType": "appealType":
repFormData.appealType, repFormData.appealType,
"repDetails": "repDetails":
repFormData repFormData,
}), }),
setRepresentationSubmit( setRepresentationSubmit(
false false
@@ -676,8 +586,6 @@ const RepCompleteSubmit = (props) => {
"myrepresentations:rep-check-tandc-para-three" "myrepresentations:rep-check-tandc-para-three"
)} )}
</p> </p>
<p></p>
{checkRepDatePassed() ? ( {checkRepDatePassed() ? (
<div className="govuk-warning-text noticebanner"> <div className="govuk-warning-text noticebanner">
<strong className="govuk-warning-text__text"> <strong className="govuk-warning-text__text">
@@ -716,63 +624,8 @@ const RepCompleteSubmit = (props) => {
{t("myrepresentations:rep-wait-label")} {t("myrepresentations:rep-wait-label")}
</p> </p>
</div> </div>
) : ShowDocLinks ? (
<>
{" "}
<div className="govuk-warning-text ">
<span
className="govuk-warning-text__icon"
aria-hidden="true"
>
!
</span>
<strong className="govuk-warning-text__text govuk-!-margin-top-2">
<span className="govuk-visually-hidden">
Notice
</span>
{t(
"myrepresentations:docsoffline-reps-label"
)}
{" "}
</strong>
</div>{" "}
<Link className="govuk-link" href="/">
{t(
"myrepresentations:return-to-myportal-link"
)}
</Link>
</>
) : ( ) : (
<> <>
{repFormData.representationType ==
"Questionnaire" && (
<div className="govuk-checkboxes govuk-checkboxes--small">
<div className="govuk-checkboxes__item">
<input
name="pinswg_downloadQuestionnaire"
id="pinswg_downloadQuestionnaire"
type="checkbox"
className="govuk-checkboxes__input"
checked={
downloadQuestionnaire
}
onChange={(e) => {
setDownloadQuestionnaire(
e.target.checked
);
}}
/>
<label
className="govuk-label govuk-checkboxes__label"
htmlFor="pinswg_downloadQuestionnaire"
>
{t(
"myrepresentations:rep-check-tandc-para-five"
)}
</label>
</div>
</div>
)}
<div className="govuk-form-group"> <div className="govuk-form-group">
<div className="govuk-checkboxes govuk-checkboxes--small"> <div className="govuk-checkboxes govuk-checkboxes--small">
<div className="govuk-checkboxes__item"> <div className="govuk-checkboxes__item">
@@ -811,11 +664,10 @@ const RepCompleteSubmit = (props) => {
type="submit" type="submit"
className="govuk-button" className="govuk-button"
data-module="govuk-button" data-module="govuk-button"
onClick={async () => { onClick={() => {
// setRepresentationSubmitConfirmation( // setRepresentationSubmitConfirmation(
// true // true
// ); // );
await triggerQuestionnaireDownload();
setRepresentationSubmit( setRepresentationSubmit(
true true
); );
@@ -852,7 +704,7 @@ const mapStateToProps = (state) => {
currentView: state.currentView, currentView: state.currentView,
myRepresentations: state.myRepresentations, myRepresentations: state.myRepresentations,
initialValues: state.currentView.caseReference.repDetails, initialValues: state.currentView.caseReference.repDetails,
accountDetails: state.accountDetails accountDetails: state.accountDetails,
//form: state.form, //form: state.form,
}; };
}; };
@@ -861,7 +713,7 @@ const mapDispatchToProps = (dispatch) => {
return { return {
setCurrentReference: (currentReference) => { setCurrentReference: (currentReference) => {
dispatch(setCurrentReference(currentReference)); dispatch(setCurrentReference(currentReference));
} },
}; };
}; };
@@ -8,7 +8,7 @@ const RepDetails = (props) => {
const router = useRouter(); const router = useRouter();
const { locale } = router; const { locale } = router;
const { currentType, casesObj, appealType } = props; const { currentType, casesObj } = props;
let { caseReference, ticketnumber } = props; let { caseReference, ticketnumber } = props;
@@ -97,14 +97,10 @@ const RepDetails = (props) => {
</div> </div>
<div className="govuk-grid-row"> <div className="govuk-grid-row">
<p className="govuk-body"> <p className="govuk-body">
{appealType == 846040002 {t("myrepresentations:capacity-para-one")}
? t("myrepresentations:sips-capacity-para-one")
: t("myrepresentations:capacity-para-one")}
</p> </p>
<p className="govuk-body"> <p className="govuk-body">
{appealType == 846040002 {t("myrepresentations:capacity-para-two")}
? t("myrepresentations:sips-capacity-para-two")
: t("myrepresentations:capacity-para-two")}
</p> </p>
</div> </div>
</div> </div>
@@ -13,8 +13,8 @@ import {
deleteBlob, deleteBlob,
deleteRepBlob, deleteRepBlob,
getFilesFromBlobHashed, getFilesFromBlobHashed,
getFilesFromBlobproxy getFilesFromBlobproxy,
} from "../../../actions/services/documentService"; } from "../../../actions";
const LoadingMessage = () => <div>Loading the editor...</div>; const LoadingMessage = () => <div>Loading the editor...</div>;
@@ -23,7 +23,7 @@ const ReactQuill = dynamic(
() => import("react-quill-new").then((mod) => mod.default), () => import("react-quill-new").then((mod) => mod.default),
{ {
ssr: false, ssr: false,
loading: () => <LoadingMessage /> // This is valid as long as it's a valid React component loading: () => <LoadingMessage />, // This is valid as long as it's a valid React component
} }
); );
import { useDispatch } from "react-redux"; // Import the useDispatch hook import { useDispatch } from "react-redux"; // Import the useDispatch hook
@@ -35,13 +35,13 @@ import {
parseISO, parseISO,
subDays, subDays,
subMonths, subMonths,
subYears subYears,
} from "date-fns"; } from "date-fns";
import { import {
bytesToSize, bytesToSize,
getThumbnailIconByExtension, getThumbnailIconByExtension,
updateLinks updateLinks,
} from "../../utils"; } from "../../utils";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@@ -258,26 +258,6 @@ export const RenderCondtionalRadioList = ({
}) => { }) => {
const required = (value) => (value ? undefined : "Required"); const required = (value) => (value ? undefined : "Required");
let { t } = useTranslation(); let { t } = useTranslation();
const yesValue = t("myrepresentations:questionnaire-yes");
const noValue = t("myrepresentations:questionnaire-no");
const normalizeYesNo = (rawValue) => {
if (rawValue === true) return "Yes";
if (rawValue === false) return "No";
if (rawValue === "Yes" || rawValue === yesValue) return "Yes";
if (rawValue === "No" || rawValue === noValue) return "No";
return rawValue;
};
const isYesSelected = normalizeYesNo(value) === "Yes";
const requiredIfYes = (fieldValue, allValues) => {
const selectedValue = normalizeYesNo(allValues?.[id]);
return selectedValue === "Yes" && !String(fieldValue || "").trim()
? "Required"
: undefined;
};
return ( return (
<> <>
<div <div
@@ -324,16 +304,8 @@ export const RenderCondtionalRadioList = ({
{custom.hint} {custom.hint}
</div> </div>
<div className="govuk-radios"> <div className="govuk-radios">
{Object.keys(options).map((key, index) => { {Object.keys(options).map((key, index) => (
const normalizedOptionValue = normalizeYesNo( <div key={key} className="govuk-!-margin-bottom-3">
options[key]
);
return (
<div
key={key}
className="govuk-!-margin-bottom-3"
>
<div <div
className="govuk-radios__item" className="govuk-radios__item"
data-children-count={key} data-children-count={key}
@@ -345,7 +317,7 @@ export const RenderCondtionalRadioList = ({
component="input" component="input"
type="radio" type="radio"
className="govuk-radios__input" className="govuk-radios__input"
value={normalizedOptionValue} value={options[key]}
validate={[required]} validate={[required]}
/> />
<label <label
@@ -361,8 +333,7 @@ export const RenderCondtionalRadioList = ({
)} )}
</label> </label>
</div> </div>
{isYesSelected && {value == "Yes" && options[key] == "Yes" && (
normalizedOptionValue === "Yes" && (
<div <div
className="govuk-radios__conditional " className="govuk-radios__conditional "
id={"conditional-" + id} id={"conditional-" + id}
@@ -373,9 +344,7 @@ export const RenderCondtionalRadioList = ({
> >
<label <label
className="govuk-label" className="govuk-label"
htmlFor={ htmlFor={id + "_details"}
id + "_details"
}
> >
{t( {t(
"myrepresentations:representation-onbehalfof-label" "myrepresentations:representation-onbehalfof-label"
@@ -385,13 +354,9 @@ export const RenderCondtionalRadioList = ({
className="govuk-input govuk-!-width-one-half" className="govuk-input govuk-!-width-one-half"
id={id + "_details"} id={id + "_details"}
name={id + "_details"} name={id + "_details"}
component={ component={RenderTextfield}
RenderTextfield
}
type="text" type="text"
validate={[ validate={[required]}
requiredIfYes
]}
errorMsg={t( errorMsg={t(
"myrepresentations:is-required-label" "myrepresentations:is-required-label"
)} )}
@@ -400,8 +365,7 @@ export const RenderCondtionalRadioList = ({
</div> </div>
)} )}
</div> </div>
); ))}
})}
</div> </div>
</fieldset> </fieldset>
</div> </div>
@@ -582,8 +546,7 @@ export const RenderPickList = ({
? "Sylwadau ysgrifenedig" ? "Sylwadau ysgrifenedig"
: optionsArr[key] == "Inquiry" : optionsArr[key] == "Inquiry"
? "Ymchwiliad" ? "Ymchwiliad"
: optionsArr[key] == : optionsArr[key] == "Hearing"
"Hearing"
? "Gwrandawiad" ? "Gwrandawiad"
: optionsArr[key] : optionsArr[key]
: optionsArr[key]} : optionsArr[key]}
@@ -771,19 +734,13 @@ export const RenderMultiline = ({
input.onChange(valStr); input.onChange(valStr);
}; };
const handleBlur = () => {
const updated = updateLinks(editValue);
setEditValue(updated);
input.onChange(updated);
};
var modules = { var modules = {
toolbar: [ toolbar: [
[{ "header": [1, 2, false] }], [{ "header": [1, 2, false] }],
["bold", "italic", "underline", "blockquote"], ["bold", "italic", "underline", "blockquote"],
[{ "list": "ordered" }, { "list": "bullet" }], [{ "list": "ordered" }, { "list": "bullet" }],
["clean"] ["clean"],
] ],
}; };
return ( return (
@@ -807,7 +764,6 @@ export const RenderMultiline = ({
theme="snow" theme="snow"
value={editValue} value={editValue}
onChange={changeEdit} onChange={changeEdit}
onBlur={handleBlur}
/> />
<textarea <textarea
{...input} {...input}
@@ -839,23 +795,18 @@ export const RenderRichMultiline = ({
); );
const changeEdit = (valStr) => { const changeEdit = (valStr) => {
valStr = updateLinks(valStr);
setEditValue(valStr); setEditValue(valStr);
input.onChange(valStr); input.onChange(valStr);
}; };
const handleBlur = () => {
const updated = updateLinks(editValue);
setEditValue(updated);
input.onChange(updated);
};
var modules = { var modules = {
toolbar: [ toolbar: [
[{ "header": [1, 2, false] }], [{ "header": [1, 2, false] }],
["bold", "italic", "underline", "blockquote"], ["bold", "italic", "underline", "blockquote"],
[{ "list": "ordered" }, { "list": "bullet" }], [{ "list": "ordered" }, { "list": "bullet" }],
["clean"] ["clean"],
] ],
}; };
return ( return (
@@ -868,7 +819,6 @@ export const RenderRichMultiline = ({
theme="snow" theme="snow"
value={editValue} value={editValue}
onChange={changeEdit} onChange={changeEdit}
onBlur={handleBlur}
/> />
<textarea <textarea
{...input} {...input}
@@ -924,19 +874,19 @@ const baseStyle = {
borderStyle: "dashed", borderStyle: "dashed",
backgroundColor: "#fafafa", backgroundColor: "#fafafa",
color: "#bdbdbd", color: "#bdbdbd",
transition: "border .3s ease-in-out" transition: "border .3s ease-in-out",
}; };
const activeStyle = { const activeStyle = {
borderColor: "#2196f3" borderColor: "#2196f3",
}; };
const acceptStyle = { const acceptStyle = {
borderColor: "#00e676" borderColor: "#00e676",
}; };
const rejectStyle = { const rejectStyle = {
borderColor: "#ff1744" borderColor: "#ff1744",
}; };
export const RenderFileUpload = (field) => { export const RenderFileUpload = (field) => {
@@ -947,7 +897,7 @@ export const RenderFileUpload = (field) => {
const style = useMemo( const style = useMemo(
() => ({ () => ({
...baseStyle ...baseStyle,
// ...(isDragActive ? activeStyle : {}), // ...(isDragActive ? activeStyle : {}),
// ...(isDragAccept ? acceptStyle : {}), // ...(isDragAccept ? acceptStyle : {}),
// ...(isDragReject ? rejectStyle : {}), // ...(isDragReject ? rejectStyle : {}),
@@ -1043,7 +993,7 @@ export const RenderFileUpload = (field) => {
typeof filesUploadObj[key].name != "undefined" && typeof filesUploadObj[key].name != "undefined" &&
buildAppealFilesArray.push({ buildAppealFilesArray.push({
"name": filesUploadObj[key].name, "name": filesUploadObj[key].name,
"size": filesUploadObj[key].size "size": filesUploadObj[key].size,
}); });
} }
@@ -1092,12 +1042,9 @@ export const RenderFileUpload = (field) => {
}); });
}; };
const [errorMessage, setErrorMessage] = useState(null);
const [rejectedFiles, setRejectedFiles] = useState([]); // Store rejected files const [rejectedFiles, setRejectedFiles] = useState([]); // Store rejected files
const [completedUploadFiles, setCompletedUploadFiles] = useState(false); const [completedUploadFiles, setCompletedUploadFiles] = useState(false);
const [uploadCountMessage, setUploadCountMessage] = useState(""); const [uploadCountMessage, setUploadCountMessage] = useState("");
const [totalUploadFiles, setTotalUploadFiles] = useState(0);
const handleDropRejected = (fileRejections) => { const handleDropRejected = (fileRejections) => {
const errors = fileRejections const errors = fileRejections
@@ -1113,15 +1060,6 @@ export const RenderFileUpload = (field) => {
"myrepresentations:fileupload-file-error-invalid-type-label" "myrepresentations:fileupload-file-error-invalid-type-label"
)}`; )}`;
} }
if (error.code === "filename-invalid-chars") {
return (
error.message ||
`${file.name} ${t(
"newappeal:new-appeal-fileupload-file-error-invalid-filename-label"
)}`
);
}
return `${file.name} ${t( return `${file.name} ${t(
"myrepresentations:fileupload-file-error-invalid-label" "myrepresentations:fileupload-file-error-invalid-label"
)}`; )}`;
@@ -1138,44 +1076,6 @@ export const RenderFileUpload = (field) => {
setRejectedFiles([]); // Clear any previously rejected file errorsss setRejectedFiles([]); // Clear any previously rejected file errorsss
}; };
const FILENAME_ALLOWED = /^[A-Za-z0-9 ._\-:()—']+$/;
const validateFilename = (file, t) => {
const name = file.name;
// block #
if (name.includes("#")) {
return {
code: "filename-invalid-chars",
message: `${name} ${t(
"myrepresentations:fileupload-file-error-invalid-filename-label"
)}`
};
}
// broader blocklist (optional but recommended)
if (!FILENAME_ALLOWED.test(name)) {
return {
code: "filename-invalid-chars",
message: `${name} ${t(
"myrepresentations:fileupload-file-error-invalid-filename-label"
)}`
};
}
// block characters < > " / \ | ? *
if (/[<>"/\\|?*]/.test(name)) {
return {
code: "filename-invalid-chars",
message: `${name} ${t(
"myrepresentations:fileupload-file-error-invalid-filename-label"
)}`
};
}
return null; // valid
};
return ( return (
<> <>
<Dropzone <Dropzone
@@ -1189,30 +1089,11 @@ export const RenderFileUpload = (field) => {
"image/jpeg": [".jpg", ".jpeg"], "image/jpeg": [".jpg", ".jpeg"],
"image/png": [".png"], "image/png": [".png"],
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
[".xlsx"] [".xlsx"],
}} }}
validator={(file) => validateFilename(file, t)} onDrop={(filesToUpload, e) => {
onDrop={(acceptedFiles, fileRejections, e) => {
// build + display rejected messages (ALWAYS, even if some accepted)
if (fileRejections?.length) {
handleDropRejected(fileRejections);
} else {
// only clear rejections when nothing was rejected on this drop
setRejectedFiles([]);
setErrorMessage(null);
}
// if nothing accepted, stop (prevents showing only "uploading" when all invalid)
if (!acceptedFiles || acceptedFiles.length === 0) {
setCompletedUploadFiles(true); // optional: depends on your UX
setUploadCountMessage(0);
setTotalUploadFiles(0);
return;
}
setCompletedUploadFiles(false); setCompletedUploadFiles(false);
const renamedAcceptedFiles = filesToUpload.map(
const renamedAcceptedFiles = acceptedFiles.map(
(file) => (file) =>
new File( new File(
[file], [file],
@@ -1230,22 +1111,12 @@ export const RenderFileUpload = (field) => {
.values.repfile_name .values.repfile_name
}_-_Attachment_-_${file.name}`, }_-_Attachment_-_${file.name}`,
{ {
type: file.type type: file.type,
} }
) )
); );
field.input.onChange(renamedAcceptedFiles); field.input.onChange(renamedAcceptedFiles);
setUploadCountMessage(renamedAcceptedFiles.length);
if (typeof field.setFileCount === "function") {
field.setFileCount(
(field.uploadCount || 0) +
renamedAcceptedFiles.length
);
}
setUploadCountMessage(0);
setTotalUploadFiles(renamedAcceptedFiles.length);
uploadSingleFile( uploadSingleFile(
renamedAcceptedFiles, renamedAcceptedFiles,
@@ -1253,12 +1124,7 @@ export const RenderFileUpload = (field) => {
field.ticketnumber + field.ticketnumber +
"/" + "/" +
field.filenamePrefix.representationForm.values field.filenamePrefix.representationForm.values
.repfile_name, .repfile_name
{
onChunkComplete: ({ cumulativeUploaded }) => {
setUploadCountMessage(cumulativeUploaded);
}
}
).then((data) => { ).then((data) => {
console.log(data); console.log(data);
let buildAppealFilesArray = []; let buildAppealFilesArray = [];
@@ -1269,7 +1135,7 @@ export const RenderFileUpload = (field) => {
typeof filesUploadObj[key].name != "undefined" && typeof filesUploadObj[key].name != "undefined" &&
buildAppealFilesArray.push({ buildAppealFilesArray.push({
"name": filesUploadObj[key].name, "name": filesUploadObj[key].name,
"size": filesUploadObj[key].size "size": filesUploadObj[key].size,
}); });
} }
@@ -1330,6 +1196,8 @@ export const RenderFileUpload = (field) => {
}); });
}); });
}} }}
onDropRejected={handleDropRejected}
onDropAccepted={handleDropAccepted}
> >
{({ getRootProps, getInputProps }) => ( {({ getRootProps, getInputProps }) => (
<> <>
@@ -1356,7 +1224,7 @@ export const RenderFileUpload = (field) => {
</> </>
)} )}
</Dropzone> </Dropzone>
{rejectedFiles.length > 0 && ( {rejectedFiles.length > 0 && completedUploadFiles == true && (
<div <div
style={{ color: "red", marginTop: "10px" }} style={{ color: "red", marginTop: "10px" }}
className="govuk-body govuk-!-font-size-14 " className="govuk-body govuk-!-font-size-14 "
@@ -1368,20 +1236,17 @@ export const RenderFileUpload = (field) => {
</ul> </ul>
</div> </div>
)} )}
{totalUploadFiles > 0 && completedUploadFiles == false && ( {uploadCountMessage > 0 && completedUploadFiles == false && (
<div className="govuk-body govuk-!-font-size-14"> <div className="govuk-body govuk-!-font-size-14">
{t("home:uploading-files-label", { {t("home:uploading-files-label", {
number: number: uploadCountMessage,
totalUploadFiles > 0
? `${uploadCountMessage} of ${totalUploadFiles}`
: uploadCountMessage
})} })}
</div> </div>
)} )}
{completedUploadFiles > 0 && uploadCountMessage >= 0 && ( {completedUploadFiles > 0 && uploadCountMessage >= 0 && (
<div className="govuk-body govuk-!-font-size-14"> <div className="govuk-body govuk-!-font-size-14">
{t("home:completed-uploading-files-label", { {t("home:completed-uploading-files-label", {
number: uploadCountMessage number: uploadCountMessage,
})} })}
</div> </div>
)} )}
@@ -1520,12 +1385,6 @@ export function FileUploadField(props) {
); );
} }
export const shouldDisableButton = ({ props, formObj }) =>
!(
props?.currentView?.fileList?.length > 0 ||
typeof formObj?.representationForm?.values?.representationComments !==
"undefined"
);
// export const RepresentationGuidanceText = (appealType) => { // export const RepresentationGuidanceText = (appealType) => {
// let { t } = useTranslation(); // let { t } = useTranslation();
@@ -8,17 +8,15 @@ import { bytesToSize, getThumbnailIconByExtension } from "../../utils";
import { import {
FileUploadField, FileUploadField,
RenderCondtionalRadioList, RenderCondtionalRadioList,
RenderPickList,
RenderRichMultiline, RenderRichMultiline,
shouldDisableButton
} from "./representationElements"; } from "./representationElements";
import RepresentationActionButtons from "./elements/RepresentationActionButtons";
import RepresentationTypeSelectorBlock from "./elements/RepresentationTypeSelectorBlock";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { import {
setRepresentationCapacity, setRepresentationCapacity,
setRepresentationSubmit, setRepresentationSubmit,
setFilesForRepresentations setFilesForRepresentations,
} from "../../../store/currentView/action"; } from "../../../store/currentView/action";
const RepInterestedPartyPerson = (props) => { const RepInterestedPartyPerson = (props) => {
@@ -35,7 +33,7 @@ const RepInterestedPartyPerson = (props) => {
updateRepresentation, updateRepresentation,
setSavingStatus, setSavingStatus,
savingStatus, savingStatus,
setFilesForRepresentations setFilesForRepresentations,
} = props; } = props;
const required = (value) => (value ? undefined : "Required"); const required = (value) => (value ? undefined : "Required");
@@ -63,47 +61,62 @@ const RepInterestedPartyPerson = (props) => {
{file.path} - {file.size} bytes {file.path} - {file.size} bytes
</li> </li>
)); ));
const hasTypeSelectionInline =
typeof formObj.representationForm.values.representationType ==
"undefined" && props.representationType != "Select...";
const selectedRepresentationTypeDisplay =
router.locale == "cy"
? formObj.representationForm.values.representationType ==
"Questionnaire"
? "Holiadur"
: formObj.representationForm.values.representationType ==
"Statement"
? "Datganiad"
: formObj.representationForm.values.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values.representationType
: formObj.representationForm.values.representationType;
const handleSaveExit = () => {
let valuesObj = props.props.props.form[props.form].values || {};
delete valuesObj["_pinswg_appellant_value"];
updateRepresentation(valuesObj, false, true);
};
return ( return (
<> <>
<RepresentationTypeSelectorBlock <div className="govuk-grid-row">
t={t} <div className="govuk-form-group">
headingText={t( {typeof formObj.representationForm.values
"myrepresentations:consultation-from-an-interested-person-heading" .representationType == "undefined" &&
props.representationType != "Select..." ? (
<>
<h2 className="govuk-heading-m ">
{t(
"myrepresentations:representation-from-an-interested-person-heading"
)} )}
kindLabelText={t("myrepresentations:kind-of-rep-label")} </h2>
isTypeSelected={!hasTypeSelectionInline}
selectedTypeDisplay={selectedRepresentationTypeDisplay} <label
optionsArr={interestedPersonRepresentationArr} className="govuk-label govuk-body-m"
htmlFor="representationType"
>
{t("myrepresentations:kind-of-rep-label")}
</label>
<Field
name="representationType"
component={RenderPickList}
datafieldname="representationType"
validate={[required]} validate={[required]}
errorMsg={t("myrepresentations:select-an-option-label")} optionsArr={
interestedPersonRepresentationArr
}
errorMsg={t(
"myrepresentations:select-an-option-label"
)}
/> />
</>
) : (
<label className="govuk-label govuk-body-m">
{t("myrepresentations:representation-type")}:{" "}
{router.locale == "cy"
? formObj.representationForm.values
.representationType == "Questionnaire"
? "Holiadur"
: formObj.representationForm.values
.representationType == "Statement"
? "Datganiad"
: formObj.representationForm.values
.representationType ==
"Final comments"
? "Sylwadau terfynol"
: formObj.representationForm.values
.representationType
: formObj.representationForm.values
.representationType}
</label>
)}
</div>
</div>
{(typeof props.representationType != "undefined" || {(typeof props.representationType != "undefined" ||
typeof formObj.representationForm.values typeof formObj.representationForm.values
.representationType != "undefined") && ( .representationType != "undefined") && (
@@ -114,7 +127,12 @@ const RepInterestedPartyPerson = (props) => {
name="representationOnBehalfOf" name="representationOnBehalfOf"
datafieldname="representationOnBehalfOf" datafieldname="representationOnBehalfOf"
// label="In what capacity do you wish to make representations on this case?" // label="In what capacity do you wish to make representations on this case?"
options={["Yes", "No"]} options={[
t(
"myrepresentations:questionnaire-yes"
),
t("myrepresentations:questionnaire-no"),
]}
id="representationOnBehalfOf" id="representationOnBehalfOf"
className="govuk-radios__input" className="govuk-radios__input"
errorMsg={t( errorMsg={t(
@@ -215,16 +233,76 @@ const RepInterestedPartyPerson = (props) => {
)} )}
{typeof formObj.representationForm.values.representationType != {typeof formObj.representationForm.values.representationType !=
"undefined" && ( "undefined" && (
<RepresentationActionButtons <div className="govuk-grid-row">
t={t} <div className="govuk-button-group">
locale={router.locale} <button
isSaving={savingStatus} type="submit"
isContinueDisabled={shouldDisableButton({ className="govuk-button"
props, data-module="govuk-button"
formObj >
})} {t("common:continue-button")}
onSaveExit={handleSaveExit} </button>
{/*
<a
onClick={() => {
setRepresentationCapacity();
props.updateField(
"representationForm",
"representationCapacity",
""
);
props.updateField(
"representationForm",
"representationType",
""
);
}}
className="govuk-link"
>
{t("case:summary-back-button-label")}
</a> */}
{savingStatus ? (
<span className=" progress-save-active">
{router.locale == "cy"
? "Nôl data"
: "Saving data"}
<img
className="data-loading-icon"
src="/assets/images/loading.gif"
alt={
router.locale == "cy"
? "Nôl data"
: "Saving data"
}
/> />
</span>
) : (
<button
className="govuk-button progress-save "
onClick={() => {
let valuesObj =
props.props.props.form[props.form]
.values || {};
//console.log("valuesobj:", valuesObj);
delete valuesObj[
"_pinswg_appellant_value"
];
//console.log("on save:", valuesObj);
updateRepresentation(
valuesObj,
false,
true
);
}}
>
{t("common:save-exit-button")}
</button>
)}
</div>
</div>
)} )}
</> </>
); );
@@ -238,7 +316,7 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(change(form, field, newValue)), dispatch(change(form, field, newValue)),
setFilesForRepresentations: (fileList) => { setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList)); dispatch(setFilesForRepresentations(fileList));
} },
}); });
export default connect( export default connect(
@@ -248,6 +326,6 @@ export default connect(
reduxForm({ reduxForm({
form: "representationForm", form: "representationForm",
enableReinitialize: true, enableReinitialize: true,
destroyOnUnmount: false destroyOnUnmount: false,
})(RepInterestedPartyPerson) })(RepInterestedPartyPerson)
); );
@@ -11,7 +11,6 @@ import {
FileUploadField, FileUploadField,
RenderMultiline, RenderMultiline,
RenderPickList, RenderPickList,
shouldDisableButton,
} from "./representationElements"; } from "./representationElements";
import RepresentationProgress_enforcement from "./representationProgress/representationProgress_enforcement"; import RepresentationProgress_enforcement from "./representationProgress/representationProgress_enforcement";
import RepresentationProgress_s78 from "./representationProgress/representationProgress_s78"; import RepresentationProgress_s78 from "./representationProgress/representationProgress_s78";
@@ -511,10 +510,6 @@ let RepLPA = (props) => {
type="submit" type="submit"
className="govuk-button" className="govuk-button"
data-module="govuk-button" data-module="govuk-button"
disabled={shouldDisableButton({
props,
formObj,
})}
onClick={() => { onClick={() => {
let valuesObj = let valuesObj =
props.props.props.form[props.form] props.props.props.form[props.form]
@@ -14,12 +14,12 @@ import {
RenderPickList, RenderPickList,
RenderRadioList, RenderRadioList,
RenderRichMultiline, RenderRichMultiline,
RenderTextfield RenderTextfield,
} from "../representationElements"; } from "../representationElements";
import { import {
setRepresentationCapacity, setRepresentationCapacity,
setRepresentationSubmit, setRepresentationSubmit,
setFilesForRepresentations setFilesForRepresentations,
} from "../../../../store/currentView/action"; } from "../../../../store/currentView/action";
let Enforcement_Questionnaire = (props) => { let Enforcement_Questionnaire = (props) => {
@@ -36,7 +36,7 @@ let Enforcement_Questionnaire = (props) => {
procedureTypeValue, procedureTypeValue,
onBehalfOfLPA, onBehalfOfLPA,
showQuestionnaireSection, showQuestionnaireSection,
setFilesForRepresentations setFilesForRepresentations,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
const files = acceptedFiles.map((file) => ( const files = acceptedFiles.map((file) => (
@@ -61,10 +61,10 @@ let Enforcement_Questionnaire = (props) => {
detailsObj = jsonpath({ detailsObj = jsonpath({
path: path:
'$..[?(@ && @.pinswg_name=="' + '$..[?(@ && @.pinswg_name=="' +
currentView.caseReference.ticketnumber + currentView.caseReference.currentReference +
'")]', '")]',
json: setCaseDetailsObj, json: setCaseDetailsObj,
eval: true eval: true,
}); });
let setCaseResultssObj = router.query.hasOwnProperty("state") let setCaseResultssObj = router.query.hasOwnProperty("state")
@@ -84,10 +84,10 @@ let Enforcement_Questionnaire = (props) => {
resultsObj = jsonpath({ resultsObj = jsonpath({
path: path:
'$..[?(@ && @.ticketnumber=="' + '$..[?(@ && @.ticketnumber=="' +
currentView.caseReference.ticketnumber + currentView.caseReference.currentReference +
'")]', '")]',
json: setCaseResultssObj, json: setCaseResultssObj,
eval: true eval: true,
}); });
resultsObj = resultsObj[0]; resultsObj = resultsObj[0];
@@ -118,7 +118,7 @@ let Enforcement_Questionnaire = (props) => {
<div className="govuk-form-group"> <div className="govuk-form-group">
<div className="govuk-label"> <div className="govuk-label">
2. {t("myrepresentations:enf-section-question-2")}:{" "} 2. {t("myrepresentations:enf-section-question-2")}:{" "}
{resultsObj.pinswg_lpareference || ""} {resultsObj.pinswg_lpareference}
</div> </div>
</div> </div>
<div className="govuk-form-group"> <div className="govuk-form-group">
@@ -155,7 +155,7 @@ let Enforcement_Questionnaire = (props) => {
optionsArr={[ optionsArr={[
"Written representations", "Written representations",
"Hearing", "Hearing",
"Inquiry" "Inquiry",
]} ]}
id="procedureType" id="procedureType"
component={RenderPickList} component={RenderPickList}
@@ -190,7 +190,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -207,7 +207,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="enterNeighbouringLandToViewSite" datafieldname="enterNeighbouringLandToViewSite"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="enterNeighbouringLandToViewSite" id="enterNeighbouringLandToViewSite"
className="govuk-radios__input" className="govuk-radios__input"
@@ -236,7 +236,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="enterNeighbouringLandAccessRequired" datafieldname="enterNeighbouringLandAccessRequired"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="enterNeighbouringLandAccessRequired" id="enterNeighbouringLandAccessRequired"
className="govuk-radios__input" className="govuk-radios__input"
@@ -265,7 +265,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="healthAndSafetyIssues" datafieldname="healthAndSafetyIssues"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="healthAndSafetyIssues" id="healthAndSafetyIssues"
className="govuk-radios__input" className="govuk-radios__input"
@@ -328,7 +328,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -342,7 +342,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="feeExempt" datafieldname="feeExempt"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="feeExempt" id="feeExempt"
className="govuk-radios__input" className="govuk-radios__input"
@@ -379,7 +379,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="previousGrantedCerts" datafieldname="previousGrantedCerts"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="previousGrantedCerts" id="previousGrantedCerts"
className="govuk-radios__input" className="govuk-radios__input"
@@ -406,7 +406,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="stopNoticeServed" datafieldname="stopNoticeServed"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="stopNoticeServed" id="stopNoticeServed"
className="govuk-radios__input" className="govuk-radios__input"
@@ -433,7 +433,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="relatedCases" datafieldname="relatedCases"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="relatedCases" id="relatedCases"
className="govuk-radios__input" className="govuk-radios__input"
@@ -460,7 +460,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="previousEnforcement" datafieldname="previousEnforcement"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="previousEnforcement" id="previousEnforcement"
className="govuk-radios__input" className="govuk-radios__input"
@@ -487,7 +487,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="subjectArticle4" datafieldname="subjectArticle4"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="subjectArticle4" id="subjectArticle4"
className="govuk-radios__input" className="govuk-radios__input"
@@ -514,7 +514,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="previousPDRRestriction" datafieldname="previousPDRRestriction"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="previousPDRRestriction" id="previousPDRRestriction"
className="govuk-radios__input" className="govuk-radios__input"
@@ -594,7 +594,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -621,7 +621,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -635,7 +635,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="ROW" datafieldname="ROW"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="ROW" id="ROW"
className="govuk-radios__input" className="govuk-radios__input"
@@ -662,7 +662,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="conservationArea" datafieldname="conservationArea"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="conservationArea" id="conservationArea"
className="govuk-radios__input" className="govuk-radios__input"
@@ -689,7 +689,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="affectListedBuilding" datafieldname="affectListedBuilding"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="affectListedBuilding" id="affectListedBuilding"
className="govuk-radios__input" className="govuk-radios__input"
@@ -716,7 +716,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="TPO" datafieldname="TPO"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="TPO" id="TPO"
className="govuk-radios__input" className="govuk-radios__input"
@@ -743,7 +743,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="natureConservationSite" datafieldname="natureConservationSite"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="natureConservationSite" id="natureConservationSite"
className="govuk-radios__input" className="govuk-radios__input"
@@ -770,7 +770,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="protectedSpecies" datafieldname="protectedSpecies"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="protectedSpecies" id="protectedSpecies"
className="govuk-radios__input" className="govuk-radios__input"
@@ -802,7 +802,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -816,7 +816,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="floodingIssue" datafieldname="floodingIssue"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="floodingIssue" id="floodingIssue"
className="govuk-radios__input" className="govuk-radios__input"
@@ -843,7 +843,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="governmentDepartmentComments" datafieldname="governmentDepartmentComments"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="governmentDepartmentComments" id="governmentDepartmentComments"
className="govuk-radios__input" className="govuk-radios__input"
@@ -884,7 +884,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="developmentCarriedOutInAccordance" datafieldname="developmentCarriedOutInAccordance"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="developmentCarriedOutInAccordance" id="developmentCarriedOutInAccordance"
className="govuk-radios__input" className="govuk-radios__input"
@@ -915,7 +915,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -932,7 +932,7 @@ let Enforcement_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -946,7 +946,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="developmentAnyOtherConditions" datafieldname="developmentAnyOtherConditions"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="developmentAnyOtherConditions" id="developmentAnyOtherConditions"
className="govuk-radios__input" className="govuk-radios__input"
@@ -987,7 +987,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="copyOfEnforcementNotice" datafieldname="copyOfEnforcementNotice"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="copyOfEnforcementNotice" id="copyOfEnforcementNotice"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1014,7 +1014,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="enforcementNoticePlan" datafieldname="enforcementNoticePlan"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="enforcementNoticePlan" id="enforcementNoticePlan"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1041,7 +1041,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="listOfNotifiedOfEnforcement" datafieldname="listOfNotifiedOfEnforcement"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="listOfNotifiedOfEnforcement" id="listOfNotifiedOfEnforcement"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1068,7 +1068,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="copyOfLetterOfAppealNotification" datafieldname="copyOfLetterOfAppealNotification"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="copyOfLetterOfAppealNotification" id="copyOfLetterOfAppealNotification"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1095,7 +1095,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="lpaEIAOS" datafieldname="lpaEIAOS"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="lpaEIAOS" id="lpaEIAOS"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1125,7 +1125,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="detailsOfOtherAppeals" datafieldname="detailsOfOtherAppeals"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="detailsOfOtherAppeals" id="detailsOfOtherAppeals"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1152,7 +1152,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="detailsOfPreviousAppeals" datafieldname="detailsOfPreviousAppeals"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="detailsOfPreviousAppeals" id="detailsOfPreviousAppeals"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1179,7 +1179,7 @@ let Enforcement_Questionnaire = (props) => {
datafieldname="otherRelevantInformation" datafieldname="otherRelevantInformation"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="otherRelevantInformation" id="otherRelevantInformation"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1312,7 +1312,7 @@ Enforcement_Questionnaire = connect((state) => {
return { return {
procedureTypeValue, procedureTypeValue,
representationTypeValue representationTypeValue,
}; };
})(Enforcement_Questionnaire); })(Enforcement_Questionnaire);
@@ -1323,7 +1323,7 @@ const mapDispatchToProps = (dispatch) => {
setFilesForRepresentations: (fileList) => { setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList)); dispatch(setFilesForRepresentations(fileList));
} },
}; };
}; };
@@ -1335,7 +1335,7 @@ const mapStateToProps = (state, props) => {
appealType: state.appealType, appealType: state.appealType,
currentView: state.currentView, currentView: state.currentView,
myRepresentations: state.myRepresentations, myRepresentations: state.myRepresentations,
initialValues: state.currentView.caseReference.repDetails initialValues: state.currentView.caseReference.repDetails,
}; };
}; };
@@ -1346,6 +1346,6 @@ export default connect(
reduxForm({ reduxForm({
form: "representationForm", form: "representationForm",
enableReinitialize: false, enableReinitialize: false,
destroyOnUnmount: false destroyOnUnmount: false,
})(Enforcement_Questionnaire) })(Enforcement_Questionnaire)
); );
@@ -4,7 +4,6 @@ import { useRouter } from "next/router";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { Field, reduxForm, formValueSelector } from "redux-form"; import { Field, reduxForm, formValueSelector } from "redux-form";
import { getFormCollectionByID } from "../../../../components/utils"; import { getFormCollectionByID } from "../../../../components/utils";
import { import {
FileUploadField, FileUploadField,
RenderDatePicker, RenderDatePicker,
@@ -13,12 +12,12 @@ import {
RenderPickList, RenderPickList,
RenderRadioList, RenderRadioList,
RenderRichMultiline, RenderRichMultiline,
RenderTextfield RenderTextfield,
} from "../representationElements"; } from "../representationElements";
import { import {
setRepresentationCapacity, setRepresentationCapacity,
setRepresentationSubmit, setRepresentationSubmit,
setFilesForRepresentations setFilesForRepresentations,
} from "../../../../store/currentView/action"; } from "../../../../store/currentView/action";
import { connect } from "react-redux"; import { connect } from "react-redux";
@@ -39,7 +38,7 @@ let S78_Questionnaire = (props) => {
procedureTypeValue, procedureTypeValue,
onBehalfOfLPA, onBehalfOfLPA,
showQuestionnaireSection, showQuestionnaireSection,
setFilesForRepresentations setFilesForRepresentations,
} = props; } = props;
const { acceptedFiles, getRootProps, getInputProps } = useDropzone(); const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
const files = acceptedFiles.map((file) => ( const files = acceptedFiles.map((file) => (
@@ -63,11 +62,11 @@ let S78_Questionnaire = (props) => {
detailsObj = jsonpath({ detailsObj = jsonpath({
path: path:
'$..[?(@ && @.ticketnumber=="' + '$..[?(@ && @.pinswg_name=="' +
currentView.caseReference.ticketnumber + currentView.caseReference.currentReference +
'")]', '")]',
json: setCaseDetailsObj, json: setCaseDetailsObj,
eval: true eval: true,
}); });
let setCaseResultssObj = router.query.hasOwnProperty("state") let setCaseResultssObj = router.query.hasOwnProperty("state")
@@ -93,10 +92,10 @@ let S78_Questionnaire = (props) => {
: "ticketnumber" : "ticketnumber"
: "ticketnumber") + : "ticketnumber") +
'=="' + '=="' +
currentView.caseReference.ticketnumber + currentView.caseReference.currentReference +
'")]', '")]',
json: setCaseResultssObj, json: setCaseResultssObj,
eval: true eval: true,
}); });
resultsObj = resultsObj[0]; resultsObj = resultsObj[0];
@@ -137,7 +136,7 @@ let S78_Questionnaire = (props) => {
<div className="govuk-form-group"> <div className="govuk-form-group">
<div className="govuk-label"> <div className="govuk-label">
2. {t("myrepresentations:s78-section-question-2")}:{" "} 2. {t("myrepresentations:s78-section-question-2")}:{" "}
{resultsObj.pinswg_lpareference || ""} {resultsObj.pinswg_lpareference}
</div> </div>
</div> </div>
<div className="govuk-form-group"> <div className="govuk-form-group">
@@ -176,7 +175,7 @@ let S78_Questionnaire = (props) => {
optionsArr={[ optionsArr={[
"Written representations", "Written representations",
"Hearing", "Hearing",
"Inquiry" "Inquiry",
]} ]}
id="procedureType" id="procedureType"
component={RenderPickList} component={RenderPickList}
@@ -210,7 +209,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -225,7 +224,7 @@ let S78_Questionnaire = (props) => {
datafieldname="enterNeighbouringLandToViewSite" datafieldname="enterNeighbouringLandToViewSite"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="enterNeighbouringLandToViewSite" id="enterNeighbouringLandToViewSite"
className="govuk-radios__input" className="govuk-radios__input"
@@ -254,7 +253,7 @@ let S78_Questionnaire = (props) => {
datafieldname="enterNeighbouringLandAccessRequired" datafieldname="enterNeighbouringLandAccessRequired"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="enterNeighbouringLandAccessRequired" id="enterNeighbouringLandAccessRequired"
className="govuk-radios__input" className="govuk-radios__input"
@@ -283,7 +282,7 @@ let S78_Questionnaire = (props) => {
datafieldname="healthAndSafetyIssues" datafieldname="healthAndSafetyIssues"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="healthAndSafetyIssues" id="healthAndSafetyIssues"
className="govuk-radios__input" className="govuk-radios__input"
@@ -406,7 +405,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -435,7 +434,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -451,7 +450,7 @@ let S78_Questionnaire = (props) => {
datafieldname="ROW" datafieldname="ROW"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="ROW" id="ROW"
className="govuk-radios__input" className="govuk-radios__input"
@@ -478,7 +477,7 @@ let S78_Questionnaire = (props) => {
datafieldname="conservationArea" datafieldname="conservationArea"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="conservationArea" id="conservationArea"
className="govuk-radios__input" className="govuk-radios__input"
@@ -505,7 +504,7 @@ let S78_Questionnaire = (props) => {
datafieldname="affectListedBuilding" datafieldname="affectListedBuilding"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="affectListedBuilding" id="affectListedBuilding"
className="govuk-radios__input" className="govuk-radios__input"
@@ -532,7 +531,7 @@ let S78_Questionnaire = (props) => {
datafieldname="TPO" datafieldname="TPO"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="TPO" id="TPO"
className="govuk-radios__input" className="govuk-radios__input"
@@ -559,7 +558,7 @@ let S78_Questionnaire = (props) => {
datafieldname="natureConservationSite" datafieldname="natureConservationSite"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="natureConservationSite" id="natureConservationSite"
className="govuk-radios__input" className="govuk-radios__input"
@@ -586,7 +585,7 @@ let S78_Questionnaire = (props) => {
datafieldname="protectedSpecies" datafieldname="protectedSpecies"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="protectedSpecies" id="protectedSpecies"
className="govuk-radios__input" className="govuk-radios__input"
@@ -617,7 +616,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -630,7 +629,7 @@ let S78_Questionnaire = (props) => {
datafieldname="governmentDepartmentComments" datafieldname="governmentDepartmentComments"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="governmentDepartmentComments" id="governmentDepartmentComments"
className="govuk-radios__input" className="govuk-radios__input"
@@ -676,7 +675,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -692,7 +691,7 @@ let S78_Questionnaire = (props) => {
datafieldname="developmentCarriedOutInAccordance" datafieldname="developmentCarriedOutInAccordance"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="developmentCarriedOutInAccordance" id="developmentCarriedOutInAccordance"
className="govuk-radios__input" className="govuk-radios__input"
@@ -723,7 +722,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -742,7 +741,7 @@ let S78_Questionnaire = (props) => {
component={RenderRadioList} component={RenderRadioList}
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
type="text" type="text"
rows="5" rows="5"
@@ -758,7 +757,7 @@ let S78_Questionnaire = (props) => {
datafieldname="developmentAnyOtherConditions" datafieldname="developmentAnyOtherConditions"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="developmentAnyOtherConditions" id="developmentAnyOtherConditions"
className="govuk-radios__input" className="govuk-radios__input"
@@ -798,7 +797,7 @@ let S78_Questionnaire = (props) => {
datafieldname="copyOfApplicantsCertificate" datafieldname="copyOfApplicantsCertificate"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="copyOfApplicantsCertificate" id="copyOfApplicantsCertificate"
className="govuk-radios__input" className="govuk-radios__input"
@@ -826,7 +825,7 @@ let S78_Questionnaire = (props) => {
datafieldname="advertismentGiven" datafieldname="advertismentGiven"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="advertismentGiven" id="advertismentGiven"
className="govuk-radios__input" className="govuk-radios__input"
@@ -854,7 +853,7 @@ let S78_Questionnaire = (props) => {
datafieldname="copyOfLetterOfAppealNotification" datafieldname="copyOfLetterOfAppealNotification"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="copyOfLetterOfAppealNotification" id="copyOfLetterOfAppealNotification"
className="govuk-radios__input" className="govuk-radios__input"
@@ -881,7 +880,7 @@ let S78_Questionnaire = (props) => {
datafieldname="lpaEIAOS" datafieldname="lpaEIAOS"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="lpaEIAOS" id="lpaEIAOS"
className="govuk-radios__input" className="govuk-radios__input"
@@ -908,7 +907,7 @@ let S78_Questionnaire = (props) => {
datafieldname="advertismentConsentDiscontinuanceNotice" datafieldname="advertismentConsentDiscontinuanceNotice"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="advertismentConsentDiscontinuanceNotice" id="advertismentConsentDiscontinuanceNotice"
className="govuk-radios__input" className="govuk-radios__input"
@@ -935,7 +934,7 @@ let S78_Questionnaire = (props) => {
datafieldname="detailsOfOtherAppeals" datafieldname="detailsOfOtherAppeals"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="detailsOfOtherAppeals" id="detailsOfOtherAppeals"
className="govuk-radios__input" className="govuk-radios__input"
@@ -962,7 +961,7 @@ let S78_Questionnaire = (props) => {
datafieldname="detailsOfPreviousAppeals" datafieldname="detailsOfPreviousAppeals"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="detailsOfPreviousAppeals" id="detailsOfPreviousAppeals"
className="govuk-radios__input" className="govuk-radios__input"
@@ -989,7 +988,7 @@ let S78_Questionnaire = (props) => {
datafieldname="otherRelevantInformation" datafieldname="otherRelevantInformation"
options={[ options={[
t("myrepresentations:questionnaire-yes"), t("myrepresentations:questionnaire-yes"),
t("myrepresentations:questionnaire-no") t("myrepresentations:questionnaire-no"),
]} ]}
id="otherRelevantInformation" id="otherRelevantInformation"
className="govuk-radios__input" className="govuk-radios__input"
@@ -1121,7 +1120,7 @@ S78_Questionnaire = connect((state) => {
return { return {
procedureTypeValue, procedureTypeValue,
representationTypeValue representationTypeValue,
}; };
})(S78_Questionnaire); })(S78_Questionnaire);
@@ -1132,7 +1131,7 @@ const mapDispatchToProps = (dispatch) => {
setFilesForRepresentations: (fileList) => { setFilesForRepresentations: (fileList) => {
dispatch(setFilesForRepresentations(fileList)); dispatch(setFilesForRepresentations(fileList));
} },
}; };
}; };
@@ -1144,7 +1143,7 @@ const mapStateToProps = (state, props) => {
appealType: state.appealType, appealType: state.appealType,
currentView: state.currentView, currentView: state.currentView,
myRepresentations: state.myRepresentations, myRepresentations: state.myRepresentations,
initialValues: state.currentView.caseReference.repDetails initialValues: state.currentView.caseReference.repDetails,
}; };
}; };
@@ -1155,6 +1154,6 @@ export default connect(
reduxForm({ reduxForm({
form: "representationForm", form: "representationForm",
enableReinitialize: false, enableReinitialize: false,
destroyOnUnmount: false destroyOnUnmount: false,
})(S78_Questionnaire) })(S78_Questionnaire)
); );
@@ -1,50 +0,0 @@
import RepresentationTimetablePanel from "./RepresentationTimetablePanel";
const RepresentationFlowFormStage = ({
t,
appealIsConsultation,
currentReference,
whichControl,
appealIsLocalImpact,
renderDueDate,
renderStatementsDue,
renderMarineImpact,
renderConsultationClose,
renderFinalCommentsDue,
isQuestionnaire,
whichProgress
}) => {
return (
<>
<h1 className="govuk-heading-l">
{appealIsConsultation
? t("myrepresentations:make-a-consultation-on-label")
: t(
"myrepresentations:make-a-representation-on-label"
)}{" "}
{currentReference}{" "}
</h1>
<div id="rep-form">
<div className="govuk-grid-column-three-quarters wgForm">
{whichControl()}
</div>
<RepresentationTimetablePanel
t={t}
appealIsConsultation={appealIsConsultation}
appealIsLocalImpact={appealIsLocalImpact}
renderDueDate={renderDueDate}
renderStatementsDue={renderStatementsDue}
renderMarineImpact={renderMarineImpact}
renderConsultationClose={renderConsultationClose}
renderFinalCommentsDue={renderFinalCommentsDue}
isQuestionnaire={isQuestionnaire}
whichProgress={whichProgress}
/>
</div>
</>
);
};
export default RepresentationFlowFormStage;
@@ -1,49 +0,0 @@
const RepresentationTimetablePanel = ({
t,
appealIsConsultation,
appealIsLocalImpact,
renderDueDate,
renderStatementsDue,
renderMarineImpact,
renderConsultationClose,
renderFinalCommentsDue,
isQuestionnaire,
whichProgress
}) => {
return (
<div className="govuk-grid-column-one-quarter">
<div className="card">
<div className="card-body">
<h2 className="govuk-heading-s">
{t("myrepresentations:timetable-title")}
</h2>
<div className="govuk-summary-list">
<div className="govuk-body-s">
{appealIsLocalImpact
? t("myrepresentations:local-impact-report")
: t(
"myrepresentations:questionnaire-due-label"
)}
:{" "}
<span className="govuk-body-s">
{renderDueDate()}
</span>
</div>
{!appealIsConsultation && renderStatementsDue()}
{renderMarineImpact()}
{renderConsultationClose()}
{renderFinalCommentsDue()}
</div>
</div>
</div>
{isQuestionnaire && whichProgress()}
</div>
);
};
export default RepresentationTimetablePanel;
@@ -1,93 +0,0 @@
import { JSONPath as jsonpath } from "jsonpath-plus";
export const resolveInitialCaseDataSources = ({
hasState,
isEditState,
currentType,
myRepresentations,
searchDetailsObj,
searchResultsObj,
watchedCasesDetails
}) => {
if (hasState) {
return {
"caseDetailsSource": isEditState
? myRepresentations
: searchDetailsObj,
"caseResultsSource": isEditState
? myRepresentations
: searchResultsObj
};
}
return {
"caseDetailsSource":
currentType === "watchedCases"
? watchedCasesDetails
: searchDetailsObj,
"caseResultsSource":
currentType === "watchedCases"
? watchedCasesDetails
: searchResultsObj
};
};
export const findResultsObjForCurrentReference = ({
currentReference,
caseResultsSource
}) => {
return jsonpath({
path: `$..[?(@ && @.ticketnumber=="${currentReference}")]`,
"json": caseResultsSource,
"eval": true
})[0];
};
export const findDetailsObjForView = ({
hasState,
isEditState,
queryCreated,
ticketnumber,
caseDetailsSource
}) => {
if (hasState && isEditState) {
return jsonpath({
path: `$..[?(@ && @.repfile_name=="${queryCreated}")]`,
"json": caseDetailsSource,
"eval": true
})[0];
}
return jsonpath({
path: `$..[?(@ && @.ticketnumber=="${ticketnumber}")]`,
"json": caseDetailsSource,
"eval": true
})[0];
};
export const resolveSubmitCaseDetailsSource = ({
isEditState,
currentType,
myRepresentations,
watchedCasesDetails,
searchDetailsObj
}) => {
if (isEditState) {
return myRepresentations;
}
return currentType === "watchedCases"
? watchedCasesDetails
: searchDetailsObj;
};
export const findDetailsObjForSubmit = ({
ticketnumber,
caseDetailsSource
}) => {
return jsonpath({
path: `$..[?(@ && @.ticketnumber=="${ticketnumber}")]`,
"json": caseDetailsSource,
"eval": true
})[0];
};
@@ -1,126 +0,0 @@
export const buildRepresentationUpdateBody = ({
formattedValues,
setRepFileName
}) => {
let updateBody = setRepFileName(formattedValues);
const sanitizedBody = Object.entries(updateBody).reduce(
(acc, [key, val]) => {
if (val !== null && val !== undefined && !key.startsWith("_")) {
acc[key] = val;
}
return acc;
},
{}
);
const stringified = JSON.stringify(sanitizedBody)
.replace(/:"Yes"/g, ":true")
.replace(/:"No"/g, ":false");
updateBody = JSON.parse(stringified);
return updateBody;
};
export const buildSubmitEnrichedValues = ({
formValues,
accountDetails,
appealType,
caseReferenceObj,
detailsObj,
resultsObj,
representationCapacity,
locale
}) => {
const buildSiteAddress = () => {
const {
pinswg_siteaddressline1,
pinswg_siteaddressline2,
pinswg_siteaddresstown,
pinswg_siteaddresspostcode
} = detailsObj;
return [
pinswg_siteaddressline1,
pinswg_siteaddressline2,
pinswg_siteaddresstown,
pinswg_siteaddresspostcode
]
.filter(Boolean)
.join(" ");
};
return {
...formValues,
containerID: accountDetails.containerID,
appealType: appealType || caseReferenceObj.repDetails.appealType,
incidentID:
caseReferenceObj.incidentid ||
caseReferenceObj.repDetails.incidentid,
caseRef: caseReferenceObj.currentReference,
casereference: caseReferenceObj.currentReference,
pinswg_questionnaireduedate: detailsObj.pinswg_questionnaireduedate,
pinswg_endofrepresentationperiod:
detailsObj.pinswg_endofrepresentationperiod,
pinswg_applicationacceptedasvalid:
detailsObj.pinswg_applicationacceptedasvalid,
pinswg_statementduedate: detailsObj.pinswg_statementduedate,
pinswg_statementsduedate: detailsObj.pinswg_statementsduedate,
pinswg_finalcommentsduedate: detailsObj.pinswg_finalcommentsduedate,
pinswg_name: caseReferenceObj.currentReference,
firstname: accountDetails.firstname,
lastname: accountDetails.lastname,
emailAddress: accountDetails.emailaddress1,
siteAddress: buildSiteAddress(),
pinswg_siteaddressline1: detailsObj.pinswg_siteaddressline1,
pinswg_siteaddressline2: detailsObj.pinswg_siteaddressline2,
pinswg_siteaddresstown: detailsObj.pinswg_siteaddresstown,
pinswg_siteaddresspostcode: detailsObj.pinswg_siteaddresspostcode,
pinswg_lpareference: resultsObj?.pinswg_lpareference,
_pinswg_appellant_value: detailsObj._pinswg_appellant_value,
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue":
detailsObj[
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue"
],
_pinswg_localplanningauthority_value:
detailsObj._pinswg_localplanningauthority_value ||
detailsObj._pinswg_associatedlpa_value,
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue":
detailsObj[
"_pinswg_localplanningauthority_value@OData.Community.Display.V1.FormattedValue"
] ||
detailsObj[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
],
representationCapacity,
locale
};
};
export const runFinalisationSequence = ({
values,
containerID,
currentReference,
setFinaliseAppealProcess,
generateRepPDF,
updateLinks,
uploadRepresentationFiles,
setRepresentationSubmit,
setRepresentationSubmitConfirmation
}) => {
setFinaliseAppealProcess(true);
return generateRepPDF(values, containerID, currentReference).then(
(data) => {
if (data.status === "success") {
const updatedValues = updateLinks(values);
uploadRepresentationFiles(updatedValues);
setRepresentationSubmit(true);
setRepresentationSubmitConfirmation(true);
}
return data;
}
);
};
@@ -1,73 +0,0 @@
export const resolveJourneyStageFlags = ({
representationSubmit,
representationSubmitConfirmation
}) => {
const showCheckStage =
representationSubmit === true || representationSubmit === "true";
const showCompletionStage =
representationSubmitConfirmation === true ||
representationSubmitConfirmation === "true";
return {
showFormStage: !showCheckStage,
showCheckStage,
showCompletionStage
};
};
export const resolveRepresentationControlKey = ({
isLPA,
representationCapacity,
repDetailsCapacity,
appealType,
normalizeCapacity
}) => {
if (isLPA && (!representationCapacity || representationCapacity === "")) {
return {
controlKey: "lpa-capacity-selection",
normalizedCapacity: ""
};
}
const rawCapacity = representationCapacity || repDetailsCapacity || "false";
const normalizedCapacity = normalizeCapacity(rawCapacity.toLowerCase());
return {
controlKey: `capacity-${normalizedCapacity}`,
normalizedCapacity
};
};
export const resolveSubmitTransition = ({
representationType,
showQuestionnaireSection,
questionnaireCount
}) => {
if (representationType !== "Questionnaire") {
return "goToCheck";
}
if (
questionnaireCount !== 0 &&
showQuestionnaireSection < questionnaireCount
) {
return "advanceQuestionnaire";
}
return "goToCheck";
};
export const getQuestionnaireNextSection = (
currentSection,
questionnaireCount
) => {
if (questionnaireCount !== 0 && currentSection < questionnaireCount) {
return currentSection + 1;
}
return currentSection;
};
export const getQuestionnairePreviousSection = (currentSection) => {
return currentSection > 1 ? currentSection - 1 : currentSection;
};
+5 -5
View File
@@ -6,7 +6,7 @@ import { useEffect, useState } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import transLookup from "../../data/lookuptranslations.json"; import transLookup from "../../data/lookuptranslations.json";
import { getRepresentations } from "../../actions/services/portalService"; import { getRepresentations } from "../../actions";
import { setRepresentations } from "../../store/searchOutput/action"; import { setRepresentations } from "../../store/searchOutput/action";
import { formatDates } from "../utils"; import { formatDates } from "../utils";
@@ -63,7 +63,7 @@ const RepresentationList = (props) => {
incidentid + incidentid +
"')]", "')]",
json: item, json: item,
eval: true eval: true,
}); });
detailsObj = item; detailsObj = item;
@@ -97,7 +97,7 @@ const RepresentationList = (props) => {
] + ] +
'")].value_cy', '")].value_cy',
json: transLookup, json: transLookup,
sanbox: {} sanbox: {},
}) })
: detailsObj[ : detailsObj[
"pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue" "pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue"
@@ -216,7 +216,7 @@ const RepresentationList = (props) => {
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
...state ...state,
}; };
}; };
@@ -224,7 +224,7 @@ const mapDispatchToProps = (dispatch) => {
return { return {
setRepresentations: (representationObj) => { setRepresentations: (representationObj) => {
dispatch(setRepresentations(representationObj)); dispatch(setRepresentations(representationObj));
} },
}; };
}; };
+619 -1358
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More