11import React from 'react' ;
22import PropTypes from 'prop-types' ;
33import ImmutablePropTypes from 'react-immutable-proptypes' ;
4- import { FormattedMessage } from 'react-intl' ;
4+ import { FormattedMessage , injectIntl } from 'react-intl' ;
55import { lruMemoize } from 'reselect' ;
66import { Link } from 'react-router-dom' ;
77
@@ -16,6 +16,7 @@ import { isSupervisorRole, isEmpoweredSupervisorRole, isSuperadminRole } from '.
1616import withLinks from '../../../helpers/withLinks.js' ;
1717import { getExternalIdForCAS } from '../../../helpers/cas.js' ;
1818import { getConfigVar } from '../../../helpers/config.js' ;
19+ import { EMPTY_ARRAY } from '../../../helpers/common.js' ;
1920import Admin from './Admin.js' ;
2021
2122import './sidebar.css' ;
@@ -24,12 +25,45 @@ const URL_PREFIX = getConfigVar('URL_PATH_PREFIX');
2425
2526const getUserData = lruMemoize ( user => getJsData ( user ) ) ;
2627
28+ const processInstances = lruMemoize ( instances =>
29+ instances && instances . size > 0 ? instances . toArray ( ) . filter ( isReady ) . map ( getJsData ) : EMPTY_ARRAY
30+ ) ;
31+
32+ const _getCaption = ( caption , locale ) =>
33+ typeof caption === 'string'
34+ ? caption
35+ : caption && typeof caption === 'object'
36+ ? caption [ locale ] || caption . en || caption [ Object . keys ( caption ) [ 0 ] ]
37+ : '??' ;
38+
39+ const getExtensions = lruMemoize ( ( instances , locale ) => {
40+ const exts = [ ] ;
41+ processInstances ( instances ) . forEach ( ( { id, extensions = { } } ) =>
42+ Object . keys ( extensions ) . forEach ( extension =>
43+ exts . push ( { extension, caption : _getCaption ( extensions [ extension ] , locale ) , instance : id } )
44+ )
45+ ) ;
46+ exts . sort ( ( a , b ) => a . caption . localeCompare ( b . caption ) ) ;
47+ return exts ;
48+ } ) ;
49+
50+ const extensionClickHandler = lruMemoize ( fetchExtensionUrl => ev => {
51+ ev . preventDefault ( ) ;
52+ if ( window ) {
53+ const extension = ev . currentTarget . dataset . extension ;
54+ const instance = ev . currentTarget . dataset . instance ;
55+ const locale = ev . currentTarget . dataset . locale ;
56+ fetchExtensionUrl ( extension , instance , locale ) . then ( ( { value : url } ) => window . location . assign ( url ) ) ;
57+ }
58+ } ) ;
59+
2760const Sidebar = ( {
2861 pendingFetchOperations,
2962 loggedInUser,
3063 effectiveRole = null ,
3164 currentUrl,
3265 instances,
66+ fetchExtensionUrl,
3367 links : {
3468 HOME_URI ,
3569 FAQ_URL ,
@@ -42,6 +76,7 @@ const Sidebar = ({
4276 ARCHIVE_URI ,
4377 SIS_INTEGRATION_URI ,
4478 } ,
79+ intl : { locale } ,
4580} ) => {
4681 const user = getUserData ( loggedInUser ) ;
4782
@@ -120,21 +155,15 @@ const Sidebar = ({
120155 link = { DASHBOARD_URI }
121156 />
122157
123- { instances &&
124- instances . size > 0 &&
125- instances
126- . toArray ( )
127- . filter ( isReady )
128- . map ( getJsData )
129- . map ( ( { id, name } ) => (
130- < MenuItem
131- key = { id }
132- title = { name }
133- icon = "university"
134- currentPath = { currentUrl }
135- link = { INSTANCE_URI_FACTORY ( id ) }
136- />
137- ) ) }
158+ { processInstances ( instances ) . map ( ( { id, name } ) => (
159+ < MenuItem
160+ key = { id }
161+ title = { name }
162+ icon = "university"
163+ currentPath = { currentUrl }
164+ link = { INSTANCE_URI_FACTORY ( id ) }
165+ />
166+ ) ) }
138167
139168 { isSupervisorRole ( effectiveRole ) && (
140169 < MenuItem
@@ -181,6 +210,26 @@ const Sidebar = ({
181210 ) }
182211
183212 { isSuperadminRole ( effectiveRole ) && < Admin currentUrl = { currentUrl } /> }
213+
214+ { getExtensions ( instances , locale ) . length > 0 && (
215+ < ul
216+ className = "nav nav-pills sidebar-menu flex-column"
217+ data-lte-toggle = "treeview"
218+ role = "menu"
219+ data-accordion = "false" >
220+ < MenuTitle title = { < FormattedMessage id = "app.sidebar.menu.extensions" defaultMessage = "Extensions" /> } />
221+
222+ { getExtensions ( instances , locale ) . map ( ( { extension, caption, instance } ) => (
223+ < MenuItem
224+ key = { extension }
225+ title = { caption }
226+ icon = "share-from-square"
227+ linkData = { { extension, instance, locale } }
228+ onClick = { extensionClickHandler ( fetchExtensionUrl ) }
229+ />
230+ ) ) }
231+ </ ul >
232+ ) }
184233 </ nav >
185234 </ div >
186235 </ div >
@@ -194,7 +243,9 @@ Sidebar.propTypes = {
194243 effectiveRole : PropTypes . string ,
195244 currentUrl : PropTypes . string ,
196245 instances : ImmutablePropTypes . list ,
246+ fetchExtensionUrl : PropTypes . func . isRequired ,
197247 links : PropTypes . object ,
248+ intl : PropTypes . shape ( { locale : PropTypes . string . isRequired } ) . isRequired ,
198249} ;
199250
200- export default withLinks ( Sidebar ) ;
251+ export default withLinks ( injectIntl ( Sidebar ) ) ;
0 commit comments