1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-31 15:24:31 +03:00

Page Drafts: Added new "Delete Draft" action to draft menu

Provides a way for users to actually delte their user drafts where
required.
For #3927

Added test to cover new endpoint.

Makes update to MD editor #setText so that new selection is within new
range, otherwise it errors and fails operation.
This commit is contained in:
Dan Brown
2023-06-13 15:13:07 +01:00
parent f39938c4e3
commit b01bbf9c89
9 changed files with 101 additions and 14 deletions

View File

@ -19,18 +19,23 @@ export class PageEditor extends Component {
this.saveDraftButton = this.$refs.saveDraft;
this.discardDraftButton = this.$refs.discardDraft;
this.discardDraftWrap = this.$refs.discardDraftWrap;
this.deleteDraftButton = this.$refs.deleteDraft;
this.deleteDraftWrap = this.$refs.deleteDraftWrap;
this.draftDisplay = this.$refs.draftDisplay;
this.draftDisplayIcon = this.$refs.draftDisplayIcon;
this.changelogInput = this.$refs.changelogInput;
this.changelogDisplay = this.$refs.changelogDisplay;
this.changeEditorButtons = this.$manyRefs.changeEditor || [];
this.switchDialogContainer = this.$refs.switchDialog;
this.deleteDraftDialogContainer = this.$refs.deleteDraftDialog;
// Translations
this.draftText = this.$opts.draftText;
this.autosaveFailText = this.$opts.autosaveFailText;
this.editingPageText = this.$opts.editingPageText;
this.draftDiscardedText = this.$opts.draftDiscardedText;
this.draftDeleteText = this.$opts.draftDeleteText;
this.draftDeleteFailText = this.$opts.draftDeleteFailText;
this.setChangelogText = this.$opts.setChangelogText;
// State data
@ -75,6 +80,7 @@ export class PageEditor extends Component {
// Draft Controls
onSelect(this.saveDraftButton, this.saveDraft.bind(this));
onSelect(this.discardDraftButton, this.discardDraft.bind(this));
onSelect(this.deleteDraftButton, this.deleteDraft.bind(this));
// Change editor controls
onSelect(this.changeEditorButtons, this.changeEditor.bind(this));
@ -119,7 +125,8 @@ export class PageEditor extends Component {
try {
const resp = await window.$http.put(`/ajax/page/${this.pageId}/save-draft`, data);
if (!this.isNewDraft) {
this.toggleDiscardDraftVisibility(true);
this.discardDraftWrap.toggleAttribute('hidden', false);
this.deleteDraftWrap.toggleAttribute('hidden', false);
}
this.draftNotifyChange(`${resp.data.message} ${Dates.utcTimeStampToLocalTime(resp.data.timestamp)}`);
@ -154,7 +161,7 @@ export class PageEditor extends Component {
}, 2000);
}
async discardDraft() {
async discardDraft(notify = true) {
let response;
try {
response = await window.$http.get(`/ajax/page/${this.pageId}`);
@ -168,7 +175,7 @@ export class PageEditor extends Component {
}
this.draftDisplay.innerText = this.editingPageText;
this.toggleDiscardDraftVisibility(false);
this.discardDraftWrap.toggleAttribute('hidden', true);
window.$events.emit('editor::replace', {
html: response.data.html,
markdown: response.data.markdown,
@ -178,7 +185,30 @@ export class PageEditor extends Component {
window.setTimeout(() => {
this.startAutoSave();
}, 1000);
window.$events.emit('success', this.draftDiscardedText);
if (notify) {
window.$events.success(this.draftDiscardedText);
}
}
async deleteDraft() {
/** @var {ConfirmDialog} * */
const dialog = window.$components.firstOnElement(this.deleteDraftDialogContainer, 'confirm-dialog');
const confirmed = await dialog.show();
if (!confirmed) {
return;
}
try {
const discard = this.discardDraft(false);
const draftDelete = window.$http.delete(`/page-revisions/user-drafts/${this.pageId}`);
await Promise.all([discard, draftDelete]);
window.$events.success(this.draftDeleteText);
this.deleteDraftWrap.toggleAttribute('hidden', true);
} catch (err) {
console.error(err);
window.$events.error(this.draftDeleteFailText);
}
}
updateChangelogDisplay() {
@ -191,10 +221,6 @@ export class PageEditor extends Component {
this.changelogDisplay.innerText = summary;
}
toggleDiscardDraftVisibility(show) {
this.discardDraftWrap.classList.toggle('hidden', !show);
}
async changeEditor(event) {
event.preventDefault();

View File

@ -433,7 +433,9 @@ export class Actions {
*/
#setText(text, selectionRange = null) {
selectionRange = selectionRange || this.#getSelectionRange();
this.#dispatchChange(0, this.editor.cm.state.doc.length, text, selectionRange.from);
const newDoc = this.editor.cm.state.toText(text);
const newSelectFrom = Math.min(selectionRange.from, newDoc.length);
this.#dispatchChange(0, this.editor.cm.state.doc.length, text, newSelectFrom);
this.focus();
}

View File

@ -27,13 +27,22 @@
</a>
</li>
@endif
<li refs="page-editor@discardDraftWrap" class="{{ $isDraftRevision ? '' : 'hidden' }}">
<button refs="page-editor@discardDraft" type="button" class="text-neg icon-item">
<li refs="page-editor@discard-draft-wrap" {{ $isDraftRevision ? '' : 'hidden' }}>
<button refs="page-editor@discard-draft" type="button" class="text-warn icon-item">
@icon('cancel')
<div>{{ trans('entities.pages_edit_discard_draft') }}</div>
</button>
</li>
<li refs="page-editor@delete-draft-wrap" {{ $isDraftRevision ? '' : 'hidden' }}>
<button refs="page-editor@delete-draft" type="button" class="text-neg icon-item">
@icon('delete')
<div>{{ trans('entities.pages_edit_delete_draft') }}</div>
</button>
</li>
@if(userCan('editor-change'))
<li>
<hr>
</li>
<li>
@if($editor === 'wysiwyg')
<a href="{{ $model->getUrl($isDraft ? '' : '/edit') }}?editor=markdown-clean" refs="page-editor@changeEditor" class="icon-item">

View File

@ -13,6 +13,8 @@
option:page-editor:autosave-fail-text="{{ trans('errors.page_draft_autosave_fail') }}"
option:page-editor:editing-page-text="{{ trans('entities.pages_editing_page') }}"
option:page-editor:draft-discarded-text="{{ trans('entities.pages_draft_discarded') }}"
option:page-editor:draft-delete-text="{{ trans('entities.pages_draft_deleted') }}"
option:page-editor:draft-delete-fail-text="{{ trans('errors.page_draft_delete_fail') }}"
option:page-editor:set-changelog-text="{{ trans('entities.pages_edit_set_changelog') }}">
{{--Header Toolbar--}}
@ -47,7 +49,7 @@
class="text-link text-button hide-over-m page-save-mobile-button">@icon('save')</button>
{{--Editor Change Dialog--}}
@component('common.confirm-dialog', ['title' => trans('entities.pages_editor_switch_title'), 'ref' => 'page-editor@switchDialog'])
@component('common.confirm-dialog', ['title' => trans('entities.pages_editor_switch_title'), 'ref' => 'page-editor@switch-dialog'])
<p>
{{ trans('entities.pages_editor_switch_are_you_sure') }}
<br>
@ -60,4 +62,11 @@
<li>{{ trans('entities.pages_editor_switch_consideration_c') }}</li>
</ul>
@endcomponent
{{--Delete Draft Dialog--}}
@component('common.confirm-dialog', ['title' => trans('entities.pages_edit_delete_draft'), 'ref' => 'page-editor@delete-draft-dialog'])
<p>
{{ trans('entities.pages_edit_delete_draft_confirm') }}
</p>
@endcomponent
</div>