@@ -11,6 +11,13 @@ interface UseScopeListDataParams {
1111 org : string ;
1212}
1313
14+ const groupByOrg = ( acc : Record < string , Scope [ ] > , scope : Scope ) : Record < string , Scope [ ] > => {
15+ const orgSlug = scope . org ! . shortName ;
16+ if ( ! acc [ orgSlug ] ) { acc [ orgSlug ] = [ ] ; }
17+ acc [ orgSlug ] . push ( scope ) ;
18+ return acc ;
19+ } ;
20+
1421const useScopeListData = ( { contextType, search, org } : UseScopeListDataParams ) => {
1522 const intl = useIntl ( ) ;
1623 const {
@@ -36,16 +43,14 @@ const useScopeListData = ({ contextType, search, org }: UseScopeListDataParams)
3643
3744 const totalCount = scopesData ?. pages [ 0 ] ?. count ?? 0 ;
3845
39- const scopesByOrg = useMemo ( ( ) => allScopes
40- . filter ( ( s : Scope ) => ! ! s . org )
41- . reduce < Record < string , Scope [ ] > > ( ( acc , scope : Scope ) => {
42- const orgSlug = scope . org ! . shortName ;
43- if ( ! acc [ orgSlug ] ) { acc [ orgSlug ] = [ ] ; }
44- acc [ orgSlug ] . push ( scope ) ;
45- return acc ;
46- } , { } ) , [ allScopes ] ) ;
46+ const scopesByOrg = useMemo (
47+ ( ) => allScopes
48+ . filter ( ( s : Scope ) => ! ! s . org )
49+ . reduce < Record < string , Scope [ ] > > ( groupByOrg , { } ) ,
50+ [ allScopes ] ,
51+ ) ;
4752
48- const orderedOrgs = useMemo ( ( ) => Object . keys ( scopesByOrg ) , [ scopesByOrg ] ) ;
53+ const orderedOrgs = useMemo ( ( ) => Object . keys ( scopesByOrg ) . sort ( ) , [ scopesByOrg ] ) ;
4954
5055 const aggregateDescription = contextType === 'course'
5156 ? intl . formatMessage ( messages [ 'wizard.step2.scope.aggregate.description.course' ] )
@@ -55,9 +60,16 @@ const useScopeListData = ({ contextType, search, org }: UseScopeListDataParams)
5560 ? intl . formatMessage ( messages [ 'wizard.step2.scope.aggregate.platform.label.course' ] )
5661 : intl . formatMessage ( messages [ 'wizard.step2.scope.aggregate.platform.label.library' ] ) ;
5762
58- // Only show platform aggregate and org aggregates for administrators
59- const user = getAuthenticatedUser ( ) ;
60- const isPlatformAdmin = user ?. administrator === true ;
63+ const orgAggregateLabel = contextType === 'course'
64+ ? intl . formatMessage ( messages [ 'wizard.step2.scopeList.aggregate.label.course' ] )
65+ : intl . formatMessage ( messages [ 'wizard.step2.scopeList.aggregate.label.library' ] ) ;
66+
67+ // Only show platform aggregate and org aggregates for administrators.
68+ // getAuthenticatedUser() is stable for the lifetime of a session (no hot user-switching).
69+ const isPlatformAdmin = useMemo (
70+ ( ) => getAuthenticatedUser ( ) ?. administrator === true ,
71+ [ ] ,
72+ ) ;
6173
6274 const platformAggregateScopeItem : Scope | null = ( contextType && isPlatformAdmin )
6375 ? {
@@ -68,9 +80,23 @@ const useScopeListData = ({ contextType, search, org }: UseScopeListDataParams)
6880 }
6981 : null ;
7082
71- // Also control whether org aggregates are shown - only for admins
7283 const showOrgAggregates = isPlatformAdmin ;
7384
85+ const orgAggregateScopeItems = useMemo < Record < string , Scope > > ( ( ) => {
86+ if ( ! contextType || ! showOrgAggregates ) { return { } ; }
87+ return Object . fromEntries (
88+ orderedOrgs . map ( ( orgSlug ) => [
89+ orgSlug ,
90+ {
91+ externalKey : contextType === 'course' ? `course-v1:${ orgSlug } +*` : `lib:${ orgSlug } :*` ,
92+ displayName : orgAggregateLabel ,
93+ description : aggregateDescription ,
94+ org : { id : '0' , name : orgSlug , shortName : orgSlug } ,
95+ } satisfies Scope ,
96+ ] ) ,
97+ ) ;
98+ } , [ orderedOrgs , contextType , showOrgAggregates , orgAggregateLabel , aggregateDescription ] ) ;
99+
74100 return {
75101 organizations,
76102 orderedOrgs,
@@ -82,6 +108,7 @@ const useScopeListData = ({ contextType, search, org }: UseScopeListDataParams)
82108 } ,
83109 platformAggregateScopeItem,
84110 showOrgAggregates,
111+ orgAggregateScopeItems,
85112 } ;
86113} ;
87114
0 commit comments