Skip to content

Commit

Permalink
Fix Deploy button (#385)
Browse files Browse the repository at this point in the history
The Deploy button had unexpected behavior since Git data (`canPush`) was
not properly updated using HMR. This PR makes sure that on Studio save,
updated Git data is sent to Studio. A new type of HMR message was added
between studio which handles exclusively Git data, as to not pollute the
current HMR message type which is purely studio data from the studio
data virtual module.

Streamlined the deploy button playwright test to only screenshot the
deploy button at three stages: before change, after change, and after
deploy.

J=SLAP-2944
TEST=manual,auto
  • Loading branch information
alextaing authored Sep 26, 2023
1 parent 48f3ed7 commit 66cd396
Show file tree
Hide file tree
Showing 24 changed files with 102 additions and 36 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
8 changes: 5 additions & 3 deletions e2e-tests/tests/deploy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ studioTest.use({
studioTest("can deploy changes", async ({ studioPage }) => {
const gitOps = studioPage.gitOps;
const startingRef = await gitOps.getCurrentRef();
await studioPage.addElement("Container", "Containers");
await studioPage.takePageScreenshotAfterImgRender();
const deployButton = studioPage.deployButton;
await expect(deployButton.button).toHaveScreenshot();
await studioPage.addElement("Container", "Containers", false);
await expect(deployButton.button).toHaveScreenshot();

const numCommitsBeforeDeploy = await gitOps.getNumCommitsFromRef(startingRef);
expect(numCommitsBeforeDeploy).toEqual(0);
await studioPage.deployButton.click();

await studioPage.takePageScreenshotAfterImgRender();
await expect(deployButton.button).toHaveScreenshot();
const numCommitsMade = await gitOps.getNumCommitsFromRef(startingRef);
expect(numCommitsMade).toEqual(1);
const commitMsg = await gitOps.getCommitMessage();
Expand Down
8 changes: 8 additions & 0 deletions packages/studio-plugin/src/git/reloadGitData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ViteDevServer } from "vite";
import VirtualModuleID from "../VirtualModuleID";
import GitWrapper from "./GitWrapper";
import { GitDataHMRUpdateID } from "../types";

export default async function reloadGitData(
gitWrapper: GitWrapper,
Expand All @@ -14,4 +15,11 @@ export default async function reloadGitData(
throw new Error("Expected a GitData module.");
}
server.moduleGraph.invalidateModule(gitDataModule);
server.ws.send({
type: "custom",
event: GitDataHMRUpdateID,
data: {
gitData: gitWrapper.getStoredData(),
},
});
}
8 changes: 7 additions & 1 deletion packages/studio-plugin/src/types/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { StudioData } from "./StudioData";
import { FeaturesJson } from "./PagesJS";
import { EntitiesRequest, EntitiesResponse } from "../http/types/Entities";
import { SavedFilterData } from "../http/types/SavedFilters";
import { GitData } from "./GitData";

export enum MessageID {
SaveChanges = "studio:saveChanges",
Expand All @@ -12,7 +13,8 @@ export enum MessageID {
GetSavedFilters = "studio:getSavedFilters",
GetEntityTypes = "studio:getEntityTypes",
}
export const StudioHMRUpdateID = "studio:hmrUpdate";
export const StudioHMRUpdateID = "studio:studioDataHmrUpdate";
export const GitDataHMRUpdateID = "studio:gitDataHmrUpdate";

export interface SaveChangesPayload
extends Pick<StudioData, "pageNameToPageState"> {
Expand All @@ -35,6 +37,10 @@ export interface StudioHMRPayload {
file: string;
}

export interface GitDataHMRPayload {
gitData: GitData;
}

export type StudioEventMap = {
[MessageID.SaveChanges]: SaveChangesPayload;
[MessageID.Deploy]: SaveChangesPayload;
Expand Down
9 changes: 9 additions & 0 deletions packages/studio-ui/__mocks__/virtual_yext-studio-git-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { GitData } from "@yext/studio-plugin";

const mockGitData: GitData = {
canPush: {
status: true,
reason: "mock reason",
},
};
export default mockGitData;
4 changes: 1 addition & 3 deletions packages/studio-ui/src/components/ActionsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import useStudioStore from "../store/useStudioStore";
* and redo actions, and adding elements.
*/
export default function ActionsBar(): JSX.Element {
const studioInCBD = useStudioStore(
(store) => store.studioEnvData.isWithinCBD
);
const studioInCBD = useStudioStore((store) => store.envData.isWithinCBD);
return (
<div className="flex bg-gray-100 py-3 items-center px-4">
<AddElementButton />
Expand Down
17 changes: 9 additions & 8 deletions packages/studio-ui/src/components/DeployButton.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import useStudioStore from "../store/useStudioStore";
import { useCallback, useEffect, useState } from "react";
import gitData from "virtual_yext-studio-git-data";
import useHasChanges from "../hooks/useHasChanges";
import { Tooltip } from "react-tooltip";

const canPush = gitData.canPush.status;
const tooltipAnchorID = "YextStudio-deployButton";

/**
* Renders a button for saving, committing, and pushing changes.
*/
export default function DeployButton() {
const deploy = useStudioStore((store) => store.actions.deploy);
const [deploy, canPush] = useStudioStore((store) => [
store.actions.deploy,
store.gitData.canPush,
]);
const [deployInProgress, setDeployInProgress] = useState(false);
const hasChanges = useHasChanges();

Expand All @@ -26,10 +27,10 @@ export default function DeployButton() {
// Setting it back to false immediately after awaiting the deploy action
// can lead to an intermediate state when deployInProgress is false
// but the HMR update hasn't completed yet, resulting in a momentary flicker.
if (!canPush) {
if (!canPush.status) {
setDeployInProgress(false);
}
}, []);
}, [canPush]);

useEffect(() => {
// Websockets do not currently work in CBD, which prevents the gitData useEffect from correctly setting
Expand All @@ -39,7 +40,7 @@ export default function DeployButton() {
}
}, [hasChanges]);

const isDisabled = deployInProgress || (!hasChanges && !canPush);
const isDisabled = deployInProgress || (!hasChanges && !canPush.status);

return (
<button
Expand All @@ -49,11 +50,11 @@ export default function DeployButton() {
aria-label="Deploy Changes to Repository"
>
<span id={tooltipAnchorID}>Deploy</span>
{isDisabled && gitData.canPush.reason && (
{isDisabled && canPush.reason && (
<Tooltip
className="z-20"
anchorId={tooltipAnchorID}
content={gitData.canPush.reason}
content={canPush.reason}
/>
)}
</button>
Expand Down
4 changes: 2 additions & 2 deletions packages/studio-ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { default as App } from "./App";
export { default as hotReloadStore } from "./store/hotReloadStore";
export { StudioHMRUpdateID } from "@yext/studio-plugin";
export { hotReloadStudioData, hotReloadGitData } from "./store/hotReloadStore";
export { StudioHMRUpdateID, GitDataHMRUpdateID } from "@yext/studio-plugin";
15 changes: 13 additions & 2 deletions packages/studio-ui/src/store/hotReloadStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { StudioData, StudioHMRPayload } from "@yext/studio-plugin";
import {
GitDataHMRPayload,
StudioData,
StudioHMRPayload,
} from "@yext/studio-plugin";
import useStudioStore from "./useStudioStore";
import removeTopLevelFragments from "../utils/removeTopLevelFragments";
import dynamicImportFromBrowser from "../utils/dynamicImportFromBrowser";
Expand All @@ -9,7 +13,7 @@ import getFunctionComponent from "../utils/getFunctionComponent";
* A handler for custom Studio HMR events.
* When a custom studio HMR event is received, updates the store.
*/
export default async function hotReloadStore(payload: StudioHMRPayload) {
export async function hotReloadStudioData(payload: StudioHMRPayload) {
const { updateType, studioData } = payload;
switch (updateType) {
case "components":
Expand All @@ -30,6 +34,13 @@ export default async function hotReloadStore(payload: StudioHMRPayload) {
}
}

export function hotReloadGitData(payload: GitDataHMRPayload) {
const { gitData } = payload;
useStudioStore.setState((store) => {
store.gitData = gitData;
});
}

async function fullSync(studioData: StudioData, file: string) {
syncPages(studioData);
syncLayouts(studioData);
Expand Down
6 changes: 4 additions & 2 deletions packages/studio-ui/src/store/models/StudioStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import PageSlice from "./slices/PageSlice";
import PreviousSaveSlice from "./slices/PreviousSaveSlice";
import SiteSettingSlice from "./slices/SiteSettingsSlice";
import StudioConfigSlice from "./slices/StudioConfigSlice";
import StudioEnvDataSlice from "./slices/StudioEnvDataSlice";
import EnvDataSlice from "./slices/EnvDataSlice";
import GitDataSlice from "./slices/GitDataSlice";

/**
* The overall shape of the Zustand store as the state manager for Studio.
Expand All @@ -23,6 +24,7 @@ export type StudioStore = {
previousSave: PreviousSaveSlice;
actions: StudioActions;
studioConfig: StudioConfigSlice;
studioEnvData: StudioEnvDataSlice;
envData: EnvDataSlice;
gitData: GitDataSlice;
accountContent: AccountContentSlice;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* A slice for containing environment data.
*/
export default interface StudioEnvDataSlice {
export default interface EnvDataSlice {
isWithinCBD: boolean;
}
9 changes: 9 additions & 0 deletions packages/studio-ui/src/store/models/slices/GitDataSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* A slice for containing environment data.
*/
export default interface GitDataSlice {
canPush: {
status: boolean;
reason?: string;
};
}
9 changes: 9 additions & 0 deletions packages/studio-ui/src/store/slices/createEnvDataSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import EnvDataSlice from "../models/slices/EnvDataSlice";
import { SliceCreator } from "../models/utils";
import initialStudioData from "virtual_yext-studio";

const createEnvDataSlice: SliceCreator<EnvDataSlice> = () => ({
isWithinCBD: initialStudioData.isWithinCBD,
});

export default createEnvDataSlice;
9 changes: 9 additions & 0 deletions packages/studio-ui/src/store/slices/createGitDataSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import GitDataSlice from "../models/slices/GitDataSlice";
import { SliceCreator } from "../models/utils";
import initialGitData from "virtual_yext-studio-git-data";

const createGitDataSlice: SliceCreator<GitDataSlice> = () => ({
canPush: initialGitData.canPush,
});

export default createGitDataSlice;

This file was deleted.

6 changes: 4 additions & 2 deletions packages/studio-ui/src/store/useStudioStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import StudioActions from "./StudioActions";
import createStudioConfigSlice from "./slices/createStudioConfigSlice";
import createPreviousSaveSlice from "./slices/createPreviousSaveSlice";
import { addZundoMiddleware } from "./zundoMiddleware";
import createStudioEnvDataSlice from "./slices/createStudioEnvDataSlice";
import createEnvDataSlice from "./slices/createEnvDataSlice";
import createGitDataSlice from "./slices/createGitDataSlice";
import createAccountContentSlice from "./slices/accountContent/createAccountContentSlice";
import createLayoutSlice from "./slices/createLayoutSlice";

Expand Down Expand Up @@ -48,7 +49,8 @@ const useStudioStore = create<StudioStore>()(
() => get().studioConfig
),
studioConfig: lens(createStudioConfigSlice),
studioEnvData: lens(createStudioEnvDataSlice),
envData: lens(createEnvDataSlice),
gitData: lens(createGitDataSlice),
accountContent: lens(createAccountContentSlice),
};
})
Expand Down
15 changes: 12 additions & 3 deletions packages/studio/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { App, hotReloadStore, StudioHMRUpdateID } from "@yext/studio-ui";
import type { StudioHMRPayload } from "@yext/studio-plugin";
import {
App,
hotReloadStudioData,
hotReloadGitData,
StudioHMRUpdateID,
GitDataHMRUpdateID,
} from "@yext/studio-ui";
import type { StudioHMRPayload, GitDataHMRPayload } from "@yext/studio-plugin";
import "./tailwind-directives.css";

if (import.meta.hot) {
import.meta.hot.on(StudioHMRUpdateID, (hmrPayload: StudioHMRPayload) => {
void hotReloadStore(hmrPayload);
void hotReloadStudioData(hmrPayload);
});
import.meta.hot.on(GitDataHMRUpdateID, (hmrPayload: GitDataHMRPayload) => {
void hotReloadGitData(hmrPayload);
});
}

Expand Down

0 comments on commit 66cd396

Please sign in to comment.