Skip to content

Commit

Permalink
[Content] SEO tab VQA 2 updates (#2965)
Browse files Browse the repository at this point in the history
Resolves vqa comments:
-
#2933 (comment)
-
#2933 (comment)
  • Loading branch information
finnar-bin authored Sep 24, 2024
1 parent ea55995 commit 104efea
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 203 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"@tinymce/tinymce-react": "^4.3.0",
"@welldone-software/why-did-you-render": "^6.1.1",
"@zesty-io/core": "1.10.0",
"@zesty-io/material": "^0.15.3",
"@zesty-io/material": "^0.15.4",
"chart.js": "^3.8.0",
"chartjs-adapter-moment": "^1.0.1",
"chartjs-plugin-datalabels": "^2.0.0",
Expand Down
16 changes: 13 additions & 3 deletions src/apps/content-editor/src/app/components/Editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,19 +275,29 @@ export default memo(function Editor({
}

if (firstContentField && firstContentField.name === name) {
// Remove tags and replace MS smart quotes with regular quotes
const cleanedValue = value
?.replace(/<[^>]*>/g, "")
?.replaceAll(/[\u2018\u2019\u201A]/gm, "'")
?.replaceAll("&rsquo;", "'")
?.replaceAll(/[\u201C\u201D\u201E]/gm, '"')
?.replaceAll("&ldquo;", '"')
?.replaceAll("&rdquo;", '"')
?.slice(0, 160);

dispatch({
type: "SET_ITEM_WEB",
itemZUID,
key: "metaDescription",
value: value.replace(/<[^>]*>/g, "").slice(0, 160),
value: cleanedValue,
});

if ("og_description" in metaFields) {
dispatch({
type: "SET_ITEM_DATA",
itemZUID,
key: "og_description",
value: value.replace(/<[^>]*>/g, "").slice(0, 160),
value: cleanedValue,
});
}

Expand All @@ -296,7 +306,7 @@ export default memo(function Editor({
type: "SET_ITEM_DATA",
itemZUID,
key: "tc_description",
value: value.replace(/<[^>]*>/g, "").slice(0, 160),
value: cleanedValue,
});
}
}
Expand Down
212 changes: 118 additions & 94 deletions src/apps/content-editor/src/app/components/Editor/FieldError.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { useMemo, useRef, useEffect } from "react";
import {
useMemo,
useRef,
useEffect,
forwardRef,
useImperativeHandle,
} from "react";
import { Stack, Typography, Box, ThemeProvider } from "@mui/material";
import DangerousRoundedIcon from "@mui/icons-material/DangerousRounded";
import { theme } from "@zesty-io/material";
Expand Down Expand Up @@ -64,97 +70,115 @@ const getErrorMessage = (errors: Error) => {
return errorMessages;
};

export const FieldError = ({ errors, fields }: FieldErrorProps) => {
const errorContainerEl = useRef(null);

// Scroll to the errors on mount
useEffect(() => {
errorContainerEl?.current?.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "center",
});
}, []);

const fieldErrors = useMemo(() => {
const errorMap = Object.entries(errors)?.map(([name, errorDetails]) => {
const errorMessages = getErrorMessage(errorDetails);

const fieldData = fields?.find((field) => field.name === name);

return {
label:
fieldData?.label ||
SEO_FIELD_LABELS[name as keyof typeof SEO_FIELD_LABELS],
errorMessages,
sort: fieldData?.sort,
ZUID: fieldData?.ZUID || name,
};
});

return errorMap.sort((a, b) => a.sort - b.sort);
}, [errors, fields]);

const fieldsWithErrors = fieldErrors?.filter(
(error) => error.errorMessages.length > 0
);

const handleErrorClick = (fieldZUID: string) => {
const fieldElement = document.getElementById(fieldZUID);
fieldElement?.scrollIntoView({ behavior: "smooth" });
};

return (
<ThemeProvider theme={theme}>
<Stack
data-cy="FieldErrorsList"
ref={errorContainerEl}
p={2}
gap={1}
borderRadius={1}
sx={{ backgroundColor: "red.50", color: "error.dark" }}
>
<DangerousRoundedIcon color="inherit" fontSize="small" />
<Typography variant="h6">
Item cannot be saved due to invalid field values.
</Typography>
<Typography variant="body2">
Please correct the following {fieldsWithErrors?.length} field
{fieldsWithErrors?.length > 1 && "s"} before saving:
</Typography>
<Box component="ol" ml={2}>
{fieldErrors?.map((error, index) => {
if (error.errorMessages.length > 0) {
return (
<Typography key={index} variant="body2" component="li">
<Box
sx={{
borderBottom: 1,
borderColor: "error.dark",
cursor: "pointer",
height: 16,
display: "inline-block",
}}
component="span"
onClick={() => handleErrorClick(error.ZUID)}
>
{error.label}
</Box>
{error.errorMessages.length === 1 ? (
<i> - {error.errorMessages[0]}</i>
) : (
<Box component="ul" sx={{ pl: 3, listStyleType: "disc" }}>
{error.errorMessages.map((msg, idx) => (
<li key={idx}>{msg}</li>
))}
export const FieldError = forwardRef(
({ errors, fields }: FieldErrorProps, ref) => {
const errorContainerEl = useRef(null);

useImperativeHandle(
ref,
() => {
return {
scrollToErrors() {
errorContainerEl?.current?.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "center",
});
},
};
},
[errorContainerEl]
);

// Scroll to the errors on mount
useEffect(() => {
errorContainerEl?.current?.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "center",
});
}, []);

const fieldErrors = useMemo(() => {
const errorMap = Object.entries(errors)?.map(([name, errorDetails]) => {
const errorMessages = getErrorMessage(errorDetails);

const fieldData = fields?.find((field) => field.name === name);

return {
label:
fieldData?.label ||
SEO_FIELD_LABELS[name as keyof typeof SEO_FIELD_LABELS],
errorMessages,
sort: fieldData?.sort,
ZUID: fieldData?.ZUID || name,
};
});

return errorMap.sort((a, b) => a.sort - b.sort);
}, [errors, fields]);

const fieldsWithErrors = fieldErrors?.filter(
(error) => error.errorMessages.length > 0
);

const handleErrorClick = (fieldZUID: string) => {
const fieldElement = document.getElementById(fieldZUID);
fieldElement?.scrollIntoView({ behavior: "smooth" });
};

return (
<ThemeProvider theme={theme}>
<Stack
data-cy="FieldErrorsList"
ref={errorContainerEl}
p={2}
gap={1}
borderRadius={1}
sx={{ backgroundColor: "red.50", color: "error.dark" }}
>
<DangerousRoundedIcon color="inherit" fontSize="small" />
<Typography variant="h6">
Item cannot be saved due to invalid field values.
</Typography>
<Typography variant="body2">
Please correct the following {fieldsWithErrors?.length} field
{fieldsWithErrors?.length > 1 && "s"} before saving:
</Typography>
<Box component="ol" ml={2}>
{fieldErrors?.map((error, index) => {
if (error.errorMessages.length > 0) {
return (
<Typography key={index} variant="body2" component="li">
<Box
sx={{
borderBottom: 1,
borderColor: "error.dark",
cursor: "pointer",
height: 16,
display: "inline-block",
}}
component="span"
onClick={() => handleErrorClick(error.ZUID)}
>
{error.label}
</Box>
)}
</Typography>
);
}
})}
</Box>
</Stack>
</ThemeProvider>
);
};
{error.errorMessages.length === 1 ? (
<i> - {error.errorMessages[0]}</i>
) : (
<Box component="ul" sx={{ pl: 3, listStyleType: "disc" }}>
{error.errorMessages.map((msg, idx) => (
<li key={idx}>{msg}</li>
))}
</Box>
)}
</Typography>
);
}
})}
</Box>
</Stack>
</ThemeProvider>
);
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default memo(function PendingEditsModal(props: PendingEditsModalProps) {
answer(true);
})
.catch((err) => {
console.error(err);
// @ts-ignore
answer(false);
})
Expand Down
30 changes: 22 additions & 8 deletions src/apps/content-editor/src/app/views/ItemCreate/ItemCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export const ItemCreate = () => {
// const [hasSEOErrors, setHasSEOErrors] = useState(false);
const [SEOErrors, setSEOErrors] = useState<FieldErrors>({});
const metaRef = useRef(null);
const fieldErrorRef = useRef(null);

const [
createPublishing,
Expand Down Expand Up @@ -182,7 +183,10 @@ export const ItemCreate = () => {
setSaveClicked(true);

metaRef.current?.validateMetaFields?.();
if (hasErrors || hasSEOErrors) return;
if (hasErrors || hasSEOErrors) {
fieldErrorRef.current?.scrollToErrors?.();
return;
}

setSaving(true);

Expand Down Expand Up @@ -266,6 +270,7 @@ export const ItemCreate = () => {
setFieldErrors(errors);

// scroll to required field
fieldErrorRef.current?.scrollToErrors?.();
}

if (res.error) {
Expand Down Expand Up @@ -382,12 +387,15 @@ export const ItemCreate = () => {
direction="row"
gap={4}
>
<Box width="60%" height="100%">
<Box width="60%" minWidth={640} height="100%">
{saveClicked && (hasErrors || hasSEOErrors) && (
<FieldError
errors={{ ...fieldErrors, ...SEOErrors }}
fields={activeFields}
/>
<Box mb={3}>
<FieldError
ref={fieldErrorRef}
errors={{ ...fieldErrors, ...SEOErrors }}
fields={activeFields}
/>
</Box>
)}
<Editor
// @ts-ignore no types
Expand Down Expand Up @@ -425,8 +433,14 @@ export const ItemCreate = () => {
/>
</Box>
<ThemeProvider theme={theme}>
<Box position="sticky" top={0} alignSelf="flex-start" width="40%">
<SocialMediaPreview />
<Box
position="sticky"
top={0}
alignSelf="flex-start"
width="40%"
maxWidth={620}
>
{model?.type !== "dataset" && <SocialMediaPreview />}
</Box>
</ThemeProvider>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ export default function Content(props) {
>
<Box width="100%">
{props.saveClicked && props.hasErrors && (
<FieldError
errors={props.fieldErrors}
fields={props.activeFields}
/>
<Box mb={3}>
<FieldError
ref={props.fieldErrorRef}
errors={props.fieldErrors}
fields={props.activeFields}
/>
</Box>
)}
<Editor
// active={this.state.makeActive}
Expand Down
Loading

0 comments on commit 104efea

Please sign in to comment.