Refactor createNote (#1789)
* Update createNote to return a wrapper object * Update how createNote creates errors
This commit is contained in:
parent
d7c934cae8
commit
f7d177e6d0
@ -42,8 +42,7 @@ class AnkiNoteBuilder {
|
|||||||
duplicateScope='collection',
|
duplicateScope='collection',
|
||||||
resultOutputMode='split',
|
resultOutputMode='split',
|
||||||
glossaryLayoutMode='default',
|
glossaryLayoutMode='default',
|
||||||
compactTags=false,
|
compactTags=false
|
||||||
errors=null
|
|
||||||
}) {
|
}) {
|
||||||
let duplicateScopeDeckName = null;
|
let duplicateScopeDeckName = null;
|
||||||
let duplicateScopeCheckChildren = false;
|
let duplicateScopeCheckChildren = false;
|
||||||
@ -53,6 +52,7 @@ class AnkiNoteBuilder {
|
|||||||
duplicateScopeCheckChildren = true;
|
duplicateScopeCheckChildren = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errors = [];
|
||||||
const commonData = this._createData(dictionaryEntry, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
const commonData = this._createData(dictionaryEntry, mode, context, resultOutputMode, glossaryLayoutMode, compactTags, injectedMedia);
|
||||||
const formattedFieldValuePromises = [];
|
const formattedFieldValuePromises = [];
|
||||||
for (const [, fieldValue] of fields) {
|
for (const [, fieldValue] of fields) {
|
||||||
@ -68,7 +68,7 @@ class AnkiNoteBuilder {
|
|||||||
noteFields[fieldName] = formattedFieldValue;
|
noteFields[fieldName] = formattedFieldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const note = {
|
||||||
fields: noteFields,
|
fields: noteFields,
|
||||||
tags,
|
tags,
|
||||||
deckName,
|
deckName,
|
||||||
@ -82,6 +82,7 @@ class AnkiNoteBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return {note, errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRenderingData({
|
async getRenderingData({
|
||||||
@ -112,17 +113,15 @@ class AnkiNoteBuilder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _formatField(field, commonData, template, errors=null) {
|
async _formatField(field, commonData, template, errors) {
|
||||||
return await this._stringReplaceAsync(field, this._markerPattern, async (g0, marker) => {
|
return await this._stringReplaceAsync(field, this._markerPattern, async (g0, marker) => {
|
||||||
try {
|
try {
|
||||||
const {result} = await this._renderTemplateBatched(template, commonData, marker);
|
const {result} = await this._renderTemplateBatched(template, commonData, marker);
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (Array.isArray(errors)) {
|
|
||||||
const error = new Error(`Template render error for {${marker}}`);
|
const error = new Error(`Template render error for {${marker}}`);
|
||||||
error.data = {error: e};
|
error.data = {error: e};
|
||||||
errors.push(error);
|
errors.push(error);
|
||||||
}
|
|
||||||
return `{${marker}-render-error}`;
|
return `{${marker}-render-error}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1259,12 +1259,13 @@ class Display extends EventDispatcher {
|
|||||||
|
|
||||||
this._hideAnkiNoteErrors(true);
|
this._hideAnkiNoteErrors(true);
|
||||||
|
|
||||||
const errors = [];
|
const allErrors = [];
|
||||||
const overrideToken = this._progressIndicatorVisible.setOverride(true);
|
const overrideToken = this._progressIndicatorVisible.setOverride(true);
|
||||||
try {
|
try {
|
||||||
const {anki: {suspendNewCards}} = this._options;
|
const {anki: {suspendNewCards}} = this._options;
|
||||||
const noteContext = this._getNoteContext();
|
const noteContext = this._getNoteContext();
|
||||||
const note = await this._createNote(dictionaryEntry, mode, noteContext, true, errors);
|
const {note, errors} = await this._createNote(dictionaryEntry, mode, noteContext, true);
|
||||||
|
allErrors.push(...errors);
|
||||||
|
|
||||||
let noteId = null;
|
let noteId = null;
|
||||||
let addNoteOkay = false;
|
let addNoteOkay = false;
|
||||||
@ -1272,19 +1273,19 @@ class Display extends EventDispatcher {
|
|||||||
noteId = await yomichan.api.addAnkiNote(note);
|
noteId = await yomichan.api.addAnkiNote(note);
|
||||||
addNoteOkay = true;
|
addNoteOkay = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.length = 0;
|
allErrors.length = 0;
|
||||||
errors.push(e);
|
allErrors.push(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addNoteOkay) {
|
if (addNoteOkay) {
|
||||||
if (noteId === null) {
|
if (noteId === null) {
|
||||||
errors.push(new Error('Note could not be added'));
|
allErrors.push(new Error('Note could not be added'));
|
||||||
} else {
|
} else {
|
||||||
if (suspendNewCards) {
|
if (suspendNewCards) {
|
||||||
try {
|
try {
|
||||||
await yomichan.api.suspendAnkiCardsForNote(noteId);
|
await yomichan.api.suspendAnkiCardsForNote(noteId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push(e);
|
allErrors.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
@ -1292,13 +1293,13 @@ class Display extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push(e);
|
allErrors.push(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._progressIndicatorVisible.clearOverride(overrideToken);
|
this._progressIndicatorVisible.clearOverride(overrideToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (allErrors.length > 0) {
|
||||||
this._showAnkiNoteErrors(errors);
|
this._showAnkiNoteErrors(allErrors);
|
||||||
} else {
|
} else {
|
||||||
this._hideAnkiNoteErrors(true);
|
this._hideAnkiNoteErrors(true);
|
||||||
}
|
}
|
||||||
@ -1480,11 +1481,11 @@ class Display extends EventDispatcher {
|
|||||||
const notePromises = [];
|
const notePromises = [];
|
||||||
for (const dictionaryEntry of dictionaryEntries) {
|
for (const dictionaryEntry of dictionaryEntries) {
|
||||||
for (const mode of modes) {
|
for (const mode of modes) {
|
||||||
const notePromise = this._createNote(dictionaryEntry, mode, context, false, null);
|
const notePromise = this._createNote(dictionaryEntry, mode, context, false);
|
||||||
notePromises.push(notePromise);
|
notePromises.push(notePromise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const notes = await Promise.all(notePromises);
|
const notes = (await Promise.all(notePromises)).map(({note}) => note);
|
||||||
|
|
||||||
let infos;
|
let infos;
|
||||||
if (forceCanAddValue !== null) {
|
if (forceCanAddValue !== null) {
|
||||||
@ -1512,7 +1513,7 @@ class Display extends EventDispatcher {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createNote(dictionaryEntry, mode, context, injectMedia, errors) {
|
async _createNote(dictionaryEntry, mode, context, injectMedia) {
|
||||||
const options = this._options;
|
const options = this._options;
|
||||||
const template = this._ankiFieldTemplates;
|
const template = this._ankiFieldTemplates;
|
||||||
const {
|
const {
|
||||||
@ -1524,18 +1525,17 @@ class Display extends EventDispatcher {
|
|||||||
const {deck: deckName, model: modelName} = modeOptions;
|
const {deck: deckName, model: modelName} = modeOptions;
|
||||||
const fields = Object.entries(modeOptions.fields);
|
const fields = Object.entries(modeOptions.fields);
|
||||||
|
|
||||||
|
const errors = [];
|
||||||
let injectedMedia = null;
|
let injectedMedia = null;
|
||||||
if (injectMedia) {
|
if (injectMedia) {
|
||||||
let errors2;
|
let errors2;
|
||||||
({result: injectedMedia, errors: errors2} = await this._injectAnkiNoteMedia(dictionaryEntry, options, fields));
|
({result: injectedMedia, errors: errors2} = await this._injectAnkiNoteMedia(dictionaryEntry, options, fields));
|
||||||
if (Array.isArray(errors)) {
|
|
||||||
for (const error of errors2) {
|
for (const error of errors2) {
|
||||||
errors.push(deserializeError(error));
|
errors.push(deserializeError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return await this._ankiNoteBuilder.createNote({
|
const {note, errors: createNoteErrors} = await this._ankiNoteBuilder.createNote({
|
||||||
dictionaryEntry,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
@ -1552,6 +1552,8 @@ class Display extends EventDispatcher {
|
|||||||
injectedMedia,
|
injectedMedia,
|
||||||
errors
|
errors
|
||||||
});
|
});
|
||||||
|
errors.push(...createNoteErrors);
|
||||||
|
return {note, errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
async _injectAnkiNoteMedia(dictionaryEntry, options, fields) {
|
async _injectAnkiNoteMedia(dictionaryEntry, options, fields) {
|
||||||
@ -1959,20 +1961,16 @@ class Display extends EventDispatcher {
|
|||||||
const ankiNotes = [];
|
const ankiNotes = [];
|
||||||
const modes = this._getModes(dictionaryEntry.type === 'term');
|
const modes = this._getModes(dictionaryEntry.type === 'term');
|
||||||
for (const mode of modes) {
|
for (const mode of modes) {
|
||||||
let ankiNote;
|
let note;
|
||||||
let ankiNoteException;
|
let errors;
|
||||||
const errors = [];
|
|
||||||
try {
|
try {
|
||||||
const noteContext = this._getNoteContext();
|
const noteContext = this._getNoteContext();
|
||||||
ankiNote = await this._createNote(dictionaryEntry, mode, noteContext, false, errors);
|
({note: note, errors} = await this._createNote(dictionaryEntry, mode, noteContext, false));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ankiNoteException = e;
|
errors = [e];
|
||||||
}
|
}
|
||||||
const entry = {mode, ankiNote};
|
const entry = {mode, note};
|
||||||
if (typeof ankiNoteException !== 'undefined') {
|
if (Array.isArray(errors) && errors.length > 0) {
|
||||||
entry.ankiNoteException = ankiNoteException;
|
|
||||||
}
|
|
||||||
if (errors.length > 0) {
|
|
||||||
entry.errors = errors;
|
entry.errors = errors;
|
||||||
}
|
}
|
||||||
ankiNotes.push(entry);
|
ankiNotes.push(entry);
|
||||||
|
@ -147,8 +147,8 @@ class AnkiTemplatesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _validate(infoNode, field, mode, showSuccessResult, invalidateInput) {
|
async _validate(infoNode, field, mode, showSuccessResult, invalidateInput) {
|
||||||
|
const allErrors = [];
|
||||||
const text = this._renderTextInput.value || '';
|
const text = this._renderTextInput.value || '';
|
||||||
const errors = [];
|
|
||||||
let result = `No definition found for ${text}`;
|
let result = `No definition found for ${text}`;
|
||||||
try {
|
try {
|
||||||
const optionsContext = this._settingsController.getOptionsContext();
|
const optionsContext = this._settingsController.getOptionsContext();
|
||||||
@ -168,7 +168,7 @@ class AnkiTemplatesController {
|
|||||||
let template = options.anki.fieldTemplates;
|
let template = options.anki.fieldTemplates;
|
||||||
if (typeof template !== 'string') { template = this._defaultFieldTemplates; }
|
if (typeof template !== 'string') { template = this._defaultFieldTemplates; }
|
||||||
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = options;
|
const {general: {resultOutputMode, glossaryLayoutMode, compactTags}} = options;
|
||||||
const note = await this._ankiNoteBuilder.createNote({
|
const {note, errors} = await this._ankiNoteBuilder.createNote({
|
||||||
dictionaryEntry,
|
dictionaryEntry,
|
||||||
mode,
|
mode,
|
||||||
context,
|
context,
|
||||||
@ -180,13 +180,13 @@ class AnkiTemplatesController {
|
|||||||
],
|
],
|
||||||
resultOutputMode,
|
resultOutputMode,
|
||||||
glossaryLayoutMode,
|
glossaryLayoutMode,
|
||||||
compactTags,
|
compactTags
|
||||||
errors
|
|
||||||
});
|
});
|
||||||
result = note.fields.field;
|
result = note.fields.field;
|
||||||
|
allErrors.push(...errors);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push(e);
|
allErrors.push(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorToMessageString = (e) => {
|
const errorToMessageString = (e) => {
|
||||||
@ -205,9 +205,9 @@ class AnkiTemplatesController {
|
|||||||
return `${e}`;
|
return `${e}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasError = errors.length > 0;
|
const hasError = allErrors.length > 0;
|
||||||
infoNode.hidden = !(showSuccessResult || hasError);
|
infoNode.hidden = !(showSuccessResult || hasError);
|
||||||
infoNode.textContent = hasError ? errors.map(errorToMessageString).join('\n') : (showSuccessResult ? result : '');
|
infoNode.textContent = hasError ? allErrors.map(errorToMessageString).join('\n') : (showSuccessResult ? result : '');
|
||||||
infoNode.classList.toggle('text-danger', hasError);
|
infoNode.classList.toggle('text-danger', hasError);
|
||||||
if (invalidateInput) {
|
if (invalidateInput) {
|
||||||
this._fieldTemplatesTextarea.dataset.invalid = `${hasError}`;
|
this._fieldTemplatesTextarea.dataset.invalid = `${hasError}`;
|
||||||
|
@ -219,8 +219,7 @@ async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNot
|
|||||||
query: 'query',
|
query: 'query',
|
||||||
fullQuery: 'fullQuery'
|
fullQuery: 'fullQuery'
|
||||||
};
|
};
|
||||||
const errors = [];
|
const {note: {fields: noteFields}, errors} = await ankiNoteBuilder.createNote({
|
||||||
const noteFields = (await ankiNoteBuilder.createNote({
|
|
||||||
dictionaryEntry,
|
dictionaryEntry,
|
||||||
mode: null,
|
mode: null,
|
||||||
context,
|
context,
|
||||||
@ -234,11 +233,10 @@ async function getRenderResults(dictionaryEntries, type, mode, template, AnkiNot
|
|||||||
duplicateScope: 'collection',
|
duplicateScope: 'collection',
|
||||||
resultOutputMode: mode,
|
resultOutputMode: mode,
|
||||||
glossaryLayoutMode: 'default',
|
glossaryLayoutMode: 'default',
|
||||||
compactTags: false,
|
compactTags: false
|
||||||
errors
|
});
|
||||||
})).fields;
|
|
||||||
if (!write) {
|
if (!write) {
|
||||||
assert.deepStrictEqual(errors, []);
|
assert.strictEqual(errors.length, 0);
|
||||||
}
|
}
|
||||||
results.push(noteFields);
|
results.push(noteFields);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user