MediaWiki:Gadget-PreloadEditor.js: Difference between revisions
MediaWiki interface page
More actions
ReisuDesign (talk | contribs) No edit summary |
ReisuDesign (talk | contribs) No edit summary |
||
| Line 15: | Line 15: | ||
deletedVariables: [], | deletedVariables: [], | ||
mode: 'idle', | mode: 'idle', | ||
dirty: false, | |||
dirtyPreload: false, | |||
dirtyConfig: false | |||
}, | }, | ||
| Line 34: | Line 27: | ||
status: null, | status: null, | ||
editorTools: null, | editorTools: null, | ||
draftStorageKey: | draftStorageKey: | ||
| Line 44: | Line 36: | ||
}, | }, | ||
// Browser-local draft storage | // Browser-local draft storage | ||
getDraftStorage() { | getDraftStorage() { | ||
| Line 210: | Line 200: | ||
'edit', | 'edit', | ||
dirty: | |||
!!this.state. | !!this.state.dirty, | ||
dirtyPreload: | |||
!!this.state. | !!this.state.dirtyPreload, | ||
dirtyConfig: | |||
!!this.state.dirtyConfig, | |||
savedAt: | savedAt: | ||
| Line 423: | Line 414: | ||
} | } | ||
} | } | ||
const hasDirtyFlags = | |||
typeof draft.dirtyPreload === 'boolean' || | |||
typeof draft.dirtyConfig === 'boolean'; | |||
this.state = { | this.state = { | ||
| Line 482: | Line 477: | ||
'edit', | 'edit', | ||
dirty: | |||
hasDirtyFlags | |||
? !!draft. | ? !!( | ||
draft.dirtyPreload || | |||
draft.dirtyConfig | |||
) | |||
: true, | : true, | ||
dirtyPreload: | |||
hasDirtyFlags | |||
? !!draft. | ? !!draft.dirtyPreload | ||
: true, | : true, | ||
dirtyConfig: | |||
hasDirtyFlags | |||
? !!draft.dirtyConfig | |||
: true | |||
}; | }; | ||
| Line 513: | Line 514: | ||
}, | }, | ||
// API | // API | ||
async getPage(title) { | async getPage(title) { | ||
| Line 683: | Line 604: | ||
}, | }, | ||
// Preload parsing | // Preload parsing | ||
extractIncludeonly(source) { | extractIncludeonly(source) { | ||
| Line 798: | Line 717: | ||
}, | }, | ||
// Config | // Config | ||
getAutomaticPageField() { | getAutomaticPageField() { | ||
| Line 1,102: | Line 1,019: | ||
}, | }, | ||
// Transformation helpers | // Transformation helpers | ||
transformationObject( | transformationObject( | ||
| Line 1,148: | Line 1,063: | ||
}, | }, | ||
// UI helpers | // UI helpers | ||
createSection( | createSection( | ||
| Line 1,323: | Line 1,236: | ||
}, | }, | ||
// In-wiki dialogs | // In-wiki dialogs | ||
createConfirmDialog( | createConfirmDialog( | ||
| Line 1,357: | Line 1,268: | ||
messageLines.forEach( | messageLines.forEach( | ||
line => { | line => { | ||
if (line === '') { | |||
$('<div>') | |||
.addClass( | |||
'preload-editor-prompt-spacer' | |||
) | |||
.appendTo(box); | |||
return; | |||
} | |||
$('<p>') | $('<p>') | ||
.text(line) | .text(line) | ||
| Line 1,399: | Line 1,320: | ||
$(document.body) | $(document.body) | ||
.append(overlay); | .append(overlay); | ||
const close = | |||
value => { | |||
if (value === 'Escape') { | |||
cancel.trigger('click'); | |||
} | |||
}; | |||
overlay.on( | |||
'keydown.preloadEditor', | |||
event => { | |||
close(event.key); | |||
} | |||
); | |||
overlay.attr( | overlay.attr( | ||
| Line 1,408: | Line 1,343: | ||
overlay.on( | overlay.on( | ||
' | 'click.preloadEditor', | ||
event => { | event => { | ||
if ( | if ( | ||
event. | event.target === | ||
overlay.get(0) | |||
) { | ) { | ||
cancel.trigger('click'); | cancel.trigger('click'); | ||
} | } | ||
} | |||
} | |||
); | ); | ||
} | } | ||
| Line 1,546: | Line 1,464: | ||
$('<div>') | $('<div>') | ||
.addClass( | .addClass( | ||
'preload-editor-prompt-overlay preload-editor- | 'preload-editor-prompt-overlay preload-editor-code-review-overlay' | ||
); | ); | ||
| Line 1,552: | Line 1,470: | ||
$('<div>') | $('<div>') | ||
.addClass( | .addClass( | ||
'preload-editor-prompt preload-editor- | 'preload-editor-prompt preload-editor-code-review' | ||
); | ); | ||
$('<h2>') | $('<h2>') | ||
.text( | .text('Review config.json') | ||
.appendTo(box); | .appendTo(box); | ||
$('<p>') | $('<p>') | ||
.text( | .text( | ||
'This is the | 'This is the config.json that will be saved for the current preload.' | ||
) | ) | ||
.appendTo(box); | .appendTo(box); | ||
const | const code = | ||
$('<pre>') | $('<pre>') | ||
.addClass( | .addClass( | ||
'preload-editor-config-review | 'preload-editor-config-review' | ||
) | ) | ||
.text( | .text( | ||
| Line 1,576: | Line 1,492: | ||
); | ); | ||
box.append( | const codeWrap = | ||
$('<div>') | |||
.addClass( | |||
'preload-editor-config-review-wrap' | |||
) | |||
.append(code); | |||
box.append(codeWrap); | |||
const buttons = | const buttons = | ||
| Line 1,634: | Line 1,557: | ||
}, | }, | ||
async confirmSave( | |||
// | mode, | ||
title | |||
) { | |||
const configTitle = | |||
title.replace( | |||
/\/+$/, | |||
'' | |||
) + | |||
'/config.json'; | |||
let saveDescription; | |||
if (mode === 'preload') { | |||
if ( | saveDescription = | ||
'Save the preload page only?'; | |||
} else if (mode === 'config') { | |||
saveDescription = | |||
'Save the config.json page only?'; | |||
} else { | |||
saveDescription = | |||
'Save both the preload and config.json?'; | |||
} | } | ||
let pages = []; | |||
if ( | if ( | ||
view && | mode === 'preload' || | ||
inputHandler | mode === 'both' | ||
) { | |||
pages.push( | |||
'Preload: ' + title | |||
); | |||
} | |||
if ( | |||
mode === 'config' || | |||
mode === 'both' | |||
) { | |||
pages.push( | |||
'Config: ' + configTitle | |||
); | |||
} | |||
const message = | |||
saveDescription + | |||
'\n\n' + | |||
pages.join('\n') + | |||
'\n\nThis will write the changes to the wiki.'; | |||
return this.createConfirmDialog( | |||
'Confirm save', | |||
message, | |||
'Save', | |||
'Cancel' | |||
); | |||
}, | |||
// CodeMirror | |||
destroyEditor() { | |||
if (!this.editor) { | |||
this.editorView = null; | |||
this.editorTools = null; | |||
return; | |||
} | |||
const { | |||
view, | |||
inputHandler | |||
} = this.editor; | |||
if ( | |||
view && | |||
inputHandler | |||
) { | ) { | ||
view.dom.removeEventListener( | view.dom.removeEventListener( | ||
| Line 1,792: | Line 1,771: | ||
}, | }, | ||
// Editor tools | // Editor tools | ||
wrapSelectionWithVariable() { | wrapSelectionWithVariable() { | ||
| Line 2,229: | Line 2,206: | ||
}, | }, | ||
// Syntax highlighting | // Syntax highlighting | ||
getKnownVariables() { | getKnownVariables() { | ||
| Line 2,504: | Line 2,479: | ||
view.state.doc.toString(); | view.state.doc.toString(); | ||
this. | this.markPreloadDirty(); | ||
this.reanalyze(); | this.reanalyze(); | ||
| Line 2,599: | Line 2,571: | ||
}, | }, | ||
// Main UI | // Main UI | ||
init() { | init() { | ||
| Line 2,622: | Line 2,592: | ||
root.append(this.root); | root.append(this.root); | ||
this.renderShell(); | this.renderShell(); | ||
| Line 2,728: | Line 2,696: | ||
this.renderWelcome(); | this.renderWelcome(); | ||
}, | }, | ||
| Line 2,792: | Line 2,758: | ||
}, | }, | ||
// Load / create | |||
async loadExisting(title) { | |||
title = | |||
String(title || '').trim(); | |||
async loadExisting(title) { | |||
title = | |||
String(title || '').trim(); | |||
if (!title) { | if (!title) { | ||
| Line 3,001: | Line 2,937: | ||
deletedVariables: [], | deletedVariables: [], | ||
mode: 'new', | mode: 'new', | ||
dirty: true, | |||
dirtyPreload: true, | |||
dirtyConfig: true | |||
}; | }; | ||
| Line 3,062: | Line 2,996: | ||
deletedVariables: [], | deletedVariables: [], | ||
mode: 'new', | mode: 'new', | ||
dirty: true, | |||
dirtyPreload: true, | |||
dirtyConfig: true | |||
}; | }; | ||
| Line 3,189: | Line 3,121: | ||
mode: 'edit', | mode: 'edit', | ||
dirty: false, | |||
dirtyPreload: false, | |||
dirtyConfig: false | |||
}; | }; | ||
| Line 3,200: | Line 3,130: | ||
}, | }, | ||
// Editor | // Editor | ||
renderEditor() { | renderEditor() { | ||
| Line 3,282: | Line 3,210: | ||
editorSection.append(editorMount); | editorSection.append(editorMount); | ||
left.append(editorSection); | left.append(editorSection); | ||
const analysisSection = | const analysisSection = | ||
| Line 3,297: | Line 3,223: | ||
analysisContainer | analysisContainer | ||
); | ); | ||
const variablesSection = | const variablesSection = | ||
| Line 3,340: | Line 3,264: | ||
variableContainer | variableContainer | ||
); | ); | ||
const configurationSection = | const configurationSection = | ||
| Line 3,359: | Line 3,281: | ||
/* | /* | ||
* | * CONFIG REVIEW | ||
* | * | ||
* The | * The generated JSON is no longer displayed | ||
* | * directly in the page. It can be opened in | ||
* the custom review dialog instead. | |||
*/ | */ | ||
| Line 3,373: | Line 3,293: | ||
); | ); | ||
const | const configHelp = | ||
$('<div>') | $('<div>') | ||
.addClass( | .addClass( | ||
'preload-editor-config | 'preload-editor-help' | ||
) | |||
.text( | |||
'Review the exact config.json that will be uploaded to the wiki.' | |||
); | ); | ||
const reviewConfigButton = | |||
this.createButton( | this.createButton( | ||
'Review | 'Review config.json', | ||
' | '', | ||
() => | () => | ||
this.createConfigReviewDialog() | this.createConfigReviewDialog() | ||
); | |||
configSection.append( | configSection.append( | ||
configHelp, | |||
reviewConfigButton | |||
); | ); | ||
| Line 3,409: | Line 3,323: | ||
); | ); | ||
const savePreloadButton = | |||
this.createButton( | this.createButton( | ||
'Save Preload', | 'Save Preload', | ||
' | '', | ||
() => | () => | ||
this.savePreloadOnly() | this.savePreloadOnly() | ||
) | ); | ||
const saveConfigButton = | |||
this.createButton( | this.createButton( | ||
'Save Config', | 'Save Config', | ||
' | '', | ||
() => | () => | ||
this.saveConfigOnly() | this.saveConfigOnly() | ||
) | ); | ||
const saveBothButton = | |||
this.createButton( | this.createButton( | ||
'Save', | 'Save', | ||
'preload-editor-button-primary | 'preload-editor-button-primary', | ||
() => | () => | ||
this.saveAll() | this.saveAll() | ||
) | ); | ||
actions.append( | |||
savePreloadButton, | |||
saveConfigButton, | |||
saveBothButton | |||
); | ); | ||
| Line 3,479: | Line 3,400: | ||
} | } | ||
); | ); | ||
}, | }, | ||
| Line 3,490: | Line 3,409: | ||
source; | source; | ||
this. | this.markDirty(); | ||
this.reanalyze(); | this.reanalyze(); | ||
| Line 3,525: | Line 3,444: | ||
this.state.conditions = | this.state.conditions = | ||
analysis.conditions; | analysis.conditions; | ||
this.state.config = | this.state.config = | ||
| Line 3,539: | Line 3,451: | ||
analysis | analysis | ||
); | ); | ||
this.analysis = | this.analysis = | ||
| Line 3,578: | Line 3,473: | ||
} | } | ||
}, | }, | ||
renderAnalysis(container) { | renderAnalysis(container) { | ||
| Line 3,750: | Line 3,641: | ||
}, | }, | ||
// Variables | // Variables | ||
renderVariables(container) { | renderVariables(container) { | ||
| Line 3,942: | Line 3,831: | ||
}, | }, | ||
selectVariable(name) { | |||
name = | |||
String(name || '') | |||
.trim() | |||
.toUpperCase(); | |||
if (!name) { | |||
return; | |||
} | |||
const available = | |||
const | ['PAGE'].concat( | ||
this. | ( | ||
this.analysis && | |||
this.analysis.variables | |||
? this.analysis.variables | |||
: [] | |||
).filter( | |||
variable => | |||
variable !== 'PAGE' | |||
) | |||
); | ); | ||
if ( | const configuredUnused = | ||
container && | this.state.config && | ||
container.length | this.state.config.fields | ||
) { | ? Object.keys( | ||
this.renderVariableConfiguration( | this.state.config.fields | ||
container | ) | ||
.map( | |||
variable => | |||
variable.toUpperCase() | |||
) | |||
: []; | |||
configuredUnused.forEach( | |||
variable => { | |||
if ( | |||
!available.includes(variable) && | |||
variable !== 'PAGE' | |||
) { | |||
available.push(variable); | |||
} | |||
} | |||
); | |||
if (!available.includes(name)) { | |||
return; | |||
} | |||
this.state.selectedVariable = | |||
name; | |||
this.renderVariablesBySelector(); | |||
this.renderVariableConfigurationBySelector(); | |||
}, | |||
renderVariableConfigurationBySelector() { | |||
const container = | |||
this.root && | |||
this.root.find( | |||
'.preload-editor-variable-configuration' | |||
); | |||
if ( | |||
container && | |||
container.length | |||
) { | |||
this.renderVariableConfiguration( | |||
container | |||
); | ); | ||
} | } | ||
| Line 4,295: | Line 4,164: | ||
label.val(); | label.val(); | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,320: | Line 4,189: | ||
description.val(); | description.val(); | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,361: | Line 4,230: | ||
typeSelect.val(); | typeSelect.val(); | ||
this. | this.markDirty(); | ||
this.renderVariableConfigurationBySelector(); | this.renderVariableConfigurationBySelector(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,386: | Line 4,255: | ||
required.prop('checked'); | required.prop('checked'); | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,416: | Line 4,285: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,448: | Line 4,317: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,491: | Line 4,360: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,514: | Line 4,383: | ||
} | } | ||
const deleteButton = | const deleteButton = | ||
this.createButton( | this.createButton( | ||
| Line 4,594: | Line 4,457: | ||
} | } | ||
this.state.selectedVariable = | this.state.selectedVariable = | ||
name; | name; | ||
this. | this.markDirty(); | ||
this.renderVariablesBySelector(); | this.renderVariablesBySelector(); | ||
this.renderVariableConfigurationBySelector(); | this.renderVariableConfigurationBySelector(); | ||
this.renderAnalysisBySelector(); | this.renderAnalysisBySelector(); | ||
this. | this.renderConfigReviewAvailability(); | ||
this.setStatus( | this.setStatus( | ||
| Line 4,638: | Line 4,497: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,669: | Line 4,528: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,718: | Line 4,577: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 4,825: | Line 4,684: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
} | } | ||
); | ); | ||
| Line 5,005: | Line 4,864: | ||
} | } | ||
this. | this.markDirty(); | ||
this. | this.renderConfigReviewAvailability(); | ||
}; | }; | ||
| Line 5,050: | Line 4,909: | ||
}, | }, | ||
// Config output | |||
// Config output | |||
getCleanConfig() { | getCleanConfig() { | ||
| Line 5,097: | Line 4,954: | ||
/* | /* | ||
* Kept as a | * Kept as a compatibility helper in case CSS or | ||
* of the gadget | * another part of the gadget expects the method. | ||
* There is no longer a permanently rendered | |||
* config preview. | |||
*/ | */ | ||
renderConfigPreview(container) { | renderConfigPreview(container) { | ||
| Line 5,109: | Line 4,968: | ||
renderConfigPreviewBySelector() { | renderConfigPreviewBySelector() { | ||
this. | /* | ||
* The old generated configuration <pre> no | |||
* longer exists in the editor UI. | |||
* | |||
* Keep this method so existing calls do not | |||
* break. | |||
*/ | |||
this.renderAnalysisBySelector(); | this.renderAnalysisBySelector(); | ||
}, | }, | ||
renderConfigReviewAvailability() { | |||
/* | /* | ||
* The | * The config is generated on demand when the | ||
* Review config.json button is pressed. | |||
* | |||
*/ | */ | ||
this.renderAnalysisBySelector(); | |||
}, | |||
// Dirty state | |||
updateDirtyState() { | |||
this.state.dirty = | |||
!!( | |||
this.state.dirtyPreload || | |||
this.state.dirtyConfig | |||
); | |||
}, | |||
markPreloadDirty() { | |||
this.state.dirtyPreload = true; | |||
this.updateDirtyState(); | |||
this.saveDraft(); | |||
}, | |||
markConfigDirty() { | |||
this.state.dirtyConfig = true; | |||
this.updateDirtyState(); | |||
this.saveDraft(); | |||
}, | |||
markDirty() { | |||
/* | |||
* Existing configuration controls call | |||
* markDirty(), so keep it conservative: | |||
* both parts are considered locally dirty. | |||
*/ | |||
this.state.dirtyPreload = true; | |||
this.state.dirtyConfig = true; | |||
this.updateDirtyState(); | |||
this.saveDraft(); | |||
}, | }, | ||
// Save | // Save | ||
async | async savePreloadOnly() { | ||
let title = | let title = | ||
String( | String( | ||
| Line 5,140: | Line 5,036: | ||
if (!result) { | if (!result) { | ||
return | return; | ||
} | } | ||
title = result; | title = result; | ||
this.state.preloadTitle = | this.state.preloadTitle = | ||
title; | title; | ||
} | } | ||
this.state.preloadContent = | |||
this.getEditorContent(); | |||
const validation = | |||
const | this.validateBeforeSave(); | ||
if (validation.errors.length) { | |||
this.showValidationErrors( | |||
validation | |||
); | |||
this.saveDraft(); | |||
return; | |||
} | } | ||
const confirmed = | |||
await this.confirmSave( | |||
'preload', | |||
title | |||
); | ); | ||
if (!confirmed) { | |||
return; | |||
} | } | ||
this.setStatus( | |||
'Saving preload...', | |||
'loading' | |||
); | |||
const | try { | ||
const exists = | |||
this. | await this.pageExists(title); | ||
await this.savePage( | |||
this. | title, | ||
this.state. | this.state.preloadContent, | ||
exists | |||
? 'Updated preload with Preload Editor' | |||
: 'Created preload with Preload Editor', | |||
!exists | |||
); | ); | ||
this.state.mode = 'edit'; | |||
this. | this.state.preloadTitle = title; | ||
this.state.dirtyPreload = false; | |||
this.updateDirtyState(); | |||
if (!this.state.dirty) { | |||
. | this.clearDraft(title); | ||
} else { | |||
this.saveDraft(); | |||
} | |||
this.setStatus( | |||
this.state.dirtyConfig | |||
? 'Preload saved. Config still has unsaved changes.' | |||
: 'Preload saved successfully.', | |||
'success' | |||
); | |||
mw.notify( | |||
this.state.dirtyConfig | |||
? 'Preload saved. Config still has unsaved changes.' | |||
: 'Preload saved.', | |||
{ | |||
type: 'success' | |||
} | |||
); | |||
} catch (error) { | |||
console.error( | |||
'Preload Editor save:', | |||
error | |||
); | ); | ||
this.saveDraft(); | this.saveDraft(); | ||
this.setStatus( | |||
error.message || | |||
'Could not save preload.', | |||
'error' | |||
); | |||
mw.notify( | |||
error.message || | |||
'Could not save preload.', | |||
{ | |||
type: 'error' | |||
} | |||
: ' | |||
); | ); | ||
} | |||
}, | |||
this.state. | async saveConfigOnly() { | ||
let title = | |||
String( | |||
this.state.preloadTitle || '' | |||
).trim(); | |||
this. | if (!title) { | ||
const result = | |||
await this.createPromptDialog( | |||
'Preload title', | |||
'Enter the full title for the preload.' | |||
); | |||
if (!result) { | |||
return; | |||
if (! | |||
} | } | ||
title = result; | |||
this.state.preloadTitle = | |||
title; | |||
this. | |||
} | } | ||
this.state.preloadContent = | |||
this.getEditorContent(); | |||
this.reanalyze(); | |||
const validation = | const validation = | ||
this. | this.validateBeforeSave(); | ||
if (validation.errors.length) { | if (validation.errors.length) { | ||
| Line 5,327: | Line 5,174: | ||
this.saveDraft(); | this.saveDraft(); | ||
return; | |||
} | |||
const confirmed = | |||
await this.confirmSave( | |||
'config', | |||
title | |||
); | |||
if (!confirmed) { | |||
return; | return; | ||
} | } | ||
| Line 5,357: | Line 5,214: | ||
); | ); | ||
this.state. | this.state.mode = 'edit'; | ||
this.state.preloadTitle = title; | |||
this.state.dirtyConfig = false; | |||
this.updateDirtyState(); | this.updateDirtyState(); | ||
| Line 5,369: | Line 5,227: | ||
this.setStatus( | this.setStatus( | ||
'Config saved successfully.', | this.state.dirtyPreload | ||
? 'Config saved. Preload still has unsaved changes.' | |||
: 'Config saved successfully.', | |||
'success' | 'success' | ||
); | ); | ||
mw.notify( | mw.notify( | ||
'Preload | this.state.dirtyPreload | ||
{ | ? 'Config saved. Preload still has unsaved changes.' | ||
type: 'success' | : 'Config saved.', | ||
} | { | ||
); | type: 'success' | ||
} catch (error) { | } | ||
console.error( | ); | ||
'Preload Editor config save:', | } catch (error) { | ||
error | console.error( | ||
'Preload Editor config save:', | |||
error | |||
); | |||
this.saveDraft(); | |||
this.setStatus( | |||
error.message || | |||
'Could not save config.', | |||
'error' | |||
); | |||
mw.notify( | |||
error.message || | |||
'Could not save config.', | |||
{ | |||
type: 'error' | |||
} | |||
); | |||
} | |||
}, | |||
async saveAll() { | |||
let title = | |||
String( | |||
this.state.preloadTitle || '' | |||
).trim(); | |||
if (!title) { | |||
const result = | |||
await this.createPromptDialog( | |||
'Preload title', | |||
'Enter the full title for the preload.' | |||
); | |||
if (!result) { | |||
return; | |||
} | |||
title = result; | |||
this.state.preloadTitle = | |||
title; | |||
} | |||
this.state.preloadContent = | |||
this.getEditorContent(); | |||
this.reanalyze(); | |||
const validation = | |||
this.validateBeforeSave(); | |||
if (validation.errors.length) { | |||
this.showValidationErrors( | |||
validation | |||
); | ); | ||
this.saveDraft(); | this.saveDraft(); | ||
return; | return; | ||
} | } | ||
const confirmed = | |||
await this.confirmSave( | |||
'both', | |||
title | |||
const | |||
this. | |||
); | ); | ||
if (!confirmed) { | |||
return; | return; | ||
} | } | ||
| Line 5,468: | Line 5,354: | ||
this.state.mode = 'edit'; | this.state.mode = 'edit'; | ||
this.state.dirtyPreload = false; | |||
this.state.dirtyConfig = false; | |||
this.state.dirty = false; | |||
this.state.preloadTitle = title; | this.state.preloadTitle = title; | ||
this.clearDraft(title); | this.clearDraft(title); | ||