Merged PR 2198: update apis

Related work items: #22211
This commit is contained in:
Robert Bond
2026-03-23 12:38:30 +00:00
71 changed files with 5612 additions and 1435 deletions
-5
View File
@@ -58,10 +58,5 @@ CONTRIBUTING_AI.md
GUARDRAILS.md
ai-prompts/
context/
memory-bank/
workflows/
AI_CONTEXT.md
memory-bank/activeContext.md
memory-bank/change-log.md
memory-bank/refactor-plan-actions-index.md
memory-bank/progress.md
@@ -0,0 +1,54 @@
## 1) Prioritized debt list
1. Monolithic `actions/index.js` (over-coupled “god module”)
2. Inconsistent API error handling/response contracts across `pages/api/**`
3. Sensitive/verbose logging in app + API paths
4. Endpoint sprawl and duplicated proxy patterns (`pages/api/endpoint/*_api.js`)
5. i18n routing complexity in large rewrite maps
6. Sparse automated test coverage for high-risk flows
7. Legacy/stale commented patterns in critical files
## 2) Impact of each item
- **1) `actions/index.js` monolith**
- High blast radius for any change; weak modularity and hard ownership boundaries.
- Evidence: ~100+ exports mixing search, auth, account, file, PDF, notify, CRM concerns.
- **2) API contract inconsistency**
- Clients must handle errors inconsistently; reliability and observability suffer.
- Evidence: many handlers return raw `res.status(400).json(error)` while others shape custom outputs.
- **3) Verbose/sensitive logging**
- Privacy/security risk plus noisy telemetry.
- Evidence: 300+ `console.log` occurrences, including auth/email/upload-related contexts.
- **4) Endpoint duplication**
- Maintenance cost and drift risk (validation/auth/error semantics diverge over time).
- Evidence: repeated patterns across many `_api.js` proxy handlers.
- **5) i18n rewrite complexity**
- Higher risk of EN/CY divergence as routes evolve.
- Evidence: large manual rewrite map + separate i18n page namespace config.
- **6) Sparse tests**
- Release confidence depends heavily on manual checks; slower, riskier change cadence.
- **7) Stale patterns**
- Increased cognitive load and unclear source-of-truth behavior in some modules.
## 3) Recommended next cleanup targets
1. **Decompose `actions/index.js` by domain** (structure-only first, keep barrel exports).
2. **Add shared API handler utilities** for validation/error envelope; migrate top sensitive endpoints first.
3. **Implement logging redaction wrapper + policy** and remove direct logs in auth/email/file paths.
4. **Create high-risk smoke tests** (auth callback, search endpoint, upload negative-path, email failure-path).
5. **Extract proxy/integration helpers** (token/hash/header/retry) to reduce endpoint duplication.
6. **Add EN/CY parity CI checks** for route and locale key consistency.
## 4) Runtime note (updated)
- `server.js` and `server/server.js` exist in the repository but are **not the active production concern** for the current refactor stream.
- Current baseline runtime for this debt plan is the standard Next runtime path (`npm start`).
- Runtime canonicalization is therefore removed from the active prioritized debt list unless deployment evidence changes.
If you want, I can convert this into a sprint-ready debt register (ID, owner, effort, risk reduction, target milestone).
@@ -0,0 +1,94 @@
Absolutely — heres a senior architecture review of this repository.
## Update: TASK22211 completed slice (2026-03-23)
- Branch: `TASK22211-endpoint-search-document-contract-consistency`
- Scope completed:
- `pages/api/endpoint/getsearchdocumenthistory_api.js`
- `pages/api/endpoint/getsearchdocumenthistorypaged_api.js`
- `pages/api/endpoint/getsearchdocumentdetails_api.js`
- `pages/api/endpoint/getsearchdocumentdetailspaged_api.js`
- `pages/api/endpoint/getsearchdocumentTypes_api.js`
- `tests/phase21/endpoint-handler-contract.test.cjs`
- `memory-bank/change-log.md`
- Pattern applied:
- standardized structured error envelopes via `respondError`
- preserved existing success contract behavior via `respondSuccess`
- added explicit required-input guards for missing document/case/query inputs
- removed noisy direct `console.log` usage in touched handlers
- Validation snapshot:
- `node tests/phase21/api-contract-slice1.test.cjs` -> pass
- helper 4/4
- file-handler 11/11
- email-handler 12/12
- endpoint-handler 53/53
- `npm run lint` -> warnings only (pre-existing react-hooks warnings)
### Suggested next coherent slice
- Endpoint contract consistency follow-on for case/myportal retrieval cluster still using raw error passthrough patterns, applying the same bounded refactor + phase21 test expansion model.
## 1) Current architecture summary
- **Platform shape:** Next.js 14 (pages router) + React 18, with a **custom Node server** and also a legacy Express-style server under `server/server.js`.
- **API layer:** Large `pages/api/**` surface (endpoint/file/email/admin/auth), many routes acting as thin proxies to upstream systems (CRM/relay/Azure).
- **State/auth:** Redux (`next-redux-wrapper` + persistence) and `next-auth` + Prisma adapter for account/session persistence.
- **i18n/routing:** EN/CY via `next-translate`, `i18n.js`, and many Welsh rewrites in `next.config.js`.
- **Integration-heavy domains:** Azure storage/queues, GOV.UK Notify, mapping embeds/libs, PDF generation.
## 2) Strengths
- **Clear high-level domain separation** by folders (`pages`, `components`, `store`, `actions`, `prisma`, `locales`).
- **Strong security intent** (CSP + secure headers + auth/session infrastructure in place).
- **Bilingual-first routing model** is explicit and robustly represented in config.
- **Operational integration maturity**: telemetry, notifications, document handling, and mapping already embedded.
- **Recently added governance docs** (`.clinerules`, `GUARDRAILS.md`, `CONTRIBUTING_AI.md`, `context/`, `memory-bank/`) materially improve consistency and delivery safety.
## 3) Risks (scalability, maintainability, coupling, boundaries, operations, debt)
1. **God-module risk in `actions/index.js` (very high maintainability/coupling risk)**
Hundreds of mixed responsibilities (auth helpers, search, uploads, notifications, case operations) create high fan-in/fan-out and regression blast radius.
2. **Boundary leakage between UI and integration concerns**
Frontend-facing actions are tightly coupled to relay/API details, hashes, token flow assumptions, and endpoint naming conventions.
3. **Inconsistent runtime topology / entrypoint ambiguity**
Both root `server.js` and `server/server.js` exist with different runtime behavior, increasing deployment confusion and operational drift risk.
4. **Logging/privacy exposure risk**
Multiple debug logs in sensitive paths (auth/email/payloads) risk leaking identifiers or confidential request data.
5. **API proliferation with naming inconsistency and limited shared contract enforcement**
Many `_api.js` endpoints with repeated patterns suggest technical debt and likely drift in validation/error handling semantics.
6. **Scalability bottlenecks in synchronous proxy patterns**
High reliance on serial external calls and heavy payload operations (search/doc/PDF flows) without strong evidence of caching, backpressure, or circuit-breaking.
7. **Test coverage fragility**
Sparse automated tests means confidence depends heavily on manual checks, slowing safe change velocity and increasing incident probability.
8. **i18n rewrite complexity growth**
Large rewrite maps increase cognitive load and chance of EN/CY divergence as route count expands.
## 4) Prioritized recommendations
1. **Decompose `actions/index.js` into domain modules (highest priority)**
- Split into `actions/search`, `actions/case`, `actions/account`, `actions/docs`, `actions/notify`, etc.
- Add a stable facade export to avoid immediate call-site churn.
2. **Establish explicit service boundaries for API integrations**
- Create integration adapters in `lib/services/*` (CRM/relay/azure/notify).
- Keep API routes as orchestrators with shared validation/error wrappers.
3. **Resolve server runtime canonically**
- Choose one entrypoint for dev/test/prod, deprecate the other, simplify scripts and ops docs.
4. **Implement secure logging policy + redaction utility**
- Centralized logger; block raw payload/token/user-data logging by default.
5. **Standardize API contract/error envelope**
- Shared response/error shape and input validation helper used by all sensitive endpoints.
6. **Introduce incremental architecture tests**
- Start with high-risk auth/file/email negative-path API tests.
7. **Tame i18n rewrite sprawl**
- Introduce parity checks (lint/CI) for EN/CY route + locale key synchronization.
## 5) Low-risk next improvements (next 12 sprints)
- Add a **single redaction helper** and replace highest-risk `console.log` usage first (auth/email/file flows).
- Add **API wrapper utility** for consistent try/catch + error response formatting, then migrate 510 high-traffic routes.
- Create `actions/` module split with **barrel exports** (no behavioral change, structure-only).
- Add **CI guard checks**: `npm run lint` + locale key parity + forbidden logging patterns in sensitive files.
- Decide and document **canonical startup path** in `context/runbook.md` and package scripts.
- Add a **small smoke test suite** for auth sign-in callback, public search endpoint, and one upload negative-path scenario.
If you want, I can turn this into a concrete 30/60/90-day architecture hardening roadmap with owners, sequencing, and expected risk reduction per step.
+38
View File
@@ -0,0 +1,38 @@
# Memory Bank Operating Protocol
## Purpose
Capture durable engineering knowledge for PEDW FrontEnd so AI agents and humans make consistent, safe decisions over time.
## When to Update
Update memory-bank entries when any of the following occur:
1. A non-trivial architectural or implementation decision is made.
2. A recurring pattern is introduced or standardized.
3. A pitfall/incident/root cause is discovered.
4. A release introduces meaningful behavior/risk changes.
5. Open questions block safe delivery.
## Who Updates
- **AI agent:** must add or amend entries for non-trivial changes completed during a task.
- **Human engineer/reviewer:** validates or amends entries during PR review.
- **Tech lead/owner:** resolves open questions and marks decisions as accepted/superseded.
## Required Metadata (for every new entry)
- `date:` YYYY-MM-DD
- `author:` agent name or person
- `scope:` files/routes/features affected
- `type:` decision | pattern | pitfall | change | question | glossary
- `rationale:` why this matters
- `impact:` user/system/security/i18n/a11y implications
- `status:` proposed | accepted | superseded | open | resolved
## Entry Quality Rules
- Keep entries concise and specific to this repository.
- Link to concrete files/paths where possible.
- Do not include secrets, tokens, personal data, or sensitive payload examples.
- If uncertain, record assumptions explicitly and add to `open-questions.md`.
+131
View File
@@ -0,0 +1,131 @@
# Change Log (AI/Human Curated)
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: change
rationale: <why change was made>
impact: <user/system/security/i18n/a11y>
status: completed|rolled-back|partial
Summary:
Validation:
Follow-ups:
```
---
### CL-001: TASK22211 endpoint search-document contract consistency slice
date: 2026-03-23
author: Cline
scope: `pages/api/endpoint/{getsearchdocumenthistory_api,getsearchdocumenthistorypaged_api,getsearchdocumentdetails_api,getsearchdocumentdetailspaged_api,getsearchdocumentTypes_api}.js`, `tests/phase21/endpoint-handler-contract.test.cjs`
type: change
rationale: Continue the endpoint contract-consistency stream by normalizing a coherent search-document handler cluster that still used raw error passthrough and noisy legacy logging patterns.
impact: Improved negative-path consistency and safer error contract handling in search-document endpoints while preserving success payload behavior.
status: completed
Summary:
- Branch created from `SIPS-Development`: `TASK22211-endpoint-search-document-contract-consistency`.
- Standardized five search-document handlers to `respondError`/`respondSuccess` usage.
- Added explicit required-input guards:
- `DOCUMENT_ID_REQUIRED` for history/historypaged
- `INCIDENT_ID_REQUIRED` for details/detailspaged/types
- `ORDER_BY_REQUIRED`, `FIELD_SORT_REQUIRED`, `SHOW_NUMBER_OF_RECORDS_REQUIRED` for details-paged query requirements
- Removed noisy direct logging in paged/details code paths.
- Preserved success contract patterns (pass-through or transformed payloads where already established).
- Expanded phase21 endpoint tests with missing-input, catch-path, and success parity assertions for this cluster.
Validation:
- `node tests/phase21/api-contract-slice1.test.cjs` -> pass
- helper: 4/4
- file-handler: 11/11
- email-handler: 12/12
- endpoint-handler: 53/53
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps` warnings; no new lint errors)
Follow-ups:
- Continue the next endpoint cluster using the same pattern (bounded slice + phase21 test expansion).
- Keep response success payloads contract-stable and avoid broad relay/auth refactors in this stream.
### CL-002: TASK22211 endpoint token handler contract consistency slice
date: 2026-03-23
author: Cline
scope: `pages/api/endpoint/getToken.js`, `tests/phase21/endpoint-handler-contract.test.cjs`
type: change
rationale: Close out remaining non-standard endpoint contract handling by normalizing the legacy token endpoint to shared API response helpers and explicit error coding.
impact: Improved endpoint error consistency and test coverage for token acquisition failures while preserving successful token payload passthrough.
status: completed
Summary:
- Refactored `getToken.js` to use `respondSuccess` and `respondError` from `pages/api/middleware/apiResponse`.
- Removed legacy raw `res.status(...).json(...)`/bare status assignment pattern and dead logging artifacts.
- Added explicit catch-path contract: `TOKEN_FETCH_FAILED` with 400 status.
- Added endpoint phase21 tests for:
- success token payload passthrough
- catch-path error contract assertion
Validation:
- `node tests/phase21/api-contract-slice1.test.cjs` -> pass
- helper: 4/4
- file-handler: 11/11
- email-handler: 12/12
- endpoint-handler: 147/147
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps` warnings; no new lint errors)
Follow-ups:
- Remaining outlier API handler for this consistency stream is `pages/api/file/generateappealpdfcopy.js` (not yet on shared response helpers).
### CL-003: TASK22211 endpoint contract-hardening stream backfill (all known slices)
date: 2026-03-23
author: Cline
scope: `pages/api/endpoint/*_api.js`, `pages/api/endpoint/getToken.js`, `tests/phase21/endpoint-handler-contract.test.cjs`
type: change
rationale: Backfill memory-bank traceability so the complete known TASK22211 contract-consistency stream is documented in one place now that memory-bank is being versioned.
impact: Improves governance/auditability of API contract hardening, makes rollout and rollback analysis easier, and records exactly which endpoint clusters were normalized.
status: completed
Summary:
- Backfilled all known TASK22211 slices currently on branch (in commit order):
- `b57f3de` search-document endpoint contracts + phase21 coverage
- `9af541a` my-portal retrieval endpoint contracts
- `b880364` basic search endpoint contracts
- `a106dea` DNS basic search endpoint contracts
- `b5a3a62` portal module + LPA case endpoint contracts
- `4601d7c` case detail endpoint contracts
- `2959c7d` delete/watched-case endpoint contracts
- `b59f13a` metadata + linked-case endpoint contracts
- `bcf03a6` form + publication endpoint contracts
- `e0e91c8` DNS + representation endpoint contracts
- `98e159d` case creation + media endpoint contracts
- `88e4586` advanced-search-paged endpoint contract
- `cb69bbe` case update + CRM task endpoint contracts
- `722ef98` hash + metadata endpoint contracts
- `134f99c` address-search endpoint contract
- `8b6ed73` new-appeal appeal-types endpoint contract
- `eec59e8` token endpoint contract handling
- Across the stream, handlers were standardized toward `respondSuccess`/`respondError`, required-input guards, and explicit negative-path error codes while preserving success payload compatibility.
- Phase21 endpoint contract suite was expanded incrementally alongside each slice.
Validation:
- Stream validation baseline (latest known run):
- `node tests/phase21/api-contract-slice1.test.cjs` -> pass (endpoint-handler 147/147)
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
Follow-ups:
- Continue with remaining non-standard API outlier(s), notably `pages/api/file/generateappealpdfcopy.js`.
- Keep future slices logged in this file at commit-time now that memory-bank is versioned.
+47
View File
@@ -0,0 +1,47 @@
# Decisions (ADR-Lite)
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: decision
rationale: <why>
impact: <user/system/security/i18n/a11y>
status: proposed|accepted|superseded
Decision:
Consequences:
Related:
```
---
### D-001: AI Governance Bundle Structure
date: 2026-03-11
author: Cline
scope: .clinerules, ai-prompts/, context/, memory-bank/
type: decision
rationale: Establish a durable AI collaboration system aligned to repository risks and delivery model.
impact: Improves consistency, review quality, and safety for auth/i18n/public-service flows.
status: accepted
Decision:
Adopt four artifact pillars:
1. `.clinerules` for operating constraints,
2. `ai-prompts/` for reusable task templates,
3. `context/` for architecture/domain references,
4. `memory-bank/` for persistent project knowledge.
Consequences:
- AI/human contributors use a shared protocol.
- Non-trivial changes require memory-bank updates.
Related:
- `context/project-overview.md`
- `memory-bank/README.md`
+79
View File
@@ -0,0 +1,79 @@
# Glossary
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <domain/component>
type: glossary
rationale: <why term clarity matters>
impact: <delivery/quality implication>
status: active
Term:
Definition:
Where used:
```
---
### G-001: DNS
date: 2026-03-11
author: Cline
scope: domain flows
type: glossary
rationale: Distinguishes DNS journey from general case search flows.
impact: Reduces implementation ambiguity in routing and UI behavior.
status: active
Term:
DNS
Definition:
Developments of National Significance journey and related case/search routes.
Where used:
- `pages/dns/**`, `pages/myportal/dns/**`, DNS-related search/detail pages
### G-002: HYDRATE
date: 2026-03-11
author: Cline
scope: Redux store lifecycle
type: glossary
rationale: Critical to SSR/client state consistency.
impact: Prevents store regressions during refactors.
status: active
Term:
HYDRATE
Definition:
`next-redux-wrapper` action used to merge server-side state into client-side store.
Where used:
- `store/store.js`
### G-003: Locale Parity
date: 2026-03-11
author: Cline
scope: i18n and routing
type: glossary
rationale: Core quality expectation for bilingual public service.
impact: Ensures consistent EN/CY experience.
status: active
Term:
Locale parity
Definition:
Equivalent behavior/content correctness across English (`en`) and Welsh (`cy`) for affected user journeys.
Where used:
- `locales/**`, `i18n.js`, `next.config.js`, user-facing pages/components
+57
View File
@@ -0,0 +1,57 @@
# Open Questions
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: question
rationale: <why unresolved>
impact: <user/system/security/i18n/a11y>
status: open|resolved
Question:
Needed from:
Decision deadline:
```
---
### Q-001: Auth Logging Redaction Standard
date: 2026-03-11
author: Cline
scope: auth/email APIs and actions logging
type: question
rationale: Existing logging appears verbose in sensitive flows.
impact: Potential privacy/security exposure via operational logs.
status: open
Question:
What mandatory redaction and logging policy should be enforced for auth/email/document flows?
Needed from:
Security lead + application owner
Decision deadline:
Before next auth/notification release
### Q-002: Test Strategy Baseline for Sparse `tests/`
date: 2026-03-11
author: Cline
scope: testing strategy repository-wide
type: question
rationale: `tests/` currently appears minimal; validation relies heavily on manual checks.
impact: Increased regression risk and slower release confidence.
status: open
Question:
What minimum automated coverage should be required per change type (feature, bug fix, high-risk integration)?
Needed from:
Engineering lead + QA
Decision deadline:
Before next major feature cycle
+66
View File
@@ -0,0 +1,66 @@
# Patterns
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: pattern
rationale: <why>
impact: <user/system/security/i18n/a11y>
status: accepted|superseded
Pattern:
When to use:
Example paths:
```
---
### P-001: Thin Pages, Reusable Logic Elsewhere
date: 2026-03-11
author: Cline
scope: `pages/`, `components/`, `lib/`, `actions/`
type: pattern
rationale: Improve maintainability and reduce route-level complexity.
impact: Better testability and safer incremental changes.
status: accepted
Pattern:
Keep route pages focused on composition and orchestration; place reusable behavior in `lib/`, `components/`, or `actions/`.
When to use:
- New features in existing routes
- Refactors reducing duplication across pages/components
Example paths:
- `pages/newappeal/**`
- `components/newappeal/**`
- `actions/index.js`
### P-002: EN/CY Parity for User-Facing Changes
date: 2026-03-11
author: Cline
scope: `locales/`, `i18n.js`, `next.config.js`, user-facing pages
type: pattern
rationale: Service requires bilingual consistency and reliable route behavior.
impact: Prevents locale divergence and citizen confusion.
status: accepted
Pattern:
Any user-facing change should include EN and CY text/route validation as part of done checks.
When to use:
- New/changed labels, messages, headings
- New/changed route aliases or rewrites
Example paths:
- `locales/en/**`, `locales/cy/**`
- `next.config.js`, `i18n.js`
+62
View File
@@ -0,0 +1,62 @@
# Pitfalls
## Entry Template
```
date: YYYY-MM-DD
author: <agent|name>
scope: <files/routes/features>
type: pitfall
rationale: <why recorded>
impact: <user/system/security/i18n/a11y>
status: open|mitigated|resolved
Pitfall:
How to detect:
How to avoid:
```
---
### PF-001: Locale Rewrite Drift
date: 2026-03-11
author: Cline
scope: `next.config.js`, `i18n.js`, user-facing routes
type: pitfall
rationale: Route/content parity can silently break across EN/CY if only one side is updated.
impact: Broken navigation and inconsistent bilingual experience.
status: mitigated
Pitfall:
Adding or modifying a route in one locale without corresponding rewrite/translation updates.
How to detect:
- Manual navigation check for EN and CY aliases.
- Verify page namespace mappings in `i18n.js`.
How to avoid:
- Treat route + translation + rewrite as one change unit.
### PF-002: Sensitive Logging in Auth/Notification Paths
date: 2026-03-11
author: Cline
scope: `pages/api/auth/[...nextauth].js`, `pages/api/email/**`, `actions/index.js`
type: pitfall
rationale: Debug logs in these paths can expose identifiers or callback tokens.
impact: Security and privacy risk.
status: open
Pitfall:
Verbose console logs around auth URLs, email payloads, or user identifiers.
How to detect:
- Search changed files for `console.log` and inspect payload content.
How to avoid:
- Use redacted logging and avoid printing callback tokens/user-sensitive data.
+37
View File
@@ -0,0 +1,37 @@
# Product Context — PEDW FrontEnd
## Primary user workflows
1. **Public discovery**
- Search planning cases (basic, advanced, address, DNS).
- Open case summary pages and review documents/history.
2. Authenticated portal (`/myportal/**`)
- Sign in via magic-link email.
- View dashboards/worklists (my cases, watched cases, awaiting submission, representations).
- Start or continue appeal/representation submission flows.
3. **Role-shaped behavior**
- General users can create appeals and representations.
- LPA users get authority-scoped views and representation actions; raise-appeal behavior is restricted.
## Core domain concepts
- **Case / Incident**: core planning entity shown in search, detail, and portal journeys.
- **Appeal type**: controls collection/field behavior and some UI logic.
- **Representation window**: date-gated period controlling whether representation actions are available.
- **Watched case / email notifications**: user subscriptions to case changes.
- **DNS**: Developments of National Significance-specific journey and pages.
## Business logic patterns visible in code
- Case summary UI varies by appeal type and case attributes.
- Representation actions are conditionally shown by appeal type, role, and date windows.
- Locale-sensitive behavior affects links, routes, labels, and email template choice.
- New-case-reference notifications include preferred-language checks before template selection.
## Important user-facing behaviors
- Welsh route aliases are mapped in `next.config.js` and must remain in sync with page behavior.
- Breadcrumb/back-navigation behavior is actively maintained across search -> case -> portal routes.
- Document visibility/download flows are central to case transparency and must remain stable.
+25
View File
@@ -0,0 +1,25 @@
# Project Brief — PEDW FrontEnd
## What this project is
PEDW FrontEnd is a bilingual (English/Welsh) public-service web portal for Planning and Environment Decisions Wales. It supports public case discovery and authenticated portal workflows for planning appeals, representations, and DNS (Developments of National Significance) journeys.
## Problem it solves
- Gives citizens and stakeholders a single place to search planning cases and view case details/documents.
- Enables authenticated users to create/manage appeals and representations through structured online workflows.
- Provides role-aware dashboard experiences (e.g. general portal users and LPA users) without exposing internal CRM complexity.
## Key users / use cases
- **Public users:** search, filter, and view planning case information and documents.
- **Authenticated portal users:** manage account details, submit/continue appeals, submit representations, track watched and submitted items.
- **LPA users:** authority-scoped dashboard and representation-related actions.
- **Admin/support users:** review new appeals/documents and operational lists via admin endpoints/UI.
## High-level success criteria
1. Core public and portal journeys remain reliable (search, case detail, my portal, new appeal, representation).
2. Security-sensitive flows (auth/session, API relay/hash, file/document handling) remain intact.
3. EN/CY parity is maintained for routes and user-facing content.
4. Accessibility baseline remains acceptable for keyboard navigation, headings, labels, and focus behavior.
+51
View File
@@ -0,0 +1,51 @@
# Refactor Backlog (Maintainability + System Integrity)
Last updated: 2026-03-12
## Priority 1 — Split `actions/index.js` by concern
- **Problem:** Single high-coupling module mixes API clients, hash/token helpers, logging, file/email/domain operations.
- **Why it matters:** Hard to reason about changes; high regression risk from unrelated edits.
- **Target outcome:** Small modules with explicit boundaries (e.g. `relayClient`, `fileClient`, `notifyClient`, `caseService`, `authService`).
- **Initial scope:** create façade layer first, then migrate call sites incrementally.
- **Detailed plan:** `memory-bank/refactor-plan-actions-index.md`
- **Test gate:** add unit regression tests + coverage reporting as part of this refactor.
## Priority 2 — Centralize relay/hash/token forwarding logic
- **Problem:** `pages/api/endpoint/**` and related routes duplicate request-signing + token + forwarding behavior.
- **Why it matters:** Security-sensitive drift and inconsistent error handling.
- **Target outcome:** Shared relay utility enforcing one signing contract, one timeout/retry policy, one error map, one redacted logging strategy.
- **Initial scope:** pilot on a small endpoint group, then roll out pattern.
## Priority 3 — Extract breadcrumb/back-link route-state rules
- **Problem:** Navigation logic in `components/breadcrumbs.js` and case summary is branch-heavy and query-dependent.
- **Why it matters:** Frequent regressions in search -> case -> myportal paths.
- **Target outcome:** Pure route-state helpers with table-driven tests; UI component mainly renders output.
- **Initial scope:** isolate `va/adv/ads/key` decision matrix first.
## Priority 4 — Standardize security guards in `pages/api/file/**`
- **Problem:** Hash/guard enforcement appears inconsistent across file endpoints.
- **Why it matters:** Uneven protection for document upload/download/delete paths.
- **Target outcome:** Shared guard middleware for hash/auth/input validation + consistent negative-path responses.
- **Initial scope:** enforce a common pre-handler contract on high-risk routes first.
## Priority 5 — Establish minimum automated regression baseline
- **Problem:** Limited automated tests for high-risk logic.
- **Why it matters:** Repeated regressions and heavy manual verification burden.
- **Target outcome:** Focused test suite for pure logic and high-risk decisions.
- **Initial scope:**
1. breadcrumb decision matrix
2. representation eligibility/date windows
3. hash utility behavior
4. locale rewrite mapping sanity checks
## Sequencing recommendation
1. Priorities 2 + 4 (security/integrity foundation)
2. Priority 3 (high-change regression hotspot)
3. Priority 1 (structural maintainability)
4. Priority 5 (continuous safety net, starts early and expands)
+41
View File
@@ -0,0 +1,41 @@
# System Patterns — PEDW FrontEnd
## Architecture style
- Next.js 14 (Pages Router) monolith with route handlers in `pages/` and API handlers in `pages/api/**`.
- Mix of SSR/client rendering with Redux hydration (`HYDRATE`) and client persistence.
- Integration-heavy backend-for-frontend pattern: many internal API routes proxy to external services.
## Module boundaries
- `pages/`: route composition and API endpoints.
- `components/`: UI feature modules (case, search, dns, myportal, account, admin, mapping).
- `actions/`: shared API client helpers, token/header/hash helpers, and side-effect utilities.
- `lib/`: domain/form helper logic.
- `store/`: Redux reducers, wrapper, and persistence config.
- `prisma/`: auth/session persistence schema.
## API patterns
- Endpoint naming commonly uses `*_api.js` under `pages/api/endpoint/`, `pages/api/file/`, `pages/api/admin/`.
- Recurring endpoint implementation pattern:
1. build query path,
2. create HMAC hash (`hash` query param),
3. fetch OAuth token,
4. forward to relay URL,
5. return normalized JSON / error.
- Swagger annotations are embedded in many API files for route documentation.
## Data and integration boundaries
- **Auth/session persistence**: Prisma models (`User`, `Account`, `Session`, `VerificationToken`) on SQL Server.
- **Case/business data**: fetched via API proxy routes to Dynamics/relay endpoints (not via Prisma business models).
- **File/document handling**: Azure blob-backed APIs under `pages/api/file/**`, including hash checks on sensitive routes.
## Internal conventions and recurring implementation choices
- Bilingual route mapping through `next.config.js` rewrites plus `i18n.js` page namespace mapping.
- Security headers are split across `middleware.js` (CSP + runtime security headers) and `next.config.js` static headers.
- Breadcrumb/back-link logic is centralized in `components/breadcrumbs.js` and depends on route/query state.
- Case summary behavior is appeal-type driven with branching UI/eligibility logic in `components/case/summary.js`.
- Proxy and direct variants coexist for some APIs (`*proxy_api.js`), so behavior parity must be checked when changing one side.
+43
View File
@@ -0,0 +1,43 @@
# Tech Context — PEDW FrontEnd
## Languages and framework
- JavaScript-first codebase (TypeScript tooling present).
- Next.js `^14.2.28` with Pages Router.
- React `^18.2.0`.
## Core libraries in active use
- Auth: `next-auth` + Prisma adapters.
- Data/state: `redux`, `react-redux`, `next-redux-wrapper`, `redux-persist`, `redux-thunk`, `redux-form`.
- Data access/integration: `axios`, `crypto-js`, `jsonpath-plus`.
- i18n: `next-translate`, locale config in `i18n.js`.
- Storage/infrastructure integrations: `@azure/storage-blob`, `@azure/storage-queue`, `@azure/identity`.
- Notifications/telemetry: `notifications-node-client` (GOV.UK Notify), `applicationinsights`.
- PDF/maps: `@react-pdf/renderer`, `react-pdf`, `leaflet`, `react-leaflet`, `google-map-react`.
## Runtime and configuration
- Standard app start script uses Next runtime (`npm start`).
- Additional custom server entries exist (`server.js`, `server/server.js`) but are currently treated as non-active for the refactor baseline unless deployment evidence indicates otherwise.
- Environment-driven config for auth, relay/API roots, hash key, notify key, and database URL.
## Tooling and quality gates
- Linting: `npm run lint` (`next lint`).
- Formatting conventions from `.prettierrc`: 4 spaces, no trailing commas.
- Prisma client generation script available: `npm run prisma:generate`.
## CI/CD and deployment artifacts
- `azure-pipelines.yml` exists (legacy-looking Node 10 build pipeline).
- `Jenkinsfile` exists (Node 20 + Docker build/push/deploy flow).
- `Dockerfile` exists (Node 20 Alpine runtime).
- Repository contains mixed deployment artifacts; active production path should be treated as environment-dependent unless confirmed.
## Local development workflow
- `npm install`
- `npm run dev`
- `npm run lint`
- `npm run build && npm start` for production-like verification
+90 -46
View File
@@ -42,65 +42,109 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getCaseBlob } from "../../../actions/azurestorage";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var createCaseBody = req.body;
var contactid = req.query.contactid;
var appealTypeId = req.query.appealTypeId;
var containerName = req.query.containername;
var lpaID = req.query.lpaID;
var queryUrl = "incidents";
var token = await getToken();
const createCaseBody = req.body;
const contactid = req.query.contactid;
const appealTypeId = req.query.appealTypeId;
const containerName = req.query.containername;
const lpaID = req.query.lpaID;
const queryUrl = "incidents";
var data = {
"title": "insertion test case",
"caseorigincode": 3,
"servicestage": 1,
"customerid_contact@odata.bind": "/contacts(" + contactid + ")",
"pinswg_appealcasetype": appealTypeId,
"pinswg_AssociatedLPA@odata.bind": "/accounts(" + lpaID + ")"
};
var newData = Object.assign(data, createCaseBody);
if (!createCaseBody || typeof createCaseBody !== "object") {
return respondError(res, {
status: 400,
code: "CASE_PAYLOAD_REQUIRED",
message: "Case payload is required"
});
}
if (typeof contactid !== "string" || contactid.trim().length === 0) {
return respondError(res, {
status: 400,
code: "CONTACT_ID_REQUIRED",
message: "contactid is required"
});
}
if (typeof appealTypeId !== "string" || appealTypeId.trim().length === 0) {
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_ID_REQUIRED",
message: "appealTypeId is required"
});
}
if (
typeof containerName !== "string" ||
containerName.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CONTAINER_NAME_REQUIRED",
message: "containername is required"
});
}
if (typeof lpaID !== "string" || lpaID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "LPA_ID_REQUIRED",
message: "lpaID is required"
});
}
delete newData.lpaTypes;
delete newData.appealTypes;
try {
const token = await getToken();
console.log("/////Create Case:\n", newData, "\n//////////////");
const data = {
"title": "insertion test case",
"caseorigincode": 3,
"servicestage": 1,
"customerid_contact@odata.bind": "/contacts(" + contactid + ")",
"pinswg_appealcasetype": appealTypeId,
"pinswg_AssociatedLPA@odata.bind": "/accounts(" + lpaID + ")"
};
const newData = Object.assign(data, createCaseBody);
var config = {
method: "post",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(newData)
};
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: axios(config)
.then(({ data }) => {
getCaseBlob(containerName, data.ticketnumber, createCaseBody);
delete newData.lpaTypes;
delete newData.appealTypes;
res.status(200).json(data);
})
.catch((error) => {
//consoleLogger(error);
res.status(400).json(error);
});
console.log("/////Create Case:\n", newData, "\n//////////////");
return apiResponse;
const config = {
method: "post",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(newData)
};
const { data: responseData } = await axios(config);
await getCaseBlob(
containerName,
responseData.ticketnumber,
createCaseBody
);
return respondSuccess(res, responseData);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CASE_CREATE_FAILED",
message: "Failed to create case"
});
}
}
+16 -14
View File
@@ -42,35 +42,35 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { isNonEmptyString, sanitizeString } from "../../../actions/core/guards";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getCaseBlob } from "../../../actions/azurestorage";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var createTaskBody = req.body;
const createTaskBody = req.body;
const contactEmail = sanitizeString(createTaskBody?.contactEmail);
const contactSubject = sanitizeString(createTaskBody?.contactSubject);
const contactBody = sanitizeString(createTaskBody?.contactbody);
if (!isNonEmptyString(contactEmail) || !isNonEmptyString(contactSubject)) {
return res.status(400).json({
error: "contactEmail and contactSubject are required"
return respondError(res, {
status: 400,
code: "CONTACT_EMAIL_AND_SUBJECT_REQUIRED",
message: "contactEmail and contactSubject are required"
});
}
var queryUrl = "tasks";
var token = await getToken();
const queryUrl = "tasks";
const token = await getToken();
let contactValue = createTaskBody.typeOfContact;
const contactValue = createTaskBody.typeOfContact;
const teamMap = {
plq: "ec48450c-7e26-ec11-a97f-00224800e98c", //PET
@@ -99,7 +99,7 @@ export default async function ApiProxy(req, res) {
//console.log("/////Create Task:\n", payload, "\n//////////////");
var config = {
const config = {
method: "post",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
@@ -117,11 +117,13 @@ export default async function ApiProxy(req, res) {
try {
const { data } = await axios(config);
return res.status(200).json(data);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return res
.status(400)
.json({ error: "Failed to create CRM task", details: error });
return respondError(res, {
status: 400,
code: "CRM_TASK_CREATE_FAILED",
message: "Failed to create CRM task"
});
}
}
+55 -41
View File
@@ -11,10 +11,10 @@
// */
import axios from "axios";
import CryptoJS from "crypto-js";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -83,51 +83,65 @@ export default async function ApiProxy(req, res) {
typeof contactBind !== "string" ||
contactBind.length === 0
) {
return res.status(400).json();
return respondError(res, {
status: 400,
code: "WATCHED_CASE_BINDINGS_REQUIRED",
message:
"pinswg_WatchedCase and pinswg_Contact bindings are required"
});
}
const watchedCaseMatch = watchedCaseBind.match(/\(([^)]+)\)/);
const contactMatch = contactBind.match(/\(([^)]+)\)/);
if (!watchedCaseMatch || !contactMatch) {
return res.status(400).json();
}
const token = await getToken();
const incidentId = watchedCaseMatch[1];
const contactId = contactMatch[1];
const existingRecord = await recordExists(incidentId, contactId, token);
let method, queryUrl;
if (existingRecord) {
method = "patch";
queryUrl = `pinswg_watchlists(${existingRecord.pinswg_watchlistid})`; // adjust with your primary key logical name
} else {
method = "post";
queryUrl = "pinswg_watchlists";
}
const config = {
method: method,
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
Accept: "application/json",
Prefer: 'odata.include-annotations="*",return=representation',
Authorization: "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(data)
};
return axios(config)
.then(({ data }) => res.status(200).json(data))
.catch((err) => {
consoleLogger(err);
res.status(400).json(err.response?.data || err);
return respondError(res, {
status: 400,
code: "INVALID_BINDING_FORMAT",
message: "Invalid odata.bind format for watched case or contact"
});
}
try {
const token = await getToken();
const incidentId = watchedCaseMatch[1];
const contactId = contactMatch[1];
const existingRecord = await recordExists(incidentId, contactId, token);
let method, queryUrl;
if (existingRecord) {
method = "patch";
queryUrl = `pinswg_watchlists(${existingRecord.pinswg_watchlistid})`;
} else {
method = "post";
queryUrl = "pinswg_watchlists";
}
const config = {
method: method,
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
Accept: "application/json",
Prefer: 'odata.include-annotations="*",return=representation',
Authorization: "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(data)
};
const result = await axios(config);
return respondSuccess(res, result.data);
} catch (err) {
consoleLogger(err);
return respondError(res, {
status: 400,
code: "WATCHED_CASE_UPSERT_FAILED",
message: "Failed to create or update watched case"
});
}
}
@@ -11,39 +11,51 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentID;
var token = await getToken();
var queryUrl = "incidents(" + incidentID + ")";
const incidentID = req.query.incidentID;
var config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
return axios(config)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
try {
const token = await getToken();
const queryUrl = "incidents(" + incidentID + ")";
const config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
Accept: "application/json",
Prefer: 'odata.include-annotations="*",return=representation',
Authorization: "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "AWAITING_SUBMISSION_DELETE_FAILED",
message: "Failed to delete awaiting submission"
});
}
}
@@ -11,40 +11,56 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var myRepresentationsID = req.query.myRepresentationsID;
var token = await getToken();
var queryUrl = "pinswg_representationses(" + myRepresentationsID + ")";
const myRepresentationsID = req.query.myRepresentationsID;
var config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
return axios(config)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
if (
typeof myRepresentationsID !== "string" ||
myRepresentationsID.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "MY_REPRESENTATION_ID_REQUIRED",
message: "myRepresentationsID is required"
});
}
try {
const token = await getToken();
const queryUrl =
"pinswg_representationses(" + myRepresentationsID + ")";
const config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
Accept: "application/json",
Prefer: 'odata.include-annotations="*",return=representation',
Authorization: "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "MY_REPRESENTATION_DELETE_FAILED",
message: "Failed to delete representation"
});
}
}
+35 -26
View File
@@ -11,45 +11,54 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var watchedCaseID = req.query.watchedCaseID;
const watchedCaseID = req.query.watchedCaseID;
if (typeof watchedCaseID === "undefined" || watchedCaseID.length === 0) {
return res.status(400).json();
if (
typeof watchedCaseID !== "string" ||
watchedCaseID.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "WATCHED_CASE_ID_REQUIRED",
message: "watchedCaseID is required"
});
}
var token = await getToken();
var queryUrl = "pinswg_watchlists(" + watchedCaseID + ")";
try {
const token = await getToken();
const queryUrl = "pinswg_watchlists(" + watchedCaseID + ")";
var config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
const config = {
method: "delete",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
Accept: "application/json",
Prefer: 'odata.include-annotations="*",return=representation',
Authorization: "Bearer " + token.access_token,
"Content-Type": "application/json"
}
};
return axios(config)
.then(({ data }) => {
//console.log("deleted watched case - " + watchedCaseID);
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "WATCHED_CASE_DELETE_FAILED",
message: "Failed to delete watched case"
});
}
}
@@ -18,61 +18,50 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`;
const BASE_URL = process.env.API_ROOT || "http://localhost:3000";
export default async function ApiProxy(req, res) {
var watchedCaseID = req.query.watchedCaseID;
var token = await getToken();
const watchedCaseID = req.query.watchedCaseID;
var queryUrl =
"/api/endpoint/deletewatchedcases_api?watchedCaseID=" + watchedCaseID;
if (
typeof watchedCaseID !== "string" ||
watchedCaseID.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "WATCHED_CASE_ID_REQUIRED",
message: "watchedCaseID is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"/api/endpoint/deletewatchedcases_api?watchedCaseID=" +
watchedCaseID;
const { data } = await axios.get(
BASE_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
// data.value.forEach(function (element) {
// element.ticketnumber = element.pinswg_WatchedCase?.ticketnumber;
// element.pinswg_title =
// element[
// "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
// ];
);
// element[
// "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
// ] =
// element.pinswg_WatchedCase?.[
// "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
// ];
// element._pinswg_associatedlpa_value =
// element.pinswg_WatchedCase?._pinswg_associatedlpa_value;
// element[
// "_ownerid_value@OData.Community.Display.V1.FormattedValue"
// ] =
// element.pinswg_WatchedCase?.[
// "_ownerid_value@OData.Community.Display.V1.FormattedValue"
// ];
// element._ownerid_value =
// element.pinswg_WatchedCase?._ownerid_value;
// delete element.pinswg_WatchedCase;
// });
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "WATCHED_CASE_PROXY_DELETE_FAILED",
message: "Failed to delete watched case via proxy"
});
}
}
+26 -32
View File
@@ -13,41 +13,35 @@
* description: Success
*/
import axios from "axios";
import { respondError, respondSuccess } from "../middleware/apiResponse";
export default async function ApiProxy(req, res) {
const accessTokenEndpoint = process.env.ACCESS_TOKEN_ENDPOINT;
const tenantId = process.env.TENANT;
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";
try {
const accessTokenEndpoint = process.env.ACCESS_TOKEN_ENDPOINT;
const tenantId = process.env.TENANT;
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";
var config = {
method: "post",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Cache-Control": "no-cache",
},
url: `${accessTokenEndpoint}${tenantId}/oauth2/v2.0/token`,
body: tokenBody,
};
const { data } = await axios.post(
`${accessTokenEndpoint}${tenantId}/oauth2/v2.0/token`,
tokenBody
);
console.log("get token case:", config);
return axios
.post(`${accessTokenEndpoint}${tenantId}/oauth2/v2.0/token`, tokenBody)
.then(({ data }) => {
console.log;
res.status(200).json(data);
})
.catch((error) => {
res.status(400);
return respondSuccess(res, data);
} catch (error) {
return respondError(res, {
status: 400,
code: "TOKEN_FETCH_FAILED",
message: "Unable to fetch token"
});
}
}
+123 -90
View File
@@ -48,33 +48,69 @@
// */
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import {
azureHeadersPagedCustom,
azureHeadersPaged,
azureHeaders
} from "../../../actions/core/headers";
import { azureHeadersPagedCustom } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchstring;
var pageNumber = req.query.pageNumber;
var token = await getToken();
const rawSearchString = req.query.searchstring;
const pageNumber = req.query.pageNumber;
const orderby = req.query.orderby;
const fieldSort = req.query.fieldSort;
const showNumberOfRecords = req.query.showNumberOfRecords;
var orderby = req.query.orderby;
var fieldSort = req.query.fieldSort;
var showNumberOfRecords = req.query.showNumberOfRecords;
if (
typeof rawSearchString !== "string" ||
rawSearchString.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchstring is required"
});
}
if (typeof orderby !== "string" || orderby.trim().length === 0) {
return respondError(res, {
status: 400,
code: "ORDER_BY_REQUIRED",
message: "orderby is required"
});
}
if (typeof fieldSort !== "string" || fieldSort.trim().length === 0) {
return respondError(res, {
status: 400,
code: "FIELD_SORT_REQUIRED",
message: "fieldSort is required"
});
}
if (
typeof showNumberOfRecords !== "string" ||
showNumberOfRecords.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "SHOW_NUMBER_OF_RECORDS_REQUIRED",
message: "showNumberOfRecords is required"
});
}
searchString = _.isEmpty(searchString)
? searchString
: JSON.parse(decodeURI(searchString));
let searchString;
try {
searchString = JSON.parse(decodeURI(rawSearchString));
} catch (error) {
return respondError(res, {
status: 400,
code: "INVALID_SEARCH_STRING",
message: "searchstring must be valid encoded JSON"
});
}
var queryString = "";
@@ -146,84 +182,81 @@ export default async function ApiProxy(req, res) {
console.log("adv qu: ", queryUrl);
var apiResponse = _.isEmpty(searchString)
? res.status(400).json()
: axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(
token.access_token,
showNumberOfRecords
)
)
.then(async ({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
try {
const token = await getToken();
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(token.access_token, showNumberOfRecords)
);
if (_.has(searchString, "projecttype")) {
// await updateValueArray(data, token);
// async function updateValueArray(data, token) {
// for (let i = 0; i < data.value.length; i++) {
// const item = data.value[i];
// try {
// // Axios call using the `incidentid` to fetch additional data
// const response = await axios.get(
// WEBAPI_URL +
// "pinswg_sipses?$filter=_pinswg_sipscase_value eq " +
// item.incidentid +
// " and _pinswg_projecttype_value eq " +
// searchString.projecttype +
// "&$select=_pinswg_projecttype_value" +
// hashAPIPath(
// "pinswg_sipses?$filter=_pinswg_sipscase_value eq " +
// item.incidentid +
// " and _pinswg_projecttype_value eq " +
// searchString.projecttype +
// "&$select=_pinswg_projecttype_value"
// ),
// azureHeadersPaged(token.access_token)
// );
// // Assuming the response contains the additional data you want to add
// // console.log(response.data.value[0]);
// console.log(response.data.value);
// if (
// response.data.value.length > 0 &&
// response.data.value[0]
// ._pinswg_projecttype_value != null
// ) {
// Object.assign(
// item,
// response.data.value[0]
// ); // Update item with new data
// } else {
// console.log(
// `No project type found for incident ID ${item.incidentid}`
// );
// }
// } catch (error) {
// console.error(
// `Error fetching data for incident ID ${item.incidentid}:`,
// error
// );
// }
// }
// }
// data.value = data.value.filter(
// (item) => item._pinswg_projecttype_value != null
// );
// data["@odata.count"] = data.value.length;
}
let dataStr;
_.has(data, "@odata.nextLink") === true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
});
if (_.has(searchString, "projecttype")) {
// await updateValueArray(data, token);
// async function updateValueArray(data, token) {
// for (let i = 0; i < data.value.length; i++) {
// const item = data.value[i];
// try {
// // Axios call using the `incidentid` to fetch additional data
// const response = await axios.get(
// WEBAPI_URL +
// "pinswg_sipses?$filter=_pinswg_sipscase_value eq " +
// item.incidentid +
// " and _pinswg_projecttype_value eq " +
// searchString.projecttype +
// "&$select=_pinswg_projecttype_value" +
// hashAPIPath(
// "pinswg_sipses?$filter=_pinswg_sipscase_value eq " +
// item.incidentid +
// " and _pinswg_projecttype_value eq " +
// searchString.projecttype +
// "&$select=_pinswg_projecttype_value"
// ),
// azureHeadersPaged(token.access_token)
// );
// // Assuming the response contains the additional data you want to add
// // console.log(response.data.value[0]);
// console.log(response.data.value);
// if (
// response.data.value.length > 0 &&
// response.data.value[0]
// ._pinswg_projecttype_value != null
// ) {
// Object.assign(
// item,
// response.data.value[0]
// ); // Update item with new data
// } else {
// console.log(
// `No project type found for incident ID ${item.incidentid}`
// );
// }
// } catch (error) {
// console.error(
// `Error fetching data for incident ID ${item.incidentid}:`,
// error
// );
// }
// }
// }
// data.value = data.value.filter(
// (item) => item._pinswg_projecttype_value != null
// );
// data["@odata.count"] = data.value.length;
}
return apiResponse;
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "ADVANCED_SEARCH_PAGED_FETCH_FAILED",
message: "Failed to fetch advanced search paged results"
});
}
}
// export default async function ApiProxy(req, res) {
+59 -21
View File
@@ -29,40 +29,78 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var caseReference = req.query.caseReference;
var updateFormCollection = req.query.updateFormCollection;
var primaryAttribute = req.query.primaryAttribute;
var token = await getToken();
const caseReference = req.query.caseReference;
const updateFormCollection = req.query.updateFormCollection;
const primaryAttribute = req.query.primaryAttribute;
const queryUrl =
updateFormCollection +
"?$count=true&$select=_" +
primaryAttribute +
"s_value&$filter=pinswg_name eq '" +
caseReference +
"'";
if (
typeof caseReference !== "string" ||
caseReference.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CASE_REFERENCE_REQUIRED",
message: "caseReference is required"
});
}
return axios
.get(
if (
typeof updateFormCollection !== "string" ||
updateFormCollection.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "UPDATE_FORM_COLLECTION_REQUIRED",
message: "updateFormCollection is required"
});
}
if (
typeof primaryAttribute !== "string" ||
primaryAttribute.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "PRIMARY_ATTRIBUTE_REQUIRED",
message: "primaryAttribute is required"
});
}
try {
const token = await getToken();
const escapedCaseReference = caseReference.split("'").join("''");
const queryUrl =
updateFormCollection +
"?$count=true&$select=_" +
primaryAttribute +
"s_value&$filter=pinswg_name eq '" +
escapedCaseReference +
"'";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "APPEAL_ID_FETCH_FAILED",
message: "Failed to fetch appeal id"
});
}
}
+37 -31
View File
@@ -17,11 +17,11 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -57,45 +57,51 @@ const groupArray = (arr) => {
};
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentid;
const incidentID = req.query.incidentid;
if (typeof incidentID === "undefined" || incidentID.length === 0) {
return res.status(400).json();
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid is required"
});
}
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"pinswg_documents?$count=true&$filter=_pinswg_documentids_value eq " +
incidentID +
" and not(contains(pinswg_name,'_Appeal_Form.pdf'))&$select=pinswg_name,pinswg_isharedocumentlocations";
const queryUrl =
"pinswg_documents?$count=true&$filter=_pinswg_documentids_value eq " +
incidentID +
" and not(contains(pinswg_name,'_Appeal_Form.pdf'))&$select=pinswg_name,pinswg_isharedocumentlocations";
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
// //delete data["pinswg_documentid"];
// data.value.forEach(function (element) {
// delete element["pinswg_documentid"];
// });
);
// //delete data["pinswg_documentid"];
// data.value.forEach(function (element) {
// delete element["pinswg_documentid"];
// });
// var dataArr = groupArray(data.value);
// var dataArr = groupArray(data.value);
// // var dataStr;
// // _.has(data, "@odata.nextLink") == true &&
// // ((dataStr = JSON.stringify(data["@odata.nextLink"])),
// // (data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
// // var dataStr;
// // _.has(data, "@odata.nextLink") == true &&
// // ((dataStr = JSON.stringify(data["@odata.nextLink"])),
// // (data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
data.value.forEach((item) => {
item.name = item.pinswg_name;
});
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
data.value.forEach((item) => {
item.name = item.pinswg_name;
});
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "APPEAL_PDF_DOCUMENTS_FETCH_FAILED",
message: "Failed to fetch appeal PDF documents"
});
}
}
+24 -21
View File
@@ -10,42 +10,45 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' " +
(process.env.SHOWSIPS !== "true"
? "and attributevalue ne 846040002"
: "") +
"&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
const queryUrl =
"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' " +
(process.env.SHOWSIPS !== "true"
? "and attributevalue ne 846040002"
: "") +
"&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
// for sips
// "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
// for sips
// "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
// "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
//"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Developments of National Significance' and value ne 'LDP' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
// "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
//"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Developments of National Significance' and value ne 'LDP' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc";
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "APPEAL_TYPES_FETCH_FAILED",
message: "Failed to fetch appeal types"
});
}
}
@@ -1,3 +1,5 @@
import { respondSuccess } from "../middleware/apiResponse";
/**
* @swagger
* /api/endpoint/getappealtypesfornewappeal_api:
@@ -11,8 +13,7 @@
*/
const ApiResponse = (req, res) => {
res.statusCode = 200;
res.json({
return respondSuccess(res, {
"value": [
{
"value": "Planning Appeal - S78",
@@ -20,9 +21,9 @@ const ApiResponse = (req, res) => {
"organizationid": "01191a4d-105f-eb11-aaba-00224800be9c",
"attributevalue@OData.Community.Display.V1.FormattedValue":
"846,040,000",
"attributevalue": 846040000,
},
],
"attributevalue": 846040000
}
]
});
};
+35 -20
View File
@@ -18,39 +18,54 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var loggedInUserId = req.query.loggedInUserId;
var token = await getToken();
const loggedInUserId = req.query.loggedInUserId;
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_customerid_value eq " +
loggedInUserId +
" and servicestage eq 1 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
if (
typeof loggedInUserId !== "string" ||
loggedInUserId.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "LOGGED_IN_USER_ID_REQUIRED",
message: "loggedInUserId is required"
});
}
//console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_customerid_value eq " +
loggedInUserId +
" and servicestage eq 1 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "AWAITING_SUBMISSION_FETCH_FAILED",
message: "Failed to fetch awaiting submissions"
});
}
}
+21 -17
View File
@@ -17,37 +17,41 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002)and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002)and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_DNS_SEARCH_FETCH_FAILED",
message: "Failed to fetch basic DNS search results"
});
}
}
@@ -11,45 +11,54 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var caseReference = req.query.caseReference;
var token = await getToken();
const caseReference = req.query.caseReference;
var queryUrl =
"pinswg_dnses?$filter=pinswg_name eq '" +
caseReference +
"&$count=true";
//" and statuscode eq 1&$count=true";
if (
typeof caseReference !== "string" ||
caseReference.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CASE_REFERENCE_REQUIRED",
message: "caseReference is required"
});
}
queryUrl = queryUrl + getSelectQuery("pinswg_dnses");
try {
const token = await getToken();
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: typeof caseReference != "undefined" && caseReference.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
let queryUrl =
"pinswg_dnses?$filter=pinswg_name eq '" +
caseReference +
"&$count=true";
return apiResponse;
queryUrl = queryUrl + getSelectQuery("pinswg_dnses");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_DNS_SEARCH_DETAILS_FETCH_FAILED",
message: "Failed to fetch basic DNS search details"
});
}
}
@@ -10,50 +10,59 @@
* description: Success
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var caseReference = req.query.caseReference;
var token = await getToken();
const caseReference = req.query.caseReference;
var queryUrl =
"pinswg_dnses?$filter=pinswg_name eq '" +
caseReference +
"&$count=true";
//" and statuscode eq 1&$count=true";
if (
typeof caseReference !== "string" ||
caseReference.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CASE_REFERENCE_REQUIRED",
message: "caseReference is required"
});
}
queryUrl = queryUrl + getSelectQuery("pinswg_dnses");
try {
const token = await getToken();
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: typeof caseReference != "undefined" && caseReference.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
return res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
let queryUrl =
"pinswg_dnses?$filter=pinswg_name eq '" +
caseReference +
"&$count=true";
return apiResponse;
queryUrl = queryUrl + getSelectQuery("pinswg_dnses");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_DNS_SEARCH_DETAILS_PAGED_FETCH_FAILED",
message: "Failed to fetch paged basic DNS search details"
});
}
}
@@ -48,43 +48,75 @@ import { azureHeadersPagedCustom } from "../../../actions/core/headers";
import { getToken } from "../../../actions/core/token";
import { consoleLogger } from "../../../actions/core/logger";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var pageNumber = req.query.pageNumber;
var token = await getToken();
const pageNumber = req.query.pageNumber;
const orderby = req.query.orderby;
const fieldSort = req.query.fieldSort;
const showNumberOfRecords = req.query.showNumberOfRecords;
var orderby = req.query.orderby;
var fieldSort = req.query.fieldSort;
var showNumberOfRecords = req.query.showNumberOfRecords;
if (typeof orderby !== "string" || orderby.trim().length === 0) {
return respondError(res, {
status: 400,
code: "ORDER_BY_REQUIRED",
message: "orderby is required"
});
}
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002) and pinswg_publishtoweb eq true&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" + '<cookie pagenumber="' + pageNumber + '" />'
: "");
if (typeof fieldSort !== "string" || fieldSort.trim().length === 0) {
return respondError(res, {
status: 400,
code: "FIELD_SORT_REQUIRED",
message: "fieldSort is required"
});
}
return axios
.get(
if (
typeof showNumberOfRecords !== "string" ||
showNumberOfRecords.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "SHOW_NUMBER_OF_RECORDS_REQUIRED",
message: "showNumberOfRecords is required"
});
}
try {
const token = await getToken();
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002) and pinswg_publishtoweb eq true&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" + '<cookie pagenumber="' + pageNumber + '" />'
: "");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(token.access_token, showNumberOfRecords)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
return res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_DNS_SEARCH_PAGED_FETCH_FAILED",
message: "Failed to fetch paged basic DNS search results"
});
}
}
+34 -33
View File
@@ -17,55 +17,56 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchString;
const searchString = req.query.searchString;
if (!searchString || String(searchString).trim().length === 0) {
return res.status(400).json();
if (typeof searchString !== "string" || searchString.trim().length === 0) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchString is required"
});
}
var token = await getToken();
try {
const token = await getToken();
const escapedSearchString = searchString.replace(/\'/g, "''");
searchString = searchString.replace(/\'/g, "''");
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
escapedSearchString +
"') or contains(ticketnumber, '" +
escapedSearchString +
"')) and (pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002 ) and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
searchString +
"') or contains(ticketnumber, '" +
searchString +
"')) and (pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002 ) and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
);
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: searchString.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
let dataStr;
_.has(data, "@odata.nextLink") === true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
return apiResponse;
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_DNS_URL_SEARCH_FETCH_FAILED",
message: "Failed to fetch DNS URL search results"
});
}
}
@@ -1,41 +1,72 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeadersNoOdata } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var appealTypeName = req.query.appealTypeName;
var primaryIdAttribute = req.query.primaryIdAttribute;
var incidentID = req.query.incidentID;
var token = await getToken();
const appealTypeName = req.query.appealTypeName;
const primaryIdAttribute = req.query.primaryIdAttribute;
const incidentID = req.query.incidentID;
var queryUrl =
appealTypeName +
"?$filter=_" +
primaryIdAttribute +
"s_value eq " +
incidentID +
"&$count=true";
if (
typeof appealTypeName !== "string" ||
appealTypeName.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_NAME_REQUIRED",
message: "appealTypeName is required"
});
}
queryUrl = queryUrl; //+ getSelectQuery(appealTypeName);
if (
typeof primaryIdAttribute !== "string" ||
primaryIdAttribute.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "PRIMARY_ID_ATTRIBUTE_REQUIRED",
message: "primaryIdAttribute is required"
});
}
//console.log("///////////\nquery: ", queryUrl, "<<<<end query");
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
appealTypeName +
"?$filter=_" +
primaryIdAttribute +
"s_value eq " +
incidentID +
"&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersNoOdata(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_PART_SAVED_DETAILS_FETCH_FAILED",
message: "Failed to fetch basic part-saved details"
});
}
}
@@ -4,6 +4,7 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -728,15 +729,16 @@ export default async function ApiProxy(req, res) {
(record) => record.pinswg_publishtoweb
);
return res.status(200).json({
return respondSuccess(res, {
"@odata.count": searchResultsObj.length,
value: searchResultsObj
});
} catch (error) {
consoleLogger(error);
return res.status(500).json({
message: "Failed to retrieve search results.",
error: error?.message || error
return respondError(res, {
status: 500,
code: "BASIC_SEARCH_BY_ADDRESS_FETCH_FAILED",
message: "Failed to retrieve search results"
});
}
}
@@ -1,9 +1,9 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -285,9 +285,11 @@ export default async function ApiProxy(req, res) {
let lpaRef = (req.query.lpaRef || "").trim();
if (!lpaRef) {
return res
.status(400)
.json({ error: "Missing required query param: lpaRef" });
return respondError(res, {
status: 400,
code: "LPA_REF_REQUIRED",
message: "lpaRef is required"
});
}
// ✅ Escape single quotes for OData
@@ -298,10 +300,6 @@ export default async function ApiProxy(req, res) {
// contains(tolower(pinswg_lpaapplicationreference), 'lowered search')
const lowered = lpaRef.toLowerCase();
console.log(
`\n=== LPA REF SEARCH ===\nSearching for "${lpaRef}" (case-insensitive contains)\nAcross ${appealTypeArrayWithLpaRef.length} entity types\n======================\n`
);
const resultsPerType = await Promise.all(
appealTypeArrayWithLpaRef.map(async (item) => {
// You can expand/select more fields if needed, but keep light for speed
@@ -323,17 +321,6 @@ export default async function ApiProxy(req, res) {
`&$count=true` +
`&$orderby=modifiedon desc`;
console.log(
"\n------------------------------------------\n",
"Entity:",
item.LogicalCollectionName,
"\nQuery:",
queryUrl,
"\nFull:",
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
"\n------------------------------------------\n"
);
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
@@ -353,10 +340,6 @@ export default async function ApiProxy(req, res) {
] || null
}));
console.log(
`Returned ${normalized.length} records from ${item.LogicalCollectionName}`
);
return normalized;
})
);
@@ -372,9 +355,13 @@ export default async function ApiProxy(req, res) {
value: flattened
};
return res.status(200).json(output);
return respondSuccess(res, output);
} catch (error) {
consoleLogger(error);
return res.status(400).json(error);
return respondError(res, {
status: 400,
code: "BASIC_SEARCH_LPA_REF_FETCH_FAILED",
message: "Failed to fetch basic search by lpa reference"
});
}
}
+86 -52
View File
@@ -30,80 +30,114 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { getNavigationPropertyByPrimaryAttribute } from "../../../components/utils";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var appealTypeName = req.query.appealTypeName;
var primaryIdAttribute = req.query.primaryIdAttribute;
var incidentID = req.query.incidentID;
var token = await getToken();
const appealTypeName = req.query.appealTypeName;
const primaryIdAttribute = req.query.primaryIdAttribute;
const incidentID = req.query.incidentID;
let navigationProperty =
getNavigationPropertyByPrimaryAttribute(
primaryIdAttribute
).NavigationProperty;
if (
typeof appealTypeName !== "string" ||
appealTypeName.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_NAME_REQUIRED",
message: "appealTypeName is required"
});
}
var queryUrl =
appealTypeName +
"?$filter=_" +
(primaryIdAttribute == "pinswg_sipscase"
? "pinswg_sipscase_value"
: primaryIdAttribute + "s_value ") +
" eq " +
incidentID +
"&$count=true" +
"&$expand=" +
navigationProperty +
"($select=ticketnumber)";
if (
typeof primaryIdAttribute !== "string" ||
primaryIdAttribute.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "PRIMARY_ID_ATTRIBUTE_REQUIRED",
message: "primaryIdAttribute is required"
});
}
//" and statuscode eq 1&$count=true";
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
// queryUrl =
// queryUrl +
// getSelectQuery(appealTypeName) +
// ",_" +
// (primaryIdAttribute == "pinswg_sipscase"
// ? "pinswg_sipscase_value"
// : primaryIdAttribute + "s_value");
try {
const token = await getToken();
queryUrl = queryUrl + getSelectQuery(appealTypeName);
const navigationProperty =
getNavigationPropertyByPrimaryAttribute(
primaryIdAttribute
).NavigationProperty;
// console.log(
// "\n==========================================\n",
// "\nSearch Details query ",
// "\nAppealType: " + appealTypeName,
// "\nIncident ID: " + incidentID,
// "\n\nQuery url: " + queryUrl,
// "\n==========================================\n"
// );
let queryUrl =
appealTypeName +
"?$filter=_" +
(primaryIdAttribute == "pinswg_sipscase"
? "pinswg_sipscase_value"
: primaryIdAttribute + "s_value ") +
" eq " +
incidentID +
"&$count=true" +
"&$expand=" +
navigationProperty +
"($select=ticketnumber)";
return axios
.get(
//" and statuscode eq 1&$count=true";
// queryUrl =
// queryUrl +
// getSelectQuery(appealTypeName) +
// ",_" +
// (primaryIdAttribute == "pinswg_sipscase"
// ? "pinswg_sipscase_value"
// : primaryIdAttribute + "s_value");
queryUrl = queryUrl + getSelectQuery(appealTypeName);
// console.log(
// "\n==========================================\n",
// "\nSearch Details query ",
// "\nAppealType: " + appealTypeName,
// "\nIncident ID: " + incidentID,
// "\n\nQuery url: " + queryUrl,
// "\n==========================================\n"
// );
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
let flattened = data.value.map((r) => ({
...r,
ticketnumber: r[navigationProperty]?.ticketnumber || null
}));
);
data.value = flattened;
let flattened = data.value.map((r) => ({
...r,
ticketnumber: r[navigationProperty]?.ticketnumber || null
}));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
data.value = flattened;
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_SEARCH_DETAILS_FETCH_FAILED",
message: "Failed to fetch basic search details"
});
}
}
@@ -30,7 +30,6 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
@@ -38,82 +37,105 @@ import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { getNavigationPropertyByPrimaryAttribute } from "../../../components/utils";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var appealTypeName = req.query.appealTypeName;
var primaryIdAttribute = req.query.primaryIdAttribute;
var incidentID = req.query.incidentID;
const appealTypeName = req.query.appealTypeName;
const primaryIdAttribute = req.query.primaryIdAttribute;
const incidentID = req.query.incidentID;
if (
!appealTypeName ||
!primaryIdAttribute ||
!incidentID ||
String(appealTypeName).trim().length === 0 ||
String(primaryIdAttribute).trim().length === 0 ||
String(incidentID).trim().length === 0
typeof appealTypeName !== "string" ||
appealTypeName.trim().length === 0
) {
return res.status(400).json();
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_NAME_REQUIRED",
message: "appealTypeName is required"
});
}
var token = await getToken();
if (
typeof primaryIdAttribute !== "string" ||
primaryIdAttribute.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "PRIMARY_ID_ATTRIBUTE_REQUIRED",
message: "primaryIdAttribute is required"
});
}
let navigationProperty =
getNavigationPropertyByPrimaryAttribute(
primaryIdAttribute
).NavigationProperty;
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
// "?$filter=_" +
// (primaryIdAttribute == "pinswg_sipscase"
// ? "pinswg_sipscase_value"
// : primaryIdAttribute + "s_value ") +
// " eq " +
// incidentID +
try {
const token = await getToken();
var queryUrl =
appealTypeName +
"?$filter=" +
incidentID +
"&$count=true" +
"&$expand=" +
navigationProperty +
"($select=ticketnumber)";
const navigationProperty =
getNavigationPropertyByPrimaryAttribute(
primaryIdAttribute
).NavigationProperty;
//" and statuscode eq 1&$count=true";
// "?$filter=_" +
// (primaryIdAttribute == "pinswg_sipscase"
// ? "pinswg_sipscase_value"
// : primaryIdAttribute + "s_value ") +
// " eq " +
// incidentID +
queryUrl =
queryUrl +
getSelectQuery(appealTypeName) +
",_" +
(primaryIdAttribute == "pinswg_sipscase"
? "pinswg_sipscase_value"
: primaryIdAttribute + "s_value");
let queryUrl =
appealTypeName +
"?$filter=" +
incidentID +
"&$count=true" +
"&$expand=" +
navigationProperty +
"($select=ticketnumber)";
return axios
.get(
//" and statuscode eq 1&$count=true";
queryUrl =
queryUrl +
getSelectQuery(appealTypeName) +
",_" +
(primaryIdAttribute == "pinswg_sipscase"
? "pinswg_sipscase_value"
: primaryIdAttribute + "s_value");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
let flattened = data.value.map((r) => ({
...r,
ticketnumber: r[navigationProperty]?.ticketnumber || null
}));
);
data.value = flattened;
let flattened = data.value.map((r) => ({
...r,
ticketnumber: r[navigationProperty]?.ticketnumber || null
}));
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
data.value = flattened;
return res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_SEARCH_DETAILS_PAGED_FETCH_FAILED",
message: "Failed to fetch paged basic search details"
});
}
}
+78 -52
View File
@@ -48,70 +48,96 @@ import { azureHeadersPagedCustom } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchString;
var pageNumber = req.query.pageNumber;
let searchString = req.query.searchString;
const pageNumber = req.query.pageNumber;
const orderby = req.query.orderby;
const fieldSort = req.query.fieldSort;
const showNumberOfRecords = req.query.showNumberOfRecords;
if (typeof searchString === "undefined" || searchString.length === 0) {
return res.status(400).json();
if (typeof searchString !== "string" || searchString.trim().length === 0) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchString is required"
});
}
var token = await getToken();
if (typeof orderby !== "string" || orderby.trim().length === 0) {
return respondError(res, {
status: 400,
code: "ORDER_BY_REQUIRED",
message: "orderby is required"
});
}
var orderby = req.query.orderby;
var fieldSort = req.query.fieldSort;
var showNumberOfRecords = req.query.showNumberOfRecords;
if (typeof fieldSort !== "string" || fieldSort.trim().length === 0) {
return respondError(res, {
status: 400,
code: "FIELD_SORT_REQUIRED",
message: "fieldSort is required"
});
}
searchString = searchString.replace(/\'/g, "''");
if (
typeof showNumberOfRecords !== "string" ||
showNumberOfRecords.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "SHOW_NUMBER_OF_RECORDS_REQUIRED",
message: "showNumberOfRecords is required"
});
}
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
searchString +
"') or contains(ticketnumber, '" +
searchString +
"') or contains(pinswg_lpareference, '" +
searchString +
"')) and pinswg_appealcasetype ne null " +
(process.env.SHOWSIPS !== "true"
? "and pinswg_appealcasetype ne 846040002 "
: "") +
"and pinswg_publishtoweb eq true&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" + '<cookie pagenumber="' + pageNumber + '" />'
: "");
try {
const token = await getToken();
var apiResponse =
searchString.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(
token.access_token,
showNumberOfRecords
)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] =
dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
searchString = searchString.replace(/\'/g, "''");
return apiResponse;
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_caseaddress,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
searchString +
"') or contains(ticketnumber, '" +
searchString +
"') or contains(pinswg_lpareference, '" +
searchString +
"')) and pinswg_appealcasetype ne null " +
(process.env.SHOWSIPS !== "true"
? "and pinswg_appealcasetype ne 846040002 "
: "") +
"and pinswg_publishtoweb eq true&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" + '<cookie pagenumber="' + pageNumber + '" />'
: "");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(token.access_token, showNumberOfRecords)
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "BASIC_SEARCH_PAGED_FETCH_FAILED",
message: "Failed to fetch paged basic search results"
});
}
}
+32 -21
View File
@@ -11,41 +11,52 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentID;
var token = await getToken();
var queryUrl =
"incidents(" +
incidentID +
")?$select=ticketnumber,title,pinswg_appealcasetype";
const incidentID = req.query.incidentID;
//console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"incidents(" +
incidentID +
")?$select=ticketnumber,title,pinswg_appealcasetype";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CASE_FETCH_FAILED",
message: "Failed to fetch case"
});
}
}
+29 -18
View File
@@ -11,38 +11,49 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentID;
var token = await getToken();
var queryUrl = "incidents(" + incidentID + ")";
const incidentID = req.query.incidentID;
//console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl = "incidents(" + incidentID + ")";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json([data]);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, [data]);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CASE_BY_ID_FETCH_FAILED",
message: "Failed to fetch case by id"
});
}
}
+12 -8
View File
@@ -1,10 +1,10 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import OSPoint from "ospoint";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -75,16 +75,16 @@ const keysToRemove = [
];
export default async function ApiProxy(req, res) {
var token = await getToken();
const token = await getToken();
var queryUrl =
const queryUrl =
"pinswg_dnses?$select=pinswg_projectlocation,pinswg_mapzoomlevel,pinswg_name,pinswg_anticipatedgridreferenceeastingtext,pinswg_anticipatedgridreferencenorthingtext,pinswg_projectname,pinswg_dnsid,_pinswg_associatedlpa_value,_pinswg_appellant_value&$filter=pinswg_anticipatedgridreferencenorthingtext ne null and pinswg_anticipatedgridreferenceeastingtext ne null&$count=true";
//console.log("dns ", queryUrl);
var queryUrlSips =
const queryUrlSips =
"pinswg_sipses?$select=pinswg_projectlocation,pinswg_mapzoomlevel,pinswg_name,pinswg_anticipatedgridrefeasting,pinswg_anticipatedgridrefnorthing,pinswg_projectname,pinswg_sipscase,_pinswg_associatedlpa_value,_pinswg_appellant_value&$filter=pinswg_anticipatedgridrefeasting ne null and pinswg_anticipatedgridrefnorthing ne null&$count=true";
var coordsObj = { value: [] };
const coordsObj = { value: [] };
try {
// First Axios request
@@ -150,11 +150,15 @@ export default async function ApiProxy(req, res) {
};
return req.query.hasOwnProperty("fordmw")
? res.status(200).json(updatedData)
: res.status(200).json(coordsObj);
? respondSuccess(res, updatedData)
: respondSuccess(res, coordsObj);
} catch (error) {
// Catch any errors and send an error response
consoleLogger(error);
return res.status(400).json(error);
return respondError(res, {
status: 400,
code: "DNS_COORDS_FETCH_FAILED",
message: "Failed to fetch DNS coordinates"
});
}
}
+21 -25
View File
@@ -1,44 +1,40 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_appealcasetype,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,statuscode,ticketnumber,title &$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002) and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_appealcasetype,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,statuscode,ticketnumber,title &$filter=(pinswg_appealcasetype eq 846040011 or pinswg_appealcasetype eq 846040002) and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true";
function renameJsonKey(jsonObj, oldKey, newKey) {
if (jsonObj.hasOwnProperty(oldKey)) {
jsonObj[newKey] = jsonObj[oldKey]; // Add new key with the same value
delete jsonObj[oldKey]; // Delete old key
}
return jsonObj;
}
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
var dataStr;
);
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
let dataStr;
_.has(data, "@odata.nextLink") === true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "DNS_LIST_FETCH_FAILED",
message: "Failed to fetch DNS list"
});
}
}
+28 -16
View File
@@ -1,33 +1,45 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var whichForm = req.query.whichForm;
var token = await getToken();
const whichForm = req.query.whichForm;
var queryUrl =
"systemforms?$select=formid,name,formxml,type,objecttypecode&$filter=(objecttypecode eq 'pinswg_" +
whichForm +
"' and type eq 2)&$count=true&$top=201";
if (typeof whichForm !== "string" || whichForm.trim().length === 0) {
return respondError(res, {
status: 400,
code: "WHICH_FORM_REQUIRED",
message: "whichForm is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"systemforms?$select=formid,name,formxml,type,objecttypecode&$filter=(objecttypecode eq 'pinswg_" +
whichForm +
"' and type eq 2)&$count=true&$top=201";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "FORM_DATA_FETCH_FAILED",
message: "Failed to fetch form data"
});
}
}
+12 -3
View File
@@ -1,6 +1,7 @@
import { hashAPIPath } from "../../../actions/core/hash";
import nextConnect from "next-connect";
import { getSession } from "next-auth/react";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const ApiProxy = nextConnect();
@@ -8,7 +9,11 @@ ApiProxy.get(async (req, res) => {
const session = await getSession({ req });
if (!session) {
return res.status(401).json();
return respondError(res, {
status: 401,
code: "UNAUTHENTICATED",
message: "Authentication required"
});
}
const rawQueryPath = req.query.path;
@@ -39,10 +44,14 @@ ApiProxy.get(async (req, res) => {
!allowedPrefix.some((prefix) => queryPath.startsWith(prefix)) ||
queryPath.includes("/api/endpoint/gethash_api")
) {
return res.status(400).json();
return respondError(res, {
status: 400,
code: "INVALID_HASH_PATH",
message: "Invalid path for hash generation"
});
}
return res.status(200).json({ hash: hashAPIPath(rawQueryPath) });
return respondSuccess(res, { hash: hashAPIPath(rawQueryPath) });
});
export default ApiProxy;
+31 -35
View File
@@ -16,53 +16,49 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchString;
var token = await getToken();
let searchString = req.query.searchString;
searchString = searchString.replace(/\'/g, "''");
if (typeof searchString !== "string" || searchString.trim().length === 0) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchString is required"
});
}
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=incidentid eq " +
searchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
try {
const token = await getToken();
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: searchString.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
//console.log(
("\n==========================================\n",
// "basic search incident: " + queryUrl,
// "\n\n",
// "data: " + JSON.stringify(data),
// "\n\n",
"publihs:" + JSON.stringify(data.value[0]),
"\n==========================================\n");
//);
return res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
searchString = searchString.replace(/\'/g, "''");
return apiResponse;
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=incidentid eq " +
searchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "INCIDENT_BY_ID_FETCH_FAILED",
message: "Failed to fetch incident by id"
});
}
}
+28 -27
View File
@@ -16,48 +16,49 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchString;
var token = await getToken();
const searchString = req.query.searchString;
searchString = searchString.replace(/\'/g, "''");
if (typeof searchString !== "string" || searchString.trim().length === 0) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchString is required"
});
}
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,ticketnumber,title, _primarycontactid_value&$filter=incidentid eq " +
searchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
try {
const token = await getToken();
console.log(
"\n==========================================\n",
"basic search: " + queryUrl,
"\n\n",
"basic search relay link: " +
WEBAPI_URL +
queryUrl +
hashAPIPath(queryUrl),
"\n==========================================\n"
);
const escapedSearchString = searchString.split("'").join("''");
return axios
.get(
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,pinswg_publishtoweb,ticketnumber,title, _primarycontactid_value&$filter=incidentid eq " +
escapedSearchString +
" and pinswg_appealcasetype ne null &$orderby=createdon desc&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "IS_PUBLISHED_FETCH_FAILED",
message: "Failed to fetch published state"
});
}
}
+31 -16
View File
@@ -17,35 +17,50 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var parentIncidentid = req.query.parentincidentid;
var token = await getToken();
const parentIncidentid = req.query.parentincidentid;
var queryUrl =
"incidents?$count=true&$filter=_parentcaseid_value eq " +
parentIncidentid +
" and pinswg_appealcasetype ne null and pinswg_publishtoweb eq true &$select=title, incidentid";
if (
typeof parentIncidentid !== "string" ||
parentIncidentid.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "PARENT_INCIDENT_ID_REQUIRED",
message: "parentincidentid is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"incidents?$count=true&$filter=_parentcaseid_value eq " +
parentIncidentid +
" and pinswg_appealcasetype ne null and pinswg_publishtoweb eq true &$select=title, incidentid";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "LINKED_CASES_FETCH_FAILED",
message: "Failed to fetch linked cases"
});
}
}
+16 -14
View File
@@ -13,33 +13,35 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"accounts?$count=true&$filter=pinswg_isalocalplanningauthorityaccount eq 846040000&$select=name&$orderby=name asc";
const queryUrl =
"accounts?$count=true&$filter=pinswg_isalocalplanningauthorityaccount eq 846040000&$select=name&$orderby=name asc";
//console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "LPA_FETCH_FAILED",
message: "Failed to fetch local planning authorities"
});
}
}
+23 -5
View File
@@ -1,3 +1,5 @@
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
@@ -5,16 +7,32 @@ const WEBAPI_URL =
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var whichForm = req.query.whichForm;
const whichForm = req.query.whichForm;
if (typeof whichForm !== "string" || whichForm.trim().length === 0) {
return respondError(res, {
status: 400,
code: "WHICH_FORM_REQUIRED",
message: "whichForm is required"
});
}
// var queryUrl =
// "EntityDefinitions(LogicalName='pinswg_" +
// whichForm +
// "')/Attributes?$count=true&$select=LogicalName,RequiredLevel";
const mandatoryFieldsData = require("../../../data/mandatoryfields/pinswg_" +
whichForm +
".json");
try {
const mandatoryFieldsData = require(
"../../../data/mandatoryfields/pinswg_" + whichForm + ".json"
);
return res.status(200).json(mandatoryFieldsData);
return respondSuccess(res, mandatoryFieldsData);
} catch (error) {
return respondError(res, {
status: 404,
code: "MANDATORY_FIELDS_NOT_FOUND",
message: "Mandatory fields data not found for requested form"
});
}
}
+33 -22
View File
@@ -18,43 +18,54 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var loggedInUserId = req.query.loggedInUserId;
var token = await getToken();
const loggedInUserId = req.query.loggedInUserId;
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,pinswg_publishtoweb,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_customerid_value eq " +
loggedInUserId +
" and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
if (
typeof loggedInUserId !== "string" ||
loggedInUserId.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "LOGGED_IN_USER_ID_REQUIRED",
message: "loggedInUserId is required"
});
}
// Removed servicestage but not sure why.....
//" and servicestage eq 0 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
try {
const token = await getToken();
//console.log("///////////\nPortal query: ", queryUrl, "<<<<end query");
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,pinswg_publishtoweb,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_customerid_value eq " +
loggedInUserId +
" and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "MY_CASES_FETCH_FAILED",
message: "Failed to fetch my cases"
});
}
}
+53 -32
View File
@@ -24,51 +24,72 @@ import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var lpaid = req.query.lpaid;
var token = await getToken();
const lpaid = req.query.lpaid;
const lpaList = await getLPA();
if (typeof lpaid !== "string" || lpaid.trim().length === 0) {
return respondError(res, {
status: 400,
code: "LPA_ID_REQUIRED",
message: "lpaid is required"
});
}
const lpaGUID = jsonpath({
path: '$..[?(@ && @.name=="' + lpaid + '")]',
json: lpaList,
eval: true
});
try {
const token = await getToken();
const lpaList = await getLPA();
//console.log(
// '$..[?(@ && @.name="' + lpaid + '")]',
// lpaList,
// lpaid,
// "LPAGUID=",
// lpaGUID
// );
const lpaGUID = jsonpath({
path: '$..[?(@ && @.name=="' + lpaid + '")]',
json: lpaList,
eval: true
});
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_pinswg_associatedlpa_value eq " +
lpaGUID[0].accountid +
" and servicestage eq 0 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
if (!Array.isArray(lpaGUID) || !lpaGUID[0]?.accountid) {
return respondError(res, {
status: 404,
code: "LPA_NOT_FOUND",
message: "No matching LPA found"
});
}
//console.log("///////////\nPortal query: ", queryUrl, "<<<<end query");
//console.log(
// '$..[?(@ && @.name="' + lpaid + '")]',
// lpaList,
// lpaid,
// "LPAGUID=",
// lpaGUID
// );
return axios
.get(
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantlastname,pinswg_appellantfirstname,pinswg_appellantagent,pinswg_agentfirstname,pinswg_agentlastname,pinswg_agentcompanyname&$expand=primarycontactid($select=fullname)&$filter=_pinswg_associatedlpa_value eq " +
lpaGUID[0].accountid +
" and servicestage eq 0 and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
//console.log("///////////\nPortal query: ", queryUrl, "<<<<end query");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
data.value.forEach(function (element) {
element.pinswg_title = element.title;
});
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "MY_LPA_CASES_FETCH_FAILED",
message: "Failed to fetch my LPA cases"
});
}
}
+30 -17
View File
@@ -18,37 +18,50 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var loggedInUserId = req.query.loggedInUserId;
var token = await getToken();
const loggedInUserId = req.query.loggedInUserId;
var queryUrl =
"pinswg_representationses?$filter= _pinswg_contact_value eq " +
loggedInUserId +
"&$count=true&$orderby=createdon desc";
if (
typeof loggedInUserId !== "string" ||
loggedInUserId.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "LOGGED_IN_USER_ID_REQUIRED",
message: "loggedInUserId is required"
});
}
//console.log(WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
try {
const token = await getToken();
return axios
.get(
const queryUrl =
"pinswg_representationses?$filter= _pinswg_contact_value eq " +
loggedInUserId +
"&$count=true&$orderby=createdon desc";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "MY_REPRESENTATIONS_FETCH_FAILED",
message: "Failed to fetch my representations"
});
}
}
+35 -36
View File
@@ -1,55 +1,54 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var searchString = req.query.searchString;
var token = await getToken();
const searchString = req.query.searchString;
searchString = searchString.replace(/\'/g, "''");
if (typeof searchString !== "string" || searchString.trim().length === 0) {
return respondError(res, {
status: 400,
code: "SEARCH_STRING_REQUIRED",
message: "searchString is required"
});
}
var queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
searchString +
"') or contains(ticketnumber, '" +
searchString +
"')) and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
try {
const token = await getToken();
const escapedSearchString = searchString.replace(/\'/g, "''");
//console.log("basic search ", queryUrl);
const queryUrl =
"incidents?$select=pinswg_environmentalstatementlocation,modifiedon,description,numberofchildincidents,_accountid_value,_customerid_value,_pinswg_associatedlpa_value,_ownerid_value,pinswg_appealcasetype,statuscode,ticketnumber,title, _primarycontactid_value,pinswg_lpareference,pinswg_appellantagent,pinswg_appellantfirstname,pinswg_appellantlastname&$expand=primarycontactid($select=fullname)&$filter=(contains(title, '" +
escapedSearchString +
"') or contains(ticketnumber, '" +
escapedSearchString +
"')) and pinswg_appealcasetype ne null&$orderby=createdon desc&$count=true";
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: searchString.length > 0
? axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
var dataStr;
// dataStr = dataStr.replace(/: true/gm, `: "Yes"`);
// dataStr = dataStr.replace(/: false/gm, `: "No"`);
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
);
// console.log("replaced strinig:", dataStr);
let dataStr;
_.has(data, "@odata.nextLink") === true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
})
: res.status(400).json();
return apiResponse;
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "PART_SAVED_APPEAL_FETCH_FAILED",
message: "Failed to fetch part-saved appeals"
});
}
}
+23 -5
View File
@@ -17,6 +17,8 @@
* description: hello world
*/
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
@@ -24,16 +26,32 @@ const WEBAPI_URL =
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var whichForm = req.query.whichForm;
const whichForm = req.query.whichForm;
if (typeof whichForm !== "string" || whichForm.trim().length === 0) {
return respondError(res, {
status: 400,
code: "WHICH_FORM_REQUIRED",
message: "whichForm is required"
});
}
// var queryUrl =
// "EntityDefinitions(LogicalName='pinswg_" +
// whichForm +
// "')/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=OptionSet,GlobalOptionSet&$count=true";
const pickListData = require("../../../data/picklistdata/pinswg_" +
whichForm +
".json");
try {
const pickListData = require(
"../../../data/picklistdata/pinswg_" + whichForm + ".json"
);
return res.status(200).json(pickListData);
return respondSuccess(res, pickListData);
} catch (error) {
return respondError(res, {
status: 404,
code: "PICKLISTS_NOT_FOUND",
message: "Picklist data not found for requested form"
});
}
}
@@ -24,44 +24,64 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var appealType = req.query.appealType;
var caseReference = req.query.caseReference.split("'").join("''");
var token = await getToken();
const appealType = req.query.appealType;
const caseReference = req.query.caseReference;
//console.log("the case:", req.query, caseReference);
if (typeof appealType !== "string" || appealType.trim().length === 0) {
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_REQUIRED",
message: "appealType is required"
});
}
var queryUrl =
appealType +
"?$filter=pinswg_name eq '" +
caseReference +
"'&$count=true";
if (
typeof caseReference !== "string" ||
caseReference.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CASE_REFERENCE_REQUIRED",
message: "caseReference is required"
});
}
queryUrl = queryUrl + getSelectQuery(appealType);
try {
const token = await getToken();
const escapedCaseReference = caseReference.split("'").join("''");
//console.log("test:", WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
let queryUrl =
appealType +
"?$filter=pinswg_name eq '" +
escapedCaseReference +
"'&$count=true";
return axios
.get(
queryUrl = queryUrl + getSelectQuery(appealType);
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "PORTAL_MODULE_DETAILS_FETCH_FAILED",
message: "Failed to fetch portal module details"
});
}
}
@@ -24,40 +24,64 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { getSelectQuery } from "../../../actions/selectQueryTypes";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var appealType = req.query.appealType;
var caseReference = req.query.caseReference;
var token = await getToken();
const appealType = req.query.appealType;
const caseReference = req.query.caseReference;
var queryUrl =
appealType +
"?$filter=pinswg_name eq '" +
caseReference +
"'&$count=true";
if (typeof appealType !== "string" || appealType.trim().length === 0) {
return respondError(res, {
status: 400,
code: "APPEAL_TYPE_REQUIRED",
message: "appealType is required"
});
}
queryUrl = queryUrl + getSelectQuery(appealType);
if (
typeof caseReference !== "string" ||
caseReference.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "CASE_REFERENCE_REQUIRED",
message: "caseReference is required"
});
}
return axios
.get(
try {
const token = await getToken();
const escapedCaseReference = caseReference.split("'").join("''");
let queryUrl =
appealType +
"?$filter=pinswg_name eq '" +
escapedCaseReference +
"'&$count=true";
queryUrl = queryUrl + getSelectQuery(appealType);
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "PORTAL_MODULE_DETAILS_PROXY_FETCH_FAILED",
message: "Failed to fetch portal module details proxy"
});
}
}
+16 -15
View File
@@ -10,34 +10,35 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var token = await getToken();
try {
const token = await getToken();
var queryUrl =
"pinswg_sipsprojecttypes?$select=pinswg_name,pinswg_sipsprojecttypeid&$orderby=pinswg_name asc&$count=true";
const queryUrl =
"pinswg_sipsprojecttypes?$select=pinswg_name,pinswg_sipsprojecttypeid&$orderby=pinswg_name asc&$count=true";
//console.log(queryUrl);
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "PROJECT_TYPES_FETCH_FAILED",
message: "Failed to fetch project types"
});
}
}
+28 -17
View File
@@ -18,36 +18,47 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var loggedInUserId = req.query.loggedInUserId;
var incidentID = req.query.incidentID;
var token = await getToken();
const incidentID = req.query.incidentID;
var queryUrl =
"pinswg_representationses?$filter= _pinswg_case_value eq " +
incidentID +
" and pinswg_publishtoweb eq true&$count=true&$orderby=createdon desc";
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentID is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"pinswg_representationses?$filter= _pinswg_case_value eq " +
incidentID +
" and pinswg_publishtoweb eq true&$count=true&$orderby=createdon desc";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "REPRESENTATIONS_FETCH_FAILED",
message: "Failed to fetch representations"
});
}
}
@@ -17,11 +17,11 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
@@ -57,37 +57,41 @@ const groupArray = (arr) => {
};
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentid;
var token = await getToken();
const incidentID = req.query.incidentid;
var queryUrl =
"pinswg_documents?$count=true&$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null&$select=pinswg_isharedocumentlocations";
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid is required"
});
}
//console.log("docu: ", WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
try {
const token = await getToken();
return axios
.get(
const queryUrl =
"pinswg_documents?$count=true&$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null&$select=pinswg_isharedocumentlocations";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
//delete data["pinswg_documentid"];
data.value.forEach(function (element) {
delete element["pinswg_documentid"];
});
);
var dataArr = groupArray(data.value);
// var dataStr;
// _.has(data, "@odata.nextLink") == true &&
// ((dataStr = JSON.stringify(data["@odata.nextLink"])),
// (data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(dataArr);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
data.value.forEach(function (element) {
delete element["pinswg_documentid"];
});
const dataArr = groupArray(data.value);
return respondSuccess(res, dataArr);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SEARCH_DOCUMENT_TYPES_FETCH_FAILED",
message: "Failed to fetch search document types"
});
}
}
@@ -23,6 +23,7 @@ import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
@@ -44,41 +45,53 @@ const encryptDocReference = (documentRef) => {
};
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentid;
var token = await getToken();
const incidentID = req.query.incidentid;
var queryUrl =
"pinswg_documents?$count=true&$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null&$select=pinswg_isharedocumentlocations,_pinswg_documentids_value,pinswg_isharelabelcasetype,pinswg_isharelabellpaname,pinswg_publishtoweb,pinswg_uploadstatus,pinswg_isharedocumentclassification,pinswg_isharedocumentreference,pinswg_name,pinswg_latestpublishedversion,pinswg_latestpublisheddate,pinswg_documentpublisheddate";
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid is required"
});
}
//console.log("docu: ", WEBAPI_URL + queryUrl + hashAPIPath(queryUrl));
try {
const token = await getToken();
return axios
.get(
const queryUrl =
"pinswg_documents?$count=true&$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null&$select=pinswg_isharedocumentlocations,_pinswg_documentids_value,pinswg_isharelabelcasetype,pinswg_isharelabellpaname,pinswg_publishtoweb,pinswg_uploadstatus,pinswg_isharedocumentclassification,pinswg_isharedocumentreference,pinswg_name,pinswg_latestpublishedversion,pinswg_latestpublisheddate,pinswg_documentpublisheddate";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
data.value.forEach(function (element) {
Object.assign(element, {
"pinswg_documentpublisheddate":
element.pinswg_documentpublisheddate != null
? element.pinswg_documentpublisheddate
: element.pinswg_latestpublisheddate
});
element.pinswg_hashlink = encryptDocReference(
element.pinswg_isharedocumentreference
);
);
data.value.forEach(function (element) {
Object.assign(element, {
"pinswg_documentpublisheddate":
element.pinswg_documentpublisheddate != null
? element.pinswg_documentpublisheddate
: element.pinswg_latestpublisheddate
});
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
element.pinswg_hashlink = encryptDocReference(
element.pinswg_isharedocumentreference
);
});
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SEARCH_DOCUMENT_DETAILS_FETCH_FAILED",
message: "Failed to fetch search document details"
});
}
}
@@ -49,6 +49,7 @@ import { azureHeadersPagedCustom } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WORDKEY = process.env.HASHKEY;
@@ -70,20 +71,53 @@ const encryptDocReference = (documentRef) => {
};
export default async function ApiProxy(req, res) {
var pageNumber = req.query.pageNumber;
var incidentID = req.query.incidentid;
var token = await getToken();
const pageNumber = req.query.pageNumber;
const incidentID = req.query.incidentid;
const orderby = req.query.orderby;
const fieldSort = req.query.fieldSort;
const showNumberOfRecords = req.query.showNumberOfRecords;
const documentType = req.query.documentType || "all";
var orderby = req.query.orderby;
var fieldSort = req.query.fieldSort;
var showNumberOfRecords = req.query.showNumberOfRecords;
var documentType = req.query.documentType || "all";
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid is required"
});
}
if (typeof orderby !== "string" || orderby.trim().length === 0) {
return respondError(res, {
status: 400,
code: "ORDER_BY_REQUIRED",
message: "orderby is required"
});
}
if (typeof fieldSort !== "string" || fieldSort.trim().length === 0) {
return respondError(res, {
status: 400,
code: "FIELD_SORT_REQUIRED",
message: "fieldSort is required"
});
}
if (
typeof showNumberOfRecords !== "string" ||
showNumberOfRecords.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "SHOW_NUMBER_OF_RECORDS_REQUIRED",
message: "showNumberOfRecords is required"
});
}
// (documentType != "all"
// ? documentType.indexOf(",")<0?" and pinswg_isharedocumentlocations eq " + documentType :
// : "") +
var docTypeQueryString = "";
let docTypeQueryString = "";
if (documentType != "all") {
if (documentType.indexOf(",") >= 0) {
@@ -91,8 +125,6 @@ export default async function ApiProxy(req, res) {
docTypeQueryString = " and (";
documentTypeArr.forEach(function (item, index) {
console.log(item, index);
if (item != "all") {
docTypeQueryString +=
" pinswg_isharedocumentlocations eq " + item;
@@ -118,47 +150,53 @@ export default async function ApiProxy(req, res) {
//console.log("has this passed docuemntType:", documentType);
//(documentType !="all" && " pinswg_pinswg_isharedocumentlocations eq " + )
var queryUrl =
"pinswg_documents?$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null" +
docTypeQueryString +
"&$select=pinswg_isharedocumentlocations,_pinswg_documentids_value,pinswg_isharelabelcasetype,pinswg_isharelabellpaname,pinswg_publishtoweb,pinswg_uploadstatus,pinswg_isharedocumentclassification,pinswg_isharedocumentreference,pinswg_name,pinswg_latestpublishedversion,pinswg_latestpublisheddate,pinswg_documentpublisheddate&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" + ('<cookie pagenumber="' + pageNumber + '" />')
: "");
try {
const token = await getToken();
console.log("docu paged 1: ", queryUrl);
const queryUrl =
"pinswg_documents?$filter=pinswg_publishtoweb eq true and _pinswg_documentids_value eq " +
incidentID +
" and pinswg_latestpublishedversion ne null and pinswg_latestpublisheddate ne null" +
docTypeQueryString +
"&$select=pinswg_isharedocumentlocations,_pinswg_documentids_value,pinswg_isharelabelcasetype,pinswg_isharelabellpaname,pinswg_publishtoweb,pinswg_uploadstatus,pinswg_isharedocumentclassification,pinswg_isharedocumentreference,pinswg_name,pinswg_latestpublishedversion,pinswg_latestpublisheddate,pinswg_documentpublisheddate&$orderby=" +
orderby +
" " +
fieldSort +
"&$count=true" +
(typeof pageNumber != "undefined"
? "&$skiptoken=" +
('<cookie pagenumber="' + pageNumber + '" />')
: "");
return axios
.get(
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPagedCustom(token.access_token, showNumberOfRecords)
)
.then(({ data }) => {
data.value.forEach(function (element) {
Object.assign(element, {
"pinswg_documentpublisheddate":
element.pinswg_documentpublisheddate != null
? element.pinswg_documentpublisheddate
: element.pinswg_latestpublisheddate
});
element.pinswg_hashlink = encryptDocReference(
element.pinswg_isharedocumentreference
);
);
data.value.forEach(function (element) {
Object.assign(element, {
"pinswg_documentpublisheddate":
element.pinswg_documentpublisheddate != null
? element.pinswg_documentpublisheddate
: element.pinswg_latestpublisheddate
});
var dataStr;
_.has(data, "@odata.nextLink") == true &&
((dataStr = JSON.stringify(data["@odata.nextLink"])),
(data["@odata.nextLink"] = dataStr.split("/v8.2/")[1]));
return res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
element.pinswg_hashlink = encryptDocReference(
element.pinswg_isharedocumentreference
);
});
if (_.has(data, "@odata.nextLink") === true) {
const dataStr = JSON.stringify(data["@odata.nextLink"]);
data["@odata.nextLink"] = dataStr.split("/v8.2/")[1];
}
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SEARCH_DOCUMENT_DETAILS_PAGED_FETCH_FAILED",
message: "Failed to fetch paged search document details"
});
}
}
@@ -17,34 +17,45 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var documentID = req.query.documentid;
var token = await getToken();
const documentID = req.query.documentid;
var queryUrl =
"pinswg_documenthistories?$count=true&$select=_pinswg_documentid_value,pinswg_createddate,pinswg_state,pinswg_fileexists,statecode,pinswg_publisheddate&$filter=_pinswg_documentid_value eq " +
documentID;
if (typeof documentID !== "string" || documentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "DOCUMENT_ID_REQUIRED",
message: "documentid is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"pinswg_documenthistories?$count=true&$select=_pinswg_documentid_value,pinswg_createddate,pinswg_state,pinswg_fileexists,statecode,pinswg_publisheddate&$filter=_pinswg_documentid_value eq " +
documentID;
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SEARCH_DOCUMENT_HISTORY_FETCH_FAILED",
message: "Failed to fetch search document history"
});
}
}
@@ -43,39 +43,50 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeadersPaged } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var documentID = req.query.documentid;
var pageNumber = req.query.pageNumber;
var token = await getToken();
const documentID = req.query.documentid;
var queryUrl =
"pinswg_documenthistories?$count=true&$select=_pinswg_documentid_value,pinswg_createddate,pinswg_state,pinswg_fileexists,statecode,pinswg_publisheddate&$filter=_pinswg_documentid_value eq " +
documentID;
// +
// (typeof pageNumber != "undefined"
// ? "&$skiptoken=" + ('<cookie pagenumber="' + pageNumber + '" />')
// : "");
if (typeof documentID !== "string" || documentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "DOCUMENT_ID_REQUIRED",
message: "documentid is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"pinswg_documenthistories?$count=true&$select=_pinswg_documentid_value,pinswg_createddate,pinswg_state,pinswg_fileexists,statecode,pinswg_publisheddate&$filter=_pinswg_documentid_value eq " +
documentID;
// +
// (typeof pageNumber != "undefined"
// ? "&$skiptoken=" + ('<cookie pagenumber="' + pageNumber + '" />')
// : "");
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeadersPaged(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SEARCH_DOCUMENT_HISTORY_PAGED_FETCH_FAILED",
message: "Failed to fetch paged search document history"
});
}
}
+28 -16
View File
@@ -1,33 +1,45 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var caseid = req.query.caseid;
var token = await getToken();
const caseid = req.query.caseid;
var queryUrl =
"pinswg_sipsevents?$filter=_pinswg_sipseventsid_value eq " +
caseid +
"&$count=true";
if (typeof caseid !== "string" || caseid.trim().length === 0) {
return respondError(res, {
status: 400,
code: "CASE_ID_REQUIRED",
message: "caseid is required"
});
}
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"pinswg_sipsevents?$filter=_pinswg_sipseventsid_value eq " +
caseid +
"&$count=true";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "SIPS_EVENTS_FETCH_FAILED",
message: "Failed to fetch SIPS events"
});
}
}
+2 -11
View File
@@ -1,13 +1,4 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
import { respondSuccess } from "../middleware/apiResponse";
// export default async function ApiProxy(req, res) {
// var caseid = req.query.caseid;
@@ -134,5 +125,5 @@ export default function ApiProx(req, res) {
}
]
};
return res.status(200).json(data);
return respondSuccess(res, data);
}
+52 -47
View File
@@ -18,71 +18,76 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders } from "../../../actions/core/headers";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var loggedInUserId = req.query.loggedInUserId;
var token = await getToken();
const loggedInUserId = req.query.loggedInUserId;
var queryUrl =
"pinswg_watchlists?$filter= _pinswg_contact_value eq " +
loggedInUserId +
"&$select=pinswg_emailnotifications,modifiedon,pinswg_appealcasetype,pinswg_watchlistid,_pinswg_watchedcase_value,statuscode,pinswg_representationsubmitted,pinswg_representationtype&$count=true&$orderby=createdon desc&$expand=pinswg_WatchedCase($select=pinswg_AssociatedLPA)";
if (
typeof loggedInUserId !== "string" ||
loggedInUserId.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "LOGGED_IN_USER_ID_REQUIRED",
message: "loggedInUserId is required"
});
}
//console.log(queryUrl);
return axios
.get(
try {
const token = await getToken();
const queryUrl =
"pinswg_watchlists?$filter= _pinswg_contact_value eq " +
loggedInUserId +
"&$select=pinswg_emailnotifications,modifiedon,pinswg_appealcasetype,pinswg_watchlistid,_pinswg_watchedcase_value,statuscode,pinswg_representationsubmitted,pinswg_representationtype&$count=true&$orderby=createdon desc&$expand=pinswg_WatchedCase($select=pinswg_AssociatedLPA)";
const { data } = await axios.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
data.value.forEach(function (element) {
element.ticketnumber = element.pinswg_WatchedCase?.ticketnumber;
element.pinswg_title =
element[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
];
);
data.value.forEach(function (element) {
element.ticketnumber = element.pinswg_WatchedCase?.ticketnumber;
element.pinswg_title =
element[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
];
element[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
] =
element.pinswg_WatchedCase?.[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
] =
element.pinswg_WatchedCase?.[
"_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue"
];
element._pinswg_associatedlpa_value =
element.pinswg_WatchedCase?._pinswg_associatedlpa_value;
element[
];
element._pinswg_associatedlpa_value =
element.pinswg_WatchedCase?._pinswg_associatedlpa_value;
element[
"_ownerid_value@OData.Community.Display.V1.FormattedValue"
] =
element.pinswg_WatchedCase?.[
"_ownerid_value@OData.Community.Display.V1.FormattedValue"
] =
element.pinswg_WatchedCase?.[
"_ownerid_value@OData.Community.Display.V1.FormattedValue"
];
element._ownerid_value =
element.pinswg_WatchedCase?._ownerid_value;
];
element._ownerid_value = element.pinswg_WatchedCase?._ownerid_value;
delete element.pinswg_WatchedCase;
});
// const uniqueItems = Array.from(
// new Map(
// data.value.map((item) => [item.ticketnumber, item])
// ).values()
// );
// data = { "@odata.count": uniqueItems.length, "value": uniqueItems };
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
delete element.pinswg_WatchedCase;
});
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "WATCHED_CASES_FETCH_FAILED",
message: "Failed to fetch watched cases"
});
}
}
+37 -34
View File
@@ -11,51 +11,54 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import _ from "lodash";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var incidentID = req.query.incidentid;
var queryUrl = "incidents(" + incidentID + ")";
var token = await getToken();
const incidentID = req.query.incidentid;
var data = JSON.stringify({
"servicestage": 0
});
if (typeof incidentID !== "string" || incidentID.trim().length === 0) {
return respondError(res, {
status: 400,
code: "INCIDENT_ID_REQUIRED",
message: "incidentid is required"
});
}
//console.log(data, WEBAPI_URL + queryUrl);
try {
const queryUrl = "incidents(" + incidentID + ")";
const token = await getToken();
var config = {
method: "patch",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: data
};
const config = {
method: "patch",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify({
"servicestage": 0
})
};
var apiResponse = _.isEmpty(req.query)
? res.status(400).json()
: axios(config)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
});
return apiResponse;
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CASE_PATCH_FAILED",
message: "Failed to patch case"
});
}
}
+57 -31
View File
@@ -11,45 +11,71 @@
*/
import axios from "axios";
import CryptoJS from "crypto-js";
import { consoleLogger } from "../../../actions/core/logger";
import { getToken } from "../../../actions/core/token";
import { hashAPIPath } from "../../../actions/core/hash";
import { respondError, respondSuccess } from "../middleware/apiResponse";
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
export default async function ApiProxy(req, res) {
var data = JSON.stringify(req.body);
var appealObj = req.query.appealObj;
var incidentID = req.query.incident;
const updatePayload = req.body;
const appealObj = req.query.appealObj;
const updateFormCollection = req.query.updateFormCollection;
var updateFormCollection = req.query.updateFormCollection;
var queryUrl = updateFormCollection + "(" + appealObj + ")";
var token = await getToken();
var config = {
method: "patch",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: data
};
//console.log("update case:", data);
return axios(config)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
res.status(400);
if (!updatePayload || typeof updatePayload !== "object") {
return respondError(res, {
status: 400,
code: "CASE_UPDATE_PAYLOAD_REQUIRED",
message: "Case update payload is required"
});
}
if (typeof appealObj !== "string" || appealObj.trim().length === 0) {
return respondError(res, {
status: 400,
code: "APPEAL_OBJECT_ID_REQUIRED",
message: "appealObj is required"
});
}
if (
typeof updateFormCollection !== "string" ||
updateFormCollection.trim().length === 0
) {
return respondError(res, {
status: 400,
code: "UPDATE_FORM_COLLECTION_REQUIRED",
message: "updateFormCollection is required"
});
}
try {
const queryUrl = updateFormCollection + "(" + appealObj + ")";
const token = await getToken();
const config = {
method: "patch",
url: WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
headers: {
"OData-MaxVersion": "4.0",
"OData-Version": "4.0",
"Accept": "application/json",
"Prefer": 'odata.include-annotations="*",return=representation',
"Authorization": "Bearer " + token.access_token,
"Content-Type": "application/json"
},
data: JSON.stringify(updatePayload)
};
const { data } = await axios(config);
return respondSuccess(res, data);
} catch (error) {
consoleLogger(error);
return respondError(res, {
status: 400,
code: "CASE_UPDATE_FAILED",
message: "Failed to update case"
});
}
}
File diff suppressed because it is too large Load Diff