@@ -117,51 +117,91 @@ $(() => {
117117 } ) ;
118118
119119 /**
120- * @typedef {{
121- * body: string
122- * comment?: string
123- * excerpt?: string
124- * license?: string
125- * tag_name?: string
126- * tags?: string[]
127- * title?: string
128- * }} PostDraft
129- *
120+ * Temporarily displays the draft's status with a given message
121+ * @param {JQuery<Element> } $field draftable field
122+ * @param {string } message draft status message
123+ * @returns {void }
124+ */
125+ const flashDraftStatus = ( $field , message ) => {
126+ const $statusEl = $field . parents ( '.widget' ) . find ( '.js-post-draft-status' ) ;
127+
128+ $statusEl . text ( message ) ;
129+ $statusEl . removeClass ( 'transparent' ) ;
130+
131+ setTimeout ( ( ) => {
132+ $statusEl . addClass ( 'transparent' ) ;
133+ } , 1500 ) ;
134+ } ;
135+
136+ /**
137+ * Removes the "draft loaded" notice from the page
138+ * @returns {void }
139+ */
140+ const removeDraftLoadedNotice = ( ) => {
141+ document . querySelector ( '.js-draft-notice' ) ?. remove ( ) ;
142+ } ;
143+
144+ /**
130145 * Attempts to save a post draft
131- * @param {PostDraft } draft post draft
132- * @param {JQuery<Element> } $field body input element
146+ * @param {QPixelDraft } draft post draft
147+ * @param {JQuery<Element> } $field draftable field
133148 * @param {boolean } [manual] whether manual draft saving is enabled
134149 * @returns {Promise<void> }
135150 */
136151 const saveDraft = async ( draft , $field , manual = false ) => {
137152 const autosavePref = await QPixel . preference ( 'autosave' , true ) ;
153+
138154 if ( autosavePref !== 'on' && ! manual ) {
139155 return ;
140156 }
141157
142- const resp = await QPixel . fetchJSON ( '/posts/save- draft' , { ... draft , path : location . pathname } ) ;
158+ const data = await QPixel . saveDraft ( draft ) ;
143159
144- if ( resp . status === 200 ) {
145- const $statusEl = $field . parents ( '.widget' ) . find ( '.js-post-draft-status' ) ;
160+ QPixel . handleJSONResponse ( data , ( ) => {
161+ flashDraftStatus ( $field , 'draft saved' ) ;
162+ } ) ;
163+ } ;
164+
165+ /**
166+ * Attempts to remove a post draft
167+ * @param {JQuery<Element> } $field draftable field
168+ * @returns {Promise<boolean> }
169+ */
170+ const deleteDraft = async ( $field ) => {
171+ const data = await QPixel . deleteDraft ( ) ;
146172
147- $statusEl . removeClass ( 'transparent' ) ;
173+ return QPixel . handleJSONResponse ( data , ( ) => {
174+ flashDraftStatus ( $field , 'draft deleted' ) ;
175+ removeDraftLoadedNotice ( ) ;
176+ } ) ;
177+ }
148178
149- setTimeout ( ( ) => {
150- $statusEl . addClass ( 'transparent' ) ;
151- } , 1500 ) ;
152- }
179+ /**
180+ * Helper for getting draft-related elements from a given event target
181+ * @param {EventTarget } target post field or one of the draft buttons
182+ * @returns {{
183+ * $form: JQuery<HTMLFormElement>,
184+ * $field: JQuery<HTMLElement>
185+ * }}
186+ */
187+ const getDraftElements = ( target ) => {
188+ const $tgt = $ ( target ) ;
189+ const $form = $tgt . parents ( 'form' ) ;
190+ const $field = $form . find ( '.js-post-field' ) ;
191+ return { $form, $field } ;
153192 } ;
154193
155194 /**
156195 * Extracts draft info from a given target
157- * @param {EventTarget } target post input field or "save draft" button
158- * @returns {{ draft: PostDraft, field: any } }
196+ * @param {EventTarget } target post field or one of the draft buttons
197+ * @returns {{
198+ * draft: QPixelDraft,
199+ * $field: JQuery<HTMLElement>
200+ * }}
159201 */
160202 const parseDraft = ( target ) => {
161- const $tgt = $ ( target ) ;
162- const $form = $tgt . parents ( 'form' ) ;
203+ const { $field : $bodyField , $form } = getDraftElements ( target ) ;
163204
164- const $bodyField = $form . find ( '.js-post-field' ) ;
165205 const $licenseField = $form . find ( '.js-license-select' ) ;
166206 const $excerptField = $form . find ( '.js-tag-excerpt' ) ;
167207
@@ -178,7 +218,7 @@ $(() => {
178218 const titleText = $titleField . val ( ) ?. toString ( ) ;
179219 const tagName = $tagNameField . val ( ) ?. toString ( ) ;
180220
181- /** @type {PostDraft } */
221+ /** @type {QPixelDraft } */
182222 const draft = {
183223 body : bodyText ,
184224 comment : commentText ,
@@ -189,12 +229,17 @@ $(() => {
189229 title : titleText ,
190230 } ;
191231
192- return { draft, field : $bodyField } ;
232+ return { draft, $ field : $bodyField } ;
193233 } ;
194234
235+ $ ( '.js-delete-draft' ) . on ( 'click' , async ( ev ) => {
236+ const { $field } = getDraftElements ( ev . target ) ;
237+ await deleteDraft ( $field ) ;
238+ } ) ;
239+
195240 $ ( '.js-save-draft' ) . on ( 'click' , async ( ev ) => {
196- const { draft, field } = parseDraft ( ev . target ) ;
197- await saveDraft ( draft , field , true ) ;
241+ const { draft, $ field } = parseDraft ( ev . target ) ;
242+ await saveDraft ( draft , $ field, true ) ;
198243 } ) ;
199244
200245 let featureTimeout = null ;
@@ -215,8 +260,8 @@ $(() => {
215260 $ ( draftFieldsSelectors . join ( ', ' ) ) . on ( 'keyup change' , ( ev ) => {
216261 clearTimeout ( draftTimeout ) ;
217262 draftTimeout = setTimeout ( ( ) => {
218- const { draft, field } = parseDraft ( ev . target ) ;
219- saveDraft ( draft , field ) ;
263+ const { draft, $ field } = parseDraft ( ev . target ) ;
264+ saveDraft ( draft , $ field) ;
220265 } , 1000 ) ;
221266 } ) ;
222267
@@ -299,35 +344,37 @@ $(() => {
299344
300345 $postFields . parents ( 'form' ) . on ( 'submit' , async ( ev ) => {
301346 const $tgt = $ ( ev . target ) ;
302- const field = $tgt . find ( '.post-field' ) ;
347+ const $ field = $tgt . find ( '.js- post-field' ) ;
303348
304349 const draftDeleted = $tgt . attr ( 'data-draft-deleted' ) === 'true' ;
305350 const isValidated = $tgt . attr ( 'data-validated' ) === 'true' ;
306351
307352 if ( draftDeleted && isValidated ) {
308353 return ;
309354 }
355+
310356 ev . preventDefault ( ) ;
311357
312358 // Draft handling
313359 if ( ! draftDeleted ) {
314- const resp = await QPixel . fetchJSON ( '/posts/delete-draft' , { path : location . pathname } ) ;
315- if ( resp . status === 200 ) {
360+ const status = await deleteDraft ( $field ) ;
361+
362+ if ( status ) {
316363 $tgt . attr ( 'data-draft-deleted' , 'true' ) ;
317364
318365 if ( isValidated ) {
319366 $tgt . submit ( ) ;
320367 }
321368 }
322369 else {
323- QPixel . createNotification ( 'danger' , `Failed to delete post draft. (${ resp . status } )` ) ;
370+ QPixel . createNotification ( 'danger' , `Failed to delete post draft. (${ status } )` ) ;
324371 }
325372 }
326373
327374
328375 // Validation
329376 if ( ! isValidated ) {
330- const text = $ ( field ) . val ( ) ?. toString ( ) ;
377+ const text = $field . val ( ) ?. toString ( ) ;
331378 const validated = QPixel . validatePost ( text ) ;
332379 if ( validated [ 0 ] === true ) {
333380 $tgt . attr ( 'data-validated' , 'true' ) ;
@@ -369,7 +416,7 @@ $(() => {
369416 } ) ;
370417
371418 $ ( '.js-draft-loaded' ) . each ( ( _i , e ) => {
372- $ ( e ) . parents ( '.widget' ) . after ( `<div class="notice is-info has-font-size-caption">
419+ $ ( e ) . parents ( '.widget' ) . after ( `<div class="notice is-info has-font-size-caption js-draft-notice ">
373420 <i class="fas fa-exclamation-circle"></i> <strong>Draft loaded.</strong>
374421 You had edited this before but haven't saved it. We loaded the edits for you.
375422 </div>` ) ;
@@ -456,7 +503,9 @@ $(() => {
456503 return ;
457504 }
458505
459- await QPixel . fetchJSON ( '/posts/delete-draft' , { path : location . pathname } ) ;
506+ const { $field } = getDraftElements ( ev . target ) ;
507+
508+ await deleteDraft ( $field ) ;
460509
461510 location . href = $btn . attr ( 'href' ) ;
462511 } ) ;
0 commit comments