diff --git a/api/src/paths/project/{projectId}/update.ts b/api/src/paths/project/{projectId}/update.ts index 9c45bb8900..279a5f0388 100644 --- a/api/src/paths/project/{projectId}/update.ts +++ b/api/src/paths/project/{projectId}/update.ts @@ -247,7 +247,8 @@ GET.apiDoc = { description: 'ISO 8601 date string for the funding end_date' }, agency_project_id: { - type: 'string' + type: 'string', + nullable: true }, revision_count: { type: 'number' diff --git a/app/src/components/fields/ReadMoreField.tsx b/app/src/components/fields/ReadMoreField.tsx index 12642ec04d..a36f35e66a 100644 --- a/app/src/components/fields/ReadMoreField.tsx +++ b/app/src/components/fields/ReadMoreField.tsx @@ -1,12 +1,14 @@ +import { Typography, TypographyProps } from '@material-ui/core'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; -import Typography from '@material-ui/core/Typography'; +import { mdiChevronDown, mdiChevronUp } from '@mdi/js'; +import Icon from '@mdi/react'; import React, { useState } from 'react'; -import { v4 as uuidv4 } from 'uuid'; export interface IReadMoreFieldProps { text: string; maxCharLength: number; + TypographyProps?: Partial; } /** @@ -15,78 +17,51 @@ export interface IReadMoreFieldProps { * @return {*} */ export const ReadMoreField: React.FC = (props) => { - const { text, maxCharLength } = props; + const { text, maxCharLength, TypographyProps } = props; + const [showTruncated, setShowTruncated] = useState(false); - /* - Determines whether or not the given body of text will be truncated based on - the max character length. - */ - const willTruncateText = (content: string): boolean => { - return content?.trim().length > maxCharLength || false; - }; + if (!text || maxCharLength <= 0) { + return <>; + } - const [isTruncatedText, setIsTruncatedText] = useState(willTruncateText(text)); + const sanitizedText = String(text).trim(); + const willTruncateText = sanitizedText.length > maxCharLength; - const renderParagraph = (paragraph: string) => { - if (paragraph) { - return ( - - {paragraph} - - ); - } - return

; - }; + if (!willTruncateText) { + return {sanitizedText}; + } - /* - Function that finds a nice index (at a period ending a sentence) - to truncate objectives longer than maxCharLength characters - */ - const determineTruncatingLength = () => { - const periodIndices = []; + let truncationIndex = sanitizedText.slice(0, maxCharLength).lastIndexOf(' '); + if (truncationIndex < 0) { + truncationIndex = maxCharLength; + } - for (let i = 0; i < text.length; i++) { - if (text[i - 1] === '.' && text[i] === ' ') { - periodIndices.push(i); - } - } - - return periodIndices.reduce((prev, curr) => { - return Math.abs(curr - maxCharLength) < Math.abs(prev - maxCharLength) ? curr : prev; - }); - }; + const persistentTextPortion = sanitizedText.slice(0, truncationIndex); return ( - {isTruncatedText && ( - <> - {text - .slice(0, determineTruncatingLength()) - .split('\n') - .map((paragraph: string) => { - return renderParagraph(paragraph); - })} - - - - - )} - {!isTruncatedText && ( - <> - {text?.split('\n').map((paragraph: string) => { - return renderParagraph(paragraph); - })} - {willTruncateText(text) && ( - - - - )} - - )} + + {showTruncated ? ( + {sanitizedText} + ) : ( + <> + {persistentTextPortion} + + + )} + + + + ); }; diff --git a/app/src/features/projects/edit/EditProjectPage.tsx b/app/src/features/projects/edit/EditProjectPage.tsx index bccedf67d3..6979d6d587 100644 --- a/app/src/features/projects/edit/EditProjectPage.tsx +++ b/app/src/features/projects/edit/EditProjectPage.tsx @@ -197,14 +197,7 @@ const EditProjectPage: React.FC = (props) => { -