diff --git a/prismicCustomTypes.md b/prismicCustomTypes.md index 2c45b25e16..5b3ff0236c 100644 --- a/prismicCustomTypes.md +++ b/prismicCustomTypes.md @@ -113,73 +113,156 @@ name: `sponsor` JSON: ``` { - "Main": { - "title": { - "type": "StructuredText", - "config": { - "single": "heading6", - "label": "Title", - "placeholder": "Sponsor(s) card title" + "Main" : { + "title" : { + "type" : "StructuredText", + "config" : { + "single" : "heading6", + "label" : "Title", + "placeholder" : "Sponsor(s) card title" } }, - "language": { - "type": "StructuredText", + "language" : { + "type" : "StructuredText", + "config" : { + "single" : "heading6", + "label" : "language", + "placeholder" : "Language (en, es or fr)" + } + }, + "order" : { + "type" : "StructuredText", + "config" : { + "single" : "heading6", + "label" : "Order", + "placeholder" : "The order you wish the sponsor to appear" + } + }, + "items" : { + "type" : "Group", + "config" : { + "fields" : { + "logo" : { + "type" : "Image", + "config" : { + "constraint" : { }, + "thumbnails" : [ ], + "label" : "Logo" + } + }, + "name" : { + "type" : "StructuredText", + "config" : { + "single" : "heading5", + "label" : "name", + "placeholder" : "Sponsor's name" + } + }, + "description" : { + "type" : "StructuredText", + "config" : { + "multi" : "paragraph,preformatted,heading1,heading2,heading3,heading4,heading5,heading6,strong,em,hyperlink,image,embed,list-item,o-list-item,rtl", + "allowTargetBlank" : true, + "label" : "description", + "placeholder" : "Sponsor's description" + } + }, + "link" : { + "type" : "Link", + "config" : { + "label" : "link", + "select" : null, + "allowTargetBlank" : true, + "placeholder" : "Logo's link" + } + } + }, + "label" : "Sponsor's info" + } + } + } +} +``` + +### 3. Footer custom type + +name: `footer` + +JSON: +``` +{ + "Main": { + "title": { + "type": "Text", "config": { - "single": "heading6", - "label": "language", - "placeholder": "Language (en, es or fr)" + "label": "Title" } }, "order": { - "type": "StructuredText", + "type": "Number", "config": { - "single": "heading6", - "label": "Order", - "placeholder": "The order you wish the sponsor to appear" + "label": "Order" } }, "items": { "type": "Group", "config": { "fields": { - "logo": { - "type": "Image", + "item_title": { + "type": "Text", "config": { - "constraint": {}, - "thumbnails": [], - "label": "Logo" + "label": "Item Title" } }, - "name": { - "type": "StructuredText", + "item_url": { + "type": "Link", "config": { - "single": "heading5", - "label": "name", - "placeholder": "Sponsor's name" + "label": "Item URL", + "select": null, + "allowTargetBlank": true, + "placeholder": "External URL (outside site)" } }, - "description": { - "type": "StructuredText", + "path": { + "type": "Text", "config": { - "multi": "paragraph,preformatted,heading1,heading2,heading3,heading4,heading5,heading6,strong,em,hyperlink,image,embed,list-item,o-list-item,rtl", - "allowTargetBlank": true, - "label": "description", - "placeholder": "Sponsor's description" + "label": "Path" + } + } + }, + "label": "Items" + } + }, + "social": { + "type": "Group", + "config": { + "fields": { + "name": { + "type": "Text", + "config": { + "label": "Name", + "placeholder": "twitter/facebook/github/linked" } }, - "link": { + "url": { "type": "Link", "config": { - "label": "link", - "select": null, "allowTargetBlank": true, - "placeholder": "Logo's link" + "label": "url", + "placeholder": "URL to your social media account", + "select": null + } + }, + "path": { + "type": "Text", + "config": { + "label": "Path" } } }, - "label": "Sponsor's info" + "label": "social" } } } } -``` \ No newline at end of file +``` diff --git a/site/gatsby-site/cypress.config.js b/site/gatsby-site/cypress.config.js index 99aa7c7feb..1dd28c4dad 100644 --- a/site/gatsby-site/cypress.config.js +++ b/site/gatsby-site/cypress.config.js @@ -2,7 +2,6 @@ const { defineConfig } = require('cypress'); module.exports = defineConfig({ video: false, - videoUploadOnPasses: false, chromeWebSecurity: false, screenshotOnRunFailure: false, retries: { diff --git a/site/gatsby-site/cypress/e2e/integration/admin.cy.js b/site/gatsby-site/cypress/e2e/integration/admin.cy.js index 77bbee0e6b..f89e822c1c 100644 --- a/site/gatsby-site/cypress/e2e/integration/admin.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/admin.cy.js @@ -5,8 +5,7 @@ const { gql } = require('@apollo/client'); describe('Admin', () => { const baseUrl = '/admin'; - //TODO: (Issue #2272): Temporarily skip flaky test. - it.skip('Should show not enough permissions message', () => { + it('Should show not enough permissions message', () => { cy.visit(baseUrl); cy.contains('Not enough permissions').should('be.visible'); diff --git a/site/gatsby-site/cypress/e2e/integration/submit.cy.js b/site/gatsby-site/cypress/e2e/integration/submit.cy.js index 9c5ad24f33..482c57da7f 100644 --- a/site/gatsby-site/cypress/e2e/integration/submit.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/submit.cy.js @@ -458,14 +458,14 @@ describe('The Submit form', () => { it('Should pull parameters form the query string and auto-fill fields', () => { const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', submitters: 'test submitter', incident_date: '2022-01-01', date_published: '2021-01-02', date_downloaded: '2021-01-03', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', incident_ids: [1], text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', tags: 'test tag', @@ -482,7 +482,7 @@ describe('The Submit form', () => { date_downloaded: '2021-01-03', incident_date: '2022-01-01', incident_ids: [1], - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', tags: 'test tag', editor_notes: 'Here are some notes', @@ -544,8 +544,8 @@ describe('The Submit form', () => { tags: [values.tags], plain_text: 'Sit quo accusantium\n\nquia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }); @@ -557,13 +557,13 @@ describe('The Submit form', () => { cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', incident_date: '2022-01-01', date_published: '2021-01-02', date_downloaded: '2021-01-03', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', incident_ids: [1], text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', tags: 'test tag', @@ -577,7 +577,7 @@ describe('The Submit form', () => { authors: 'test author', date_published: '2021-01-02', date_downloaded: '2021-01-03', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', }).as('parseNews'); @@ -637,8 +637,8 @@ describe('The Submit form', () => { tags: [values.tags], plain_text: 'Sit quo accusantium\n\nquia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }); @@ -647,6 +647,8 @@ describe('The Submit form', () => { }); it('Should show a list of related reports', () => { + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + const relatedReports = { byURL: { data: { @@ -871,6 +873,9 @@ describe('The Submit form', () => { // cy.setEditorText doesn't seem to trigger a render of the relateBbyText component it('Should show related reports based on semantic similarity', () => { cy.visit(url); + + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.setEditorText( `Recent news stories and blog posts highlighted the underbelly of YouTube Kids, Google's children-friendly version of the wide world of YouTube. While all content on YouTube Kids is meant to be suitable for children under the age of 13, some inappropriate videos using animations, cartoons, and child-focused keywords manage to get past YouTube's algorithms and in front of kids' eyes. Now, YouTube will implement a new policy in an attempt to make the whole of YouTube safer: it will age-restrict inappropriate videos masquerading as children's content in the main YouTube app.` ); @@ -888,6 +893,8 @@ describe('The Submit form', () => { it('Should *not* show semantically related reports when the text is under 256 non-space characters', () => { cy.visit(url); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.setEditorText( `Recent news stories and blog posts highlighted the underbelly of YouTube Kids, Google's children-friendly version of the wide world of YouTube.` ); @@ -897,7 +904,7 @@ describe('The Submit form', () => { it('Should show fallback preview image on initial load', () => { const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', submitters: 'test submitter', @@ -930,7 +937,7 @@ describe('The Submit form', () => { it('Should update preview image when url is typed', () => { const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', submitters: 'test submitter', @@ -975,8 +982,10 @@ describe('The Submit form', () => { it('Should show the editor notes field', () => { cy.visit(url); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + const valuesStep1 = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', date_published: '2021-01-02', @@ -999,7 +1008,7 @@ describe('The Submit form', () => { const valuesStep2 = { submitters: 'test submitter', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', }; for (const key in valuesStep2) { @@ -1022,6 +1031,8 @@ describe('The Submit form', () => { it('Should show a popover', () => { cy.visit(url); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.get('[data-cy="label-title"]').trigger('mouseenter'); cy.get('[data-cy="popover-title"]').should('be.visible'); @@ -1034,6 +1045,8 @@ describe('The Submit form', () => { it('Should show a translated popover', () => { cy.visit(`/es/apps/submit/`); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.get('[data-cy="label-title"]').trigger('mouseenter'); cy.get('[data-cy="popover-title"]').should('be.visible'); @@ -1194,6 +1207,8 @@ describe('The Submit form', () => { { data: { incident: null } } ); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); cy.contains('button', 'Submit').click(); @@ -1203,14 +1218,14 @@ describe('The Submit form', () => { it('Should submit a new report response', () => { const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', submitters: 'test submitter', incident_date: '2022-01-01', date_published: '2021-01-02', date_downloaded: '2021-01-03', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', incident_ids: [1], text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', tags: 'response', @@ -1248,7 +1263,7 @@ describe('The Submit form', () => { } ); - cy.intercept('GET', parserURL).as('parseNews'); + cy.intercept('GET', parserURL, values).as('parseNews'); cy.visit(url + `?${params.toString()}`); @@ -1281,8 +1296,8 @@ describe('The Submit form', () => { tags: [values.tags], plain_text: 'Sit quo accusantium\n\nquia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }); }); @@ -1314,10 +1329,12 @@ describe('The Submit form', () => { probablyRelatedReports ); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'BBC News', incident_date: '2022-01-01', @@ -1366,7 +1383,7 @@ describe('The Submit form', () => { authors: [values.authors], plain_text: 'Sit quo accusantium quia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, + source_domain: `incidentdatabase.ai`, editor_dissimilar_incidents: [2], editor_similar_incidents: [3], }); @@ -1376,6 +1393,8 @@ describe('The Submit form', () => { it('Should *not* show related reports based on author', () => { cy.visit(url); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + const valuesStep1 = { authors: 'test author', }; @@ -1421,10 +1440,12 @@ describe('The Submit form', () => { } ); + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); const valuesStep1 = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', date_published: '2021-01-02', @@ -1457,7 +1478,7 @@ describe('The Submit form', () => { const valuesStep2 = { submitters: 'test submitter', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', }; for (const key in valuesStep2) { @@ -1492,8 +1513,8 @@ describe('The Submit form', () => { tags: [], plain_text: 'Sit quo accusantium quia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }); }); @@ -1580,18 +1601,18 @@ describe('The Submit form', () => { it('Should load from localstorage', () => { const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', authors: ['test author'], title: 'test title', date_published: '2021-01-02', date_downloaded: '2021-01-03', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', incident_ids: [1], text: '## Sit quo accusantium \n\n quia **assumenda**. Quod delectus similique labore optio quaease', submitters: ['test submitters'], tags: ['test tags'], - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }; @@ -1627,18 +1648,20 @@ describe('The Submit form', () => { tags: values.tags, plain_text: 'Sit quo accusantium\n\nquia assumenda. Quod delectus similique labore optio quaease\n', - source_domain: `test.com`, - cloudinary_id: `reports/test.com/image.jpg`, + source_domain: `incidentdatabase.ai`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, editor_notes: 'Here are some notes', }); }); }); it('Should save form data in local storage', () => { + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); const valuesStep1 = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', title: 'test title', authors: 'test author', date_published: '2021-01-02', @@ -1671,7 +1694,7 @@ describe('The Submit form', () => { const valuesStep2 = { submitters: 'test submitter', - image_url: 'https://test.com/image.jpg', + image_url: 'https://incidentdatabase.ai/image.jpg', language: 'en', }; @@ -1710,7 +1733,7 @@ describe('The Submit form', () => { deployers: [valuesStep3.deployers], harmed_parties: [valuesStep3.harmed_parties], nlp_similar_incidents: [], - cloudinary_id: `reports/test.com/image.jpg`, + cloudinary_id: `reports/incidentdatabase.ai/image.jpg`, text: 'Sit quo accusantium quia assumenda. Quod delectus similique labore optio quaease', incident_ids: [], incident_editors: [], @@ -1722,7 +1745,7 @@ describe('The Submit form', () => { cy.intercept('GET', parserURL, parseNews).as('parseNews'); const values = { - url: 'https://test.com', + url: 'https://incidentdatabase.ai', authors: 'test author', title: 'test title', date_published: '2021-01-02', @@ -1756,6 +1779,8 @@ describe('The Submit form', () => { }); it('Should display an error message if Date Published is not in the past', () => { + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); cy.waitForStableDOM(); @@ -1770,6 +1795,8 @@ describe('The Submit form', () => { }); it('Should display an error message if Date Downloaded is not in the past', () => { + cy.intercept('GET', parserURL, parseNews).as('parseNews'); + cy.visit(url); cy.waitForStableDOM(); diff --git a/site/gatsby-site/src/components/landing/Sponsors.js b/site/gatsby-site/src/components/landing/Sponsors.js index 4bd8a474e7..486cc3f522 100644 --- a/site/gatsby-site/src/components/landing/Sponsors.js +++ b/site/gatsby-site/src/components/landing/Sponsors.js @@ -77,7 +77,7 @@ export default function Sponsors({ sponsors = [] }) { View the Responsible AI Collaborative’s{' '} @@ -85,7 +85,7 @@ export default function Sponsors({ sponsors = [] }) { {' '} and{' '} diff --git a/site/gatsby-site/src/components/layout/Footer.js b/site/gatsby-site/src/components/layout/Footer.js index 698be44d2b..d981916249 100644 --- a/site/gatsby-site/src/components/layout/Footer.js +++ b/site/gatsby-site/src/components/layout/Footer.js @@ -30,6 +30,29 @@ export default function Footer() { } } } + allPrismicFooter(sort: { data: { order: ASC } }) { + edges { + node { + data { + title + items { + item_title + item_url { + url + } + path + } + order + social { + name + url { + url + } + } + } + } + } + } } `); @@ -37,8 +60,53 @@ export default function Footer() { site: { siteMetadata: { githubUrl, facebookUrl, linkedInUrl }, }, + allPrismicFooter, } = data; + const footerContent = []; + + if (allPrismicFooter.edges.length > 0) { + allPrismicFooter.edges.forEach((group) => { + const title = group.node.data.title; + + let items = group.node.data.items.map((item) => { + return { + title: item.item_title, + url: item.item_url?.url || item.path, + }; + }); + + footerContent.push({ + title, + items, + socialItems: group.node.data.social.map((item) => { + return { + name: item.name, + url: item.url?.url || item.path, + }; + }), + }); + }); + } else { + //Fallback to config + config.footer.navConfig.map((group) => { + const title = group.title; + + const items = group.items.map((item) => { + return { + title: item.title, + url: item.url, + label: item.label, + }; + }); + + footerContent.push({ + title, + items, + }); + }); + } + const { t } = useTranslation(['footer']); return ( @@ -46,117 +114,180 @@ export default function Footer() { id="main-footer" className="bg-text-light-gray relative sm:grid sm:grid-cols-2 md:grid-cols-4 gap-5 p-5 z-50" > - {config.footer.navConfig.map((group) => ( -
-

{t(group.title)}

-
+
+ ); + })} + + {allPrismicFooter.edges.length <= 0 && ( +
+

2023 - AI Incident Database

+ + + Terms of use + +
+ + Privacy Policy + +
+ + + + + + + + + + + + + + + + + + + +
- + )} ); } diff --git a/site/gatsby-site/src/components/users/UserInfoCells.js b/site/gatsby-site/src/components/users/UserInfoCells.js new file mode 100644 index 0000000000..381237d26f --- /dev/null +++ b/site/gatsby-site/src/components/users/UserInfoCells.js @@ -0,0 +1,65 @@ +import React from 'react'; +import { format } from 'date-fns'; +import { FIND_USER } from '../../graphql/users'; +import { useQuery } from '@apollo/client/react'; +import { Badge, Spinner } from 'flowbite-react'; + +const UserCreationDateCell = ({ userId }) => { + const { data, loading } = useQuery(FIND_USER, { + variables: { query: { userId } }, + }); + + return ( + <> + {loading && ( +
+ +
+ )} + {!loading && + data?.user?.adminData?.creationDate && + format(new Date(data.user.adminData.creationDate), 'yyyy-MM-dd')} + + ); +}; + +const UserLastAuthDateCell = ({ userId }) => { + const { data, loading } = useQuery(FIND_USER, { + variables: { query: { userId } }, + }); + + return ( + <> + {loading && ( +
+ +
+ )} + {!loading && + data?.user?.adminData?.lastAuthenticationDate && + format(new Date(data.user.adminData.lastAuthenticationDate), 'yyyy-MM-dd')} + + ); +}; + +const UserEmailCell = ({ userId }) => { + const { data, loading } = useQuery(FIND_USER, { + variables: { query: { userId } }, + }); + + return ( + <> + {loading && ( +
+ +
+ )} + {!loading && + data && + data.user && + (data.user?.adminData?.email || Not found)} + + ); +}; + +export { UserCreationDateCell, UserLastAuthDateCell, UserEmailCell }; diff --git a/site/gatsby-site/src/components/users/UsersTable.js b/site/gatsby-site/src/components/users/UsersTable.js index 187af0792f..86c95b4a2e 100644 --- a/site/gatsby-site/src/components/users/UsersTable.js +++ b/site/gatsby-site/src/components/users/UsersTable.js @@ -1,12 +1,9 @@ import React, { useState } from 'react'; import { useFilters, usePagination, useSortBy, useTable } from 'react-table'; -import Table, { - DefaultColumnFilter, - DefaultColumnHeader, - DefaultDateCell, -} from 'components/ui/Table'; +import Table, { DefaultColumnFilter, DefaultColumnHeader } from 'components/ui/Table'; import { Badge, Button } from 'flowbite-react'; import UserEditModal from './UserEditModal'; +import { UserCreationDateCell, UserEmailCell, UserLastAuthDateCell } from './UserInfoCells'; function RolesCell({ cell }) { return ( @@ -35,7 +32,8 @@ export default function UsersTable({ data, className = '', ...props }) { { title: 'Email', accessor: 'adminData.email', - Cell: ({ cell }) => cell.value || Not found, + className: 'min-w-[240px]', + Cell: ({ row: { values } }) => , }, { title: 'Id', @@ -57,12 +55,12 @@ export default function UsersTable({ data, className = '', ...props }) { { title: 'Creation Date', accessor: 'adminData.creationDate', - Cell: DefaultDateCell, + Cell: ({ row: { values } }) => , }, { title: 'Last Login Date', accessor: 'adminData.lastAuthenticationDate', - Cell: DefaultDateCell, + Cell: ({ row: { values } }) => , }, { id: 'actions', @@ -88,7 +86,6 @@ export default function UsersTable({ data, className = '', ...props }) { columns, data, defaultColumn, - initialState: { sortBy: [{ id: 'email', desc: true }] }, }, useFilters, useSortBy, diff --git a/site/gatsby-site/src/graphql/users.js b/site/gatsby-site/src/graphql/users.js index 130be88eaf..e25caf6db0 100644 --- a/site/gatsby-site/src/graphql/users.js +++ b/site/gatsby-site/src/graphql/users.js @@ -7,12 +7,6 @@ export const FIND_USERS = gql` userId first_name last_name - adminData { - email - disabled - creationDate - lastAuthenticationDate - } } } `; diff --git a/site/gatsby-site/src/pages/apps/csettool/{mongodbAiidprodIncidents.incident_id}.js b/site/gatsby-site/src/pages/apps/csettool/{mongodbAiidprodIncidents.incident_id}.js index d39655990e..a83414802d 100644 --- a/site/gatsby-site/src/pages/apps/csettool/{mongodbAiidprodIncidents.incident_id}.js +++ b/site/gatsby-site/src/pages/apps/csettool/{mongodbAiidprodIncidents.incident_id}.js @@ -34,13 +34,15 @@ const ToolPage = (props) => { }; for (const classification of data.classifications) { - const json = classification.attributes.find( - (a) => a.short_name == attribute.short_name - ).value_json; + const item = classification.attributes.find((a) => a.short_name == attribute.short_name); - const value = JSON.parse(json); + if (item) { + const value = JSON.parse(item.value_json); - row[classification.namespace] = value; + row[classification.namespace] = value; + } else { + row[classification.namespace] = null; + } } rows.push(row);