diff --git a/src/api/fragments/SectionData.ts b/src/api/fragments/SectionData.ts index 8d0d64b3..ee2647cc 100644 --- a/src/api/fragments/SectionData.ts +++ b/src/api/fragments/SectionData.ts @@ -20,6 +20,8 @@ export const BaseSectionData = gql` startDate endDate status + followable + allowAds } `; export const SectionData = gql` diff --git a/src/api/generatedTypes.ts b/src/api/generatedTypes.ts index aa750b71..3d675ff4 100644 --- a/src/api/generatedTypes.ts +++ b/src/api/generatedTypes.ts @@ -608,6 +608,8 @@ export type CreateCollectionStoryInput = { export type CreateCustomSectionInput = { /** Indicates whether or not a Section is available for display. */ active: Scalars['Boolean']; + /** Whether ads can be displayed in this section. */ + allowAds?: InputMaybe; /** The source which created the Section. */ createSource: ActivitySource; /** The description of the custom section displayed to the users. */ @@ -622,6 +624,8 @@ export type CreateCustomSectionInput = { * Format: YYYY-MM-DD. */ endDate?: InputMaybe; + /** Whether users can follow this section. */ + followable?: InputMaybe; /** An optional description or supporting text for use in hero modules. */ heroDescription?: InputMaybe; /** An optional title used in hero modules. */ @@ -2165,6 +2169,8 @@ export type Section = { __typename?: 'Section'; /** Indicates whether or not a Section is available for display. */ active: Scalars['Boolean']; + /** Whether ads can be displayed in this section. */ + allowAds: Scalars['Boolean']; /** The source which created the Section. */ createSource: ActivitySource; /** A Unix timestamp of when the Section was created. */ @@ -2183,6 +2189,8 @@ export type Section = { endDate?: Maybe; /** An alternative primary key in UUID format. */ externalId: Scalars['ID']; + /** Whether users can follow this section. */ + followable: Scalars['Boolean']; /** * An optional description or supporting text for use in hero modules. * Relevant for custom sections. @@ -2539,12 +2547,16 @@ export type UpdateCollectionStorySortOrderInput = { /** Input data for updating a Custom Editorial Section */ export type UpdateCustomSectionInput = { + /** Whether ads can be displayed in this section. */ + allowAds?: InputMaybe; /** The description of the custom section displayed to the users. */ description: Scalars['String']; /** An optional date of when the Section should stop being displayed. */ endDate?: InputMaybe; /** An alternative primary key in UUID format supplied by ML. */ externalId: Scalars['ID']; + /** Whether users can follow this section. */ + followable?: InputMaybe; /** An optional description or supporting text for use in hero modules. */ heroDescription?: InputMaybe; /** An optional title used in hero modules. */ @@ -2793,6 +2805,8 @@ export type BaseSectionDataFragment = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; iab?: { __typename?: 'IABMetadata'; taxonomy: string; @@ -2817,6 +2831,8 @@ export type SectionDataFragment = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; sectionItems: Array<{ __typename?: 'SectionItem'; createdAt: number; @@ -3393,6 +3409,8 @@ export type CreateCustomSectionMutation = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; iab?: { __typename?: 'IABMetadata'; taxonomy: string; @@ -3635,6 +3653,8 @@ export type DisableEnableSectionMutation = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; sectionItems: Array<{ __typename?: 'SectionItem'; createdAt: number; @@ -4338,6 +4358,8 @@ export type UpdateCustomSectionMutation = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; iab?: { __typename?: 'IABMetadata'; taxonomy: string; @@ -5213,6 +5235,8 @@ export type GetSectionsWithSectionItemsQuery = { startDate?: any | null; endDate?: any | null; status: SectionStatus; + followable: boolean; + allowAds: boolean; sectionItems: Array<{ __typename?: 'SectionItem'; createdAt: number; @@ -5472,6 +5496,8 @@ export const BaseSectionDataFragmentDoc = gql` startDate endDate status + followable + allowAds } `; export const BaseSectionItemDataFragmentDoc = gql` diff --git a/src/curated-corpus/components/CustomSectionDetails/CustomSectionDetails.tsx b/src/curated-corpus/components/CustomSectionDetails/CustomSectionDetails.tsx index 77c3ed2a..67746f42 100644 --- a/src/curated-corpus/components/CustomSectionDetails/CustomSectionDetails.tsx +++ b/src/curated-corpus/components/CustomSectionDetails/CustomSectionDetails.tsx @@ -16,6 +16,8 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; import AdUnitsIcon from '@mui/icons-material/AdUnits'; +import BookmarkIcon from '@mui/icons-material/Bookmark'; +import BookmarkBorderIcon from '@mui/icons-material/BookmarkBorder'; import { DateTime } from 'luxon'; import { useMutation } from '@apollo/client'; import { @@ -470,6 +472,40 @@ export const CustomSectionDetails: React.FC = ({ {section.sectionItems?.length || 0} items + + + Followable + + + + ) : ( + + ) + } + size="small" + /> + + + + + Ads + + + } + size="small" + /> + + {/* IAB Category */} diff --git a/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.test.tsx b/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.test.tsx index 690f41f8..50fa2dcb 100644 --- a/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.test.tsx +++ b/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.test.tsx @@ -89,4 +89,49 @@ describe('CustomSectionForm', () => { screen.getByRole('button', { name: /save changes/i }), ).toBeInTheDocument(); }); + + it('should render followable and allow ads checkboxes checked by default', () => { + render( + , + ); + + expect(screen.getByRole('checkbox', { name: /followable/i })).toBeChecked(); + expect(screen.getByRole('checkbox', { name: /allow ads/i })).toBeChecked(); + }); + + it('should reflect initial values for followable and allowAds', () => { + render( + , + ); + + expect( + screen.getByRole('checkbox', { name: /followable/i }), + ).not.toBeChecked(); + expect( + screen.getByRole('checkbox', { name: /allow ads/i }), + ).not.toBeChecked(); + }); + + it('should toggle followable and allowAds checkboxes', () => { + render( + , + ); + + const followableCheckbox = screen.getByRole('checkbox', { + name: /followable/i, + }); + const allowAdsCheckbox = screen.getByRole('checkbox', { + name: /allow ads/i, + }); + + fireEvent.click(followableCheckbox); + expect(followableCheckbox).not.toBeChecked(); + + fireEvent.click(allowAdsCheckbox); + expect(allowAdsCheckbox).not.toBeChecked(); + }); }); diff --git a/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.tsx b/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.tsx index fd9cf4bd..9b0e384d 100644 --- a/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.tsx +++ b/src/curated-corpus/components/CustomSectionForm/CustomSectionForm.tsx @@ -1,7 +1,15 @@ import React, { useState } from 'react'; import { DateTime } from 'luxon'; import { Formik, Form, Field } from 'formik'; -import { Box, TextField, MenuItem, Button } from '@mui/material'; +import { + Box, + TextField, + MenuItem, + Button, + Checkbox, + FormControlLabel, + FormGroup, +} from '@mui/material'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { AdapterLuxon } from '@mui/x-date-pickers/AdapterLuxon'; @@ -51,6 +59,8 @@ export const CustomSectionForm: React.FC = ({ startDate: DateTime.now(), endDate: null, iabCategory: '', + followable: true, + allowAds: true, }; const mergedInitialValues = { @@ -172,6 +182,31 @@ export const CustomSectionForm: React.FC = ({ ))} + + + setFieldValue('followable', e.target.checked) + } + /> + } + label="Followable" + /> + + setFieldValue('allowAds', e.target.checked) + } + /> + } + label="Allow Ads" + /> + + {isEditMode && onDelete && (