diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/OrgUnitField/useSearchScopeWithFallback.ts b/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/OrgUnitField/useSearchScopeWithFallback.ts index 679946ab8c..ee70ea1d9f 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/OrgUnitField/useSearchScopeWithFallback.ts +++ b/src/core_modules/capture-core/components/WidgetEnrollment/TransferModal/OrgUnitField/useSearchScopeWithFallback.ts @@ -1,18 +1,36 @@ -import { useMemo } from 'react'; import { useApiMetadataQuery } from '../../../../utils/reactQueryHelpers'; -import { CurrentUser } from '../../../../utils/userInfo/CurrentUser'; type Props = { searchText?: string; }; +type OrgUnit = { id: string; path: string }; +type MeOrgUnitScope = { + teiSearchOrganisationUnits: Array; + organisationUnits: Array; +}; +type OrgUnitsResponse = { organisationUnits: Array }; + export const useSearchScopeWithFallback = ({ searchText }: Props) => { - const orgUnitRootsFromUser = useMemo(() => { - const { teiSearchOrganisationUnits, organisationUnits } = CurrentUser.get(); - return teiSearchOrganisationUnits.length ? teiSearchOrganisationUnits : organisationUnits; - }, []); + const { data: orgUnitRoots, isInitialLoading } = useApiMetadataQuery>( + ['organisationUnits', 'userOrgUnitScope'], + { + resource: 'me', + params: { + fields: 'teiSearchOrganisationUnits[id,path],organisationUnits[id,path]', + }, + }, + { + enabled: !searchText, + select: ({ teiSearchOrganisationUnits, organisationUnits }) => + (teiSearchOrganisationUnits.length ? teiSearchOrganisationUnits : organisationUnits), + }, + ); - const { data: searchOrgUnits, isInitialLoading: isInitialLoadingSearch } = useApiMetadataQuery( + const { + data: searchOrgUnits, + isInitialLoading: isInitialLoadingSearch, + } = useApiMetadataQuery>( ['organisationUnits', 'userOrgUnitScope', 'search', searchText], { resource: 'organisationUnits', @@ -27,15 +45,12 @@ export const useSearchScopeWithFallback = ({ searchText }: Props) => { { enabled: Boolean(searchText), cacheTime: 120 * 60 * 1000, - select: (data) => { - const { organisationUnits } = data as any; - return organisationUnits; - }, + select: ({ organisationUnits }) => organisationUnits, }, ); return { - orgUnitRoots: searchText?.length ? searchOrgUnits : orgUnitRootsFromUser, - isLoading: searchText?.length ? isInitialLoadingSearch : false, + orgUnitRoots: searchText?.length ? searchOrgUnits : orgUnitRoots, + isLoading: searchText?.length ? isInitialLoadingSearch : isInitialLoading, }; }; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.container.tsx b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.container.tsx index b12329ae40..0dc21430ee 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.container.tsx +++ b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.container.tsx @@ -6,14 +6,14 @@ import { useOrgUnitNameWithAncestors } from '../../metadataRetrieval/orgUnitName import { useTrackedEntities } from './hooks/useTrackedEntities'; import { useEnrollment } from './hooks/useEnrollment'; import { useProgram } from './hooks/useProgram'; -import { CurrentUser } from '../../utils/userInfo/CurrentUser'; +import { useUserLocale } from '../../utils/localeData/useUserLocale'; import type { Props } from './enrollment.types'; import { plainStatus } from './constants/status.const'; -const useError = (errorEnrollment: any, errorProgram: any, errorOwnerOrgUnit: any, errorOrgUnit: any) => +const useError = (errorEnrollment: any, errorProgram: any, errorOwnerOrgUnit: any, errorOrgUnit: any, errorLocale: any) => useMemo( - () => errorEnrollment ?? errorProgram ?? errorOwnerOrgUnit ?? errorOrgUnit, - [errorEnrollment, errorProgram, errorOwnerOrgUnit, errorOrgUnit], + () => errorEnrollment ?? errorProgram ?? errorOwnerOrgUnit ?? errorOrgUnit ?? errorLocale, + [errorEnrollment, errorProgram, errorOwnerOrgUnit, errorOrgUnit, errorLocale], ); const useContainsAutoGeneratedEvent = (program: any) => @@ -73,10 +73,10 @@ export const WidgetEnrollment = ({ const { error: errorOrgUnit, displayName } = useOrgUnitNameWithAncestors( typeof ownerOrgUnit === 'string' ? ownerOrgUnit : undefined, ); - const locale = CurrentUser.get().uiLocale; + const { error: errorLocale, locale } = useUserLocale(); const canAddNew = useCanAddNew(enrollments, programId, program?.trackedEntityType.access); const containsAutoGeneratedEvent = useContainsAutoGeneratedEvent(program); - const error = useError(errorEnrollment, errorProgram, errorOwnerOrgUnit, errorOrgUnit); + const error = useError(errorEnrollment, errorProgram, errorOwnerOrgUnit, errorOrgUnit, errorLocale); const events = useEnrollmentEvents(externalData); if (error) { diff --git a/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.tsx b/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.tsx index 70a3c6c444..e4b5cc05df 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.tsx +++ b/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.tsx @@ -15,9 +15,9 @@ import { useProgram, useTrackedEntityInstances, useClientAttributesWithSubvalues, + useUserRoles, useTeiDisplayName, } from './hooks'; -import { CurrentUser } from '../../utils/userInfo/CurrentUser'; import { DataEntry, dataEntryActionTypes, TEI_MODAL_STATE, convertClientToView } from './DataEntry'; import { ReactQueryAppNamespace } from '../../utils/reactQueryHelpers'; import { CHANGELOG_ENTITY_TYPES } from '../WidgetsChangelog'; @@ -57,13 +57,15 @@ const showEditModal = (loading: boolean, error: any, showEdit: boolean, modalSta const computeLoadingState = ( programsLoading: boolean, trackedEntityInstancesLoading: boolean, + userRolesLoading: boolean, configIsFetched: boolean, -) => programsLoading || trackedEntityInstancesLoading || !configIsFetched; +) => programsLoading || trackedEntityInstancesLoading || userRolesLoading || !configIsFetched; const computeError = ( programsError: any, trackedEntityInstancesError: any, -) => programsError || trackedEntityInstancesError; + userRolesError: any, +) => programsError || trackedEntityInstancesError || userRolesError; const WidgetProfilePlain = ({ teiId, @@ -96,8 +98,12 @@ const WidgetProfilePlain = ({ programWriteAccess, trackedEntityTypeWriteAccess, } = useEnrollmentAccessContext(); + const { + loading: userRolesLoading, + error: userRolesError, + userRoles, + } = useUserRoles(); const trackedEntityTypeName = program?.trackedEntityType?.displayName; - const userRoles = CurrentUser.get().userRoles; const hasNoAttributes = !program?.programTrackedEntityAttributes?.length; @@ -113,8 +119,8 @@ const WidgetProfilePlain = ({ return null; }, [isEditable, readOnlyMode, hasNoAttributes]); - const loading = computeLoadingState(programsLoading, trackedEntityInstancesLoading, configIsFetched); - const error = computeError(programsError, trackedEntityInstancesError); + const loading = computeLoadingState(programsLoading, trackedEntityInstancesLoading, userRolesLoading, configIsFetched); + const error = computeError(programsError, trackedEntityInstancesError, userRolesError); const clientAttributesWithSubvalues = useClientAttributesWithSubvalues( teiId, program as any, diff --git a/src/core_modules/capture-core/components/WidgetProfile/hooks/index.ts b/src/core_modules/capture-core/components/WidgetProfile/hooks/index.ts index d5fc613397..9796657555 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/hooks/index.ts +++ b/src/core_modules/capture-core/components/WidgetProfile/hooks/index.ts @@ -1,4 +1,5 @@ export { useProgram } from './useProgram'; export { useTrackedEntityInstances } from './useTrackedEntityInstances'; export { useClientAttributesWithSubvalues } from './useClientAttributesWithSubvalues'; +export { useUserRoles } from './useUserRoles'; export { useTeiDisplayName } from './useTeiDisplayName'; diff --git a/src/core_modules/capture-core/components/WidgetProfile/hooks/useUserRoles.ts b/src/core_modules/capture-core/components/WidgetProfile/hooks/useUserRoles.ts new file mode 100644 index 0000000000..4a5e9d10f3 --- /dev/null +++ b/src/core_modules/capture-core/components/WidgetProfile/hooks/useUserRoles.ts @@ -0,0 +1,36 @@ +import { useMemo } from 'react'; +import { useDataQuery } from '@dhis2/app-runtime'; + +const fields = 'userCredentials[userRoles]'; + +export const useUserRoles = () => { + const { error, loading, data } = useDataQuery( + useMemo( + () => ({ + userData: { + resource: 'me.json', + params: { + fields, + }, + }, + }), + [], + ), + ); + + const userRoles = useMemo( + () => { + if (!loading && data?.userData) { + const userData = data.userData as { + userCredentials?: { + userRoles?: Array<{ id: string }> + } + }; + return userData.userCredentials?.userRoles?.map(({ id }) => id) ?? []; + } + return []; + }, + [loading, data], + ); + return { error, loading, userRoles }; +}; diff --git a/src/core_modules/capture-core/utils/localeData/useUserLocale.ts b/src/core_modules/capture-core/utils/localeData/useUserLocale.ts new file mode 100644 index 0000000000..902fcc507a --- /dev/null +++ b/src/core_modules/capture-core/utils/localeData/useUserLocale.ts @@ -0,0 +1,29 @@ +import { useDataEngine } from '@dhis2/app-runtime'; +import { useQuery } from '@tanstack/react-query'; + +export const useUserLocale = (): { + locale: any; + isLoading: boolean; + isError: boolean; + error: unknown; +} => { + const dataEngine = useDataEngine(); + + const { data, isInitialLoading, isError, error } = useQuery( + ['userLocale'], + () => dataEngine.query({ + userSettings: { + resource: 'me', + params: { + fields: 'settings[keyUiLocale]', + }, + }, + })); + + return { + locale: (data as any)?.userSettings?.settings?.keyUiLocale, + isLoading: isInitialLoading, + isError, + error, + }; +};