Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 35 additions & 4 deletions studio-ui/ui/app/src/components/FormsEngine/FormsEngine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import {
displayFormBeingSavedSnack,
fetchUpdateRequirements,
generateDefaultChangesComment,
generateDefaultCreationComment,
getAdditionalFieldsIdsFromDescriptor,
resolveControlDescriptors,
getCurrentChildFormStateSummary,
Expand All @@ -104,6 +105,7 @@ import {
internalLockContentService,
internalUnlockContentService,
prepareEmbeddedItemForm,
produceCreationMessage,
setFieldAtoms,
useUnlockOnClose,
useValidateFormProps
Expand Down Expand Up @@ -286,6 +288,7 @@ function FormBootstrap(props: FormsEngineProps) {
const triggerReload = useCallback(() => setReloadNonce((nonce) => nonce + 1), []);
const effectiveUpdatePath = renamedPath ?? update?.path;
const customControls = useSelection((state) => state.uiConfig.controls);
const { formatMessage } = useIntl();

const contextApi = useMemo<FormsEngineFormApiContextProps>(() => {
const getInitialValues = () => stableFormContextRef.current.originalValues;
Expand Down Expand Up @@ -491,7 +494,9 @@ function FormBootstrap(props: FormsEngineProps) {
lockResult: lockResultAtom,
readonly: atom(false),
expandedStateBySectionId: buildSectionExpandedStateAtoms(contentType.sections),
fileName: atom('')
fileName: atom(''),
// Default version comment for new content.
versionComment: atom(produceCreationMessage('', formatMessage))
});
const contentObject = createObjectWithSystemProps(contentType);
const values = createParsedValuesObject(
Expand Down Expand Up @@ -718,8 +723,12 @@ function FormOrchestrator(props: FormsEngineProps) {
const effectRefs = useUpdateRefs({
fieldsToRender,
versionCommentAtom: stableFormContext.atoms.versionComment,
fileNameAtom: stableFormContext.atoms.fileName,
lockStatus
});
// Holds the create mode comment generated last, so that a comment written by the user isn't overwritten. Starts off
// with the default comment the version comment atom was created with.
const lastCreationCommentRef = useRef(produceCreationMessage('', formatMessage));
const [collapseHeader, setCollapseHeader] = useState(false);
const [saveAsDraftAction, setSaveAsDraftAction] = useState(false);
const [invalidForm, setInvalidForm] = useState(false);
Expand Down Expand Up @@ -752,9 +761,22 @@ function FormOrchestrator(props: FormsEngineProps) {
// String-type fields have auto-rollback detection; the fieldUpdates$ will emit anyway. Checking if the fieldId
// emitted is in changedFieldIds should tell if the field was rolled back.
setHasPendingChanges(changedFieldIds.size > 0);
// No comment generation for content creation.
if (isCreateMode) return;
const versionCommentAtom = effectRefs.current.versionCommentAtom;
// Create mode bases the comment off of the page URL (file-name) instead of the fields changed. Note that any
// field update re-runs this since every field's validation depends on the file name.
if (isCreateMode) {
const newMessage = generateDefaultCreationComment(
store.get(effectRefs.current.fileNameAtom),
store.get(versionCommentAtom).trim(),
lastCreationCommentRef.current,
formatMessage
);
if (newMessage) {
lastCreationCommentRef.current = newMessage;
store.set(versionCommentAtom, newMessage);
}
return;
}
Comment thread
jvega190 marked this conversation as resolved.
const newMessage = generateDefaultChangesComment(
contentType.fields,
effectRefs.current.fieldsToRender,
Expand All @@ -766,7 +788,16 @@ function FormOrchestrator(props: FormsEngineProps) {
return () => {
sub.unsubscribe();
};
}, [changedFieldIds, contentType.fields, effectRefs, setHasPendingChanges, fieldUpdates$, store, isCreateMode]);
}, [
changedFieldIds,
contentType.fields,
effectRefs,
setHasPendingChanges,
fieldUpdates$,
store,
isCreateMode,
formatMessage
]);

const sourceMapPaths = useMemo(() => Object.values(sourceMap ?? []).sort(), [sourceMap]);
useFetchContentItems(sourceMapPaths);
Expand Down
42 changes: 42 additions & 0 deletions studio-ui/ui/app/src/components/FormsEngine/lib/formUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,48 @@ export function generateDefaultChangesComment(
return newMessage;
}

/**
* Produces the "save comment" for content being created at the supplied page URL (file name). An empty page URL
* produces the generic comment new content forms start off with.
**/
export function produceCreationMessage(pageUrl: string, formatMessage: IntlShape['formatMessage']): string {
return pageUrl
? formatMessage({ defaultMessage: 'Created {pageUrl}' }, { pageUrl })
: formatMessage({ defaultMessage: 'Created content' });
}

/**
* Generates the default "save comment" for content being created, based on the page URL (file name) it will be
* created at.
* @param pageUrl The current value of the file name field.
* @param currentMessage The version comment currently held by the form.
* @param lastGeneratedMessage The comment this function generated last, used to detect user input on the comment.
* @returns The new comment, or undefined when the comment should be left untouched.
**/
export function generateDefaultCreationComment(
pageUrl: string,
currentMessage: string,
lastGeneratedMessage: string,
formatMessage: IntlShape['formatMessage']
): string | undefined {
const newMessage = pageUrl
? formatMessage({ defaultMessage: 'Created {pageUrl}' }, { pageUrl })
: formatMessage({ defaultMessage: 'Created content' });
if (
// Nothing to change
currentMessage === newMessage ||
// If message is blank, no point in checking if the user has altered the message.
(currentMessage !== '' &&
// The version comment has been manually altered by the user (i.e. if the current message isn't the last
// message generated here, we can assume the message has been altered by user input)
currentMessage !== lastGeneratedMessage)
) {
// Do not set a new message
return;
}
return newMessage;
}

/**
* Creates a summary of the state the current stacked form being rendered (last one on the stack)
**/
Expand Down