Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Content | Schema] Block Selector #3090

Merged
merged 78 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
6946f92
initial commit
agalin920 Oct 28, 2024
702282d
info panel
agalin920 Oct 28, 2024
299cf7b
add border and remove max width
agalin920 Oct 28, 2024
acb58b1
task: add block create option
finnar-bin Oct 30, 2024
83088ee
task: add block models to sidebar
finnar-bin Oct 30, 2024
fadb365
task: add block group selection ui
finnar-bin Oct 30, 2024
2d47968
task: auto-create og_image field when creating a new block model
finnar-bin Oct 30, 2024
4154a06
task: hide og_image field in the fields list for block models
finnar-bin Oct 30, 2024
371343e
task: do not check block nav entry
finnar-bin Oct 30, 2024
ac51960
task: update model header actions
finnar-bin Oct 31, 2024
90cfe42
task: add block group input to duplicate model modal
finnar-bin Oct 31, 2024
0752e01
task: change logic to hide og_image field
finnar-bin Oct 31, 2024
4fc811b
task: hide block group dropdown for non block models
finnar-bin Oct 31, 2024
216fe3e
task: add update block group in info tab
finnar-bin Oct 31, 2024
8b55963
task: make sure dialog designs are constant
finnar-bin Oct 31, 2024
44dd9db
task: minor ui updates
finnar-bin Oct 31, 2024
a232e17
task: bump zesty-io/material version
finnar-bin Nov 4, 2024
75a5ce0
task: update block icon
finnar-bin Nov 4, 2024
327e4c8
task: wire block api call
finnar-bin Nov 4, 2024
c88a0e7
task: hide block group ui
finnar-bin Nov 4, 2024
1bdd078
task: updated schema tests
finnar-bin Nov 5, 2024
8d61e45
fix redirect and flows
agalin920 Nov 6, 2024
344db1a
variants
agalin920 Nov 7, 2024
27c9317
task: add block selector in field create flow
finnar-bin Nov 7, 2024
dab6f79
task: add content block selector
finnar-bin Nov 8, 2024
d149410
create variant button
agalin920 Nov 11, 2024
fda2fc4
create content filter out block models
agalin920 Nov 11, 2024
8af24a3
global search support
agalin920 Nov 11, 2024
b9e0b83
duplicate item support
agalin920 Nov 11, 2024
629d6ac
variant search support
agalin920 Nov 11, 2024
d2908be
rename variant
agalin920 Nov 11, 2024
1efaea5
blocks onboarding in localstorage
agalin920 Nov 13, 2024
b2ba4ed
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Nov 13, 2024
bbbc10e
task: only close create model dialog once og_image field is created
finnar-bin Nov 15, 2024
ce44c9c
task: fixed incorrect import
finnar-bin Nov 15, 2024
30083e4
task: do not open variant selector if no model is selected
finnar-bin Nov 15, 2024
c721fa9
task: wire search variant
finnar-bin Nov 15, 2024
b7966b8
task: make image height customizable
finnar-bin Nov 15, 2024
862f9a2
task: wire no search results
finnar-bin Nov 15, 2024
32db3d8
task: wire no variants created screen
finnar-bin Nov 15, 2024
8fd8594
task: remove unused variables
finnar-bin Nov 15, 2024
1e1f3d3
task: update block selector type
finnar-bin Nov 19, 2024
4fb3b6d
task: remove dummy block field
finnar-bin Nov 19, 2024
67b2330
task: create ui for image preview on hover
finnar-bin Nov 19, 2024
5495ad3
task: wire select block variant and error handling
finnar-bin Nov 19, 2024
0f6a4c0
task: create selected variant preview
finnar-bin Nov 19, 2024
ab53e40
task: only show preview when a variant is selected
finnar-bin Nov 19, 2024
a9f9981
task: setup variant preview links
finnar-bin Nov 21, 2024
01c93be
schema file warning
agalin920 Nov 21, 2024
c81b2e5
task: add tests
finnar-bin Nov 22, 2024
c34a6db
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Nov 22, 2024
a0231fa
task: update value format
finnar-bin Nov 26, 2024
d6e3b6e
task: revert to old value format
finnar-bin Nov 28, 2024
0aceb76
task: change format of selected block variant
finnar-bin Nov 29, 2024
274cf19
task: update how block data is derived
finnar-bin Nov 29, 2024
d4a4745
Add webengine preview
agalin920 Dec 3, 2024
ca5b52b
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Dec 3, 2024
1efe6aa
task: use og_image for the previews
finnar-bin Dec 4, 2024
e6a806c
finish webengine preview
agalin920 Dec 4, 2024
3c607dd
remove bypass
agalin920 Dec 4, 2024
df332de
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Dec 4, 2024
de8faed
preview screenshots
agalin920 Dec 5, 2024
a22d68d
solve conflicts
agalin920 Dec 5, 2024
6792395
POM cypress tests
agalin920 Dec 5, 2024
191e18c
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Dec 5, 2024
87cb40c
update street view import
agalin920 Dec 5, 2024
b0b241a
task: add error bypass
finnar-bin Dec 6, 2024
e08ff5a
Merge branch 'feature/blocks' into feature/3052-blocks-selector
finnar-bin Dec 6, 2024
ada9ab1
Merge branch 'dev' into feature/3052-blocks-selector
finnar-bin Dec 16, 2024
71a0659
Merge branch 'dev' into feature/3052-blocks-selector
finnar-bin Jan 2, 2025
c0d93a5
Merge branch 'dev' into feature/3052-blocks-selector
finnar-bin Jan 3, 2025
ccf684a
Merge branch 'dev' into feature/3052-blocks-selector
finnar-bin Jan 13, 2025
2e1a863
fix: prevent double blocks sidebar entry
finnar-bin Jan 14, 2025
1641a9a
task: remove unneeded debounce
finnar-bin Jan 14, 2025
4361e03
task: only show block selector option to @zesty.io users
finnar-bin Jan 15, 2025
65749e2
task: show og_image for image tooltip
finnar-bin Jan 15, 2025
696c424
fix: updated tests
finnar-bin Jan 15, 2025
dbf2fc5
fix: fix broken test
finnar-bin Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions cypress/e2e/content/content.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,25 @@ describe("Content Specs", () => {
.should("have.value", "12:00 pm");
});
});

describe("Block Selector Field", () => {
before(() => {
cy.waitOn("/v1/content/models*", () => {
cy.visit("/content/6-556370-8sh47g/7-b939a4-457q19");
});
});

it("Sets a block variant", () => {
cy.getBySelector("BlockSelectorModelField", { timeout: 10000 })
.find("input")
.click();
cy.get(".MuiAutocomplete-popper .MuiAutocomplete-option")
.contains("Test Block Do Not Delete")
.click();

cy.getBySelector("BlockSelectorVariantField", { timeout: 10000 }).click();
cy.getBySelector("Variant_0").click();
cy.getBySelector("BlockFieldVariantPreview").should("exist");
});
});
});
37 changes: 36 additions & 1 deletion cypress/e2e/schema/field.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const SELECTORS = {
FIELD_SELECT_BOOLEAN: "FieldItem_yes_no",
FIELD_SELECT_ONE_TO_ONE: "FieldItem_one_to_one",
FIELD_SELECT_CURRENCY: "FieldItem_currency",
FIELD_SELECT_BLOCK_SELECTOR: "FieldItem_block_selector",
MEDIA_CHECKBOX_LIMIT: "MediaCheckbox_limit",
MEDIA_CHECKBOX_LOCK: "MediaCheckbox_group_id",
DROPDOWN_ADD_OPTION: "DropdownAddOption",
Expand Down Expand Up @@ -322,7 +323,7 @@ describe("Schema: Fields", () => {
// Select a related model
cy.getBySelector(SELECTORS.AUTOCOMPLETE_MODEL_ZUID)
.should("exist")
.type("cypress");
.type("group with visible");
cy.get("[role=listbox] [role=option]").first().click();

cy.wait("@getFields");
Expand Down Expand Up @@ -397,6 +398,40 @@ describe("Schema: Fields", () => {
cy.getBySelector(`Field_${fieldName}`).should("exist");
});

it("Creates a Block field", () => {
cy.intercept("**/fields?showDeleted=true").as("getFields");

const fieldLabel = `Block Selector ${timestamp}`;
const fieldName = `block_selector_${timestamp}`;

// Open the add field modal
cy.getBySelector(SELECTORS.ADD_FIELD_BTN).should("exist").click();
cy.getBySelector(SELECTORS.ADD_FIELD_MODAL).should("exist");

// Select one-to-one relationship field
cy.getBySelector(SELECTORS.FIELD_SELECT_BLOCK_SELECTOR)
.should("exist")
.click();

// Fill up fields
cy.getBySelector(SELECTORS.INPUT_LABEL).should("exist").type(fieldLabel);
cy.get("input[name='label']")
.should("exist")
.should("have.value", fieldLabel);
cy.get("input[name='name']")
.should("exist")
.should("have.value", fieldName);

// Click done
cy.getBySelector(SELECTORS.SAVE_FIELD_BUTTON).should("exist").click();
cy.getBySelector(SELECTORS.ADD_FIELD_MODAL).should("not.exist");

cy.wait("@getFields");

// Check if field exists
cy.getBySelector(`Field_${fieldName}`).should("exist");
});

it("Creates a field via add another field button", () => {
cy.intercept("**/fields?showDeleted=true").as("getFields");

Expand Down
7 changes: 7 additions & 0 deletions src/apps/content-editor/src/app/components/Editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ export default memo(function Editor({
}
}

if (field.datatype === "block_selector") {
errors[name] = {
...(errors[name] ?? []),
INVALID_BLOCK_VARIANT: false,
};
}

onUpdateFieldErrors(errors);

// Always dispatch the data update
Expand Down
13 changes: 13 additions & 0 deletions src/apps/content-editor/src/app/components/Editor/Field/Field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { FieldTypeDate } from "../../../../../../../shell/components/FieldTypeDa
import { FieldTypeDateTime } from "../../../../../../../shell/components/FieldTypeDateTime";
import { FieldTypeSort } from "../../../../../../../shell/components/FieldTypeSort";
import { FieldTypeNumber } from "../../../../../../../shell/components/FieldTypeNumber";
import { FieldTypeBlockSelector } from "../../../../../../../shell/components/FieldTypeBlockSelector";

import styles from "./Field.less";
import { MemoryRouter } from "react-router";
Expand Down Expand Up @@ -961,6 +962,18 @@ export const Field = ({
</FieldShell>
);

case "block_selector":
return (
<FieldShell settings={fieldData} errors={errors}>
<FieldTypeBlockSelector
value={value ? value?.toString() : null}
onChange={(value) => onChange(value, name, datatype)}
requiredError={errors?.MISSING_REQUIRED}
missingVariantError={errors?.INVALID_BLOCK_VARIANT}
/>
</FieldShell>
);

default:
return (
<AppLink to={`/schema/${contentModelZUID}/field/${ZUID}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export type Error = {
REGEX_PATTERN_MISMATCH?: string;
REGEX_RESTRICT_PATTERN_MATCH?: string;
INVALID_RANGE?: string;
INVALID_BLOCK_VARIANT?: boolean;
};

type FieldShellProps = {
Expand Down Expand Up @@ -112,6 +113,10 @@ export const FieldShell = ({
errorMessages.push(errors.CUSTOM_ERROR);
}

if (errors?.INVALID_BLOCK_VARIANT) {
errorMessages.push("Please select a block variant.");
}

if (errorMessages.length === 0) {
return "";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const getErrorMessage = (errors: Error) => {
errorMessages.push(errors.CUSTOM_ERROR);
}

if (errors?.INVALID_BLOCK_VARIANT) {
errorMessages.push("Please select a block variant.");
}

return errorMessages;
};

Expand Down
17 changes: 16 additions & 1 deletion src/apps/content-editor/src/app/views/ItemCreate/ItemCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,11 @@ export const ItemCreate = () => {
})
);
if (res.err || res.error) {
if (res.missingRequired || res.lackingCharLength) {
if (
res.missingRequired ||
res.lackingCharLength ||
res.invalidBlockVariantValue
) {
const missingRequiredFieldNames: string[] =
res.missingRequired?.reduce(
(acc: string[], curr: ContentModelField) => {
Expand Down Expand Up @@ -269,6 +273,17 @@ export const ItemCreate = () => {
});
}

if (res.invalidBlockVariantValue?.length) {
res.invalidBlockVariantValue?.forEach(
(field: ContentModelField) => {
errors[field.name] = {
...(errors[field.name] ?? {}),
INVALID_BLOCK_VARIANT: true,
};
}
);
}

setFieldErrors(errors);

// scroll to required field
Expand Down
9 changes: 9 additions & 0 deletions src/apps/content-editor/src/app/views/ItemEdit/ItemEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,15 @@ export default function ItemEdit() {
});
}

if (res.invalidBlockVariantValue?.length) {
res.invalidBlockVariantValue?.forEach((field) => {
errors[field.name] = {
...(errors[field.name] ?? {}),
INVALID_BLOCK_VARIANT: true,
};
});
}

setFieldErrors(errors);
throw new Error(errors);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,20 @@ import {
} from "@mui/material";
import SearchIcon from "@mui/icons-material/Search";
import CloseIcon from "@mui/icons-material/Close";
import { useSelector } from "react-redux";

import { FieldItem } from "../FieldItem";
import { FieldListData, FIELD_COPY_CONFIG } from "../../configs";
import { isZestyEmail } from "../../../../../../../utility/isZestyEmail";
import { AppState } from "../../../../../../../shell/store/types";
import { User } from "../../../../../../../shell/services/types";

interface Props {
onFieldClick: (fieldType: string, fieldName: string) => void;
onModalClose: () => void;
}
export const FieldSelection = ({ onFieldClick, onModalClose }: Props) => {
const user: User = useSelector((state: AppState) => state.user);
const [fieldTypes, setFieldTypes] = useState(FIELD_COPY_CONFIG);

const handleFilterFields = (e: React.ChangeEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -140,18 +145,27 @@ export const FieldSelection = ({ onFieldClick, onModalClose }: Props) => {
rowGap={1.5}
columnGap={2}
>
{fieldTypes[fieldKey].map((field: FieldListData, index) => (
<FieldItem
key={index}
fieldName={field.name}
shortDescription={field.shortDescription}
fieldType={field.type}
description={field.description}
commonUses={field.commonUses}
proTip={field.proTip}
onFieldClick={() => onFieldClick(field.type, field.name)}
/>
))}
{fieldTypes[fieldKey].map((field: FieldListData, index) => {
if (
!isZestyEmail(user.email) &&
field?.type === "block_selector"
) {
return <></>;
}

return (
<FieldItem
key={index}
fieldName={field.name}
shortDescription={field.shortDescription}
fieldType={field.type}
description={field.description}
commonUses={field.commonUses}
proTip={field.proTip}
onFieldClick={() => onFieldClick(field.type, field.name)}
/>
);
})}
</Box>
</Box>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const Rules = ({
formData?.minCharLimit !== null && formData?.maxCharLimit !== null
);

if (type === "uuid") {
if (type === "uuid" || type === "block_selector") {
return <ComingSoon />;
}

Expand Down
7 changes: 6 additions & 1 deletion src/apps/schema/src/app/components/Field/FieldIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import ToggleOnRounded from "@mui/icons-material/ToggleOnRounded";
import KeyboardArrowDownRounded from "@mui/icons-material/KeyboardArrowDownRounded";
import ColorLensRounded from "@mui/icons-material/ColorLensRounded";
import FormatListNumberedRounded from "@mui/icons-material/FormatListNumberedRounded";
import { Markdown, OneToOne } from "@zesty-io/material";
import { Markdown, OneToOne, Block } from "@zesty-io/material";
import { Box } from "@mui/system";
import { SvgIcon } from "@mui/material";

Expand Down Expand Up @@ -67,6 +67,11 @@ const icons: Icons = {
backgroundColor: "pink.50",
borderColor: "pink.600",
},
block_selector: {
icon: Block as SvgIconComponent,
backgroundColor: "pink.50",
borderColor: "pink.600",
},
markdown: {
icon: Markdown as SvgIconComponent,
backgroundColor: "green.50",
Expand Down
19 changes: 18 additions & 1 deletion src/apps/schema/src/app/components/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export type FieldType =
| "files"
| "fontawesome"
| "wysiwyg_advanced"
| "article_writer";
| "article_writer"
| "block_selector"; // TODO: Will need to confirm if this type is already supported by the api
interface FieldListData {
type: FieldType;
name: string;
Expand Down Expand Up @@ -185,6 +186,17 @@ const FIELD_COPY_CONFIG: { [key: string]: FieldListData[] } = {
"You can use External URL fields if you want to link to external websites.",
subHeaderText: "Use this field to link to an internal content item",
},
{
type: "block_selector",
name: "Block Selector",
shortDescription: "Link to a variant of a block model",
description:
"The Block Selector field allows a user to select a unique variant of any block model they would like to see rendered on their page.",
commonUses: ["Footer Section", "Block at the end of article", "Forms"],
proTip:
"These are great to use when you want to use different end blocks at the end of different pages of the same model",
subHeaderText: "Link to a variant of a block model",
},
],
numeric: [
{
Expand Down Expand Up @@ -351,6 +363,7 @@ const TYPE_TEXT: Record<FieldType, string> = {
wysiwyg_advanced: "WYSIWYG (Advanced)",
wysiwyg_basic: "WYSIWYG",
yes_no: "Boolean",
block_selector: "Block Selector",
};

const COMMON_FIELDS: InputField[] = [
Expand Down Expand Up @@ -700,6 +713,10 @@ const FORM_CONFIG: Record<FieldType, FormConfig> = {
],
rules: [...COMMON_RULES],
},
block_selector: {
details: [...COMMON_FIELDS],
rules: [],
},
};

const SYSTEM_FIELDS: readonly SystemField[] = [
Expand Down
1 change: 1 addition & 0 deletions src/apps/schema/src/app/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export const getCategory = (type: string) => {
case "one_to_many":
case "link":
case "internal_link":
case "block_selector":
category = "relationship";
break;

Expand Down
Loading
Loading