diff --git a/static/src/js/App.jsx b/static/src/js/App.jsx
index 85076eded..030d22ac6 100644
--- a/static/src/js/App.jsx
+++ b/static/src/js/App.jsx
@@ -16,8 +16,8 @@ import MetadataFormPage from '@/js/pages/MetadataFormPage/MetadataFormPage'
import OrderOptionFormPage from '@/js/pages/OrderOptionFormPage/OrderOptionFormPage'
import OrderOptionListPage from '@/js/pages/OrderOptionListPage/OrderOptionListPage'
import OrderOptionPage from '@/js/pages/OrderOptionPage/OrderOptionPage'
-// Import PermissionListPage from '@/js/pages/PermissionListPage/PermissionListPage'
-// Import PermissionPage from '@/js/pages/PermissionPage/PermissionPage'
+import PermissionListPage from '@/js/pages/PermissionListPage/PermissionListPage'
+import PermissionPage from '@/js/pages/PermissionPage/PermissionPage'
import ProviderPermissionsPage from '@/js/pages/ProviderPermissionsPage/ProviderPermissionsPage'
import ProvidersPage from '@/js/pages/ProvidersPage/ProvidersPage'
import RevisionListPage from '@/js/pages/RevisionListPage/RevisionListPage'
@@ -31,7 +31,6 @@ import ErrorPageNotFound from '@/js/components/ErrorPageNotFound/ErrorPageNotFou
import Layout from '@/js/components/Layout/Layout'
import LayoutUnauthenticated from '@/js/components/LayoutUnauthenticated/LayoutUnauthenticated'
import Notifications from '@/js/components/Notifications/Notifications'
-// Import PermissionFormPage from '@/js/pages/PermissionFormPage/PermissionFormPage'
import PublishPreview from '@/js/components/PublishPreview/PublishPreview'
import TemplateForm from '@/js/components/TemplateForm/TemplateForm'
import TemplateList from '@/js/components/TemplateList/TemplateList'
@@ -40,6 +39,7 @@ import TemplatePreview from '@/js/components/TemplatePreview/TemplatePreview'
import REDIRECTS from '@/js/constants/redirectsMap/redirectsMap'
import withProviders from '@/js/providers/withProviders/withProviders'
+import PermissionFormPage from './pages/PermissionFormPage/PermissionFormPage'
import '../css/index.scss'
@@ -140,36 +140,20 @@ export const App = () => {
},
{
path: '/permissions',
- element:
+ element:
},
- // {
- // path: '/permissions',
- // element:
- // },
{
path: '/permissions/new',
- element:
+ element:
},
- // {
- // path: '/permissions/new',
- // element:
- // },
{
path: '/permissions/:conceptId/edit',
- element:
+ element:
},
- // {
- // path: '/permissions/:conceptId/edit',
- // element:
- // },
{
path: '/permissions/:conceptId',
- element:
+ element:
},
- // {
- // path: '/permissions/:conceptId',
- // element:
- // },
{
path: '/order-options',
element:
diff --git a/static/src/js/components/CollectionSelector/CollectionSelector.jsx b/static/src/js/components/CollectionSelector/CollectionSelector.jsx
index 2003a7ea9..56b22f7fa 100644
--- a/static/src/js/components/CollectionSelector/CollectionSelector.jsx
+++ b/static/src/js/components/CollectionSelector/CollectionSelector.jsx
@@ -192,7 +192,7 @@ const CollectionSelector = ({ onChange, formData }) => {
}
},
shortName: `${inputValue}*`,
- limit: 20
+ limit: 100
}
},
onCompleted: (data) => {
diff --git a/static/src/js/components/CollectionSelector/__tests__/CollectionSelector.test.jsx b/static/src/js/components/CollectionSelector/__tests__/CollectionSelector.test.jsx
index ae82a18f4..e779f81f8 100644
--- a/static/src/js/components/CollectionSelector/__tests__/CollectionSelector.test.jsx
+++ b/static/src/js/components/CollectionSelector/__tests__/CollectionSelector.test.jsx
@@ -270,7 +270,7 @@ describe('CollectionSelector', () => {
await user.type(searchField, 'C')
- expect(await screen.findByText('Showing 2 items')).toBeInTheDocument()
+ expect(await screen.findByText('Showing 1 items')).toBeInTheDocument()
})
})
diff --git a/static/src/js/components/Layout/Layout.jsx b/static/src/js/components/Layout/Layout.jsx
index 99427b015..a9566f550 100644
--- a/static/src/js/components/Layout/Layout.jsx
+++ b/static/src/js/components/Layout/Layout.jsx
@@ -138,11 +138,11 @@ const Layout = ({ className, displayNav }) => {
{
to: '/templates/collections',
title: 'Templates'
+ },
+ {
+ to: '/permissions',
+ title: 'Permissions'
}
- // {
- // to: '/permissions',
- // title: 'Permissions'
- // }
]
},
{
diff --git a/static/src/js/components/Layout/__tests__/Layout.test.jsx b/static/src/js/components/Layout/__tests__/Layout.test.jsx
index d9aeaec2f..1bcfbfdbb 100644
--- a/static/src/js/components/Layout/__tests__/Layout.test.jsx
+++ b/static/src/js/components/Layout/__tests__/Layout.test.jsx
@@ -103,11 +103,11 @@ describe('Layout component', () => {
{
to: '/templates/collections',
title: 'Templates'
+ },
+ {
+ title: 'Permissions',
+ to: '/permissions'
}
- // {
- // title: 'Permissions',
- // to: '/permissions'
- // }
]
},
{
@@ -215,11 +215,11 @@ describe('Layout component', () => {
{
to: '/templates/collections',
title: 'Templates'
+ },
+ {
+ title: 'Permissions',
+ to: '/permissions'
}
- // {
- // title: 'Permissions',
- // to: '/permissions'
- // }
]
},
{
diff --git a/static/src/js/components/PermissionForm/PermissionForm.jsx b/static/src/js/components/PermissionForm/PermissionForm.jsx
index 27dbcaee3..916870cca 100644
--- a/static/src/js/components/PermissionForm/PermissionForm.jsx
+++ b/static/src/js/components/PermissionForm/PermissionForm.jsx
@@ -1,5 +1,6 @@
import Form from '@rjsf/core'
import React, { useEffect, useState } from 'react'
+import PropTypes from 'prop-types'
import Button from 'react-bootstrap/Button'
import Col from 'react-bootstrap/Col'
@@ -32,10 +33,10 @@ import { UPDATE_ACL } from '@/js/operations/mutations/updateAcl'
import CollectionSelectorPage from '@/js/pages/CollectionSelectorPage/CollectionSelectorPage'
+import { cloneDeep } from '@apollo/client/utilities'
import {
GET_COLLECTION_FOR_PERMISSION_FORM
} from '@/js/operations/queries/getCollectionForPermissionForm'
-
import CustomArrayFieldTemplate from '../CustomArrayFieldTemplate/CustomArrayFieldTemplate'
import CustomDateTimeWidget from '../CustomDateTimeWidget/CustomDateTimeWidget'
import CustomFieldTemplate from '../CustomFieldTemplate/CustomFieldTemplate'
@@ -164,7 +165,7 @@ const validate = (formData, errors) => {
*
* )
*/
-const PermissionForm = () => {
+const PermissionForm = ({ selectedCollectionsPageSize }) => {
const {
draft,
originalDraft,
@@ -217,16 +218,59 @@ const PermissionForm = () => {
TitleField: CustomTitleFieldTemplate
}
- const { data } = useSuspenseQuery(GET_COLLECTION_FOR_PERMISSION_FORM, {
+ const [error, setError] = useState(null)
+
+ const updateQuery = (prev, { fetchMoreResult }) => {
+ const newResult = cloneDeep(prev)
+ const { acl } = newResult
+ const { collections } = acl
+ const { items = [] } = collections || {}
+
+ items.push(...fetchMoreResult.acl.collections.items)
+
+ return newResult
+ }
+
+ const { data, fetchMore } = useSuspenseQuery(GET_COLLECTION_FOR_PERMISSION_FORM, {
skip: conceptId === 'new',
variables: {
conceptId,
params: {
- limit: 2000
+ offset: 0,
+ limit: selectedCollectionsPageSize
}
}
})
+ useEffect(() => {
+ async function fetchData() {
+ if (!data) return
+
+ const { acl } = data
+ const { collections } = acl
+ const { count, items = [] } = collections || {}
+
+ if (items.length < count) {
+ await fetchMore({
+ variables: {
+ conceptId,
+ params: {
+ offset: items.length,
+ limit: selectedCollectionsPageSize
+ }
+ },
+ updateQuery
+ })
+ }
+ }
+
+ fetchData()
+ .catch((err) => {
+ errorLogger('Error fetching more collection permissions', 'PermissionForm: fetchData')
+ setError(err)
+ })
+ }, [data])
+
useEffect(() => {
if (conceptId === 'new') {
setDraft({})
@@ -234,6 +278,12 @@ const PermissionForm = () => {
}
}, [conceptId])
+ useEffect(() => {
+ if (error) {
+ throw error
+ }
+ }, [error])
+
/**
* Updates the UI schema based on the granule access permission in the provided form data.
*
@@ -729,4 +779,12 @@ const PermissionForm = () => {
)
}
+PermissionForm.defaultProps = {
+ selectedCollectionsPageSize: 2000
+}
+
+PermissionForm.propTypes = {
+ selectedCollectionsPageSize: PropTypes.number
+}
+
export default PermissionForm
diff --git a/static/src/js/components/PermissionForm/__tests__/PermissionForm.test.jsx b/static/src/js/components/PermissionForm/__tests__/PermissionForm.test.jsx
index 49ae735e4..02dec1e3e 100644
--- a/static/src/js/components/PermissionForm/__tests__/PermissionForm.test.jsx
+++ b/static/src/js/components/PermissionForm/__tests__/PermissionForm.test.jsx
@@ -1,6 +1,7 @@
import {
render,
screen,
+ waitFor,
within
} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
@@ -33,6 +34,7 @@ import {
GET_COLLECTION_FOR_PERMISSION_FORM
} from '@/js/operations/queries/getCollectionForPermissionForm'
import PermissionForm from '../PermissionForm'
+import ErrorBoundary from '../../ErrorBoundary/ErrorBoundary'
vi.mock('@/js/utils/errorLogger')
vi.mock('@/js/hooks/useAvailableProviders')
@@ -114,9 +116,11 @@ const setup = ({
-
-
+
+
+
+
+
)
}
path="new"
@@ -125,9 +129,11 @@ const setup = ({
path=":conceptId/edit"
element={
(
-
-
-
+
+
+
+
+
)
}
/>
@@ -199,7 +205,8 @@ describe('PermissionForm', () => {
variables: {
conceptId: 'ACL1000000-MMT',
params: {
- limit: 2000
+ offset: 0,
+ limit: 1
}
}
},
@@ -234,7 +241,72 @@ describe('PermissionForm', () => {
shortName: 'This is collection 2',
entryTitle: 'Collection 1',
version: '1'
+ }
+ ]
+ },
+ groups: {
+ __typename: 'AclGroupList',
+ items: [
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'guest',
+ id: null,
+ name: null,
+ tag: null
},
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'registered',
+ id: null,
+ name: null,
+ tag: null
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 1,
+ limit: 1
+ }
+ }
+ },
+ result: {
+ data: {
+ acl: {
+ __typename: 'Acl',
+ conceptId: 'ACL1000000-CMR',
+ identityType: 'Catalog Item',
+ location: 'https://cmr.sit.earthdata.nasa.gov:443/access-control/acls/ACL1200427411-CMR',
+ name: 'Mock ACL',
+ providerIdentity: null,
+ revisionId: 1,
+ systemIdentity: null,
+ catalogItemIdentity: {
+ __typename: 'CatalogItemIdentity',
+ collectionIdentifier: {},
+ collectionApplicable: true,
+ granuleApplicable: false,
+ granuleIdentifier: null,
+ providerId: 'MM_2'
+ },
+ collections: {
+ __typename: 'CollectionList',
+ count: 2,
+ items: [
{
__typename: 'Collection',
conceptId: 'C13000000-MMT_2',
@@ -320,6 +392,110 @@ describe('PermissionForm', () => {
expect(navigateSpy).toHaveBeenCalledTimes(1)
expect(navigateSpy).toHaveBeenCalledWith('/permissions/ACL1000000-MMT')
})
+
+ test('should render error when fetchMore fails', async () => {
+ const navigateSpy = vi.fn()
+ vi.spyOn(router, 'useNavigate').mockImplementation(() => navigateSpy)
+ setup({
+ pageUrl: '/permissions/ACL1000000-MMT/edit',
+ mocks: [{
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 0,
+ limit: 1
+ }
+ }
+ },
+ result: {
+ data: {
+ acl: {
+ __typename: 'Acl',
+ conceptId: 'ACL1000000-CMR',
+ identityType: 'Catalog Item',
+ location: 'https://cmr.sit.earthdata.nasa.gov:443/access-control/acls/ACL1200427411-CMR',
+ name: 'Mock ACL',
+ providerIdentity: null,
+ revisionId: 1,
+ systemIdentity: null,
+ catalogItemIdentity: {
+ __typename: 'CatalogItemIdentity',
+ collectionIdentifier: {},
+ collectionApplicable: true,
+ granuleApplicable: false,
+ granuleIdentifier: null,
+ providerId: 'MM_2'
+ },
+ collections: {
+ __typename: 'CollectionList',
+ count: 2,
+ items: [
+ {
+ __typename: 'Collection',
+ conceptId: 'C12000000-MMT_2',
+ directDistributionInformation: null,
+ provider: 'MMT_2',
+ shortName: 'This is collection 2',
+ entryTitle: 'Collection 1',
+ version: '1'
+ }
+ ]
+ },
+ groups: {
+ __typename: 'AclGroupList',
+ items: [
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'guest',
+ id: null,
+ name: null,
+ tag: null
+ },
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'registered',
+ id: null,
+ name: null,
+ tag: null
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 1,
+ limit: 1
+ }
+ }
+ },
+ error: new Error('An error occurred')
+ }]
+ })
+
+ await waitFor(() => {
+ expect(errorLogger).toHaveBeenCalledTimes(1)
+ })
+
+ expect(errorLogger).toHaveBeenCalledWith(
+ 'Error fetching more collection permissions',
+ 'PermissionForm: fetchData'
+ )
+ })
})
describe('when filling out the form and only filling out search and order permission and submitting', () => {
@@ -370,7 +546,8 @@ describe('PermissionForm', () => {
variables: {
conceptId: 'ACL1000000-MMT',
params: {
- limit: 2000
+ offset: 0,
+ limit: 1
}
}
},
@@ -405,7 +582,72 @@ describe('PermissionForm', () => {
shortName: 'This is collection 2',
entryTitle: 'Collection 1',
version: '1'
+ }
+ ]
+ },
+ groups: {
+ __typename: 'AclGroupList',
+ items: [
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'guest',
+ id: null,
+ name: null,
+ tag: null
},
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'registered',
+ id: null,
+ name: null,
+ tag: null
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 1,
+ limit: 1
+ }
+ }
+ },
+ result: {
+ data: {
+ acl: {
+ __typename: 'Acl',
+ conceptId: 'ACL1000000-CMR',
+ identityType: 'Catalog Item',
+ location: 'https://cmr.sit.earthdata.nasa.gov:443/access-control/acls/ACL1200427411-CMR',
+ name: 'Mock ACL',
+ providerIdentity: null,
+ revisionId: 1,
+ systemIdentity: null,
+ catalogItemIdentity: {
+ __typename: 'CatalogItemIdentity',
+ collectionIdentifier: {},
+ collectionApplicable: true,
+ granuleApplicable: false,
+ granuleIdentifier: null,
+ providerId: 'MM_2'
+ },
+ collections: {
+ __typename: 'CollectionList',
+ count: 2,
+ items: [
{
__typename: 'Collection',
conceptId: 'C13000000-MMT_2',
@@ -583,7 +825,8 @@ describe('PermissionForm', () => {
variables: {
conceptId: 'ACL1000000-MMT',
params: {
- limit: 2000
+ offset: 0,
+ limit: 1
}
}
},
@@ -618,7 +861,72 @@ describe('PermissionForm', () => {
shortName: 'This is collection 2',
entryTitle: 'Collection 1',
version: '1'
+ }
+ ]
+ },
+ groups: {
+ __typename: 'AclGroupList',
+ items: [
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'guest',
+ id: null,
+ name: null,
+ tag: null
},
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'registered',
+ id: null,
+ name: null,
+ tag: null
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 1,
+ limit: 1
+ }
+ }
+ },
+ result: {
+ data: {
+ acl: {
+ __typename: 'Acl',
+ conceptId: 'ACL1000000-CMR',
+ identityType: 'Catalog Item',
+ location: 'https://cmr.sit.earthdata.nasa.gov:443/access-control/acls/ACL1200427411-CMR',
+ name: 'Mock ACL',
+ providerIdentity: null,
+ revisionId: 1,
+ systemIdentity: null,
+ catalogItemIdentity: {
+ __typename: 'CatalogItemIdentity',
+ collectionIdentifier: {},
+ collectionApplicable: true,
+ granuleApplicable: false,
+ granuleIdentifier: null,
+ providerId: 'MM_2'
+ },
+ collections: {
+ __typename: 'CollectionList',
+ count: 2,
+ items: [
{
__typename: 'Collection',
conceptId: 'C13000000-MMT_2',
@@ -662,11 +970,16 @@ describe('PermissionForm', () => {
{
request: {
query: GET_PERMISSION_COLLECTIONS,
- variables: {}
+ variables: {
+ params: {
+ limit: 100
+ }
+ }
},
result: {
data: {
collections: {
+ count: 2,
items: [
{
conceptId: 'C1200444618-AMD_USAPDC',
@@ -726,7 +1039,8 @@ describe('PermissionForm', () => {
variables: {
conceptId: 'ACL1000000-MMT',
params: {
- limit: 2000
+ offset: 0,
+ limit: 1
}
}
},
@@ -761,7 +1075,72 @@ describe('PermissionForm', () => {
shortName: 'This is collection 2',
entryTitle: 'Collection 1',
version: '1'
+ }
+ ]
+ },
+ groups: {
+ __typename: 'AclGroupList',
+ items: [
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'guest',
+ id: null,
+ name: null,
+ tag: null
},
+ {
+ __typename: 'AclGroup',
+ permissions: [
+ 'read'
+ ],
+ userType: 'registered',
+ id: null,
+ name: null,
+ tag: null
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ {
+ request: {
+ query: GET_COLLECTION_FOR_PERMISSION_FORM,
+ variables: {
+ conceptId: 'ACL1000000-MMT',
+ params: {
+ offset: 1,
+ limit: 1
+ }
+ }
+ },
+ result: {
+ data: {
+ acl: {
+ __typename: 'Acl',
+ conceptId: 'ACL1000000-CMR',
+ identityType: 'Catalog Item',
+ location: 'https://cmr.sit.earthdata.nasa.gov:443/access-control/acls/ACL1200427411-CMR',
+ name: 'Mock ACL',
+ providerIdentity: null,
+ revisionId: 1,
+ systemIdentity: null,
+ catalogItemIdentity: {
+ __typename: 'CatalogItemIdentity',
+ collectionIdentifier: {},
+ collectionApplicable: true,
+ granuleApplicable: false,
+ granuleIdentifier: null,
+ providerId: 'MM_2'
+ },
+ collections: {
+ __typename: 'CollectionList',
+ count: 2,
+ items: [
{
__typename: 'Collection',
conceptId: 'C13000000-MMT_2',
@@ -802,6 +1181,7 @@ describe('PermissionForm', () => {
}
}
}
+
]
})
@@ -811,6 +1191,8 @@ describe('PermissionForm', () => {
const submitButton = screen.getByRole('button', { name: 'Submit' })
await user.click(submitButton)
+ expect(await screen.findByText('Showing selected 2 items')).toBeInTheDocument()
+
expect(navigateSpy).toHaveBeenCalledTimes(1)
expect(navigateSpy).toHaveBeenCalledWith('/permissions/ACL1000000-MMT')
})
@@ -830,7 +1212,8 @@ describe('PermissionForm', () => {
variables: {
conceptId: 'ACL1000000-MMT',
params: {
- limit: 2000
+ offset: 0,
+ limit: 1
}
}
},
@@ -911,6 +1294,7 @@ describe('PermissionForm', () => {
result: {
data: {
collections: {
+ count: 2,
items: [
{
conceptId: 'C1200444618-AMD_USAPDC',
diff --git a/static/src/js/operations/queries/getCollectionForPermissionForm.js b/static/src/js/operations/queries/getCollectionForPermissionForm.js
index 8fc814666..d25aaa501 100644
--- a/static/src/js/operations/queries/getCollectionForPermissionForm.js
+++ b/static/src/js/operations/queries/getCollectionForPermissionForm.js
@@ -20,6 +20,7 @@ export const GET_COLLECTION_FOR_PERMISSION_FORM = gql`
}
}
collections(params: $params) {
+ count
items {
conceptId,
shortName,