diff --git a/src/__tests__/pages/api/dataSources/personnel.test.ts b/src/__tests__/pages/api/dataSources/personnel.test.ts index 9a80827ff..0040c4bcb 100644 --- a/src/__tests__/pages/api/dataSources/personnel.test.ts +++ b/src/__tests__/pages/api/dataSources/personnel.test.ts @@ -22,6 +22,8 @@ const mockData = { lastModifiedAt: '2021-10-01', } +const mockLastModifiedAt = '2021-10-01' + describe('Personnel API', () => { describe('getUserData', () => { test('call getUserData with an id', async () => { @@ -31,7 +33,7 @@ describe('Personnel API', () => { personnelAPI.baseURL = 'https://example.com' // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post'); + const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post') mockPost.mockResolvedValue({ data: mockData }) const result = await personnelAPI.getUserData('1234567890') @@ -59,7 +61,7 @@ describe('Personnel API', () => { personnelAPI.baseURL = 'https://example.com' // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post'); + const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post') mockPost.mockResolvedValue({ data: mockData }) const result = await personnelAPI.getGuardianDirectory() @@ -78,4 +80,60 @@ describe('Personnel API', () => { ) }) }) + + describe('getLastModifiedAt', () => { + test('call getLastModifiedAt with an id', async () => { + const mockCache = {} as KeyValueCache + const personnelAPI = new PersonnelAPI({ cache: mockCache }) + + personnelAPI.baseURL = 'https://example.com' + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post') + mockPost.mockResolvedValue({ data: mockLastModifiedAt }) + + const result = await personnelAPI.getLastModifiedAt() + + expect(result).toEqual({ data: mockLastModifiedAt }) + }) + + test('throw an error when there is no baseURL', async () => { + const mockCache = {} as KeyValueCache + const personnelAPI = new PersonnelAPI({ cache: mockCache }) + + personnelAPI.baseURL = '' + + await expect(personnelAPI.getLastModifiedAt()).rejects.toThrow( + 'No Personnel API URL found' + ) + }) + }) + + describe('searchGuardianDirectory', () => { + test('call searchGuardianDirectory with an id', async () => { + const mockCache = {} as KeyValueCache + const personnelAPI = new PersonnelAPI({ cache: mockCache }) + + personnelAPI.baseURL = 'https://example.com' + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const mockPost = jest.spyOn(PersonnelAPI.prototype as any, 'post') + mockPost.mockResolvedValue({ data: mockData }) + + const result = await personnelAPI.searchGuardianDirectory('1234567890') + + expect(result).toEqual({ data: mockData }) + }) + + test('throw an error when there is no baseURL', async () => { + const mockCache = {} as KeyValueCache + const personnelAPI = new PersonnelAPI({ cache: mockCache }) + + personnelAPI.baseURL = '' + + await expect( + personnelAPI.searchGuardianDirectory('1234567890') + ).rejects.toThrow('No Personnel API URL found') + }) + }) }) diff --git a/src/operations/portal/queries/getLastModifiedAt.graphql b/src/operations/portal/queries/getLastModifiedAt.graphql new file mode 100644 index 000000000..f2b4b5a6b --- /dev/null +++ b/src/operations/portal/queries/getLastModifiedAt.graphql @@ -0,0 +1,3 @@ +query getLastModifiedAt { + getLastModifiedAt +} diff --git a/src/pages/api/dataSources/personnel.ts b/src/pages/api/dataSources/personnel.ts index d229eebc3..30b3f575a 100644 --- a/src/pages/api/dataSources/personnel.ts +++ b/src/pages/api/dataSources/personnel.ts @@ -32,6 +32,16 @@ class PersonnelAPI extends RESTDataSource { }) } + async getLastModifiedAt() { + if (!this.baseURL) throw new Error('No Personnel API URL found') + + return this.post(this.baseURL + `/api/graphql`, { + body: { + query: getLastModifiedAtQuery, + }, + }) + } + async searchGuardianDirectory(query: string) { if (!this.baseURL) throw new Error('No Personnel API URL found') @@ -92,6 +102,12 @@ query GetGuardianDirectory { } ` +const getLastModifiedAtQuery = ` +query GetLastModifiedAt { + getLastModifiedAt +} +` + const searchGuardianDirectoryQuery = ` query SearchGuardianDirectory($search: String!) { searchGuardianDirectory(search: $search) { diff --git a/src/pages/guardian-directory.tsx b/src/pages/guardian-directory.tsx index b6418cc47..746cf6ead 100644 --- a/src/pages/guardian-directory.tsx +++ b/src/pages/guardian-directory.tsx @@ -9,6 +9,7 @@ import styles from 'styles/pages/guardianDirectory.module.scss' import { GuardianDirectoryTable } from 'components/GuardianDirectoryTable/GuardianDirectoryTable' import { useGetGuardianDirectoryQuery } from 'operations/portal/queries/getGuardianDirectory.g' import { useSearchGuardianDirectoryQuery } from 'operations/portal/queries/searchGuardianDirectory.g' +import { useGetLastModifiedAtQuery } from 'operations/portal/queries/getLastModifiedAt.g' import { GuardianDirectory as GuardianDirectoryType } from 'types' const GuardianDirectory = () => { @@ -17,6 +18,7 @@ const GuardianDirectory = () => { const { loading } = useUser() const [directory, setDirectory] = useState(Array) const { data } = useGetGuardianDirectoryQuery() + const { data: lastModifiedAt } = useGetLastModifiedAtQuery() const [searchQuery, setSearchQuery] = useState('') const { data: searchData, loading: loadingSearch } = @@ -108,6 +110,15 @@ const GuardianDirectory = () => { rows={directory} /> )} + +

+ Last updated:{' '} + {lastModifiedAt?.getLastModifiedAt && + new Date(lastModifiedAt.getLastModifiedAt).toLocaleDateString( + 'en-US', + { year: 'numeric', month: 'short', day: 'numeric' } + )} +

) diff --git a/src/resolvers/index.ts b/src/resolvers/index.ts index c23f63fbd..1d116da2a 100644 --- a/src/resolvers/index.ts +++ b/src/resolvers/index.ts @@ -119,6 +119,14 @@ type GetGuardianDirectoryPromise = { } } +type GetLastModifiedAtPromise = { + data: { + getLastModifiedAt: { + lastModifiedAt: string + } + } +} + type SearchGuardianDirectoryPromise = { data: { searchGuardianDirectory: [ @@ -168,6 +176,7 @@ type PortalUserContext = { personnelAPI: { getUserData: (dodId: string) => Promise getGuardianDirectory: () => Promise + getLastModifiedAt: () => Promise searchGuardianDirectory: ( query: string ) => Promise @@ -255,6 +264,17 @@ const resolvers = { // Root resolvers Query: { + getLastModifiedAt: async ( + _: undefined, + args: undefined, + { dataSources }: PortalUserContext + ) => { + const { + data: { getLastModifiedAt }, + } = await dataSources.personnelAPI.getLastModifiedAt() + + return getLastModifiedAt + }, searchGuardianDirectory: async ( _: undefined, { search }: { search: string }, diff --git a/src/schema.tsx b/src/schema.tsx index 7322f1fda..495314f6a 100644 --- a/src/schema.tsx +++ b/src/schema.tsx @@ -77,6 +77,7 @@ export const typeDefs = gql` theme: String! personnelData: PersonnelData guardianDirectory: [GuardianDirectory] + getLastModifiedAt: String searchGuardianDirectory(search: String!): [GuardianDirectory] }