From eb7bc503c25a706ebfdb84576a8d3aeb2f8dd669 Mon Sep 17 00:00:00 2001 From: Oliver Hamlet Date: Tue, 7 Jun 2016 18:31:21 +0100 Subject: [PATCH] Move the conflicts filter UI into the Filters sidebar tab Instead of having a toggle button in each card's dropdown menu, implement it as a dropdown menu in the Filters sidebar tab, containing a list of plugin filenames, plus a "No plugin" option. Closes #580. --- docs/LOOT Readme.html | 11 +++--- src/gui/html/css/style.css | 4 +++ src/gui/html/elements/loot-plugin-card.html | 36 ------------------- src/gui/html/index.html | 19 ++++++++++ src/gui/html/js/events.js | 35 +++++++----------- src/gui/html/js/filters.js | 19 ++++++++++ src/gui/html/js/initialise.js | 5 ++- src/gui/html/js/plugin.js | 1 - src/gui/html/js/translateStaticText.js | 3 +- .../html/elements/test_loot-plugin-card.html | 4 --- src/tests/gui/html/js/test_game.js | 1 - src/tests/gui/html/js/test_plugin.js | 6 ---- 12 files changed, 62 insertions(+), 82 deletions(-) diff --git a/docs/LOOT Readme.html b/docs/LOOT Readme.html index f84f9567..d18092b2 100644 --- a/docs/LOOT Readme.html +++ b/docs/LOOT Readme.html @@ -321,7 +321,7 @@ figure > div {
  • The Empty Plugin icon.
  • The Loads Archive icon.
  • The Has User Metadata icon. -
  • The plugin menu button, which provides access to a few plugin-specific features, including a conflict filter and access to it in the metadata editor. These are explained in later sections. +
  • The plugin menu button, which provides access to metadata-related features for the plugin. These are explained in later sections.

    Bash Tag suggestions and messages are displayed below the plugin card's header. @@ -342,13 +342,10 @@ figure > div {

  • Hide inactive plugins: Hides all plugins that are inactive.
  • Hide messageless plugins: Hides all plugins that have no visible messages. -

    The filter toggles have their states saved on quitting LOOT, and they are restored when LOOT is next launched. There are also two other filters: +

    The filter toggles have their states saved on quitting LOOT, and they are restored when LOOT is next launched. There are also two other filters in the sidebar tab:

    Editing Plugin Metadata

    diff --git a/src/gui/html/css/style.css b/src/gui/html/css/style.css index 9e60c136..ed9e3a53 100644 --- a/src/gui/html/css/style.css +++ b/src/gui/html/css/style.css @@ -78,6 +78,10 @@ div[drawer] > iron-pages { padding: 0 16px; height: 48px; } +#conflictsFilter { + padding: 0 16px; + height: 48px; +} /* Panel */ #main { diff --git a/src/gui/html/elements/loot-plugin-card.html b/src/gui/html/elements/loot-plugin-card.html index e37a0ec6..401ae858 100644 --- a/src/gui/html/elements/loot-plugin-card.html +++ b/src/gui/html/elements/loot-plugin-card.html @@ -1,16 +1,3 @@ - - @@ -104,13 +91,6 @@ loot-clear-metadata #clearMetadata { cursor: pointer; } - #showOnlyConflicts { - min-height: 48px; - padding: 0 16px; - font-weight: 500; - --paper-toggle-button-label-spacing: 16px; - white-space: nowrap; - } [hidden] { display: none; } @@ -135,7 +115,6 @@ loot-clear-metadata - Show Only Conflicts Edit Metadata @@ -177,14 +156,12 @@ loot-clear-metadata }, attached() { - this.$.showOnlyConflicts.addEventListener('change', this._onShowOnlyConflicts); this.$.editMetadata.addEventListener('click', this.onShowEditor); this.$.copyMetadata.addEventListener('click', this._onCopyMetadata); this.$.clearMetadata.addEventListener('click', this._onClearMetadata); }, detached() { - this.$.showOnlyConflicts.removeEventListener('change', this._onShowOnlyConflicts); this.$.editMetadata.removeEventListener('click', this.onShowEditor); this.$.copyMetadata.removeEventListener('click', this._onCopyMetadata); this.$.clearMetadata.removeEventListener('click', this._onClearMetadata); @@ -201,9 +178,6 @@ loot-clear-metadata this.$.isMaster.hidden = !this.data.isMaster; this.$.isEmpty.hidden = !this.data.isEmpty; this.$.loadsArchive.hidden = !this.data.loadsArchive; - - /* Also set highlight if the conflict filter is active. */ - this.classList.toggle('highlight', this.data.isConflictFilterChecked); } }, @@ -256,9 +230,6 @@ loot-clear-metadata this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true })); } } - - /* Update the conflict filter toggle state. */ - this.$.showOnlyConflicts.checked = this.data.isConflictFilterChecked; } }, @@ -282,13 +253,6 @@ loot-clear-metadata })); }, - _onShowOnlyConflicts(evt) { - evt.target.dispatchEvent(new CustomEvent('loot-filter-conflicts', { - detail: evt.currentTarget.checked, - bubbles: true, - })); - }, - _onCopyMetadata(evt) { evt.target.dispatchEvent(new CustomEvent('loot-copy-metadata', { bubbles: true, diff --git a/src/gui/html/index.html b/src/gui/html/index.html index 0fbc62fe..e11fefb1 100644 --- a/src/gui/html/index.html +++ b/src/gui/html/index.html @@ -27,6 +27,7 @@ + @@ -45,6 +46,7 @@ +
    @@ -187,6 +202,10 @@ Hide messageless plugins Press Enter or click outside the input to set the filter. + +
    No plugin
    + +
    diff --git a/src/gui/html/js/events.js b/src/gui/html/js/events.js index 9460a883..33e4ecde 100644 --- a/src/gui/html/js/events.js +++ b/src/gui/html/js/events.js @@ -34,6 +34,9 @@ function onChangeGame(evt) { const gameInfo = JSON.parse(result, loot.Plugin.fromJson); loot.game = new loot.Game(gameInfo, loot.l10n); + /* Re-initialise conflicts filter plugin list. */ + loot.Filters.fillConflictsFilterList(loot.game.plugins); + /* Now update virtual lists. */ filterPluginData(loot.game.plugins, loot.filters); @@ -69,7 +72,7 @@ function onUpdateMasterlist() { }).catch(loot.handlePromiseError); } function onSortPlugins() { - if (undoConflictsFilter()) { + if (loot.filters.deactivateConflictsFilter()) { /* Conflicts filter was undone, update the displayed cards. */ filterPluginData(loot.game.plugins, loot.filters); } @@ -231,6 +234,9 @@ function onContentRefresh() { const game = JSON.parse(result, loot.Plugin.fromJson); loot.game = new loot.Game(game, loot.l10n); + /* Re-initialise conflicts filter plugin list. */ + loot.Filters.fillConflictsFilterList(loot.game.plugins); + /* Reapply filters. */ filterPluginData(loot.game.plugins, loot.filters); @@ -402,32 +408,15 @@ function onEditorClose(evt) { loot.state.exitEditingState(); }).catch(loot.handlePromiseError); } -function undoConflictsFilter() { - const wasConflictsFilterEnabled = loot.filters.deactivateConflictsFilter(); - - /* Deactivate any existing plugin conflict filter. */ - loot.game.plugins.forEach((plugin) => { - plugin.isConflictFilterChecked = false; - }); - /* Un-highlight any existing filter plugin. */ - const cards = document.getElementById('main').getElementsByTagName('loot-plugin-card'); - for (let i = 0; i < cards.length; ++i) { - cards[i].classList.toggle('highlight', false); - } - - return wasConflictsFilterEnabled; -} function onConflictsFilter(evt) { /* Deactivate any existing plugin conflict filter. */ - undoConflictsFilter(); - /* evt.detail is true if the filter has been activated. */ - if (evt.detail) { - evt.target.data.isConflictFilterChecked = true; - evt.target.classList.toggle('highlight', true); - + loot.filters.deactivateConflictsFilter(); + /* evt.currentTarget.value is the name of the target plugin, or an empty string + if the filter has been deactivated. */ + if (evt.currentTarget.value) { /* Now get conflicts for the plugin. */ loot.Dialog.showProgress(loot.l10n.translate('Identifying conflicting plugins...')); - loot.filters.activateConflictsFilter(evt.target.getName()).then((plugins) => { + loot.filters.activateConflictsFilter(evt.currentTarget.value).then((plugins) => { plugins.forEach((plugin) => { const gamePlugin = loot.game.plugins.find(item => item.name === plugin.name); if (gamePlugin) { diff --git a/src/gui/html/js/filters.js b/src/gui/html/js/filters.js index f9034a1e..db5dd52f 100644 --- a/src/gui/html/js/filters.js +++ b/src/gui/html/js/filters.js @@ -94,4 +94,23 @@ return plugins; }).catch(handlePromiseError); } + + static fillConflictsFilterList(plugins) { + const list = document.getElementById('conflictsFilter'); + + /* Remove any existing plugin items. */ + while (list.children.length > 1) { + list.removeChild(list.lastElementChild); + } + + plugins.forEach(plugin => { + const item = document.createElement('div'); + + item.className = 'paper-item'; + item.setAttribute('value', plugin.name); + item.textContent = plugin.name; + + list.appendChild(item); + }); + } })); diff --git a/src/gui/html/js/initialise.js b/src/gui/html/js/initialise.js index 44328380..2def7ef3 100644 --- a/src/gui/html/js/initialise.js +++ b/src/gui/html/js/initialise.js @@ -49,10 +49,8 @@ document.getElementById('hideInactivePlugins').addEventListener('change', onSidebarFilterToggle); document.getElementById('hideAllPluginMessages').addEventListener('change', onSidebarFilterToggle); document.getElementById('hideMessagelessPlugins').addEventListener('change', onSidebarFilterToggle); - document.body.addEventListener('loot-filter-conflicts', onConflictsFilter); - - /* Set up event handlers for content filter. */ document.getElementById('contentFilter').addEventListener('change', onSidebarFilterToggle); + document.getElementById('conflictsFilter').addEventListener('iron-select', onConflictsFilter); /* Set up handlers for buttons. */ document.getElementById('redatePluginsButton').addEventListener('click', onRedatePlugins); @@ -231,6 +229,7 @@ appData.game = new Game(game, appData.l10n); document.getElementById('cardsNav').items = appData.game.plugins; document.getElementById('pluginCardList').items = appData.game.plugins; + appData.Filters.fillConflictsFilterList(appData.game.plugins); applyEnabledFilters(appData.filters, appData.settings, appData.game.plugins); Dialog.closeProgress(); }); diff --git a/src/gui/html/js/plugin.js b/src/gui/html/js/plugin.js index 743b5542..ea381dce 100644 --- a/src/gui/html/js/plugin.js +++ b/src/gui/html/js/plugin.js @@ -185,7 +185,6 @@ /* UI state variables */ this.id = this.name.replace(/\s+/g, ''); this._isEditorOpen = false; - this.isConflictFilterChecked = false; this._isSearchResult = false; } diff --git a/src/gui/html/js/translateStaticText.js b/src/gui/html/js/translateStaticText.js index 7ff92285..9508011b 100644 --- a/src/gui/html/js/translateStaticText.js +++ b/src/gui/html/js/translateStaticText.js @@ -20,7 +20,6 @@ pluginCard.querySelector('paper-tooltip[for=loadsArchive]').textContent = l10n.translate('Loads Archive'); pluginCard.querySelector('paper-tooltip[for=hasUserEdits]').textContent = l10n.translate('Has User Metadata'); - pluginCard.getElementById('showOnlyConflicts').textContent = l10n.translate('Show Only Conflicts'); pluginCard.getElementById('editMetadata').lastChild.textContent = l10n.translate('Edit Metadata'); pluginCard.getElementById('copyMetadata').lastChild.textContent = l10n.translate('Copy Metadata'); pluginCard.getElementById('clearMetadata').lastChild.textContent = l10n.translate('Clear User Metadata'); @@ -202,6 +201,8 @@ document.getElementById('hideAllPluginMessages').textContent = l10n.translate('Hide all plugin messages'); document.getElementById('hideInactivePlugins').textContent = l10n.translate('Hide inactive plugins'); document.getElementById('hideMessagelessPlugins').textContent = l10n.translate('Hide messageless plugins'); + document.getElementById('conflictsFilter').label = l10n.translate('Show only conflicting plugins for'); + document.getElementById('conflictsFilter').firstElementChild.textContent = l10n.translate('No plugin'); document.getElementById('hiddenPluginsTxt').textContent = l10n.translate('Hidden plugins:'); document.getElementById('hiddenMessagesTxt').textContent = l10n.translate('Hidden messages:'); } diff --git a/src/tests/gui/html/elements/test_loot-plugin-card.html b/src/tests/gui/html/elements/test_loot-plugin-card.html index 9831c540..7e35d885 100644 --- a/src/tests/gui/html/elements/test_loot-plugin-card.html +++ b/src/tests/gui/html/elements/test_loot-plugin-card.html @@ -45,9 +45,6 @@ function onEditorClose() { alert('Editor closed'); } - function onFilterConflicts() { - alert('Conflicts filter toggle clicked'); - } function onCopyMetadata() { alert('Copy metadata button clicked'); } @@ -77,7 +74,6 @@ document.addEventListener('loot-editor-open', onEditorOpen); document.addEventListener('loot-editor-close', onEditorClose); - document.addEventListener('loot-filter-conflicts', onFilterConflicts); document.addEventListener('loot-copy-metadata', onCopyMetadata); document.addEventListener('loot-clear-metadata', onClearMetadata); diff --git a/src/tests/gui/html/js/test_game.js b/src/tests/gui/html/js/test_game.js index 7e094d8b..55ff5579 100644 --- a/src/tests/gui/html/js/test_game.js +++ b/src/tests/gui/html/js/test_game.js @@ -408,7 +408,6 @@ describe('Game', () => { id: '', _isEditorOpen: true, - isConflictFilterChecked: true, _isSearchResult: true, }]; diff --git a/src/tests/gui/html/js/test_plugin.js b/src/tests/gui/html/js/test_plugin.js index 550d2d47..2915522f 100644 --- a/src/tests/gui/html/js/test_plugin.js +++ b/src/tests/gui/html/js/test_plugin.js @@ -262,12 +262,6 @@ describe('Plugin', () => { plugin.isEditorOpen.should.be.false(); }); - it('should set isConflictFilterChecked to false', () => { - const plugin = new loot.Plugin({ name: 'test' }); - - plugin.isConflictFilterChecked.should.be.false(); - }); - it('should set isSearchResult to false', () => { const plugin = new loot.Plugin({ name: 'test' });