Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
347656f
add wizards app
jerome-ng Jan 29, 2026
d94d71e
add wizards app with initial setup and configuration
jerome-ng Jan 29, 2026
63dcade
implement wizard context and provider; add wizard state management an…
jerome-ng Jan 29, 2026
64733e5
add hardcoded wizard definitions and retrieval functions
jerome-ng Jan 29, 2026
5a914d3
add Step 1 selection component with wizard loading and error handling
jerome-ng Jan 29, 2026
0753d15
add Step 2 introduction component with loading and error handling
jerome-ng Jan 29, 2026
74778d7
add Step 3 form component with loading, error handling, and dynamic f…
jerome-ng Jan 29, 2026
66044ed
add Step 4 results component with loading, error handling, and config…
jerome-ng Jan 29, 2026
85815fa
Refactor code structure for improved readability and maintainability.…
jerome-ng Jan 29, 2026
a9b3b3a
Enhance wizard components with error handling, retry functionality, a…
jerome-ng Jan 29, 2026
95bfb54
Refactor deep link handling to use path instead of route, update rela…
jerome-ng Jan 30, 2026
1de6399
Enhance wizard type definitions with step configuration and state man…
jerome-ng Jan 31, 2026
9d61a21
Refactor wizard context and shell to use currentStepIndex for improve…
jerome-ng Jan 31, 2026
3bbed61
Add getCurrentStepConfig helper to WizardContext for step configurati…
jerome-ng Jan 31, 2026
13618e8
Add wizard step components and styles for improved user flow
jerome-ng Jan 31, 2026
452f6b5
Refactor wizard components and styles for improved consistency and us…
jerome-ng Jan 31, 2026
c9abb4e
Add error handling and styling to WizardShell for improved user feedback
jerome-ng Jan 31, 2026
85ed36b
Add select field support to StepForm with validation and error handling
jerome-ng Jan 31, 2026
b52bb5a
Update WizardShell to show progress for single-step wizards and enhan…
jerome-ng Jan 31, 2026
b0deae6
Implement deep link generation in StepForm and add corresponding tests
jerome-ng Jan 31, 2026
b81a81f
Add documentation comments for wizard components and context
jerome-ng Jan 31, 2026
4f6af6a
Enhance wizard field definitions with required flags and placeholders
jerome-ng Jan 31, 2026
d8cdfee
Refactor WizardShell to implement breadcrumb navigation and remove pr…
jerome-ng Jan 31, 2026
e7fdeae
Refactor StepForm styles for improved layout and responsiveness
jerome-ng Jan 31, 2026
e9f83da
Enhance StepForm component with improved field rendering and validati…
jerome-ng Jan 31, 2026
caf14fe
Refactor StepForm tests to simplify button selection and improve read…
jerome-ng Jan 31, 2026
33f33c4
Refactor imports in StepForm, WizardShell, and tests to use named imp…
jerome-ng Jan 31, 2026
8fe5084
Refactor wizard definitions and add CDW configuration mapping for age…
jerome-ng Jan 31, 2026
b2d5435
Add axios dependency and implement CDW configuration integration for …
jerome-ng Jan 31, 2026
6608374
Remove obsolete test files for StepForm, WizardShell, and WizardContext
jerome-ng Jan 31, 2026
3b4202c
Add pako for compression and implement MRI bookmark format in deep li…
jerome-ng Jan 31, 2026
be97d50
Enhance wizard definitions by adding gender field and updating enrich…
jerome-ng Jan 31, 2026
a01b240
Add chartOptions support to deep link generation and MRI bookmark cre…
jerome-ng Jan 31, 2026
32dd577
Implement TypeaheadField component for dynamic attribute fetching and…
jerome-ng Feb 1, 2026
d657638
Enhance StepForm to prevent form submission on Enter key press and im…
jerome-ng Feb 1, 2026
fc6d4c9
Add translation for wizards in i18n default configuration
jerome-ng Feb 1, 2026
52cb969
Update WizardShell styles to set height and enable vertical scrolling
jerome-ng Feb 1, 2026
08ba800
Optimize TypeaheadField to prevent redundant fetch calls and prefetch…
jerome-ng Feb 1, 2026
902ba16
Refactor StepForm input type to text and enhance validation for numer…
jerome-ng Feb 1, 2026
074adb4
Refactor enrichField function to prioritize existing field labels; re…
jerome-ng Feb 1, 2026
9e53362
Update README.md to clarify local testing workflow and emphasize prod…
jerome-ng Feb 1, 2026
be80597
Update WIZARD_FIELDS to correct age label and add ethnicity and race …
jerome-ng Feb 2, 2026
e125917
Add measurement field to WIZARD_FIELDS and enhance mriQuery for fixed…
jerome-ng Feb 2, 2026
90c236b
Add new measurement fields to WIZARD_FIELDS and enhance mriQuery for …
jerome-ng Feb 2, 2026
bd195fc
Comment out condition fields in WIZARD_FIELDS for clarity and update …
jerome-ng Feb 2, 2026
92679ea
Refactor deep link handling to improve parameter extraction and stora…
jerome-ng Feb 2, 2026
a1819e2
Add wizards parameter handling in deep link processing and generation
jerome-ng Feb 2, 2026
8fe976f
Add title to success alert message in deep link processing
jerome-ng Feb 2, 2026
da3c066
Add yearRange field type and implement handling in StepForm and deep …
jerome-ng Feb 2, 2026
4cbc834
Add wizard-only fields to wizard definitions and update deep link gen…
jerome-ng Feb 2, 2026
238dec1
Add wizard ID handling to deep link generation
jerome-ng Feb 2, 2026
0109c68
Fix popover position handling in PatientCount component
jerome-ng Feb 2, 2026
afc47a8
feat: add wizard configuration editor and API integration
jerome-ng Feb 3, 2026
cb37067
Jerome ng/1633 wizards (#1780)
jerome-ng Feb 4, 2026
4ca1197
Jerome ng/1633 wizards (#1785)
jerome-ng Feb 5, 2026
06e0d16
Setup shinydashboards in PA
khairul-syazwan Feb 6, 2026
ce25ed5
Merge branch 'jerome-ng/1633-1653-wizards-dashboard' into khairul-sya…
khairul-syazwan Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions functions/mri-pa-config/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {
Connection,
getUser,
utils,
QueryObject as qo,
} from "@alp/alp-base-utils";

const QueryObject = qo.QueryObject;
import * as xsenv from "@sap/xsenv";
import express from "express";
import { MRIConfig } from "./config/config";
Expand Down Expand Up @@ -187,6 +190,137 @@ function initRoutes() {
res.json(configDefaultValues)
});

// Wizards config endpoints
const WIZARDS_CONFIG_ID = "wizards-config";
const WIZARDS_CONFIG_VERSION = "1";
const WIZARDS_CONFIG_TYPE = "WIZARDS";

app.get("/pa-config-svc/wizards/config", (req: IRequest, res) => {
const { db } = req.dbConnections;

const query = QueryObject.format(
`SELECT "Data" FROM "ConfigDbModels_Config" WHERE "Id" = %s AND "Version" = %s`,
WIZARDS_CONFIG_ID,
WIZARDS_CONFIG_VERSION
);

query.executeQuery(db, (err, result) => {
if (err) {
log.error("Error fetching wizards config:", err);
return res.status(500).json({ error: "Failed to fetch wizards config" });
}

if (!result || !result.data || result.data.length === 0) {
return res.status(200).json({ wizards: [] });
}

try {
const data = JSON.parse(result.data[0].Data);
return res.status(200).json(data);
} catch (parseErr) {
log.error("Error parsing wizards config:", parseErr);
return res.status(500).json({ error: "Failed to parse wizards config" });
}
});
});

app.put("/pa-config-svc/wizards/config", (req: IRequest, res) => {
const user = getUser(req);
const { db } = req.dbConnections;
const configData = req.body;

if (!configData || !configData.wizards) {
return res.status(400).json({ error: "Invalid config format. Expected { wizards: [...] }" });
}

const dataJson = JSON.stringify(configData);
const username = user.getUser();
const now = new Date();

// Check if config exists
const checkQuery = QueryObject.format(
`SELECT "Id" FROM "ConfigDbModels_Config" WHERE "Id" = %s AND "Version" = %s`,
WIZARDS_CONFIG_ID,
WIZARDS_CONFIG_VERSION
);

checkQuery.executeQuery(db, (err, result) => {
if (err) {
log.error("Error checking existing config:", err);
return res.status(500).json({ error: "Failed to check existing config" });
}

const exists = result && result.data && result.data.length > 0;

if (exists) {
const updateQuery = QueryObject.format(
`UPDATE "ConfigDbModels_Config" SET "Data" = %s, "Modifier" = %s, "Modified" = %t WHERE "Id" = %s AND "Version" = %s`,
dataJson,
username,
now,
WIZARDS_CONFIG_ID,
WIZARDS_CONFIG_VERSION
);

updateQuery.executeUpdate(db, (updateErr) => {
if (updateErr) {
log.error("Error updating wizards config:", updateErr);
return res.status(500).json({ error: "Failed to update wizards config" });
}
db.commit();
return res.status(200).json({ success: true, message: "Config updated" });
});
} else {
const insertQuery = QueryObject.format(
`INSERT INTO "ConfigDbModels_Config" ("Id", "Version", "Status", "Name", "Type", "Creator", "Created", "Modifier", "Modified", "Data") VALUES (%s, %s, %s, %s, %s, %s, %t, %s, %t, %s)`,
WIZARDS_CONFIG_ID,
WIZARDS_CONFIG_VERSION,
"A",
"Wizards Configuration",
WIZARDS_CONFIG_TYPE,
username,
now,
username,
now,
dataJson
);

insertQuery.executeUpdate(db, (insertErr) => {
if (insertErr) {
log.error("Error inserting wizards config:", insertErr);
return res.status(500).json({ error: "Failed to create wizards config" });
}
db.commit();
return res.status(201).json({ success: true, message: "Config created" });
});
}
});
});

app.delete("/pa-config-svc/wizards/config", (req: IRequest, res) => {
const { db } = req.dbConnections;

const deleteQuery = QueryObject.format(
`DELETE FROM "ConfigDbModels_Config" WHERE "Id" = %s AND "Version" = %s`,
WIZARDS_CONFIG_ID,
WIZARDS_CONFIG_VERSION
);

deleteQuery.executeUpdate(db, (err, linesEffected) => {
if (err) {
log.error("Error deleting wizards config:", err);
return res.status(500).json({ error: "Failed to delete wizards config" });
}
db.commit();

if (linesEffected === 0) {
return res.status(404).json({ error: "Config not found" });
}

return res.status(200).json({ success: true, message: "Config deleted" });
});
});

app.use((err, req, res, next) => {
if (err) {
log.enrichErrorWithRequestCorrelationID(err, req);
Expand Down
19 changes: 19 additions & 0 deletions functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,25 @@
"PAConfig.svc"
]
},
{
"path": "^/pa-config-svc/wizards/config$",
"scopes": [
"PAConfig.svc/read"
],
"httpMethods": [
"GET"
]
},
{
"path": "^/pa-config-svc/wizards/config$",
"scopes": [
"PAConfig.svc"
],
"httpMethods": [
"PUT",
"DELETE"
]
},
{
"path": "^/hc/hph/cdw/config/services/config.xsjs(.*)",
"scopes": [
Expand Down
2 changes: 1 addition & 1 deletion ui/apps/portal/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ SSL_CRT_FILE="../../.cert/local_alp_portal_public.crt"
REACT_APP_ALP_RELEASE_VERSION=v22.8-hotaka-dake

# Plugin definition. Only required when running yarn start in portal folder
REACT_APP_PLUGINS={ "researcher": [ { "enabled": true, "type": "app", "autoMount": true, "featureFlag": "conceptSets", "name": "Concepts", "nameI18nKey": "UI_PLUGIN_CONCEPTS", "pluginPath": "/resources/concept-sets/lifecycles.js", "requiredRoles": [ "RESEARCHER" ], "route": "concepts" }, { "enabled": true, "featureFlag": "cohort", "name": "Cohorts", "nameI18nKey": "UI_PLUGIN_COHORTS", "pluginPath": "plugins/mri/PatientAnalytics/module", "requiredRoles": [ "RESEARCHER" ], "route": "cohort" }, { "enabled": false, "featureFlag": "cohorts", "name": "Cohorts M", "pluginPath": "plugins/Cohort/module", "requiredRoles": [ "RESEARCHER" ], "route": "cohorts" }, { "enabled": true, "type": "app", "featureFlag": "starboard", "name": "Notebooks", "nameI18nKey": "UI_PLUGIN_NOTEBOOKS", "pluginPath": "/resources/notebook-ui/lifecycles.js", "requiredRoles": [ "RESEARCHER" ], "route": "starboard", "data": { "uiFilesUrl":"https://localhost:41100/" } }, { "enabled": true, "type": "app", "name": "Analysis", "nameI18nKey": "UI_PLUGIN_ANALYSIS", "route": "analysis", "pluginPath": "/resources/analysis-ui/lifecycles.js", "featureFlag": "strategus", "requiredRoles": [ "RESEARCHER" ] }, {"name": "Kaplan-Meier", "nameI18nKey": "UI_PLUGIN_KAPLAN_MEIER", "route": "kaplan-meier", "pluginPath": "plugins/Researcher/KaplanMeier/module", "featureFlag": "kaplanMeier", "requiredRoles": ["RESEARCHER"], "enabled": false}], "setup": [ { "description": "Database connection and credentials", "descriptionI18nKey": "UI_PLUGIN_SETUP_DB_DESCRIPTION", "enabled": true, "name": "Databases", "nameI18nKey": "UI_PLUGIN_DATABASES", "notes": "", "pluginPath": "plugins/Setup/Db/module", "route": "db" }, { "description": "Allow user to sign-in with Azure Active Directory", "enabled": false, "name": "Azure AD integration", "notes": "Notes: Require manual update of the environment variable to switch the identity provider to Azure", "pluginPath": "plugins/Setup/AzureAD/module", "route": "azure-ad" }, { "description": "Allow user to configure the git information", "descriptionI18nKey": "UI_PLUGIN_SETUP_GIT_DESCRIPTION", "enabled": true, "name": "Git configuration", "nameI18nKey": "UI_PLUGIN_GIT_CONFIG", "pluginPath": "plugins/Setup/GitConfig/module", "route": "git-config" }, { "description": "Enable / disable feature", "descriptionI18nKey": "UI_PLUGIN_SETUP_FEATURE_FLAGS_DESCRIPTION", "enabled": true, "name": "Feature flags", "nameI18nKey": "UI_PLUGIN_FEATURE_FLAGS", "pluginPath": "plugins/Setup/Feature/module", "route": "feature" }, { "description": "Configure dataset metadata and tags", "descriptionI18nKey": "UI_PLUGIN_SETUP_METADATA_DESCRIPTION", "enabled": true, "name": "Metadata", "nameI18nKey": "UI_PLUGIN_METADATA", "notes": "", "pluginPath": "plugins/Setup/Metadata/module", "route": "metadata" }, { "description": "Configure cohort builder", "descriptionI18nKey": "UI_PLUGIN_SETUP_PATIENT_ANALYTICS_DESCRIPTION", "enabled": true, "name": "Cohort Builder config", "nameI18nKey": "UI_PLUGIN_PATIENT_ANALYTICS_CONFIG", "notes": "", "pluginPath": "plugins/mri/PatientAnalyticsConfig/module", "route": "pa-config" }, { "description": "Configure CDM", "descriptionI18nKey": "UI_PLUGIN_SETUP_CDM_DESCRIPTION", "enabled": true, "name": "CDM Config", "nameI18nKey": "UI_PLUGIN_CDM_CONFIG", "notes": "", "pluginPath": "plugins/mri/CDM/module", "route": "cdm-config" }, { "description": "Configure patient summary", "enabled": false, "name": "Patient Summary Config", "notes": "", "pluginPath": "plugins/mri/PatientSummaryConfig/module", "route": "ps-config" }, { "description": "Configure overview description text", "descriptionI18nKey": "UI_PLUGIN_SETUP_OVERVIEW_DESCRIPTION", "enabled": true, "name": "Overview description", "nameI18nKey": "UI_PLUGIN_OVERVIEW_DESCRIPTION", "notes": "", "pluginPath": "plugins/Setup/OverviewDescription/module", "route": "overview-description" }, { "description": "Configure hybrid search for concepts", "descriptionI18nKey": "UI_PLUGIN_SETUP_HYBRID_SEARCH_DESCRIPTION", "enabled": true, "name": "Hybrid search", "nameI18nKey": "UI_PLUGIN_HYBRID_SEARCH", "notes": "", "pluginPath": "plugins/Setup/HybridSearch/module", "route": "hybrid-search" }, { "description": "Manage plugins", "descriptionI18nKey": "UI_PLUGIN_SETUP_PLUGINS_DESCRIPTION", "enabled": true, "name": "Plugins", "nameI18nKey": "UI_PLUGIN_PLUGINS", "notes": "", "pluginPath": "plugins/Setup/TrexPlugins/module", "route": "plugins" }, { "description": "Setting up demo dataset", "descriptionI18nKey": "UI_PLUGIN_SETUP_DEMO_DESCRIPTION", "enabled": true, "name": "Demo setup", "nameI18nKey": "UI_PLUGIN_DEMO_SETUP", "notes": "", "pluginPath": "plugins/Setup/DemoSetup/module", "route": "demo-setup" } ], "systemadmin": [ { "name": "Users", "nameI18nKey": "UI_PLUGIN_USERS", "enabled": true, "pluginPath": "plugins/SystemAdmin/UserOverview/module", "route": "user-overview" }, { "name": "Datasets", "nameI18nKey": "UI_PLUGIN_DATASETS", "enabled": true, "pluginPath": "plugins/SystemAdmin/StudyOverview/module", "route": "dataset-overview" }, { "name": "Jobs", "nameI18nKey": "UI_PLUGIN_JOBS", "enabled": true, "pluginPath": "plugins/SystemAdmin/Jobs/module", "route": "jobs" }, { "name": "ETL", "nameI18nKey": "UI_PLUGIN_ETL", "enabled": true, "route": "etl", "data": { "dnBaseUrl": "https://localhost:41100/", "mappingSuggestion": false }, "pluginPath": "/flow/module.js" }, {"name": "Studies", "nameI18nKey": "UI_PLUGIN_STUDIES", "enabled": true, "route": "study-page", "pluginPath": "plugins/SystemAdmin/StudyPage/module"}, { "name": "Setup", "nameI18nKey": "UI_PLUGIN_SETUP", "enabled": true, "pluginPath": "plugins/Setup/module", "route": "setup" }, {"enabled":true,"pluginPath":"plugins/SystemAdmin/D2ELogs/module","name":"Logs","nameI18nKey":"UI_PLUGIN_LOGS","route":"docker-logs", "featureFlag": "d2eLogs"} ] }
REACT_APP_PLUGINS={ "researcher": [ { "enabled": true, "type": "app", "autoMount": true, "featureFlag": "conceptSets", "name": "Concepts", "nameI18nKey": "UI_PLUGIN_CONCEPTS", "pluginPath": "/resources/concept-sets/lifecycles.js", "requiredRoles": [ "RESEARCHER" ], "route": "concepts" }, { "enabled": true, "featureFlag": "cohort", "name": "Cohorts", "nameI18nKey": "UI_PLUGIN_COHORTS", "pluginPath": "plugins/mri/PatientAnalytics/module", "requiredRoles": [ "RESEARCHER" ], "route": "cohort" }, { "enabled": false, "featureFlag": "cohorts", "name": "Cohorts M", "pluginPath": "plugins/Cohort/module", "requiredRoles": [ "RESEARCHER" ], "route": "cohorts" }, { "enabled": true, "type": "app", "featureFlag": "starboard", "name": "Notebooks", "nameI18nKey": "UI_PLUGIN_NOTEBOOKS", "pluginPath": "/resources/notebook-ui/lifecycles.js", "requiredRoles": [ "RESEARCHER" ], "route": "starboard", "data": { "uiFilesUrl":"https://localhost:41100/" } }, { "enabled": true, "type": "app", "name": "Analysis", "nameI18nKey": "UI_PLUGIN_ANALYSIS", "route": "analysis", "pluginPath": "/resources/analysis-ui/lifecycles.js", "featureFlag": "strategus", "requiredRoles": [ "RESEARCHER" ] }, { "enabled": false, "type": "app", "name": "Wizards", "nameI18nKey": "UI_PLUGIN_WIZARDS", "route": "wizards", "pluginPath": "/resources/wizards/lifecycles.js", "featureFlag": "wizards", "requiredRoles": [ "RESEARCHER" ] }, {"name": "Kaplan-Meier", "nameI18nKey": "UI_PLUGIN_KAPLAN_MEIER", "route": "kaplan-meier", "pluginPath": "plugins/Researcher/KaplanMeier/module", "featureFlag": "kaplanMeier", "requiredRoles": ["RESEARCHER"], "enabled": false}], "setup": [ { "description": "Database connection and credentials", "descriptionI18nKey": "UI_PLUGIN_SETUP_DB_DESCRIPTION", "enabled": true, "name": "Databases", "nameI18nKey": "UI_PLUGIN_DATABASES", "notes": "", "pluginPath": "plugins/Setup/Db/module", "route": "db" }, { "description": "Allow user to sign-in with Azure Active Directory", "enabled": false, "name": "Azure AD integration", "notes": "Notes: Require manual update of the environment variable to switch the identity provider to Azure", "pluginPath": "plugins/Setup/AzureAD/module", "route": "azure-ad" }, { "description": "Allow user to configure the git information", "descriptionI18nKey": "UI_PLUGIN_SETUP_GIT_DESCRIPTION", "enabled": true, "name": "Git configuration", "nameI18nKey": "UI_PLUGIN_GIT_CONFIG", "pluginPath": "plugins/Setup/GitConfig/module", "route": "git-config" }, { "description": "Enable / disable feature", "descriptionI18nKey": "UI_PLUGIN_SETUP_FEATURE_FLAGS_DESCRIPTION", "enabled": true, "name": "Feature flags", "nameI18nKey": "UI_PLUGIN_FEATURE_FLAGS", "pluginPath": "plugins/Setup/Feature/module", "route": "feature" }, { "description": "Configure dataset metadata and tags", "descriptionI18nKey": "UI_PLUGIN_SETUP_METADATA_DESCRIPTION", "enabled": true, "name": "Metadata", "nameI18nKey": "UI_PLUGIN_METADATA", "notes": "", "pluginPath": "plugins/Setup/Metadata/module", "route": "metadata" }, { "description": "Configure cohort builder", "descriptionI18nKey": "UI_PLUGIN_SETUP_PATIENT_ANALYTICS_DESCRIPTION", "enabled": true, "name": "Cohort Builder config", "nameI18nKey": "UI_PLUGIN_PATIENT_ANALYTICS_CONFIG", "notes": "", "pluginPath": "plugins/mri/PatientAnalyticsConfig/module", "route": "pa-config" }, { "description": "Configure CDM", "descriptionI18nKey": "UI_PLUGIN_SETUP_CDM_DESCRIPTION", "enabled": true, "name": "CDM Config", "nameI18nKey": "UI_PLUGIN_CDM_CONFIG", "notes": "", "pluginPath": "plugins/mri/CDM/module", "route": "cdm-config" }, { "description": "Configure patient summary", "enabled": false, "name": "Patient Summary Config", "notes": "", "pluginPath": "plugins/mri/PatientSummaryConfig/module", "route": "ps-config" }, { "description": "Configure overview description text", "descriptionI18nKey": "UI_PLUGIN_SETUP_OVERVIEW_DESCRIPTION", "enabled": true, "name": "Overview description", "nameI18nKey": "UI_PLUGIN_OVERVIEW_DESCRIPTION", "notes": "", "pluginPath": "plugins/Setup/OverviewDescription/module", "route": "overview-description" }, { "description": "Configure hybrid search for concepts", "descriptionI18nKey": "UI_PLUGIN_SETUP_HYBRID_SEARCH_DESCRIPTION", "enabled": true, "name": "Hybrid search", "nameI18nKey": "UI_PLUGIN_HYBRID_SEARCH", "notes": "", "pluginPath": "plugins/Setup/HybridSearch/module", "route": "hybrid-search" }, { "description": "Manage plugins", "descriptionI18nKey": "UI_PLUGIN_SETUP_PLUGINS_DESCRIPTION", "enabled": true, "name": "Plugins", "nameI18nKey": "UI_PLUGIN_PLUGINS", "notes": "", "pluginPath": "plugins/Setup/TrexPlugins/module", "route": "plugins" }, { "description": "Setting up demo dataset", "descriptionI18nKey": "UI_PLUGIN_SETUP_DEMO_DESCRIPTION", "enabled": true, "name": "Demo setup", "nameI18nKey": "UI_PLUGIN_DEMO_SETUP", "notes": "", "pluginPath": "plugins/Setup/DemoSetup/module", "route": "demo-setup" } ], "systemadmin": [ { "name": "Users", "nameI18nKey": "UI_PLUGIN_USERS", "enabled": true, "pluginPath": "plugins/SystemAdmin/UserOverview/module", "route": "user-overview" }, { "name": "Datasets", "nameI18nKey": "UI_PLUGIN_DATASETS", "enabled": true, "pluginPath": "plugins/SystemAdmin/StudyOverview/module", "route": "dataset-overview" }, { "name": "Jobs", "nameI18nKey": "UI_PLUGIN_JOBS", "enabled": true, "pluginPath": "plugins/SystemAdmin/Jobs/module", "route": "jobs" }, { "name": "ETL", "nameI18nKey": "UI_PLUGIN_ETL", "enabled": true, "route": "etl", "data": { "dnBaseUrl": "https://localhost:41100/", "mappingSuggestion": false }, "pluginPath": "/flow/module.js" }, {"name": "Studies", "nameI18nKey": "UI_PLUGIN_STUDIES", "enabled": true, "route": "study-page", "pluginPath": "plugins/SystemAdmin/StudyPage/module"}, { "name": "Setup", "nameI18nKey": "UI_PLUGIN_SETUP", "enabled": true, "pluginPath": "plugins/Setup/module", "route": "setup" }, {"enabled":true,"pluginPath":"plugins/SystemAdmin/D2ELogs/module","name":"Logs","nameI18nKey":"UI_PLUGIN_LOGS","route":"docker-logs", "featureFlag": "d2eLogs"} ] }

USE_PUBLIC_WEBAPI_PROXY=false
PUBLIC_WEBAPI_PROXY_URL=http://localhost:3001
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ describe("Researcher - Deep Link Integration", () => {
expect(feedback?.message).toBe("Unable to Open Dataset");
});

it("should route to /cohort when route=cohort and pass PA params", () => {
// Setup: URL with route=cohort and PA params (linkType, query)
it("should route to /information with all non-datasetId query params when no path stored", () => {
// Setup: URL with query params but no stored path
(window as any).location = {
href: "http://localhost:3000/researcher?datasetId=dataset-2&route=cohort&linkType=cohort-definition&query=abc",
};
Expand All @@ -228,8 +228,8 @@ describe("Researcher - Deep Link Integration", () => {
// Verify correct dataset was set
expect(result.current.activeDataset.activeDataset.id).toBe("dataset-2");

// Verify navigation routes to /cohort with only PA params (not datasetId/route)
expect(mockNavigate).toHaveBeenCalledWith("/researcher/cohort?linkType=cohort-definition&query=abc", {
// Without a stored path, defaults to /information with all non-datasetId params
expect(mockNavigate).toHaveBeenCalledWith("/researcher/information?route=cohort&linkType=cohort-definition&query=abc", {
state: { tenantId: "t1" },
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,7 @@ export const i18nDefault = {
UI_PLUGIN_SETUP_PATIENT_ANALYTICS_DESCRIPTION: "Configure cohort builder",
UI_PLUGIN_SETUP_PLUGINS_DESCRIPTION: "Manage plugins",
UI_PLUGIN_SETUP_GIT_DESCRIPTION: "Allow user to configure the git information",
UI_PLUGIN_WIZARDS: "Wizards",
UPDATE_SCHEMA_DIALOG__CANCEL: "Cancel",
UPDATE_SCHEMA_DIALOG__CONFIRM: "Are you sure you want to update the schema of this dataset:",
UPDATE_SCHEMA_DIALOG__ERROR: "Schema for dataset {0} failed to update",
Expand Down
2 changes: 2 additions & 0 deletions ui/apps/portal/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import "import-map-overrides";

// Save deep link params BEFORE any redirects happen
// This must run synchronously before React initializes
// Only whitelisted paths (/researcher/cohort, /researcher/wizards) will have params extracted
// New params always replace existing ones
try {
const params = extractDeepLinkParamsFromUrl(window.location.href);
if (Object.keys(params).length > 0) {
Expand Down
Loading
Loading