From b0f9ac09567b845c2974c155cd2a6d68e990cf61 Mon Sep 17 00:00:00 2001 From: Joakim Melseth Date: Thu, 30 Jul 2026 07:27:37 +0000 Subject: [PATCH] feat: filter out non-accessible TEAs --- i18n/en.pot | 4 +- .../WidgetProfile/hooks/useApiProgram.ts | 3 +- .../WidgetProfile/hooks/useProgram.ts | 81 ++++++++++++++----- 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index d04cbca43f..05aecc49dc 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2026-07-21T13:35:51.419Z\n" -"PO-Revision-Date: 2026-07-21T13:35:51.419Z\n" +"POT-Creation-Date: 2026-07-30T07:27:38.193Z\n" +"PO-Revision-Date: 2026-07-30T07:27:38.193Z\n" msgid "The application could not be loaded." msgstr "The application could not be loaded." diff --git a/src/core_modules/capture-core/components/WidgetProfile/hooks/useApiProgram.ts b/src/core_modules/capture-core/components/WidgetProfile/hooks/useApiProgram.ts index ada6c9dde0..690531aa5b 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/hooks/useApiProgram.ts +++ b/src/core_modules/capture-core/components/WidgetProfile/hooks/useApiProgram.ts @@ -21,7 +21,8 @@ const fields = 'options[id,displayName,code,style, translations]]]]],' + 'programTrackedEntityAttributes[trackedEntityAttribute[id,displayName,displayShortName,displayFormName,' + 'displayDescription,valueType,optionSetValue,unique,orgunitScope,pattern,translations[property,locale,value],' + - 'optionSet[id,displayName,version,valueType,options[id,displayName,name,code,style,translations]]],' + + 'optionSet[id,displayName,version,valueType,options[id,displayName,name,code,style,translations]],' + + 'access[read]],' + 'displayInList,searchable,mandatory,renderOptionsAsRadio,allowFutureDate],' + 'trackedEntityType[id,access,displayName,allowAuditLog,minAttributesRequiredToSearch,featureType,' + 'trackedEntityTypeAttributes[trackedEntityAttribute[id],displayInList,mandatory,searchable],' + diff --git a/src/core_modules/capture-core/components/WidgetProfile/hooks/useProgram.ts b/src/core_modules/capture-core/components/WidgetProfile/hooks/useProgram.ts index 6a3d9ac2d9..d35bbfaba4 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/hooks/useProgram.ts +++ b/src/core_modules/capture-core/components/WidgetProfile/hooks/useProgram.ts @@ -2,10 +2,30 @@ import { useMemo } from 'react'; import { useApiProgram } from './useApiProgram'; import { useOptionGroups } from './useOptionGroups'; -type ProgramType = { - trackedEntityType?: { - allowAuditLog?: boolean; - changelogEnabled?: boolean; +type ApiProgram = { + trackedEntityType: { + allowAuditLog: boolean; + [key: string]: any; + }; + programTrackedEntityAttributes: Array<{ + trackedEntityAttribute: { + optionSet?: { + id: string; + [key: string]: any; + }; + access: { + read: boolean + }; + [key: string]: any; + }; + [key: string]: any; + }>; + [key: string]: any; +}; + +type Program = { + trackedEntityType: { + changelogEnabled: boolean; [key: string]: any; }; programTrackedEntityAttributes: Array<{ @@ -21,26 +41,49 @@ type ProgramType = { [key: string]: any; }; + export const useProgram = (programId: string) => { const { error: programError, loading: programLoading, program } = useApiProgram(programId); const { error: optionGroupsError, loading: optionGroupsLoading, optionGroups } = useOptionGroups(program); - const programMetadata = useMemo(() => { + const programMetadata: Program | null = useMemo(() => { if (program && optionGroups) { - const typedProgram = program as ProgramType; - if (typedProgram.trackedEntityType) { - typedProgram.trackedEntityType.changelogEnabled = typedProgram.trackedEntityType.allowAuditLog; - delete typedProgram.trackedEntityType.allowAuditLog; - } - typedProgram.programTrackedEntityAttributes = typedProgram.programTrackedEntityAttributes.map( - (attribute: any) => { - const tea = attribute.trackedEntityAttribute; - if (tea.optionSet) { - tea.optionSet.optionGroups = optionGroups[tea.optionSet.id]; - } - return attribute; - }); - return typedProgram; + const apiProgram = program as ApiProgram; + const { allowAuditLog, ...restTrackedEntityType } = apiProgram.trackedEntityType; + + return { + ...apiProgram, + trackedEntityType: { + ...restTrackedEntityType, + changelogEnabled: allowAuditLog, + }, + programTrackedEntityAttributes: apiProgram.programTrackedEntityAttributes + .filter(programTrackedEntityAttribute => + programTrackedEntityAttribute.trackedEntityAttribute.access.read) + .map((programTrackedEntityAttribute) => { + const { access: _, ...restTrackedEntityAttribute } = + programTrackedEntityAttribute.trackedEntityAttribute; + + if (restTrackedEntityAttribute.optionSet) { + const originalOptionSet = restTrackedEntityAttribute.optionSet; + const optionSet = { + ...originalOptionSet, + optionGroups: optionGroups[originalOptionSet.id], + }; + return { + ...programTrackedEntityAttribute, + trackedEntityAttribute: { + ...restTrackedEntityAttribute, + optionSet, + }, + }; + } + return { + ...programTrackedEntityAttribute, + trackedEntityAttribute: restTrackedEntityAttribute, + }; + }), + }; } return null; }, [program, optionGroups]);