Skip to content

Commit

Permalink
fix(app-record-locking): decorate singleton entry form (#4325)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 authored Oct 10, 2024
1 parent 65fd703 commit bb500f4
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 22 deletions.
5 changes: 5 additions & 0 deletions packages/app-headless-cms/src/ContentEntryEditorConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { useContentEntryForm } from "./admin/components/ContentEntryForm/useCont
import { useContentEntry } from "~/admin/views/contentEntries/hooks";
import { ContentEntry } from "~/admin/views/contentEntries/ContentEntry";
import { ContentEntryEditorConfig as BaseContentEntryEditorConfig } from "./admin/config/contentEntries";
import { SingletonContentEntry } from "~/admin/views/contentEntries/ContentEntry/SingletonContentEntry";
import { useSingletonContentEntry } from "~/admin/views/contentEntries/hooks/useSingletonContentEntry";

export const ContentEntryEditorConfig = Object.assign(BaseContentEntryEditorConfig, {
ContentEntry: Object.assign(ContentEntry, {
Expand All @@ -21,6 +23,9 @@ export const ContentEntryEditorConfig = Object.assign(BaseContentEntryEditorConf
}),
ContentEntryFormPreview
}),
SingletonContentEntry: Object.assign(SingletonContentEntry, {
useSingletonContentEntry
}),
FieldRenderers: {
DynamicZone: {
Template: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { ContentEntryEditorConfig } from "~/ContentEntryEditorConfig";
import { ContentEntryEditorConfig } from "~/admin/config/contentEntries";
import { useContentEntryForm } from "~/admin/components/ContentEntryForm/useContentEntryForm";

const { Actions } = ContentEntryEditorConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Elevation as BaseElevation } from "@webiny/ui/Elevation";
import { CircularProgress } from "@webiny/ui/Progress";
import { ContentEntryForm } from "~/admin/components/ContentEntryForm/ContentEntryForm";
import { makeDecoratable } from "@webiny/app";
import { useSingletonContentEntry } from "~/admin/views/contentEntries/hooks/useSingletonContentEntry";
import { useSingletonContentEntry } from "../hooks/useSingletonContentEntry";
import { PartialCmsContentEntryWithId } from "~/admin/contexts/Cms";
import { SingletonHeader } from "~/admin/components/ContentEntryForm/SingletonHeader";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
import { useSnackbar, useIsMounted } from "@webiny/app-admin";
import { useCms } from "~/admin/hooks";
import { useContentEntries } from "~/admin/views/contentEntries/hooks/useContentEntries";
import { CmsContentEntry, CmsModel } from "~/types";
import * as Cms from "~/admin/contexts/Cms";
import type { CmsContentEntry, CmsModel } from "~/types";
import type * as Cms from "~/admin/contexts/Cms";

export type UpdateEntryParams = Omit<Cms.UpdateEntryRevisionParams, "model">;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useContentEntry } from "@webiny/app-headless-cms";
import { useRecordLocking } from "~/hooks";
import { Elevation } from "@webiny/ui/Elevation";
import { CircularProgress } from "@webiny/ui/Progress";
Expand All @@ -7,6 +6,7 @@ import styled from "@emotion/styled";
import React, { useEffect, useState } from "react";
import { LockedRecord } from "../LockedRecord";
import { IRecordLockingLockRecord } from "~/types";
import { CmsContentEntry, CmsModel } from "@webiny/app-headless-cms/types";

const DetailsContainer = styled("div")({
height: "calc(100% - 10px)",
Expand All @@ -31,12 +31,14 @@ const elevationStyles = css({
});

export interface IContentEntryGuardProps {
loading: boolean;
entry: CmsContentEntry;
model: CmsModel;
children: React.ReactElement;
}

export const ContentEntryGuard = (props: IContentEntryGuardProps) => {
const { loading, entry, contentModel: model } = useContentEntry();
const { children } = props;
const { loading, entry, model, children } = props;
const { fetchLockedEntryLockRecord } = useRecordLocking();

const [locked, setLocked] = useState<IRecordLockingLockRecord | null | undefined>(undefined);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useContentEntriesList, useContentEntry } from "@webiny/app-headless-cms";
import React, { useEffect, useRef } from "react";
import { useRecordLocking } from "~/hooks";
import { IIsRecordLockedParams, IRecordLockingIdentity, IRecordLockingLockRecord } from "~/types";
Expand All @@ -10,12 +9,16 @@ import {
import { parseIdentifier } from "@webiny/utils";
import { useDialogs } from "@webiny/app-admin";
import styled from "@emotion/styled";
import { CmsContentEntry, CmsModel } from "@webiny/app-headless-cms/types";

const Bold = styled.span`
font-weight: 600;
`;

export interface IContentEntryLockerProps {
entry: CmsContentEntry;
model: CmsModel;
onEntryUnlocked: () => void;
onDisablePrompt: (flag: boolean) => void;
children: React.ReactElement;
}
Expand All @@ -39,13 +42,16 @@ const ForceUnlocked = ({ user }: IForceUnlockedProps) => {
);
};

export const ContentEntryLocker = ({ onDisablePrompt, children }: IContentEntryLockerProps) => {
const { entry, contentModel: model } = useContentEntry();
export const ContentEntryLocker = ({
onEntryUnlocked,
onDisablePrompt,
entry,
model,
children
}: IContentEntryLockerProps) => {
const { updateEntryLock, unlockEntry, fetchLockedEntryLockRecord, removeEntryLock } =
useRecordLocking();

const { navigateTo } = useContentEntriesList();

const subscription = useRef<IWebsocketsSubscription<any>>();

const websockets = useWebsockets();
Expand Down Expand Up @@ -77,7 +83,7 @@ export const ContentEntryLocker = ({ onDisablePrompt, children }: IContentEntryL
onClose: undefined,
cancelLabel: undefined
});
navigateTo();
onEntryUnlocked();
}
);

Expand All @@ -87,7 +93,7 @@ export const ContentEntryLocker = ({ onDisablePrompt, children }: IContentEntryL
}
subscription.current.off();
};
}, [entry.id, navigateTo, model.modelId]);
}, [entry.id, onEntryUnlocked, model.modelId]);

useEffect(() => {
if (!entry.id) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useState } from "react";
import { CompositionScope, createGenericContext } from "@webiny/app-admin";
import { ContentEntryEditorConfig } from "@webiny/app-headless-cms";
import { ContentEntryEditorConfig, ContentEntryListConfig } from "@webiny/app-headless-cms";
import { Prompt } from "@webiny/react-router";
import { ContentEntryGuard } from "./ContentEntryGuard";
import { ContentEntryLocker } from "./ContentEntryLocker";

const { ContentEntry } = ContentEntryEditorConfig;
const { ContentEntry, SingletonContentEntry } = ContentEntryEditorConfig;

const DisablePrompt = createGenericContext<{ disablePrompt: boolean }>("DisablePrompt");

Expand All @@ -20,7 +20,8 @@ const PromptDecorator = Prompt.createDecorator(Original => {
const ContentEntryDecorator = ContentEntry.createDecorator(Original => {
return function RecordLockingContentEntry() {
const [disablePrompt, setDisablePrompt] = useState(false);
const { entry } = ContentEntry.useContentEntry();
const { entry, contentModel, loading } = ContentEntry.useContentEntry();
const { navigateTo } = ContentEntryListConfig.ContentEntries.useContentEntriesList();
/**
* New entry does not have ID yet.
*/
Expand All @@ -34,9 +35,40 @@ const ContentEntryDecorator = ContentEntry.createDecorator(Original => {
/**
* Continue with existing entry.
*/
const props = { entry, model: contentModel };

return (
<ContentEntryGuard {...props} loading={loading}>
<ContentEntryLocker
{...props}
onDisablePrompt={flag => setDisablePrompt(flag)}
onEntryUnlocked={navigateTo}
>
<DisablePrompt.Provider disablePrompt={disablePrompt}>
<Original />
</DisablePrompt.Provider>
</ContentEntryLocker>
</ContentEntryGuard>
);
};
});

const SingletonContentEntryDecorator = SingletonContentEntry.createDecorator(Original => {
return function RecordLockingSingletonContentEntry() {
const [disablePrompt, setDisablePrompt] = useState(false);
const { entry, contentModel, loading } = SingletonContentEntry.useSingletonContentEntry();

const props = { entry, model: contentModel };

return (
<ContentEntryGuard>
<ContentEntryLocker onDisablePrompt={flag => setDisablePrompt(flag)}>
<ContentEntryGuard {...props} loading={loading}>
<ContentEntryLocker
{...props}
onDisablePrompt={flag => setDisablePrompt(flag)}
onEntryUnlocked={() => {
// There's nowhere to go, since singleton entry doesn't have a list view.
}}
>
<DisablePrompt.Provider disablePrompt={disablePrompt}>
<Original />
</DisablePrompt.Provider>
Expand All @@ -50,6 +82,7 @@ export const HeadlessCmsContentEntry = () => {
return (
<>
<ContentEntryDecorator />
<SingletonContentEntryDecorator />
<CompositionScope name={"cms.contentEntryForm"}>
<PromptDecorator />
</CompositionScope>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useCallback } from "react";
import { useRecordLocking } from "~/hooks";
import { ContentEntryEditorConfig } from "@webiny/app-headless-cms";
import { ContentEntryEditorConfig, useModel } from "@webiny/app-headless-cms";
import { useSnackbar } from "@webiny/app-admin";

const {
ContentEntry: { ContentEntryForm, useContentEntry }
ContentEntry: { ContentEntryForm }
} = ContentEntryEditorConfig;

type SaveEntry = ReturnType<typeof ContentEntryForm.useContentEntryForm>["saveEntry"];
Expand All @@ -13,9 +13,11 @@ export const UseSaveEntryDecorator = ContentEntryForm.useContentEntryForm.create
originalHook => {
return function useRecordLockingUseSave() {
const hook = originalHook();
const { entry, contentModel: model } = useContentEntry();
const { fetchLockedEntryLockRecord, updateEntryLock } = useRecordLocking();
const { showSnackbar } = useSnackbar();
const { model } = useModel();

const { entry } = hook;

const saveEntry: SaveEntry = useCallback(
async (...params) => {
Expand Down

0 comments on commit bb500f4

Please sign in to comment.