Improve AnkiController to indicate when the model/deck is invalid (#1611)
This commit is contained in:
parent
20d60a2ba7
commit
bbf47865ff
@ -340,15 +340,13 @@ class AnkiCardController {
|
|||||||
this._cardMenu = node.dataset.ankiCardMenu;
|
this._cardMenu = node.dataset.ankiCardMenu;
|
||||||
this._eventListeners = new EventListenerCollection();
|
this._eventListeners = new EventListenerCollection();
|
||||||
this._fieldEventListeners = new EventListenerCollection();
|
this._fieldEventListeners = new EventListenerCollection();
|
||||||
this._deck = null;
|
|
||||||
this._model = null;
|
|
||||||
this._fields = null;
|
this._fields = null;
|
||||||
this._modelChangingTo = null;
|
this._modelChangingTo = null;
|
||||||
this._ankiCardDeckSelect = null;
|
|
||||||
this._ankiCardModelSelect = null;
|
|
||||||
this._ankiCardFieldsContainer = null;
|
this._ankiCardFieldsContainer = null;
|
||||||
this._cleaned = false;
|
this._cleaned = false;
|
||||||
this._fieldEntries = [];
|
this._fieldEntries = [];
|
||||||
|
this._deckController = new AnkiCardSelectController();
|
||||||
|
this._modelController = new AnkiCardSelectController();
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
@ -359,19 +357,16 @@ class AnkiCardController {
|
|||||||
const cardOptions = this._getCardOptions(ankiOptions, this._cardType);
|
const cardOptions = this._getCardOptions(ankiOptions, this._cardType);
|
||||||
if (cardOptions === null) { return; }
|
if (cardOptions === null) { return; }
|
||||||
const {deck, model, fields} = cardOptions;
|
const {deck, model, fields} = cardOptions;
|
||||||
this._deck = deck;
|
this._deckController.prepare(this._node.querySelector('.anki-card-deck'), deck);
|
||||||
this._model = model;
|
this._modelController.prepare(this._node.querySelector('.anki-card-model'), model);
|
||||||
this._fields = fields;
|
this._fields = fields;
|
||||||
|
|
||||||
this._ankiCardDeckSelect = this._node.querySelector('.anki-card-deck');
|
|
||||||
this._ankiCardModelSelect = this._node.querySelector('.anki-card-model');
|
|
||||||
this._ankiCardFieldsContainer = this._node.querySelector('.anki-card-fields');
|
this._ankiCardFieldsContainer = this._node.querySelector('.anki-card-fields');
|
||||||
|
|
||||||
this._setupSelects([], []);
|
|
||||||
this._setupFields();
|
this._setupFields();
|
||||||
|
|
||||||
this._eventListeners.addEventListener(this._ankiCardDeckSelect, 'change', this._onCardDeckChange.bind(this), false);
|
this._eventListeners.addEventListener(this._deckController.select, 'change', this._onCardDeckChange.bind(this), false);
|
||||||
this._eventListeners.addEventListener(this._ankiCardModelSelect, 'change', this._onCardModelChange.bind(this), false);
|
this._eventListeners.addEventListener(this._modelController.select, 'change', this._onCardModelChange.bind(this), false);
|
||||||
this._eventListeners.on(this._settingsController, 'permissionsChanged', this._onPermissionsChanged.bind(this));
|
this._eventListeners.on(this._settingsController, 'permissionsChanged', this._onPermissionsChanged.bind(this));
|
||||||
|
|
||||||
await this.updateAnkiState();
|
await this.updateAnkiState();
|
||||||
@ -387,7 +382,8 @@ class AnkiCardController {
|
|||||||
if (this._fields === null) { return; }
|
if (this._fields === null) { return; }
|
||||||
const {deckNames, modelNames} = await this._ankiController.getAnkiData();
|
const {deckNames, modelNames} = await this._ankiController.getAnkiData();
|
||||||
if (this._cleaned) { return; }
|
if (this._cleaned) { return; }
|
||||||
this._setupSelects(deckNames, modelNames);
|
this._deckController.setOptionValues(deckNames);
|
||||||
|
this._modelController.setOptionValues(modelNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
isStale() {
|
isStale() {
|
||||||
@ -456,31 +452,6 @@ class AnkiCardController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setupSelects(deckNames, modelNames) {
|
|
||||||
const deck = this._deck;
|
|
||||||
const model = this._model;
|
|
||||||
if (!deckNames.includes(deck)) { deckNames = [...deckNames, deck]; }
|
|
||||||
if (!modelNames.includes(model)) { modelNames = [...modelNames, model]; }
|
|
||||||
|
|
||||||
this._setSelectOptions(this._ankiCardDeckSelect, deckNames);
|
|
||||||
this._ankiCardDeckSelect.value = deck;
|
|
||||||
|
|
||||||
this._setSelectOptions(this._ankiCardModelSelect, modelNames);
|
|
||||||
this._ankiCardModelSelect.value = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
_setSelectOptions(select, optionValues) {
|
|
||||||
const fragment = document.createDocumentFragment();
|
|
||||||
for (const optionValue of optionValues) {
|
|
||||||
const option = document.createElement('option');
|
|
||||||
option.value = optionValue;
|
|
||||||
option.textContent = optionValue;
|
|
||||||
fragment.appendChild(option);
|
|
||||||
}
|
|
||||||
select.textContent = '';
|
|
||||||
select.appendChild(fragment);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setupFields() {
|
_setupFields() {
|
||||||
this._fieldEventListeners.removeAllEventListeners();
|
this._fieldEventListeners.removeAllEventListeners();
|
||||||
|
|
||||||
@ -551,7 +522,7 @@ class AnkiCardController {
|
|||||||
|
|
||||||
let fieldNames;
|
let fieldNames;
|
||||||
try {
|
try {
|
||||||
fieldNames = await this._ankiController.getModelFieldNames(this._model);
|
fieldNames = await this._ankiController.getModelFieldNames(this._modelController.value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -568,8 +539,8 @@ class AnkiCardController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _setDeck(value) {
|
async _setDeck(value) {
|
||||||
if (this._deck === value) { return; }
|
if (this._deckController.value === value) { return; }
|
||||||
this._deck = value;
|
this._deckController.value = value;
|
||||||
|
|
||||||
await this._settingsController.modifyProfileSettings([{
|
await this._settingsController.modifyProfileSettings([{
|
||||||
action: 'set',
|
action: 'set',
|
||||||
@ -579,12 +550,13 @@ class AnkiCardController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _setModel(value) {
|
async _setModel(value) {
|
||||||
|
const select = this._modelController.select;
|
||||||
if (this._modelChangingTo !== null) {
|
if (this._modelChangingTo !== null) {
|
||||||
// Revert
|
// Revert
|
||||||
this._ankiCardModelSelect.value = this._modelChangingTo;
|
select.value = this._modelChangingTo;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this._model === value) { return; }
|
if (this._modelController.value === value) { return; }
|
||||||
|
|
||||||
let fieldNames;
|
let fieldNames;
|
||||||
let options;
|
let options;
|
||||||
@ -594,7 +566,7 @@ class AnkiCardController {
|
|||||||
options = await this._ankiController.settingsController.getOptions();
|
options = await this._ankiController.settingsController.getOptions();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Revert
|
// Revert
|
||||||
this._ankiCardModelSelect.value = this._model;
|
select.value = this._modelController.value;
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
this._modelChangingTo = null;
|
this._modelChangingTo = null;
|
||||||
@ -623,7 +595,7 @@ class AnkiCardController {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
this._model = value;
|
this._modelController.value = value;
|
||||||
this._fields = fields;
|
this._fields = fields;
|
||||||
|
|
||||||
await this._settingsController.modifyProfileSettings(targets);
|
await this._settingsController.modifyProfileSettings(targets);
|
||||||
@ -724,3 +696,81 @@ class AnkiCardController {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AnkiCardSelectController {
|
||||||
|
constructor() {
|
||||||
|
this._value = null;
|
||||||
|
this._select = null;
|
||||||
|
this._optionValues = null;
|
||||||
|
this._hasExtraOption = false;
|
||||||
|
this._selectNeedsUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(value) {
|
||||||
|
this._value = value;
|
||||||
|
this._updateSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
get select() {
|
||||||
|
return this._select;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare(select, value) {
|
||||||
|
this._select = select;
|
||||||
|
this._value = value;
|
||||||
|
this._updateSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
setOptionValues(optionValues) {
|
||||||
|
this._optionValues = optionValues;
|
||||||
|
this._selectNeedsUpdate = true;
|
||||||
|
this._updateSelect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private
|
||||||
|
|
||||||
|
_updateSelect() {
|
||||||
|
const value = this._value;
|
||||||
|
let optionValues = this._optionValues;
|
||||||
|
const hasOptionValues = Array.isArray(optionValues) && optionValues.length > 0;
|
||||||
|
|
||||||
|
if (!hasOptionValues) {
|
||||||
|
optionValues = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasExtraOption = !optionValues.includes(value);
|
||||||
|
if (hasExtraOption) {
|
||||||
|
optionValues = [...optionValues, value];
|
||||||
|
}
|
||||||
|
|
||||||
|
const select = this._select;
|
||||||
|
if (this._selectNeedsUpdate || hasExtraOption !== this._hasExtraOption) {
|
||||||
|
this._setSelectOptions(select, optionValues);
|
||||||
|
select.value = value;
|
||||||
|
this._hasExtraOption = hasExtraOption;
|
||||||
|
this._selectNeedsUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasOptionValues) {
|
||||||
|
select.dataset.invalid = `${hasExtraOption}`;
|
||||||
|
} else {
|
||||||
|
delete select.dataset.invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_setSelectOptions(select, optionValues) {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
for (const optionValue of optionValues) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = optionValue;
|
||||||
|
option.textContent = optionValue;
|
||||||
|
fragment.appendChild(option);
|
||||||
|
}
|
||||||
|
select.textContent = '';
|
||||||
|
select.appendChild(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user