mirror of
https://github.com/strapi/strapi.git
synced 2025-11-09 06:40:42 +00:00
enhancement: cmd+enter and ctrl+enter to save entry (#22311)
* enhancement: keyboard shortcuts to save entry * chore: add e2e test * chore: restore validate fn * fix: don't register cmd+s for arc browser * fix: remove cmd+s and ctrl+s
This commit is contained in:
parent
d6bba97c7e
commit
03640aa70e
@ -768,22 +768,14 @@ const UpdateAction: DocumentActionComponent = ({
|
||||
const setErrors = useForm('UpdateAction', (state) => state.setErrors);
|
||||
const resetForm = useForm('PublishAction', ({ resetForm }) => resetForm);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Disabled when:
|
||||
* - the form is submitting
|
||||
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
||||
* - the active tab is the published tab
|
||||
*/
|
||||
disabled: isSubmitting || (!modified && !isCloning) || activeTab === 'published',
|
||||
label: formatMessage({
|
||||
id: 'global.save',
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
onClick: async () => {
|
||||
const handleUpdate = React.useCallback(async () => {
|
||||
setSubmitting(true);
|
||||
|
||||
try {
|
||||
if (!modified) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { errors } = await validate(true, {
|
||||
status: 'draft',
|
||||
});
|
||||
@ -837,11 +829,7 @@ const UpdateAction: DocumentActionComponent = ({
|
||||
transformData(document)
|
||||
);
|
||||
|
||||
if (
|
||||
'error' in res &&
|
||||
isBaseQueryError(res.error) &&
|
||||
res.error.name === 'ValidationError'
|
||||
) {
|
||||
if ('error' in res && isBaseQueryError(res.error) && res.error.name === 'ValidationError') {
|
||||
setErrors(formatValidationErrors(res.error));
|
||||
} else {
|
||||
resetForm();
|
||||
@ -874,7 +862,58 @@ const UpdateAction: DocumentActionComponent = ({
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
},
|
||||
}, [
|
||||
clone,
|
||||
cloneMatch?.params.origin,
|
||||
collectionType,
|
||||
create,
|
||||
document,
|
||||
documentId,
|
||||
formatMessage,
|
||||
formatValidationErrors,
|
||||
isCloning,
|
||||
model,
|
||||
modified,
|
||||
navigate,
|
||||
params,
|
||||
rawQuery,
|
||||
resetForm,
|
||||
setErrors,
|
||||
setSubmitting,
|
||||
toggleNotification,
|
||||
update,
|
||||
validate,
|
||||
]);
|
||||
|
||||
// Auto-save on CMD+S or CMD+Enter on macOS, and CTRL+S or CTRL+Enter on Windows/Linux
|
||||
React.useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
handleUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [handleUpdate]);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Disabled when:
|
||||
* - the form is submitting
|
||||
* - the document is not modified & we're not cloning (you can save a clone entity straight away)
|
||||
* - the active tab is the published tab
|
||||
*/
|
||||
disabled: isSubmitting || (!modified && !isCloning) || activeTab === 'published',
|
||||
label: formatMessage({
|
||||
id: 'global.save',
|
||||
defaultMessage: 'Save',
|
||||
}),
|
||||
onClick: handleUpdate,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -250,6 +250,11 @@ test.describe('Edit View', () => {
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await findAndClose(page, 'Saved Document');
|
||||
|
||||
// Check that we can save with keyboard shortcuts
|
||||
await page.getByRole('textbox', { name: 'title' }).fill('Being an American...');
|
||||
await page.keyboard.press('Control+Enter');
|
||||
await findAndClose(page, 'Saved Document');
|
||||
|
||||
await expect(page.getByRole('tab', { name: 'Draft' })).toHaveAttribute(
|
||||
'aria-selected',
|
||||
'true'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user