Skip to content

Conversation

@eperedo
Copy link
Contributor

@eperedo eperedo commented Dec 8, 2025

📌 References

📝 Implementation

  • Add new DataSet configuration page (list, create, edit and delete dataSet Configurations)
  • Only show dataSets configured according current user (super admin has access to everything)
  • Restrict actions to users and userGroups configured per dataSet
  • Apply custom logic to submit and complete/revoke and incomplete a dataSet
  • Update org. unit selector to avoid showing org. units that are not assigned to the dataSet selected.

📹 Screenshots/Screen capture

List dataSet configurations

image

Create/Edit dataSet configuration Form

image

Delete a dataSet configuration

image

🔥 Notes to the tester

  • I've created the configuration for NHWA dataSet (attached metadata and dataStore files on issue)
  • Configuration will be saved in dataStore under the key dataset-approval

#869bd706j

@eperedo eperedo requested a review from Ramon-Jimenez December 8, 2025 20:19
@eperedo eperedo marked this pull request as ready for review December 18, 2025 01:40
Copilot AI review requested due to automatic review settings December 18, 2025 01:40
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a comprehensive DataSet configuration system that allows administrators to manage dataset approval workflows through a UI. The implementation replaces hardcoded configuration files with a dynamic dataStore-based solution.

Key changes:

  • Introduces DataSet configuration management (CRUD operations) accessible only to super admins
  • Implements granular permission system for dataset actions (read, complete, incomplete, revoke, submit, approve) based on users and user groups
  • Adds custom workflow logic for submit/complete and revoke/incomplete actions
  • Migrates from static configuration files to dynamic dataStore-based configuration

Reviewed changes

Copilot reviewed 71 out of 73 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
yarn.lock, package.json Updates react-router-dom to 6.30.2, adds real-cancellable-promise and typed-immutable-map dependencies
src/domain/entities/DataSetConfiguration.ts New entity representing dataset configuration with validation and permission checking logic
src/domain/usecases/GetApprovalConfigurationsUseCase.ts Use case to retrieve dataset configurations with permissions for current user
src/data/DataSetConfigurationD2Repository.ts Repository implementation for storing/retrieving configurations from dataStore
src/webapp/pages/*.tsx New pages for managing dataset configurations (list, add, edit)
src/webapp/components/dataset-config/*.tsx UI components for dataset configuration table and form
src/data/common/Dhis2ConfigRepository.ts Removes hardcoded approval settings, simplifies configuration loading
src/domain/reports/mal-data-approval/usecases/*.ts Updates use cases to use dynamic configurations instead of static settings
src/data/reports/mal-data-approval/MalDataApprovalDefaultRepository.ts Refactors to use dataSet configurations for approval operations
src/webapp/reports/Reports.tsx Adds routing for dataset settings pages with loader pattern

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 50 to 55
return new User({
id: d2User.id,
name: d2User.displayName,
userGroups: d2User.userGroups,
...d2User.userCredentials,
isSuperAdmin: true,
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hard-coded value 'true' should be replaced with a proper check for whether the user is a super admin. Currently, all users will be marked as super admin.

Suggested change
return new User({
id: d2User.id,
name: d2User.displayName,
userGroups: d2User.userGroups,
...d2User.userCredentials,
isSuperAdmin: true,
const isSuperAdmin =
!!d2User.userCredentials &&
Array.isArray(d2User.userCredentials.userRoles) &&
d2User.userCredentials.userRoles.some(
role => Array.isArray(role.authorities) && role.authorities.includes("ALL")
);
return new User({
id: d2User.id,
name: d2User.displayName,
userGroups: d2User.userGroups,
...d2User.userCredentials,
isSuperAdmin,

Copilot uses AI. Check for mistakes.
organisationUnits: { id: true },
},
filter: { code: { in: dataSetCodes } },
filter: { code: { in: [] } },
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filter with an empty array filter: { code: { in: [] } } will always return no results. This appears to be a placeholder that should either use the malDataSetCodes or be removed if dataSets are now configured differently.

Suggested change
filter: { code: { in: [] } },
filter: { code: { in: malDataSetCodes } },

Copilot uses AI. Check for mistakes.
Comment on lines 769 to 771
// const settings = await this.getSettingByDataSet([originalDataSetId]);
// const dataSetSettings = settings.find(setting => setting.dataSetId === originalDataSetId);
// if (!dataSetSettings) throw new Error(`Data set settings not found: ${originalDataSetId}`);
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented-out code should be removed rather than left in the codebase. If this logic is no longer needed, it should be deleted to improve code cleanliness.

Suggested change
// const settings = await this.getSettingByDataSet([originalDataSetId]);
// const dataSetSettings = settings.find(setting => setting.dataSetId === originalDataSetId);
// if (!dataSetSettings) throw new Error(`Data set settings not found: ${originalDataSetId}`);

Copilot uses AI. Check for mistakes.
): Promise<boolean> {
try {
const { approvalDataSetId, dataSetId } = await this.getApprovalDataSetId(dataValues);
// const { approvalDataSetId } = await this.getApprovalDataSetId(dataValues);
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented-out code should be removed rather than left in the codebase. This appears to be old logic that has been replaced.

Suggested change
// const { approvalDataSetId } = await this.getApprovalDataSetId(dataValues);

Copilot uses AI. Check for mistakes.
import { promiseMap } from "../utils/promises";
import { WmrDiffReport } from "../domain/reports/WmrDiffReport";
import { AppSettingsD2Repository } from "../data/AppSettingsD2Repository";
import { dataSetApprovalName, WmrDiffReport } from "../domain/reports/WmrDiffReport";
Copy link

Copilot AI Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import dataSetApprovalName.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants