Skip to content

Commit

Permalink
basic solution
Browse files Browse the repository at this point in the history
  • Loading branch information
alextaing committed Sep 20, 2023
1 parent fed1e42 commit c18188d
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 26 deletions.
15 changes: 12 additions & 3 deletions packages/studio-ui/src/components/AddPageButton/AddPageButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AddPageContext from "./AddPageContext";
import useStudioStore from "../../store/useStudioStore";
import AddPageContextProvider from "./AddPageContextProvider";
import { FlowStep, flowStepModalMap } from "./FlowStep";
import { GetPathVal } from "@yext/studio-plugin";
import { LayoutState } from "@yext/studio-plugin";

export default function AddPageButton() {
return (
Expand All @@ -27,7 +27,7 @@ function AddPageButtonInternal() {
const { resetState } = actions;

const handleConfirm = useCallback(
async (pageName = "", getPathVal?: GetPathVal) => {
async (layout?: LayoutState) => {
switch (step) {
case FlowStep.SelectPageType:
setStep(
Expand All @@ -38,7 +38,16 @@ function AddPageButtonInternal() {
setStep(FlowStep.GetBasicPageData);
break;
case FlowStep.GetBasicPageData:
await createPage(pageName, getPathVal, state.streamScope);
setStep(FlowStep.SelectLayout);
break;
case FlowStep.SelectLayout:
state.pageName &&
(await createPage(
state.pageName,
state.getPathVal,
state.streamScope,
layout
));
break;
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { StreamScope } from "@yext/studio-plugin";
import { GetPathVal, StreamScope } from "@yext/studio-plugin";
import { createContext } from "react";

export interface AddPageData {
isStatic: boolean;
streamScope?: StreamScope;
pageName?: string;
getPathVal?: GetPathVal;
}

export interface AddPageActions {
setIsStatic: (isStatic: boolean) => void;
setStreamScope: (streamScope: StreamScope) => void;
setPageName: (pageName: string) => void;
setGetPathVal: (getPathVal: GetPathVal) => void;
resetState: () => void;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AddPageContext, {
AddPageContextValue,
AddPageData,
} from "./AddPageContext";
import { StreamScope } from "@yext/studio-plugin";
import { GetPathVal, StreamScope } from "@yext/studio-plugin";

const initialPageData: AddPageData = {
isStatic: true,
Expand All @@ -16,9 +16,22 @@ export default function AddPageContextProvider(props: PropsWithChildren) {
() => ({
state,
actions: {
setIsStatic: (isStatic: boolean) => setState({ ...state, isStatic }),
setIsStatic: (isStatic: boolean) =>
setState((state) => {
return { ...state, isStatic };
}),
setStreamScope: (streamScope: StreamScope) =>
setState({ ...state, streamScope }),
setState((state) => {
return { ...state, streamScope };
}),
setPageName: (pageName: string) =>
setState((state) => {
return { ...state, pageName };
}),
setGetPathVal: (getPathVal: GetPathVal) =>
setState((state) => {
return { ...state, getPathVal };
}),
resetState: () => setState(initialPageData),
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function BasicPageDataCollector({
const isPagesJSRepo = useStudioStore(
(store) => store.studioConfig.isPagesJSRepo
);
const { state } = useContext(AddPageContext);
const { state, actions } = useContext(AddPageContext);
const isEntityPage = isPagesJSRepo && !state.isStatic;
const pageDataValidator = useMemo(
() => new PageDataValidator(isEntityPage),
Expand Down Expand Up @@ -53,19 +53,16 @@ export default function BasicPageDataCollector({
setErrorMessage(validationResult.errorMessages.join("\r\n"));
return false;
}
try {
await handleConfirm(data.pageName, getPathValue);
return true;
} catch (err: unknown) {
if (err instanceof Error) {
setErrorMessage(err.message);
return false;
} else {
throw err;
}
if (!getPathValue) {
setErrorMessage('Required "getPathValue" does not exist.');
return false;
}
actions.setPageName(data.pageName);
actions.setGetPathVal(getPathValue);
await handleConfirm();
return true;
},
[handleConfirm, isEntityPage, pageDataValidator]
[actions, handleConfirm, isEntityPage, pageDataValidator]
);

const transformOnChangeValue = useCallback(
Expand All @@ -84,10 +81,12 @@ export default function BasicPageDataCollector({
title={modalTitle}
formData={formData}
initialFormValue={initialFormValue}
closeOnConfirm={false}
errorMessage={errorMessage}
handleClose={handleClose}
handleConfirm={onConfirm}
transformOnChangeValue={transformOnChangeValue}
confirmButtonText="Next"
/>
);
}
Expand Down
7 changes: 5 additions & 2 deletions packages/studio-ui/src/components/AddPageButton/FlowStep.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { GetPathVal } from "@yext/studio-plugin";
import BasicPageDataCollector from "./BasicPageDataCollector";
import PageTypeSelector from "./PageTypeSelector";
import StreamScopeCollector from "./StreamScopeCollector";
import LayoutSelector from "./LayoutSelector";
import { LayoutState } from "@yext/studio-plugin";

export enum FlowStep {
SelectPageType,
GetStreamScope,
GetBasicPageData,
SelectLayout,
}

export interface FlowStepModalProps {
isOpen: boolean;
handleClose: () => Promise<void>;
handleConfirm: (pageName?: string, getPathVal?: GetPathVal) => Promise<void>;
handleConfirm: (layout?: LayoutState) => Promise<void>;
}

type FlowStepModalMap = {
Expand All @@ -23,4 +25,5 @@ export const flowStepModalMap: FlowStepModalMap = {
[FlowStep.SelectPageType]: PageTypeSelector,
[FlowStep.GetStreamScope]: StreamScopeCollector,
[FlowStep.GetBasicPageData]: BasicPageDataCollector,
[FlowStep.SelectLayout]: LayoutSelector,
};
68 changes: 68 additions & 0 deletions packages/studio-ui/src/components/AddPageButton/LayoutSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ChangeEvent, useCallback, useState } from "react";
import { FlowStepModalProps } from "./FlowStep";
import useStudioStore from "../../store/useStudioStore";
import DialogModal from "../common/DialogModal";
import { selectCssClasses } from "../UnionPropInput";
import { twMerge } from "tailwind-merge";

export default function LayoutSelector({
isOpen,
handleClose,
handleConfirm,
}: FlowStepModalProps) {
const layouts = useStudioStore(
(store) => store.layouts.layoutNameToLayoutState
);
const [selectedLayout, setSelectedLayout] = useState<string>("");
const [errorMessage, setErrorMessage] = useState<string>();

const onConfirm = useCallback(async () => {
const layoutState = layouts[selectedLayout];

try {
await handleConfirm(layoutState);
await handleClose();
} catch (err: unknown) {
if (err instanceof Error) {
setErrorMessage(err.message);
} else {
throw err;
}
}
}, [handleClose, handleConfirm, layouts, selectedLayout]);

const handleChange = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
setSelectedLayout(e.target.value);
},
[setSelectedLayout]
);

const selectClasses = twMerge(selectCssClasses, "w-full mb-6");
const body = (
<label>
<select className={selectClasses} onChange={handleChange}>
<option key="" value="">
No layout selected
</option>
{Object.entries(layouts).map(([layoutName]) => (
<option key={layoutName} value={layoutName}>
{layoutName}
</option>
))}
</select>
</label>
);

return (
<DialogModal
isOpen={isOpen}
handleClose={handleClose}
handleConfirm={onConfirm}
title="Select Layout"
body={body}
confirmButtonText="Save"
errorMessage={errorMessage}
/>
);
}
14 changes: 9 additions & 5 deletions packages/studio-ui/src/store/StudioActions/CreatePageAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
PageState,
PagesJsState,
ResponseType,
LayoutState,
} from "@yext/studio-plugin";
import path from "path-browserify";
import StudioConfigSlice from "../models/slices/StudioConfigSlice";
Expand All @@ -21,7 +22,8 @@ export default class CreatePageAction {
createPage = async (
pageName: string,
getPathValue?: GetPathVal,
streamScope?: StreamScope
streamScope?: StreamScope,
layout?: LayoutState
) => {
const pagesPath = this.getStudioConfigSlice().paths.pages;
const filepath = path.join(pagesPath, pageName + ".tsx");
Expand All @@ -31,7 +33,8 @@ export default class CreatePageAction {
filepath,
isPagesJSRepo,
getPathValue,
streamScope
streamScope,
layout
);
this.getPageSlice().addPage(pageName, pageState);

Expand All @@ -51,11 +54,12 @@ export default class CreatePageAction {
filepath: string,
isPagesJSRepo: boolean,
getPathValue?: GetPathVal,
streamScope?: StreamScope
streamScope?: StreamScope,
layout?: LayoutState
) {
const pageState: PageState = {
componentTree: [],
cssImports: [],
componentTree: layout ? layout.componentTree : [],
cssImports: layout ? layout.cssImports : [],
filepath,
};
if (isPagesJSRepo && getPathValue) {
Expand Down

0 comments on commit c18188d

Please sign in to comment.