Skip to content

Commit

Permalink
Feature/super admin hoc (#5187)
Browse files Browse the repository at this point in the history
* create hoc for super admin components

* wrap domain disco btn in hoc

* wrap archive domain switch in hoc

* wrap super admin user list in hoc

* fix orginfo tests

* add loading and error messages

* add i18nProvider to tests
  • Loading branch information
lcampbell2 committed Mar 25, 2024
1 parent fae3d9f commit 40d6425
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 292 deletions.
73 changes: 39 additions & 34 deletions frontend/src/admin/AdminDomainModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { useMutation } from '@apollo/client'
import { DomainField } from '../components/fields/DomainField'
import { CREATE_DOMAIN, UPDATE_DOMAIN } from '../graphql/mutations'
import { ABTestVariant, ABTestWrapper } from '../app/ABTestWrapper'
import withSuperAdmin from '../app/withSuperAdmin'

export function AdminDomainModal({ isOpen, onClose, validationSchema, orgId, ...props }) {
const {
Expand All @@ -49,7 +50,6 @@ export function AdminDomainModal({ isOpen, onClose, validationSchema, orgId, ...
orgSlug,
archived,
hidden,
permission,
mutation,
orgCount,
} = props
Expand Down Expand Up @@ -387,38 +387,11 @@ export function AdminDomainModal({ isOpen, onClose, validationSchema, orgId, ...
<Trans>Hide domain</Trans>
</Badge>
</Flex>
{permission === 'SUPER_ADMIN' && (
<Box>
<Flex align="center">
<Tooltip
label={t`Prevent this domain from being visible, scanned, and being counted in any summaries.`}
>
<QuestionOutlineIcon tabIndex={0} />
</Tooltip>
<label>
<Switch
colorScheme="red"
isFocusable={true}
name="archiveDomain"
mx="2"
defaultChecked={values.archiveDomain}
onChange={handleChange}
/>
</label>
<Badge variant="outline" color="gray.900" p="1.5">
<Trans>Archive domain</Trans>
</Badge>
</Flex>

<Text fontSize="sm">
{orgCount > 0 ? (
<Trans>Note: This will affect results for {orgCount} organizations</Trans>
) : (
<Trans>Note: This could affect results for multiple organizations</Trans>
)}
</Text>
</Box>
)}
<ArchiveDomainSwitch
defaultChecked={values.archiveDomain}
handleChange={handleChange}
orgCount={orgCount}
/>
<Text>
<Trans>Please allow up to 24 hours for summaries to reflect any changes.</Trans>
</Text>
Expand All @@ -438,6 +411,39 @@ export function AdminDomainModal({ isOpen, onClose, validationSchema, orgId, ...
)
}

const ArchiveDomainSwitch = withSuperAdmin(({ defaultChecked, handleChange, orgCount }) => {
return (
<Box>
<Flex align="center">
<Tooltip label={t`Prevent this domain from being visible, scanned, and being counted in any summaries.`}>
<QuestionOutlineIcon tabIndex={0} />
</Tooltip>
<label>
<Switch
colorScheme="red"
isFocusable={true}
name="archiveDomain"
mx="2"
defaultChecked={defaultChecked}
onChange={handleChange}
/>
</label>
<Badge variant="outline" color="gray.900" p="1.5">
<Trans>Archive domain</Trans>
</Badge>
</Flex>

<Text fontSize="sm">
{orgCount > 0 ? (
<Trans>Note: This will affect results for {orgCount} organizations</Trans>
) : (
<Trans>Note: This could affect results for multiple organizations</Trans>
)}
</Text>
</Box>
)
})

AdminDomainModal.propTypes = {
isOpen: bool,
onClose: func,
Expand All @@ -449,7 +455,6 @@ AdminDomainModal.propTypes = {
tagInputList: array,
archived: bool,
hidden: bool,
permission: string,
orgSlug: string,
mutation: string,
orgCount: number,
Expand Down
9 changes: 3 additions & 6 deletions frontend/src/admin/AdminDomains.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ import { usePaginatedCollection } from '../utilities/usePaginatedCollection'
import { PAGINATED_ORG_DOMAINS_ADMIN_PAGE as FORWARD } from '../graphql/queries'
import { REMOVE_DOMAIN } from '../graphql/mutations'
import { Formik } from 'formik'
import { SubdomainDiscoveryButton } from '../domains/SubdomainDiscoveryButton'
import SubdomainDiscoveryButton from '../domains/SubdomainDiscoveryButton'
import { ABTestWrapper, ABTestVariant } from '../app/ABTestWrapper'

export function AdminDomains({ orgSlug, orgId, permission }) {
export function AdminDomains({ orgSlug, orgId }) {
const toast = useToast()
const { i18n } = useLingui()

Expand Down Expand Up @@ -306,9 +306,7 @@ export function AdminDomains({ orgSlug, orgId, permission }) {
/>
<ABTestWrapper>
<ABTestVariant name="B">
{permission === 'SUPER_ADMIN' && (
<SubdomainDiscoveryButton domainUrl={domain} orgId={orgId} orgSlug={orgSlug} ml="2" />
)}
<SubdomainDiscoveryButton domainUrl={domain} orgId={orgId} orgSlug={orgSlug} ml="2" />
</ABTestVariant>
</ABTestWrapper>
</Flex>
Expand Down Expand Up @@ -422,7 +420,6 @@ export function AdminDomains({ orgSlug, orgId, permission }) {
validationSchema={createValidationSchema(['domainUrl', 'selectors'])}
orgId={orgId}
orgSlug={orgSlug}
permission={permission}
{...modalProps}
/>
<Modal isOpen={removeIsOpen} onClose={removeOnClose} motionPreset="slideInBottom">
Expand Down
45 changes: 26 additions & 19 deletions frontend/src/admin/AdminPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import { ADMIN_PAGE } from '../graphql/queries'
import { Dropdown } from '../components/Dropdown'
import { ErrorFallbackMessage } from '../components/ErrorFallbackMessage'
import { useDebouncedFunction } from '../utilities/useDebouncedFunction'
import { bool } from 'prop-types'
import { bool, func, string } from 'prop-types'
import { SuperAdminUserList } from './SuperAdminUserList'
import { AuditLogTable } from './AuditLogTable'
import { ErrorBoundary } from 'react-error-boundary'
import withSuperAdmin from '../app/withSuperAdmin'

export default function AdminPage({ isLoginRequired }) {
const [selectedOrg, setSelectedOrg] = useState('none')
Expand Down Expand Up @@ -142,10 +143,8 @@ export default function AdminPage({ isLoginRequired }) {
orgSlug={orgDetails.slug}
mb="1rem"
removeOrgCallback={setSelectedOrg}
// set key, this resets state when switching orgs (closes editing box)
key={orgDetails.slug}
key={orgDetails.slug} // set key, this resets state when switching orgs (closes editing box)
isLoginRequired={isLoginRequired}
isUserSuperAdmin={data?.isUserSuperAdmin}
/>
<AdminPanel
activeMenu={activeMenu}
Expand All @@ -165,7 +164,7 @@ export default function AdminPage({ isLoginRequired }) {

let adminPanel
if (activeMenu === 'users' && data?.isUserSuperAdmin) {
adminPanel = <SuperAdminUserList permission={data?.isUserSuperAdmin ? 'SUPER_ADMIN' : 'ADMIN'} />
adminPanel = <SuperAdminUserList />
} else if (activeMenu === 'audit-logs' && data?.isUserSuperAdmin) {
adminPanel = (
<ErrorBoundary FallbackComponent={ErrorFallbackMessage}>
Expand All @@ -178,25 +177,33 @@ export default function AdminPage({ isLoginRequired }) {

return (
<Stack spacing={10} w="100%" px={4}>
{data?.isUserSuperAdmin && (
<label>
<Flex align="center">
<Text fontSize="lg" fontWeight="bold" mr="2">
<Trans>Super Admin Menu:</Trans>
</Text>
<Select w="20%" defaultValue={activeMenu} onChange={(e) => changeActiveMenu(e.target.value)}>
<option value="organizations">{t`Organizations`}</option>
<option value="users">{t`Users`}</option>
<option value="audit-logs">{t`Audit Logs`}</option>
</Select>
</Flex>
</label>
)}
<SuperAdminMenu activeMenu={activeMenu} changeActiveMenu={changeActiveMenu} />
{adminPanel}
</Stack>
)
}

const SuperAdminMenu = withSuperAdmin(({ activeMenu, changeActiveMenu }) => {
return (
<label>
<Flex align="center">
<Text fontSize="lg" fontWeight="bold" mr="2">
<Trans>Super Admin Menu:</Trans>
</Text>
<Select w="20%" defaultValue={activeMenu} onChange={(e) => changeActiveMenu(e.target.value)}>
<option value="organizations">{t`Organizations`}</option>
<option value="users">{t`Users`}</option>
<option value="audit-logs">{t`Audit Logs`}</option>
</Select>
</Flex>
</label>
)
})

SuperAdminMenu.propTypes = {
activeMenu: string,
changeActiveMenu: func,
}
AdminPage.propTypes = {
isLoginRequired: bool,
}
2 changes: 1 addition & 1 deletion frontend/src/admin/AdminPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function AdminPanel({ activeMenu, orgSlug, permission, orgId }) {
<TabPanels>
<TabPanel>
<ErrorBoundary FallbackComponent={ErrorFallbackMessage}>
<AdminDomains permission={permission} orgSlug={orgSlug} orgId={orgId} />
<AdminDomains orgSlug={orgSlug} orgId={orgId} />
</ErrorBoundary>
</TabPanel>
<TabPanel>
Expand Down
27 changes: 16 additions & 11 deletions frontend/src/admin/OrganizationInformation.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ import { FormField } from '../components/fields/FormField'
import { LoadingMessage } from '../components/LoadingMessage'
import { ErrorFallbackMessage } from '../components/ErrorFallbackMessage'
import { getRequirement, schemaToValidation } from '../utilities/fieldRequirements'
import withSuperAdmin from '../app/withSuperAdmin'

export function OrganizationInformation({ orgSlug, removeOrgCallback: setSelectedOrg, isUserSuperAdmin, ...props }) {
export function OrganizationInformation({ orgSlug, removeOrgCallback: setSelectedOrg, ...props }) {
const toast = useToast()
const { isOpen: isRemovalOpen, onOpen: onRemovalOpen, onClose: onRemovalClose } = useDisclosure()
const removeOrgBtnRef = useRef()
Expand Down Expand Up @@ -292,16 +293,7 @@ export function OrganizationInformation({ orgSlug, removeOrgCallback: setSelecte
<Text fontWeight="bold" textAlign="center" mb="0.5em" gridColumn="span 4">
<Trans>Blank fields will not be included when updating the organization.</Trans>
</Text>
{isUserSuperAdmin && (
<>
<Box gridColumn={{ base: 'span 4', md: 'span 2' }}>
<FormField name="acronymEN" label={t`Acronym (EN)`} />
</Box>
<Box gridColumn={{ base: 'span 4', md: 'span 2' }}>
<FormField name="acronymFR" label={t`Acronym (FR)`} />
</Box>
</>
)}
<AcronymFields />
<Box gridColumn={{ base: 'span 4', md: 'span 2' }}>
<FormField name="nameEN" label={t`Name (EN)`} />
</Box>
Expand Down Expand Up @@ -453,6 +445,19 @@ export function OrganizationInformation({ orgSlug, removeOrgCallback: setSelecte
)
}

const AcronymFields = withSuperAdmin(() => {
return (
<>
<Box gridColumn={{ base: 'span 4', md: 'span 2' }}>
<FormField name="acronymEN" label={t`Acronym (EN)`} />
</Box>
<Box gridColumn={{ base: 'span 4', md: 'span 2' }}>
<FormField name="acronymFR" label={t`Acronym (FR)`} />
</Box>
</>
)
})

OrganizationInformation.propTypes = {
orgSlug: string.isRequired,
removeOrgCallback: func.isRequired,
Expand Down

0 comments on commit 40d6425

Please sign in to comment.