From 9abd466397b2e56ba383808212daece7064a26b7 Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Mon, 9 Oct 2023 16:19:44 +0200 Subject: [PATCH] Renamed reason to description in recommendations table (#18527) fixes https://github.com/TryGhost/Product/issues/4005 We no longer use the 'reason' of a recommendation, but allow a flexible description instead. Because this is a breaking change in the API, we do this before making this feature GA. - Added new database utils for renaming a column - Added new migration to rename the column - Updated all references in code --- .../src/api/recommendations.ts | 2 +- .../AddRecommendationModal.tsx | 4 +- .../AddRecommendationModalConfirm.tsx | 6 +- .../EditRecommendationModal.tsx | 6 +- ....tsx => RecommendationDescriptionForm.tsx} | 42 +-- .../acceptance/site/recommendations.test.ts | 4 +- .../test/utils/responses/recommendations.json | 2 +- .../components/pages/RecommendationsPage.js | 10 +- .../frontend/helpers/tpl/recommendations.hbs | 2 +- .../server/data/migrations/utils/schema.js | 33 ++- ...e-recommendations-reason-to-description.js | 3 + .../core/core/server/data/schema/commands.js | 20 ++ ghost/core/core/server/data/schema/schema.js | 2 +- .../recommendations.test.js.snap | 128 +++++----- .../e2e-api/admin/recommendations.test.js | 22 +- .../recommendations.test.js.snap | 30 +-- .../e2e-api/content/recommendations.test.js | 2 +- .../e2e-api/members/recommendations.test.js | 2 +- .../recommendation-emails.test.js.snap | 239 ++++++++++++++++++ .../services/recommendation-emails.test.js | 2 +- .../frontend/helpers/recommendations.test.js | 20 +- .../unit/server/data/schema/integrity.test.js | 2 +- .../src/BookshelfRecommendationRepository.ts | 6 +- ghost/recommendations/src/Recommendation.ts | 20 +- .../src/RecommendationController.ts | 8 +- .../BookshelfRecommendationRepository.test.ts | 12 +- .../test/Recommendation.test.ts | 32 +-- .../test/RecommendationController.test.ts | 36 +-- .../test/RecommendationService.test.ts | 38 +-- .../test/WellknownService.test.ts | 4 +- 30 files changed, 515 insertions(+), 224 deletions(-) rename apps/admin-x-settings/src/components/settings/site/recommendations/{RecommendationReasonForm.tsx => RecommendationDescriptionForm.tsx} (71%) create mode 100644 ghost/core/core/server/data/migrations/versions/5.69/2023-10-06-15-06-00-rename-recommendations-reason-to-description.js diff --git a/apps/admin-x-settings/src/api/recommendations.ts b/apps/admin-x-settings/src/api/recommendations.ts index 53c6855b9f..25f5001c7f 100644 --- a/apps/admin-x-settings/src/api/recommendations.ts +++ b/apps/admin-x-settings/src/api/recommendations.ts @@ -4,7 +4,7 @@ import {Meta, apiUrl, createInfiniteQuery, createMutation, useFetchApi} from '.. export type Recommendation = { id: string title: string - reason: string|null + description: string|null excerpt: string|null // Fetched from the site meta data featured_image: string|null // Fetched from the site meta data favicon: string|null // Fetched from the site meta data diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx index faab2694e5..2aeda99a91 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/AddRecommendationModal.tsx @@ -61,7 +61,7 @@ const AddRecommendationModal: React.FC = ({r }, onSaveError: handleError, onValidate: (state) => { - const newErrors = validateReasonForm(state); + const newErrors = validateDescriptionForm(state); if (Object.keys(newErrors).length !== 0) { showToast({ @@ -127,7 +127,7 @@ const AddRecommendationModalConfirm: React.FC = ({r } }} > - + ; }; diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/EditRecommendationModal.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/EditRecommendationModal.tsx index 41d2e26bd6..4d5feb3597 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/EditRecommendationModal.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/EditRecommendationModal.tsx @@ -2,7 +2,7 @@ import ConfirmationModal from '../../../../admin-x-ds/global/modal/ConfirmationM import Modal from '../../../../admin-x-ds/global/modal/Modal'; import NiceModal, {useModal} from '@ebay/nice-modal-react'; import React from 'react'; -import RecommendationReasonForm, {validateReasonForm} from './RecommendationReasonForm'; +import RecommendationDescriptionForm, {validateDescriptionForm} from './RecommendationDescriptionForm'; import useForm from '../../../../hooks/useForm'; import useHandleError from '../../../../utils/api/handleError'; import useRouting from '../../../../hooks/useRouting'; @@ -33,7 +33,7 @@ const EditRecommendationModal: React.FC { - const newErrors = validateReasonForm(state); + const newErrors = validateDescriptionForm(state); if (Object.keys(newErrors).length !== 0) { showToast({ @@ -119,7 +119,7 @@ const EditRecommendationModal: React.FC - + ; }; diff --git a/apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationReasonForm.tsx b/apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationDescriptionForm.tsx similarity index 71% rename from apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationReasonForm.tsx rename to apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationDescriptionForm.tsx index 04cc7e3c17..e65936362e 100644 --- a/apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationReasonForm.tsx +++ b/apps/admin-x-settings/src/components/settings/site/recommendations/RecommendationDescriptionForm.tsx @@ -18,7 +18,7 @@ interface Props { setErrors: (errors: ErrorMessages) => void } -export const validateReasonFormField = function (errors: ErrorMessages, field: 'title'|'reason', value: string|null) { +export const validateDescriptionFormField = function (errors: ErrorMessages, field: 'title'|'description', value: string|null) { const cloned = {...errors}; switch (field) { case 'title': @@ -28,11 +28,11 @@ export const validateReasonFormField = function (errors: ErrorMessages, field: ' delete cloned.title; } break; - case 'reason': + case 'description': if (value && value.length > 200) { - cloned.reason = 'Description cannot be longer than 200 characters'; + cloned.description = 'Description cannot be longer than 200 characters'; } else { - delete cloned.reason; + delete cloned.description; } break; default: @@ -43,16 +43,16 @@ export const validateReasonFormField = function (errors: ErrorMessages, field: ' return cloned; }; -export const validateReasonForm = function (formState: EditOrAddRecommendation) { +export const validateDescriptionForm = function (formState: EditOrAddRecommendation) { let newErrors: ErrorMessages = {}; - newErrors = validateReasonFormField(newErrors, 'title', formState.title); - newErrors = validateReasonFormField(newErrors, 'reason', formState.reason); + newErrors = validateDescriptionFormField(newErrors, 'title', formState.title); + newErrors = validateDescriptionFormField(newErrors, 'description', formState.description); return newErrors; }; -const RecommendationReasonForm: React.FC> = ({showURL, formState, updateForm, errors, clearError, setErrors}) => { - const [reasonLength, setReasonLength] = React.useState(formState?.reason?.length || 0); - const reasonLengthColor = reasonLength > 200 ? 'text-red' : 'text-green'; +const RecommendationDescriptionForm: React.FC> = ({showURL, formState, updateForm, errors, clearError, setErrors}) => { + const [descriptionLength, setDescriptionLength] = React.useState(formState?.description?.length || 0); + const descriptionLengthColor = descriptionLength > 200 ? 'text-red' : 'text-green'; // Do an intial validation on mounting const didValidate = React.useRef(false); @@ -61,7 +61,7 @@ const RecommendationReasonForm: React.FC {formState.title} - {formState.reason && {formState.reason}} + {formState.description && {formState.description}} {formState.one_click_subscribe && Subscribe} @@ -108,7 +108,7 @@ const RecommendationReasonForm: React.FC setErrors( - validateReasonFormField(errors, 'title', formState.title) + validateDescriptionFormField(errors, 'title', formState.title) )} onChange={(e) => { clearError?.('title'); @@ -117,22 +117,22 @@ const RecommendationReasonForm: React.FC