diff --git a/mongo.md b/mongo.md index f49823cd48..82d05541fa 100644 --- a/mongo.md +++ b/mongo.md @@ -54,10 +54,10 @@ Administering data requires administrative access to the database. This access i ### Dates -* `date_downloaded`:`2019-07-25` # (String) Date the report was downloaded. -* `date_submitted`:`2019-07-25` # (String) Date the report was submitted to the AIID. This determines citation order. -* `date_modified`: `2019-07-25` # (String) Date the report was edited. -* `date_published`: `2019-07-25` # (String) The publication date of the report. +* `date_downloaded`:`2019-07-25` # (Date) Date the report was downloaded. +* `date_submitted`:`2019-07-25` # (Date) Date the report was submitted to the AIID. This determines citation order. +* `date_modified`: `2019-07-25` # (Date) Date the report was edited. +* `date_published`: `2019-07-25` # (Date) The publication date of the report. * `epoch_incident_date`: `1564016400` # (Int) Date the incident occurred in the Unix Epoch. * `epoch_date_downloaded`:`1564016400` # (Int) Date the report was downloaded in the Unix Epoch. * `epoch_date_submitted`:`1564016400` # (Int) Date the report was submitted to the AIID in the Unix Epoch. diff --git a/site/gatsby-site/cypress/e2e/incidentVariants.cy.js b/site/gatsby-site/cypress/e2e/incidentVariants.cy.js index a55169e768..c02e029fba 100644 --- a/site/gatsby-site/cypress/e2e/incidentVariants.cy.js +++ b/site/gatsby-site/cypress/e2e/incidentVariants.cy.js @@ -6,7 +6,7 @@ import { isCompleteReport, VARIANT_STATUS, } from '../../src/utils/variants'; -import { format, getUnixTime } from 'date-fns'; +import { getUnixTime } from 'date-fns'; const { gql } = require('@apollo/client'); const incidentId = 464; @@ -192,14 +192,14 @@ describe('Variants pages', () => { (req) => req.body.operationName == 'UpdateVariant' && req.body.variables.query.report_number === variant.report_number && - req.body.variables.set.date_published === new_date_published && + req.body.variables.set.date_published === new Date(new_date_published).toISOString() && req.body.variables.set.submitters[0] === variant.submitters[0] && req.body.variables.set.submitters[1] === variant.submitters[1] && req.body.variables.set.text === new_text && req.body.variables.set.inputs_outputs[0] === new_inputs_outputs_1 && req.body.variables.set.inputs_outputs[1] === new_inputs_outputs_2 && req.body.variables.set.tags.includes(VARIANT_STATUS.approved) && - req.body.variables.set.date_modified == format(now, 'yyyy-MM-dd') && + req.body.variables.set.date_modified == now.toISOString() && req.body.variables.set.epoch_date_modified == getUnixTime(now), 'updateVariant', { @@ -269,14 +269,14 @@ describe('Variants pages', () => { (req) => req.body.operationName == 'UpdateVariant' && req.body.variables.query.report_number === variant.report_number && - req.body.variables.set.date_published === new_date_published && + req.body.variables.set.date_published === new Date(new_date_published).toISOString() && req.body.variables.set.submitters[0] === variant.submitters[0] && req.body.variables.set.submitters[1] === new_submitter && req.body.variables.set.text === new_text && req.body.variables.set.inputs_outputs[0] === new_inputs_outputs_1 && req.body.variables.set.inputs_outputs[1] === new_inputs_outputs_2 && req.body.variables.set.tags.includes(VARIANT_STATUS.rejected) && - req.body.variables.set.date_modified == format(now, 'yyyy-MM-dd') && + req.body.variables.set.date_modified == now.toISOString() && req.body.variables.set.epoch_date_modified == getUnixTime(now), 'updateVariant', { @@ -346,14 +346,14 @@ describe('Variants pages', () => { (req) => req.body.operationName == 'UpdateVariant' && req.body.variables.query.report_number === variant.report_number && - req.body.variables.set.date_published === new_date_published && + req.body.variables.set.date_published === new Date(new_date_published).toISOString() && req.body.variables.set.submitters[0] === variant.submitters[0] && req.body.variables.set.submitters[1] === new_submitter && req.body.variables.set.text === new_text && req.body.variables.set.inputs_outputs[0] === new_inputs_outputs_1 && req.body.variables.set.inputs_outputs[1] === variant.inputs_outputs[1] && req.body.variables.set.tags == undefined && - req.body.variables.set.date_modified == format(now, 'yyyy-MM-dd') && + req.body.variables.set.date_modified == now.toISOString() && req.body.variables.set.epoch_date_modified == getUnixTime(now), 'updateVariant', { diff --git a/site/gatsby-site/cypress/e2e/integration/apps/variants.cy.js b/site/gatsby-site/cypress/e2e/integration/apps/variants.cy.js index 56d59263c6..7fa4ce23c3 100644 --- a/site/gatsby-site/cypress/e2e/integration/apps/variants.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/apps/variants.cy.js @@ -499,14 +499,14 @@ describe('Variants App', () => { (req) => req.body.operationName == 'UpdateVariant' && req.body.variables.query.report_number === variant.report_number && - req.body.variables.set.date_published === new_date_published && + req.body.variables.set.date_published === new Date(new_date_published).toISOString() && req.body.variables.set.submitters[0] === variant.submitters[0] && req.body.variables.set.submitters[1] === new_submitter && req.body.variables.set.text === new_text && req.body.variables.set.inputs_outputs[0] === new_inputs_outputs_1 && req.body.variables.set.inputs_outputs[1] === undefined && req.body.variables.set.tags.includes(VARIANT_STATUS.approved) && - req.body.variables.set.date_modified == format(now, 'yyyy-MM-dd') && + req.body.variables.set.date_modified == now.toISOString() && req.body.variables.set.epoch_date_modified == getUnixTime(now), 'updateVariant', { diff --git a/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js b/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js index 7f42ddab19..3f79f81cea 100644 --- a/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js +++ b/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js @@ -197,10 +197,9 @@ describe('Edit report', () => { const expectedReport = { authors: ['Test Author'], cloudinary_id: 'reports/test.com/test.jpg', - date_downloaded: '2022-01-01', + date_downloaded: new Date('2022-01-01').toISOString(), date_modified: format(now, 'yyyy-MM-dd'), - date_published: '2022-02-02', - epoch_date_downloaded: 1640995200, + date_published: new Date('2022-02-02').toISOString(), epoch_date_modified: getUnixTime(now), epoch_date_published: 1643760000, flag: null, @@ -220,8 +219,10 @@ describe('Edit report', () => { cy.wait('@updateReport').then((xhr) => { expect(xhr.request.body.variables.query.report_number).eq(expectedReport.report_number); - - expect(xhr.request.body.variables.set).to.deep.eq(expectedReport); + expect({ + ...xhr.request.body.variables.set, + date_modified: format(new Date(xhr.request.body.variables.set.date_modified), 'yyyy-MM-dd'), + }).to.deep.eq(expectedReport); }); cy.wait('@logReportHistory') @@ -232,6 +233,7 @@ describe('Edit report', () => { ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, + date_modified: input.date_modified, }; expect(input).to.deep.eq(expectedResult); @@ -401,10 +403,9 @@ describe('Edit report', () => { const expectedReport = { authors: ['Test Author'], cloudinary_id: 'reports/test.com/test.jpg', - date_downloaded: '2022-01-01', + date_downloaded: new Date('2022-01-01').toISOString(), date_modified: format(now, 'yyyy-MM-dd'), - date_published: '2022-02-02', - epoch_date_downloaded: 1640995200, + date_published: new Date('2022-02-02').toISOString(), epoch_date_modified: getUnixTime(now), epoch_date_published: 1643760000, flag: null, @@ -424,8 +425,10 @@ describe('Edit report', () => { cy.wait('@updateReport').then((xhr) => { expect(xhr.request.body.variables.query.report_number).eq(10); - - expect(xhr.request.body.variables.set).deep.eq(expectedReport); + expect({ + ...xhr.request.body.variables.set, + date_modified: format(new Date(xhr.request.body.variables.set.date_modified), 'yyyy-MM-dd'), + }).to.deep.eq(expectedReport); }); cy.wait('@logReportHistory') @@ -436,6 +439,7 @@ describe('Edit report', () => { ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, + date_modified: input.date_modified, }; expect(input).to.deep.eq(expectedResult); @@ -666,11 +670,10 @@ describe('Edit report', () => { authors: ['Marco Acevedo'], cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: '2019-04-13', + date_downloaded: new Date('2019-04-13').toISOString(), date_modified: format(now, 'yyyy-MM-dd'), - date_published: '2015-07-11', + date_published: new Date('2015-07-11').toISOString(), editor_notes: '', - epoch_date_downloaded: 1555113600, epoch_date_modified: getUnixTime(now), epoch_date_published: 1436572800, flag: null, @@ -692,7 +695,10 @@ describe('Edit report', () => { .its('request.body.variables') .then((variables) => { expect(variables.query.report_number).to.equal(23); - expect(variables.set).deep.eq(expectedReport); + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).deep.eq(expectedReport); }); cy.wait('@logReportHistory') @@ -703,6 +709,7 @@ describe('Edit report', () => { ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, + date_modified: input.date_modified, }; expect(input).to.deep.eq(expectedResult); @@ -934,8 +941,8 @@ describe('Edit report', () => { authors: ['Marco Acevedo'], cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: '2019-04-13', - date_published: '2015-07-11', + date_downloaded: new Date('2019-04-13').toISOString(), + date_published: new Date('2015-07-11').toISOString(), flag: null, image_url: 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', @@ -950,7 +957,6 @@ describe('Edit report', () => { editor_notes: '', language: 'en', source_domain: 'change.org', - epoch_date_downloaded: 1555113600, epoch_date_published: 1436572800, date_modified: format(now, 'yyyy-MM-dd'), epoch_date_modified: getUnixTime(now), @@ -960,7 +966,10 @@ describe('Edit report', () => { .its('request.body.variables') .then((variables) => { expect(variables.query.report_number).to.equal(23); - expect(variables.set).deep.eq(expectedReport); + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).deep.eq(expectedReport); }); cy.wait('@logReportHistory') @@ -971,6 +980,7 @@ describe('Edit report', () => { ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, + date_modified: input.date_modified, }; expect(input).to.deep.eq(expectedResult); @@ -1128,8 +1138,8 @@ describe('Edit report', () => { authors: ['Marco Acevedo'], cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: '2019-04-13', - date_published: '2015-07-11', + date_downloaded: new Date('2019-04-13').toISOString(), + date_published: new Date('2015-07-11').toISOString(), flag: null, image_url: 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', @@ -1144,7 +1154,6 @@ describe('Edit report', () => { editor_notes: '', language: 'en', source_domain: 'change.org', - epoch_date_downloaded: 1555113600, epoch_date_published: 1436572800, date_modified: format(now, 'yyyy-MM-dd'), epoch_date_modified: getUnixTime(now), @@ -1154,7 +1163,10 @@ describe('Edit report', () => { .its('request.body.variables') .then((variables) => { expect(variables.query.report_number).to.equal(23); - expect(variables.set).deep.eq(expectedReport); + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).deep.eq(expectedReport); }); cy.wait('@logReportHistory') @@ -1165,6 +1177,7 @@ describe('Edit report', () => { ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, + date_modified: input.date_modified, }; expect(input).to.deep.eq(expectedResult); diff --git a/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js b/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js index bc100dea5b..3c67252f39 100644 --- a/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js +++ b/site/gatsby-site/cypress/e2e/unit/functions/promoteSubmissionToReport.cy.js @@ -225,10 +225,10 @@ describe('Functions', () => { report_number: 2, is_incident_report: true, title: 'Submisssion 1 title', - date_downloaded: '2020-10-30', - date_modified: '2021-07-27', - date_published: '2017-05-03', - date_submitted: '2020-10-30', + date_downloaded: new Date('2020-10-30'), + date_modified: new Date('2021-07-27'), + date_published: new Date('2017-05-03'), + date_submitted: new Date('2020-10-30'), epoch_date_downloaded: 1604016000, epoch_date_modified: 1686182943, epoch_date_published: 1493769600, @@ -384,10 +384,10 @@ describe('Functions', () => { report_number: 2, is_incident_report: true, title: 'Submisssion 1 title', - date_downloaded: '2020-10-30', - date_modified: '2021-07-27', - date_published: '2017-05-03', - date_submitted: '2020-10-30', + date_downloaded: new Date('2020-10-30'), + date_modified: new Date('2021-07-27'), + date_published: new Date('2017-05-03'), + date_submitted: new Date('2020-10-30'), epoch_date_downloaded: 1604016000, epoch_date_modified: 1686182943, epoch_date_published: 1493769600, @@ -541,10 +541,10 @@ describe('Functions', () => { report_number: 2, is_incident_report: false, title: 'Submisssion 1 title', - date_downloaded: '2020-10-30', - date_modified: '2021-07-27', - date_published: '2017-05-03', - date_submitted: '2020-10-30', + date_downloaded: new Date('2020-10-30'), + date_modified: new Date('2021-07-27'), + date_published: new Date('2017-05-03'), + date_submitted: new Date('2020-10-30'), epoch_date_downloaded: 1604016000, epoch_date_modified: 1686182943, epoch_date_published: 1493769600, @@ -843,10 +843,10 @@ describe('Functions', () => { report_number: 2, is_incident_report: true, title: 'Submisssion 1 title', - date_downloaded: '2020-10-30', - date_modified: '2021-07-27', - date_published: '2017-05-03', - date_submitted: '2020-10-30', + date_downloaded: new Date('2020-10-30'), + date_modified: new Date('2021-07-27'), + date_published: new Date('2017-05-03'), + date_submitted: new Date('2020-10-30'), epoch_date_downloaded: 1604016000, epoch_date_modified: 1686182943, epoch_date_published: 1493769600, diff --git a/site/gatsby-site/i18n/locales/es/translation.json b/site/gatsby-site/i18n/locales/es/translation.json index a2a6683179..f1e7baab4d 100644 --- a/site/gatsby-site/i18n/locales/es/translation.json +++ b/site/gatsby-site/i18n/locales/es/translation.json @@ -283,6 +283,7 @@ "csetChartDeveloped": "CSET ha desarrollado definiciones específicas para las frases subrayadas que pueden diferir de las definiciones de otras organizaciones. Como resultado, otras organizaciones pueden hacer diferentes evaluaciones sobre si un incidente de IA en particular es (o no) un daño de IA. Los detalles sobre las definiciones de CSET para el daño de la IA se pueden encontrar <1>aquí.", "csetChartMail": "Cada incidente es clasificado de forma independiente por dos anotadores CSET. Las anotaciones se revisan por pares y finalmente se seleccionan al azar para el control de calidad antes de la publicación. A pesar de este riguroso proceso, ocurren errores y se invita a los lectores a <1>informar de cualquier error que puedan descubrir mientras navegan.", "[Untitled Report]": "[Informe sin título]", + "YYYY-MM-DD": "AAAA-MM-DD", "Incidents": "Incidentes", "Incident and Issue Reports": "Incidentes e Informes de Problemas", "Issue Reports": "Informes de Problemas", diff --git a/site/gatsby-site/i18n/locales/fr/translation.json b/site/gatsby-site/i18n/locales/fr/translation.json index 8f7b0208ba..98d3bedb7b 100644 --- a/site/gatsby-site/i18n/locales/fr/translation.json +++ b/site/gatsby-site/i18n/locales/fr/translation.json @@ -271,6 +271,7 @@ "csetChartDeveloped": "Le CSET a développé des définitions spécifiques pour les phrases soulignées qui peuvent différer des définitions d'autres organisations. Par conséquent, d'autres organisations peuvent procéder à des évaluations différentes pour déterminer si un incident d'IA particulier est (ou n'est pas) un préjudice lié à l'IA. Des détails sur les définitions du CSET pour les dommages causés par l'IA peuvent être trouvés <1>ici.", "csetChartMail": "Chaque incident est classé indépendamment par deux annotateurs CSET. Les annotations sont examinées par des pairs et finalement sélectionnées au hasard pour un contrôle qualité avant publication. Malgré ce processus rigoureux, des erreurs se produisent et les lecteurs sont invités à <1>signaler toute erreur qu'ils pourraient découvrir en naviguant.", "[Untitled Report]": "[Rapport sans titre]", + "YYYY-MM-DD": "AAAA-MM-JJ", "Incidents": "Incidents", "Incident and Issue Reports": "Incidents et rapports de problèmes", "Issue Reports": "Rapports de problèmes", diff --git a/site/gatsby-site/migrations/2023.11.13T13.39.12.update-reports-date-types.js b/site/gatsby-site/migrations/2023.11.13T13.39.12.update-reports-date-types.js new file mode 100644 index 0000000000..ec373e816b --- /dev/null +++ b/site/gatsby-site/migrations/2023.11.13T13.39.12.update-reports-date-types.js @@ -0,0 +1,79 @@ +const config = require('../config'); + +/** + * + * @param {{context: {client: import('mongodb').MongoClient}}} context + */ + +exports.up = async ({ context: { client } }) => { + await client.connect(); + + const db = client.db(config.realm.production_db.db_name); + + const dbHistory = client.db(config.realm.production_db.db_name_history); + + const reports = db.collection('reports'); + + const reportsHistory = dbHistory.collection('reports'); + + let docs = await reports.find({}).toArray(); + + let docsHistory = await reportsHistory.find({}).toArray(); + + await Promise.all( + docs.map((doc) => { + // Convert epoch timestamps (in seconds) to milliseconds, and then to MongoDB's Date type + const date_downloaded = new Date(doc.epoch_date_downloaded * 1000); + + const date_modified = new Date(doc.epoch_date_modified * 1000); + + const date_published = new Date(doc.epoch_date_published * 1000); + + const date_submitted = new Date(doc.epoch_date_submitted * 1000); + + // Update the collection with the new Date type values + return reports.updateOne( + { _id: doc._id }, + { + $set: { + date_downloaded: date_downloaded, + date_modified: date_modified, + date_published: date_published, + date_submitted: date_submitted, + }, + } + ); + }) + ); + + await Promise.all( + docsHistory.map((doc) => { + // Convert epoch timestamps (in seconds) to milliseconds, and then to MongoDB's Date type + const date_downloaded = new Date(doc.epoch_date_downloaded * 1000); + + const date_modified = new Date(doc.epoch_date_modified * 1000); + + const date_published = new Date(doc.epoch_date_published * 1000); + + const date_submitted = new Date(doc.epoch_date_submitted * 1000); + + // Update the collection with the new Date type values + return reports.updateOne( + { _id: doc._id }, + { + $set: { + date_downloaded: date_downloaded, + date_modified: date_modified, + date_published: date_published, + date_submitted: date_submitted, + }, + } + ); + }) + ); + + console.log('Migration completed!'); +}; + +/** @type {import('umzug').MigrationFn} */ +exports.down = async () => {}; diff --git a/site/gatsby-site/package-lock.json b/site/gatsby-site/package-lock.json index 8f6ba03c86..62b4ddeb3b 100644 --- a/site/gatsby-site/package-lock.json +++ b/site/gatsby-site/package-lock.json @@ -74,6 +74,7 @@ "react-bootstrap-daterangepicker": "^7.0.0", "react-bootstrap-typeahead": "6.0.0-alpha.6", "react-d3-cloud": "^1.0.6", + "react-datetime": "^3.2.0", "react-dom": "^18.2.0", "react-feather": "^2.0.9", "react-helmet": "^6.1.0", @@ -28748,6 +28749,18 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "node_modules/react-datetime": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-datetime/-/react-datetime-3.2.0.tgz", + "integrity": "sha512-w5XdeNIGzBht9CadaZIJhKUhEcDTgH0XokKxGPCxeeJRYL7B3HIKA8CM6Q0xej2JFJt0n5d+zi3maMwaY3262A==", + "dependencies": { + "prop-types": "^15.5.7" + }, + "peerDependencies": { + "moment": "^2.16.0", + "react": "^16.5.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", diff --git a/site/gatsby-site/package.json b/site/gatsby-site/package.json index d4ee5386ed..7429b64d5d 100644 --- a/site/gatsby-site/package.json +++ b/site/gatsby-site/package.json @@ -70,6 +70,7 @@ "react-bootstrap-daterangepicker": "^7.0.0", "react-bootstrap-typeahead": "6.0.0-alpha.6", "react-d3-cloud": "^1.0.6", + "react-datetime": "^3.2.0", "react-dom": "^18.2.0", "react-feather": "^2.0.9", "react-helmet": "^6.1.0", diff --git a/site/gatsby-site/src/components/forms/IncidentReportForm.js b/site/gatsby-site/src/components/forms/IncidentReportForm.js index 810c63d6ca..ddb75ab2ca 100644 --- a/site/gatsby-site/src/components/forms/IncidentReportForm.js +++ b/site/gatsby-site/src/components/forms/IncidentReportForm.js @@ -4,7 +4,7 @@ import { Form, useFormikContext } from 'formik'; import * as yup from 'yup'; import TextInputGroup from '../../components/forms/TextInputGroup'; import useToastContext, { SEVERITY } from '../../hooks/useToast'; -import { dateRegExp } from '../../utils/date'; +import { dateTimeRegExp } from '../../utils/date'; import { getCloudinaryPublicID } from '../../utils/cloudinary'; import PreviewImageInputGroup from 'components/forms/PreviewImageInputGroup'; import 'react-bootstrap-typeahead/css/Typeahead.css'; @@ -21,7 +21,6 @@ import { faTag, faPenNib, faMedal, - faCalendar, faImage, faLink, faLanguage, @@ -29,6 +28,7 @@ import { faNewspaper, faAlignLeft, faTenge, + faCalendar, } from '@fortawesome/free-solid-svg-icons'; import IncidentsField from 'components/incidents/IncidentsField'; import VariantForm from 'components/variants/VariantForm'; @@ -77,11 +77,11 @@ export const schema = yup.object().shape({ .required('*Text is required'), date_published: yup .string() - .matches(dateRegExp, '*Date is not valid, must be `YYYY-MM-DD`') + .matches(dateTimeRegExp, '*Date is not valid, must be `YYYY-MM-DD`') .required('*Date published is required'), date_downloaded: yup .string() - .matches(dateRegExp, '*Date is not valid, must be `YYYY-MM-DD`') + .matches(dateTimeRegExp, '*Date is not valid, must be `YYYY-MM-DD`') .required('*Date downloaded required'), url: yup .string() @@ -156,6 +156,24 @@ const IncidentReportForm = () => { setFieldValue('cloudinary_id', values.image_url ? getCloudinaryPublicID(values.image_url) : ''); }, [values.image_url]); + useEffect(() => { + if (values?.date_published) { + const publishedDate = new Date(values.date_published); + + const formattedDate = publishedDate.toISOString().split('T')[0]; + + setFieldValue('date_published', formattedDate); + } + + if (values?.date_downloaded) { + const publishedDate = new Date(values.date_downloaded); + + const formattedDate = publishedDate.toISOString().split('T')[0]; + + setFieldValue('date_downloaded', formattedDate); + } + }, [values?.date_published, values?.date_downloaded]); + useEffect(() => { Object.keys(errors).map((key) => { setFieldTouched(key, true); @@ -273,22 +291,24 @@ const IncidentReportForm = () => { className="mt-3" {...TextInputGroupProps} /> + + {item.source_domain} ·{' '} {item.date_published - ? item.date_published.substring(0, 4) + ? format(new Date(item.date_published), 'yyyy') : item.epoch_date_published ? format(fromUnixTime(item.epoch_date_published), 'yyyy') : 'Needs publish date'} diff --git a/site/gatsby-site/src/components/variants/VariantEditModal.js b/site/gatsby-site/src/components/variants/VariantEditModal.js index f8a9688e47..3281f78fc7 100644 --- a/site/gatsby-site/src/components/variants/VariantEditModal.js +++ b/site/gatsby-site/src/components/variants/VariantEditModal.js @@ -11,7 +11,7 @@ import { getVariantStatus, VARIANT_STATUS } from 'utils/variants'; import { VariantStatusBadge } from './VariantList'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; -import { format, getUnixTime } from 'date-fns'; +import { getUnixTime } from 'date-fns'; import Link from 'components/ui/Link'; import DefaultSkeleton from 'elements/Skeletons/Default'; @@ -59,7 +59,7 @@ export default function VariantEditModal({ const handleSubmit = async (values) => { try { const updated = { - date_published: values.date_published, + date_published: new Date(values.date_published), submitters: values.submitters, text: values.text, inputs_outputs: values.inputs_outputs, @@ -74,7 +74,7 @@ export default function VariantEditModal({ const today = new Date(); - updated.date_modified = format(today, 'yyyy-MM-dd'); + updated.date_modified = today; updated.epoch_date_modified = getUnixTime(today); await updateVariant({ diff --git a/site/gatsby-site/src/components/variants/VariantForm.js b/site/gatsby-site/src/components/variants/VariantForm.js index ffd595e4e8..e02a054e08 100644 --- a/site/gatsby-site/src/components/variants/VariantForm.js +++ b/site/gatsby-site/src/components/variants/VariantForm.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { Field, FieldArray, useFormikContext } from 'formik'; import * as yup from 'yup'; import { Trans, useTranslation } from 'react-i18next'; @@ -6,10 +6,14 @@ import { Button } from 'flowbite-react'; import TextInputGroup from 'components/forms/TextInputGroup'; import TagsInputGroup from 'components/forms/TagsInputGroup'; import Label from 'components/forms/Label'; +import { dateRegExp, isPastDate } from 'utils/date'; // Schema for yup export const schema = yup.object().shape({ - date_published: yup.date(), + date_published: yup + .string() + .matches(dateRegExp, '*Date is not valid, must be `YYYY-MM-DD`') + .test(isPastDate), submitters: yup .string() .matches(/^.{3,}$/, { @@ -33,10 +37,29 @@ export const schema = yup.object().shape({ }); const VariantForm = ({ scrollInputsOutputs = false, allFieldsForm = true }) => { - const { values, errors, touched, handleChange, handleBlur, isSubmitting } = useFormikContext(); + const { values, errors, touched, handleChange, handleBlur, isSubmitting, setFieldValue } = + useFormikContext(); const { t } = useTranslation(['variants']); + useEffect(() => { + if (values?.date_published) { + const publishedDate = new Date(values.date_published); + + const formattedDate = publishedDate.toISOString().split('T')[0]; + + setFieldValue('date_published', formattedDate); + } + + if (values?.date_downloaded) { + const publishedDate = new Date(values.date_downloaded); + + const formattedDate = publishedDate.toISOString().split('T')[0]; + + setFieldValue('date_downloaded', formattedDate); + } + }, [values?.date_published, values?.date_downloaded]); + return (
{allFieldsForm && ( diff --git a/site/gatsby-site/src/components/variants/VariantList.js b/site/gatsby-site/src/components/variants/VariantList.js index aaabccf782..83ec75dbb7 100644 --- a/site/gatsby-site/src/components/variants/VariantList.js +++ b/site/gatsby-site/src/components/variants/VariantList.js @@ -18,6 +18,7 @@ import VariantEditModal from './VariantEditModal'; import { Formik } from 'formik'; import { useLazyQuery, useMutation } from '@apollo/client'; import { CREATE_VARIANT, FIND_INCIDENT_VARIANTS } from '../../graphql/variants'; +import { format } from 'date-fns'; export const VariantStatusBadge = ({ status }) => { let badgeClass; @@ -68,7 +69,9 @@ const VariantCard = ({ variant, incidentId }) => {
Incident Date:
-
{variant.date_published}
+ {variant.date_published && ( +
{format(new Date(variant.date_published), 'yyyy-MM-dd')}
+ )}
{variant.text && ( <> diff --git a/site/gatsby-site/src/graphql/reports.js b/site/gatsby-site/src/graphql/reports.js index da86efb0e3..7883a4b029 100644 --- a/site/gatsby-site/src/graphql/reports.js +++ b/site/gatsby-site/src/graphql/reports.js @@ -47,6 +47,7 @@ export const FIND_REPORT_WITH_TRANSLATIONS = gql` submitters date_published date_downloaded + date_modified image_url text plain_text diff --git a/site/gatsby-site/src/pages/apps/reports.js b/site/gatsby-site/src/pages/apps/reports.js index b766468725..614c82f01d 100644 --- a/site/gatsby-site/src/pages/apps/reports.js +++ b/site/gatsby-site/src/pages/apps/reports.js @@ -32,6 +32,9 @@ const query = gql` epoch_date_downloaded report_number flag + date_downloaded + date_modified + date_submitted } } } @@ -115,31 +118,31 @@ export default function Incidents(props) { { className: 'min-w-[240px]', title: t('Date Submitted'), - accessor: 'epoch_date_submitted', + accessor: 'date_submitted', width: 240, Filter: SelectDatePickerFilter, Cell: ({ row: { values } }) => { - return <>{formatDateField(values.epoch_date_submitted)}; + return <>{formatDateField(values.date_submitted)}; }, }, { className: 'min-w-[240px]', title: t('Date Modified'), - accessor: 'epoch_date_modified', + accessor: 'date_modified', width: 240, Filter: SelectDatePickerFilter, Cell: ({ row: { values } }) => { - return <>{formatDateField(values.epoch_date_modified)}; + return <>{formatDateField(values.date_modified)}; }, }, { className: 'min-w-[240px]', title: t('Date Downloaded'), - accessor: 'epoch_date_downloaded', + accessor: 'date_downloaded', width: 240, Filter: SelectDatePickerFilter, Cell: ({ row: { values } }) => { - return <>{formatDateField(values.epoch_date_downloaded)}; + return <>{formatDateField(values.date_downloaded)}; }, }, { @@ -184,7 +187,7 @@ export default function Incidents(props) { const filterTypes = { epoch_date_submitted: filterDateFunction, epoch_date_modified: filterDateFunction, - epoch_date_downloaded: filterDateFunction, + date_downloaded: filterDateFunction, }; const table = useTable( diff --git a/site/gatsby-site/src/pages/cite/edit.js b/site/gatsby-site/src/pages/cite/edit.js index 1b7db6b766..b0e41f8da7 100644 --- a/site/gatsby-site/src/pages/cite/edit.js +++ b/site/gatsby-site/src/pages/cite/edit.js @@ -14,7 +14,7 @@ import { } from '../../graphql/reports'; import { FIND_INCIDENTS } from '../../graphql/incidents'; import { useMutation, useQuery } from '@apollo/client/react/hooks'; -import { format, getUnixTime } from 'date-fns'; +import { getUnixTime } from 'date-fns'; import { stripMarkdown } from '../../utils/typography'; import { Formik } from 'formik'; import pick from 'lodash/pick'; @@ -184,12 +184,14 @@ function EditCitePage(props) { const now = new Date(); - values.date_modified = format(now, 'yyyy-MM-dd'); + values.date_modified = now; - values.epoch_date_downloaded = getUnixTime(new Date(values.date_downloaded)); values.epoch_date_published = getUnixTime(new Date(values.date_published)); values.epoch_date_modified = getUnixTime(now); + values.date_published = new Date(values.date_published); + values.date_downloaded = new Date(values.date_downloaded); + const updated = pick(values, reportFields); await updateReport({ diff --git a/site/gatsby-site/src/utils/date.js b/site/gatsby-site/src/utils/date.js index fc0a3bcf3a..6be814f1ec 100644 --- a/site/gatsby-site/src/utils/date.js +++ b/site/gatsby-site/src/utils/date.js @@ -2,6 +2,8 @@ import { parse } from 'date-fns'; // RegEx for date validation export const dateRegExp = /^(\+?\d{4})?\s?-?\s?(\(?\d{2}\)?)\s?-?\s?(\(?\d{2}\)?)\s?-?\s?(\?)?$/; +export const dateTimeRegExp = + /(\d{4}-[01]\d-[0-3]\d(T[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)?)?)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)?)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)?)/; export const validateDate = (date) => { const dateStr = date + ''; diff --git a/site/gatsby-site/typeDefs.js b/site/gatsby-site/typeDefs.js index 005845e39c..4a2df4f977 100644 --- a/site/gatsby-site/typeDefs.js +++ b/site/gatsby-site/typeDefs.js @@ -63,10 +63,10 @@ const typeDefs = ` image_url: String url: String submitters: [String] - date_published: String - date_submitted: String - date_modified: String - date_downloaded: String + date_published: Date + date_submitted: Date + date_modified: Date + date_downloaded: Date source_domain: String mongodb_id: String text: String diff --git a/site/realm/data_sources/mongodb-atlas/aiidprod/reports/schema.json b/site/realm/data_sources/mongodb-atlas/aiidprod/reports/schema.json index c844cb986b..7ddd931ff9 100644 --- a/site/realm/data_sources/mongodb-atlas/aiidprod/reports/schema.json +++ b/site/realm/data_sources/mongodb-atlas/aiidprod/reports/schema.json @@ -13,16 +13,16 @@ "bsonType": "string" }, "date_downloaded": { - "bsonType": "string" + "bsonType": "date" }, "date_modified": { - "bsonType": "string" + "bsonType": "date" }, "date_published": { - "bsonType": "string" + "bsonType": "date" }, "date_submitted": { - "bsonType": "string" + "bsonType": "date" }, "description": { "bsonType": "string" diff --git a/site/realm/data_sources/mongodb-atlas/history/reports/schema.json b/site/realm/data_sources/mongodb-atlas/history/reports/schema.json index fc7c9b9dee..d250f7343f 100644 --- a/site/realm/data_sources/mongodb-atlas/history/reports/schema.json +++ b/site/realm/data_sources/mongodb-atlas/history/reports/schema.json @@ -13,16 +13,16 @@ "bsonType": "string" }, "date_downloaded": { - "bsonType": "string" + "bsonType": "date" }, "date_modified": { - "bsonType": "string" + "bsonType": "date" }, "date_published": { - "bsonType": "string" + "bsonType": "date" }, "date_submitted": { - "bsonType": "string" + "bsonType": "date" }, "description": { "bsonType": "string" diff --git a/site/realm/functions/createVariant.js b/site/realm/functions/createVariant.js index 8309e4a98d..434c36c6bb 100644 --- a/site/realm/functions/createVariant.js +++ b/site/realm/functions/createVariant.js @@ -44,10 +44,10 @@ exports = async (input) => { report_number, is_incident_report: false, title: '', - date_downloaded: todayFormated, - date_modified: todayFormated, - date_published: input.variant.date_published ? input.variant.date_published : todayFormated, - date_submitted: todayFormated, + date_downloaded: now, + date_modified: now, + date_published: input.variant.date_published ? new Date(input.variant.date_published) : now, + date_submitted: now, epoch_date_downloaded: getUnixTime(todayFormated), epoch_date_modified: getUnixTime(now.toString()), epoch_date_published: getUnixTime(input.variant.date_published ? input.variant.date_published : todayFormated), diff --git a/site/realm/functions/promoteSubmissionToReport.js b/site/realm/functions/promoteSubmissionToReport.js index 0029dde991..71ca7aabd2 100644 --- a/site/realm/functions/promoteSubmissionToReport.js +++ b/site/realm/functions/promoteSubmissionToReport.js @@ -139,10 +139,10 @@ exports = async (input) => { report_number, is_incident_report: input.is_incident_report, title: submission.title, - date_downloaded: submission.date_downloaded, - date_modified: submission.date_modified, - date_published: submission.date_published, - date_submitted: submission.date_submitted, + date_downloaded: new Date(submission.date_downloaded), + date_modified: new Date(submission.date_modified), + date_published: new Date(submission.date_published), + date_submitted: new Date(submission.date_submitted), epoch_date_downloaded: getUnixTime(submission.date_downloaded), epoch_date_modified: submission.epoch_date_modified, epoch_date_published: getUnixTime(submission.date_published),