diff --git a/src/components/ContextProvider.tsx b/src/components/ContextProvider.tsx index 270af2dc1..e5487d406 100644 --- a/src/components/ContextProvider.tsx +++ b/src/components/ContextProvider.tsx @@ -17,7 +17,7 @@ export interface ContextProviderProps extends React.Props { role: string; library?: string; }[]; - featureFlags?: FeatureFlags; + featureFlags: FeatureFlags; } /** Provides a redux store, configuration options, and a function to create URLs @@ -81,6 +81,7 @@ export default class ContextProvider extends React.Component< showCircEventsDownload: PropTypes.bool.isRequired, settingUp: PropTypes.bool.isRequired, admin: PropTypes.object.isRequired, + featureFlags: PropTypes.object.isRequired, }; getChildContext() { @@ -90,6 +91,7 @@ export default class ContextProvider extends React.Component< showCircEventsDownload: this.props.showCircEventsDownload || false, settingUp: this.props.settingUp || false, admin: this.admin, + featureFlags: this.props.featureFlags, }; } diff --git a/src/components/InventoryReportRequestModal.tsx b/src/components/InventoryReportRequestModal.tsx index b84a00945..7c5bcf67e 100644 --- a/src/components/InventoryReportRequestModal.tsx +++ b/src/components/InventoryReportRequestModal.tsx @@ -37,8 +37,9 @@ const CANCEL_BUTTON_TITLE = "Cancel Report Request"; export const ACK_RESPONSE_BUTTON_CONTENT = "Ok"; const ACK_RESPONSE_BUTTON_TITLE = "Acknowledge Response"; -// Create a modal to request an inventory report library and email address and to report on success. -// *** To use the legacy context here, we need to create a `contextProps` property on this function object: +// Create a modal to request an inventory report and to describe outcome. +// *** To use the legacy context here, we need to create a `contextTypes` property on this function object +// *** and add `context` types to the function definition. // *** InventoryReportRequestModal.contextTypes = { email: PropTypes.string } // *** See: https://legacy.reactjs.org/docs/legacy-context.html#referencing-context-in-stateless-function-components const InventoryReportRequestModal = ( diff --git a/src/components/LibraryStats.tsx b/src/components/LibraryStats.tsx index f149b72e9..eb3ee965e 100644 --- a/src/components/LibraryStats.tsx +++ b/src/components/LibraryStats.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import { useState } from "react"; import * as numeral from "numeral"; import { + FeatureFlags, InventoryStatistics, LibraryStatistics, PatronStatistics, @@ -18,6 +19,8 @@ import { import { Button } from "library-simplified-reusable-components"; import InventoryReportRequestModal from "./InventoryReportRequestModal"; import SingleStatListItem from "./SingleStatListItem"; +import * as PropTypes from "prop-types"; +import Admin from "../models/Admin"; export interface LibraryStatsProps { stats: LibraryStatistics; @@ -48,7 +51,14 @@ const inventoryKeyToLabelMap = { /** Displays statistics about patrons, licenses, and collections from the server, for a single library or all libraries the admin has access to. */ -const LibraryStats = (props: LibraryStatsProps) => { +// *** To use the legacy context here, we need to create a `contextTypes` property on this function object +// *** and add `context` types to the function definition. +// *** LibraryStats.contextTypes = { email: PropTypes.string } +// *** See: https://legacy.reactjs.org/docs/legacy-context.html#referencing-context-in-stateless-function-components +const LibraryStats = ( + props: LibraryStatsProps, + context: { admin: Admin; featureFlags: FeatureFlags } +) => { const { stats, library } = props; const { name: libraryName, @@ -58,6 +68,11 @@ const LibraryStats = (props: LibraryStatsProps) => { patronStatistics: patrons, } = stats || {}; + // A feature flag controls whether to show the inventory report form. + const inventoryReportRequestEnabled = + !context.featureFlags.reportsOnlyForSysadmins || + context.admin.isSystemAdmin(); + const chartItems = collections ?.map(({ name, inventory, inventoryByMedium }) => ({ name, @@ -77,7 +92,11 @@ const LibraryStats = (props: LibraryStatsProps) => {
  • {renderPatronsGroup(patrons)}
  • {renderCirculationsGroup(patrons)}
  • - {renderInventoryGroup(inventory, library)} + {renderInventoryGroup( + inventory, + inventoryReportRequestEnabled, + library + )}
  • {renderCollectionsGroup(chartItems)} @@ -86,6 +105,13 @@ const LibraryStats = (props: LibraryStatsProps) => { ); }; +// TODO: This is needed to support legacy context provider on this component (see above). +// The overall approach should be replaced with another mechanism (e.g., `useContext` or +// `useSelector` if we move `email` to new context provider or Redux, respectively). +LibraryStats.contextTypes = { + admin: PropTypes.object.isRequired, + featureFlags: PropTypes.object.isRequired, +}; const renderPatronsGroup = (patrons: PatronStatistics) => { return ( @@ -137,13 +163,14 @@ const renderCirculationsGroup = (patrons: PatronStatistics) => { const renderInventoryGroup = ( inventory: InventoryStatistics, + inventoryReportsEnabled: boolean, library?: string ) => { const [showReportForm, setShowReportForm] = useState(false); return ( <> - {library && ( + {inventoryReportsEnabled && library && ( setShowReportForm(false)} @@ -152,7 +179,7 @@ const renderInventoryGroup = ( )}

    Inventory - {library && ( + {inventoryReportsEnabled && library && (