From a833e95a8bfc207a64fee82411af88ecde430c57 Mon Sep 17 00:00:00 2001 From: j Date: Fri, 7 Jun 2019 16:30:09 +0100 Subject: [PATCH] enable filters for documents --- pandora/config.0xdb.jsonc | 13 +- pandora/config.indiancinema.jsonc | 10 + pandora/config.pandora.jsonc | 10 + static/js/UI.js | 4 + static/js/URL.js | 1 + static/js/browser.js | 2 +- static/js/documentBrowser.js | 64 +++++- static/js/documentContentPanel.js | 14 +- static/js/documentFilter.js | 335 ++++++++++++++++++++++++++++++ static/js/documentFilterForm.js | 4 +- static/js/documentToolbar.js | 2 +- static/js/filterDialog.js | 7 +- static/js/findDocumentsElement.js | 33 ++- static/js/pandora.js | 9 + static/js/utils.js | 59 +++++- 15 files changed, 536 insertions(+), 31 deletions(-) create mode 100644 static/js/documentFilter.js diff --git a/pandora/config.0xdb.jsonc b/pandora/config.0xdb.jsonc index f7f91cf93..7b300891e 100644 --- a/pandora/config.0xdb.jsonc +++ b/pandora/config.0xdb.jsonc @@ -165,6 +165,7 @@ "type": "string", "columnWidth": 120, //"format": {"type": "date", "args": ["%a, %b %e, %Y"]}, + "filter": true, "sort": true }, { @@ -220,6 +221,7 @@ }, { "id": "size", + "filter": true, "operator": "-", "title": "Size", "type": "integer", @@ -1230,11 +1232,19 @@ }, "document": "", "documents": {}, - "documentView": "view", + "documentFiltersSize": 176, "documentSize": 256, "documentsSelection": {}, "documentsSort": [{"key": "name", "operator": "+"}], "documentsView": "grid", + "documentView": "view", + "documentFilters": [ + {"id": "author", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "place", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "date", "sort": [{"key": "name", "operator": "-"}]}, + {"id": "publisher", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "language", "sort": [{"key": "items", "operator": "-"}]} + ], "edit": "", "edits": {}, "editSelection": [], @@ -1303,6 +1313,7 @@ "showCalendarControls": true, // fixme: should be false "showClips": true, "showDocument": true, + "showDocumentFilters": false, "showFilters": true, "showIconBrowser": false, "showInfo": true, diff --git a/pandora/config.indiancinema.jsonc b/pandora/config.indiancinema.jsonc index e86731975..51fbaa562 100644 --- a/pandora/config.indiancinema.jsonc +++ b/pandora/config.indiancinema.jsonc @@ -212,6 +212,7 @@ "type": "string", "columnWidth": 120, //"format": {"type": "date", "args": ["%a, %b %e, %Y"]}, + "filter": true, "sort": true }, { @@ -1709,7 +1710,15 @@ } }, "documentView": "view", + "documentFilters": [ + {"id": "author", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "place", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "date", "sort": [{"key": "name", "operator": "-"}]}, + {"id": "publisher", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "language", "sort": [{"key": "items", "operator": "-"}]} + ], "documents": {}, + "documentFiltersSize": 176, "documentSize": 256, "documentsSelection": {}, "documentsSort": [{"key": "title", "operator": "+"}], @@ -1782,6 +1791,7 @@ "showCalendarControls": true, // fixme: should be false "showClips": true, "showDocument": true, + "showDocumentFilters": false, "showFilters": true, "showIconBrowser": false, "showInfo": true, diff --git a/pandora/config.pandora.jsonc b/pandora/config.pandora.jsonc index 90e97086f..9658b2656 100644 --- a/pandora/config.pandora.jsonc +++ b/pandora/config.pandora.jsonc @@ -217,6 +217,7 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution. "type": "string", "columnWidth": 120, //"format": {"type": "date", "args": ["%a, %b %e, %Y"]}, + "filter": true, "sort": true }, { @@ -1122,11 +1123,19 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution. }, "document": "", "documents": {}, + "documentFiltersSize": 176, "documentSize": 256, "documentView": "view", "documentsSelection": {}, "documentsSort": [{"key": "title", "operator": "+"}], "documentsView": "grid", + "documentFilters": [ + {"id": "author", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "place", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "date", "sort": [{"key": "name", "operator": "-"}]}, + {"id": "publisher", "sort": [{"key": "items", "operator": "-"}]}, + {"id": "language", "sort": [{"key": "items", "operator": "-"}]} + ], "edit": "", "edits": {}, "editSelection": [], @@ -1191,6 +1200,7 @@ examples (config.SITENAME.jsonc) that are part of this pan.do/ra distribution. "showCalendarControls": false, "showClips": true, "showDocument": true, + "showDocumentFilters": false, "showFilters": true, "showIconBrowser": false, "showInfo": true, diff --git a/static/js/UI.js b/static/js/UI.js index 149a0e810..94979e698 100644 --- a/static/js/UI.js +++ b/static/js/UI.js @@ -24,6 +24,9 @@ pandora.UI = (function() { pandora.user.ui._filterState = pandora.getFilterState( pandora.user.ui.find ); + pandora.user.ui._documentFilterState = pandora.getDocumentFilterState( + pandora.user.ui.findDocuments + ); pandora.user.ui._findState = pandora.getFindState( pandora.user.ui.find ); @@ -85,6 +88,7 @@ pandora.UI = (function() { // (values we put in add will be changed, but won't trigger) collection = pandora.getCollectionState(args.findDocuments); pandora.user.ui._collection = collection; + pandora.user.ui._documentFilterState = pandora.getDocumentFilterState(args.findDocuments); pandora.user.ui._findDocumentsState = pandora.getFindDocumentsState(args.findDocuments); if (pandora.$ui.appPanel && !pandora.stayInItemView) { // if we're not on page load, and if find isn't a context change diff --git a/static/js/URL.js b/static/js/URL.js index f31f6f15e..4a08db119 100644 --- a/static/js/URL.js +++ b/static/js/URL.js @@ -144,6 +144,7 @@ pandora.URL = (function() { pandora.user.ui._list = pandora.getListState(pandora.user.ui.find); pandora.user.ui._filterState = pandora.getFilterState(pandora.user.ui.find); + pandora.user.ui._documentFilterState = pandora.getDocumentFilterState(pandora.user.ui.findDocuments); pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); pandora.user.ui._collection = pandora.getCollectionState(pandora.user.ui.findDocuments); pandora.user.ui._findDocumentsState = pandora.getFindDocumentsState(pandora.user.ui.findDocuments); diff --git a/static/js/browser.js b/static/js/browser.js index 323011d01..4f86c1143 100644 --- a/static/js/browser.js +++ b/static/js/browser.js @@ -52,7 +52,7 @@ pandora.ui.browser = function() { selected: selected }); } - }).reloadList(); + }).reloadList(); } }); pandora.$ui.filters.updateMenus(); diff --git a/static/js/documentBrowser.js b/static/js/documentBrowser.js index 3bcb26992..411666a87 100644 --- a/static/js/documentBrowser.js +++ b/static/js/documentBrowser.js @@ -3,7 +3,69 @@ pandora.ui.documentBrowser = function() { var that; if (!pandora.user.ui.document) { - that = Ox.Element().html('fixme'); + pandora.user.ui.filterSizes = pandora.getFilterSizes(); + pandora.$ui.documentFilters = pandora.ui.documentFilters(); + that = Ox.SplitPanel({ + elements: [ + { + element: pandora.$ui.documentFilters[0], + size: pandora.user.ui.filterSizes[0] + }, + { + element: pandora.$ui.documentFiltersInnerPanel = pandora.ui.documentFiltersInnerPanel() + }, + { + element: pandora.$ui.documentFilters[4], + size: pandora.user.ui.filterSizes[4] + }, + ], + id: 'browser', + orientation: 'horizontal' + }) + .bindEvent({ + resize: function(data) { + pandora.$ui.documentFilters.forEach(function(list) { + list.size(); + }); + if (pandora.user.ui.listView == 'map') { + pandora.$ui.map.resizeMap(); + } else if (pandora.user.ui.listView == 'calendar') { + pandora.$ui.calendar.resizeCalendar(); + } else if (pandora.user.ui.listView == 'video') { + pandora.$ui.list.size(); + } + }, + resizeend: function(data) { + pandora.UI.set({documentFiltersSize: data.size}); + }, + toggle: function(data) { + data.collapsed && pandora.$ui.list.gainFocus(); + pandora.UI.set({showDocumentFilters: !data.collapsed}); + if (!data.collapsed) { + pandora.$ui.documentFilters.forEach(function($documentFilter) { + var selected = $documentFilter.options('_selected'); + if (selected) { + $documentFilter.bindEventOnce({ + load: function() { + $documentFilter.options({ + _selected: false, + selected: selected + }); + } + }).reloadList(); + } + }); + pandora.$ui.documentFilters.updateMenus(); + } + if (pandora.user.ui.listView == 'map') { + pandora.$ui.map.resizeMap(); + } else if (pandora.user.ui.listView == 'calendar') { + pandora.$ui.calendar.resizeCalendar(); + } else if (pandora.user.ui.listView == 'video') { + pandora.$ui.list.size(); + } + } + }); } else { var that = Ox.IconList({ borderRadius: 0, diff --git a/static/js/documentContentPanel.js b/static/js/documentContentPanel.js index 6e5703de6..b1bbc5d03 100644 --- a/static/js/documentContentPanel.js +++ b/static/js/documentContentPanel.js @@ -4,16 +4,14 @@ pandora.ui.documentContentPanel = function() { var that = Ox.SplitPanel({ elements: !pandora.user.ui.document ? [ { - collapsed: true, - collapsible: false, //fixme + collapsed: !pandora.user.ui.showDocumentFilters, + collapsible: true, element: pandora.$ui.documentBrowser = pandora.ui.documentBrowser(), - resizable: false, //fixme + resizable: true, resize: [96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256], - size: 96, - tooltip: '' /* fixme: - Ox._('filters') + ' ' - + Ox.SYMBOLS.shift + 'F' - */ + size: pandora.user.ui.documentFiltersSize, + tooltip: Ox._('filters') + ' ' + + Ox.SYMBOLS.shift + 'F' }, { element: pandora.$ui.list = pandora.ui.collection() diff --git a/static/js/documentFilter.js b/static/js/documentFilter.js new file mode 100644 index 000000000..8f74a197c --- /dev/null +++ b/static/js/documentFilter.js @@ -0,0 +1,335 @@ +'use strict'; + +pandora.ui.documentFilter = function(id) { + var i = Ox.getIndexById(pandora.user.ui.documentFilters, id), + filter = Ox.getObjectById(pandora.site.documentFilters, id), + panelWidth = Ox.$document.width() - (pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize) - 1, + title = Ox._(Ox.getObjectById(pandora.site.documentFilters, id).title), + //width = pandora.getFilterWidth(i, panelWidth), + that = Ox.TableList({ + _selected: !pandora.user.ui.showFilters + ? pandora.user.ui._documentFilterState[i].selected + : false, + columns: [ + { + align: 'left', + id: 'name', + format: function(value) { + var layer = Ox.getObjectById(pandora.site.layers, filter.id), + key = Ox.getObjectById(pandora.site.itemKeys, filter.id); + if ((layer && layer.translate) || (key && key.translate)) { + value = Ox._(value) + } + return filter.flag + ? $('
') + .append( + $('') + .attr({src: Ox[ + filter.flag == 'country' + ? 'getFlagByGeoname' + : 'getFlagByLanguage' + ](value, 16)}) + .css({ + float: 'left', + width: '14px', + height: '14px', + margin: '0 3px 0 -2px', + borderRadius: '4px' + }) + ) + .append( + $('
') + .addClass('flagname') + .css({ + float: 'left', + width: pandora.user.ui.filterSizes[i] + - 68 - Ox.UI.SCROLLBAR_SIZE, + textOverflow: 'ellipsis', + overflowX: 'hidden' + }) + .html(value) + ) + : value + }, + operator: filter.type == 'string' || filter.type == 'layer' ? '+' : '-', + title: title, + visible: true, + width: pandora.user.ui.filterSizes[i] - 44 - Ox.UI.SCROLLBAR_SIZE + }, + { + align: 'right', + format: function(value) { + return Ox.formatNumber(value); + }, + id: 'items', + operator: '-', + title: '#', + visible: true, + width: 44 + } + ], + columnsVisible: true, + id: 'filter_' + id, + items: function(data, callback) { + if (pandora.user.ui.showFilters) { + delete data.keys; + return pandora.api.findDocuments(Ox.extend(data, { + group: id, + query: pandora.user.ui._documentFilterState[i].find + }), callback); + } else { + callback({data: {items: data.keys ? [] : 0}}); + } + }, + scrollbarVisible: true, + selected: pandora.user.ui.showFilters + ? pandora.user.ui._documentFilterState[i].selected + : [], + sort: [{ + key: pandora.user.ui.documentFilters[i].sort[0].key, + operator: pandora.user.ui.documentFilters[i].sort[0].operator + }], + unique: 'name' + }) + .bindEvent({ + init: function(data) { + that.setColumnTitle( + 'name', + Ox._(Ox.getObjectById(pandora.site.documentFilters, id).title) + + '
' + + Ox.formatNumber(data.items) + '
' + ); + }, + paste: function(data) { + pandora.$ui.list.triggerEvent('paste', data); + }, + select: function(data) { + // fixme: cant index be an empty array, instead of -1? + // FIXME: this is still incorrect when deselecting a filter item + // makes a selected item in another filter disappear + var conditions = data.ids.map(function(value) { + return { + key: id, + value: value, + operator: '==' + }; + }), + index = pandora.user.ui._documentFilterState[i].index, + find = Ox.clone(pandora.user.ui.findDocuments, true); + if (Ox.isArray(index)) { + // this filter had multiple selections and the | query + // was on the top level, i.e. not bracketed + find = { + conditions: conditions, + operator: conditions.length > 1 ? '|' : '&' + } + } else { + if (index == -1) { + // this filter had no selection, i.e. no query + index = find.conditions.length; + if (find.operator == '|') { + find = { + conditions: [find], + operator: '&' + }; + index = 1; + } else { + find.operator = '&'; + } + } + if (conditions.length == 0) { + // nothing selected + find.conditions.splice(index, 1); + if (find.conditions.length == 1) { + if (find.conditions[0].conditions) { + // unwrap single remaining bracketed query + find = { + conditions: find.conditions[0].conditions, + operator: '|' + }; + } else { + find.operator = '&'; + } + } + } else if (conditions.length == 1) { + // one item selected + find.conditions[index] = conditions[0]; + } else { + // multiple items selected + if (pandora.user.ui.findDocuments.conditions.length == 1) { + find = { + conditions: conditions, + operator: '|' + }; + } else { + find.conditions[index] = { + conditions: conditions, + operator: '|' + }; + } + } + } + pandora.UI.set({findDocuments: find}); + pandora.$ui.documentFilters.updateMenus(); + }, + sort: function(data) { + Ox.Log('', 'SORT', data) + var filters = Ox.clone(pandora.user.ui.documentFilters); + pandora.$ui.mainMenu.checkItem('sortMenu_sortfilters_sortfilter' + id + '_' + data.key); + pandora.$ui.mainMenu.checkItem('sortMenu_orderfilters_orderfilter' + id + '_' + (data.operator == '+' ? 'ascending' : 'descending')); + filters[i].sort = [{key: data.key, operator: data.operator}]; + pandora.UI.set({filters: filters}); + } + }), + $menu = Ox.MenuButton({ + items: [ + {id: 'clearFilter', title: Ox._('Clear Filter'), keyboard: 'shift control a'}, + {id: 'clearFilters', title: Ox._('Clear All Filters'), keyboard: 'shift alt control a'}, + {}, + {group: 'filter', max: 1, min: 1, items: pandora.site.documentFilters.map(function(filter) { + return Ox.extend({checked: filter.id == id}, filter); + })} + ], + type: 'image', + }) + .css(Ox.UI.SCROLLBAR_SIZE == 8 ? { + right: '-1px', + width: '8px', + } : { + right: '2px', + width: (Ox.UI.SCROLLBAR_SIZE - 2) + 'px' + }) + .bindEvent({ + change: function(data) { + var filters = Ox.clone(pandora.user.ui.documentFilters), + find, + id_ = data.checked[0].id, + i_ = Ox.getIndexById(pandora.user.ui.documentFilters, id_); + if (i_ == -1) { + // new filter was not part of old filter set + if (pandora.user.ui._documentFilterState[i].selected.length) { + // if filter with selection gets replaced, update find + find = Ox.clone(pandora.user.ui.findDocuments, true); + find.conditions.splice(pandora.user.ui._documentFilterState[i].index, 1); + } + filters[i] = makeFilter(id_); + pandora.UI.set(Ox.extend({ + filters: filters + }, find ? { + findDocuments: find + } : {})); + replaceFilter(i, id_); + // fixme: there is an obscure special case not yet covered: + // switching to a new filter may change find from advanced to not advanced + // if part of the existing query works as a filter selection in the new filter + } else { + // swap two existing filters + var filterData = Ox.clone(pandora.user.ui._documentFilterState[i]); + pandora.user.ui._documentFilterState[i] = pandora.user.ui._documentFilterState[i_]; + pandora.user.ui._documentFilterState[i_] = filterData; + filters[i] = makeFilter(id_, pandora.user.ui.documentFilters[i_].sort); + filters[i_] = makeFilter(id, pandora.user.ui.documentFilters[i].sort); + pandora.UI.set({filters: filters}); + replaceFilter(i, id_); + replaceFilter(i_, id); + } + pandora.$ui.documentFilters.updateMenus(); + function makeFilter(id, sort) { + // makes user.ui._documentFilterState object from site.documentFilters object + var filter = Ox.getObjectById(pandora.site.documentFilters, id); + return { + id: filter.id, + sort: sort || [{key: filter.type == 'integer' ? 'name' : 'items', operator: '-'}] + }; + } + function replaceFilter(i, id) { + var isOuter = i % 4 == 0; + pandora.$ui[isOuter ? 'browser' : 'filtersInnerPanel'].replaceElement( + isOuter ? i / 2 : i - 1, + pandora.$ui.documentFilters[i] = pandora.ui.documentFilter(id) + ); + } + }, + click: function(data) { + if (data.id == 'clearFilter') { + // FIXME: List should trigger event on options change + if (!Ox.isEmpty(that.options('selected'))) { + that.options({selected: []}).triggerEvent('select', {ids: []}); + } + } else if (data.id == 'clearFilters') { + pandora.$ui.documentFilters.clearFilters(); + } + } + }) + .appendTo(that.$bar); + Ox.UI.SCROLLBAR_SIZE < 16 && $($menu.find('input')[0]).css({ + marginRight: '-3px', + marginTop: '1px', + width: '8px', + height: '8px' + }); + that.disableMenuItem = function(id) { + $menu.disableItem(id); + }; + that.enableMenuItem = function(id) { + $menu.enableItem(id); + }; + return that; +}; + +pandora.ui.documentFilters = function() { + var $filters = []; + pandora.user.ui.documentFilters.forEach(function(filter, i) { + $filters[i] = pandora.ui.documentFilter(filter.id); + }); + $filters.clearFilters = function() { + var find = Ox.clone(pandora.user.ui.findDocuments, true), + indices = pandora.user.ui._documentFilterState.map(function(filterState) { + return filterState.index; + }).filter(function(index) { + return index > -1; + }); + find.conditions = find.conditions.filter(function(condition, index) { + return !Ox.contains(indices, index); + }); + pandora.UI.set({findDocuments: find}) + }; + $filters.updateMenus = function() { + var selected = $filters.map(function($filter) { + return !Ox.isEmpty($filter.options('selected')); + }), + filtersHaveSelection = !!Ox.sum(selected); + $filters.forEach(function($filter, i) { + $filter[ + selected[i] ? 'enableMenuItem' : 'disableMenuItem' + ]('clearFilter'); + $filter[ + filtersHaveSelection ? 'enableMenuItem' : 'disableMenuItem' + ]('clearFilters'); + }); + return $filters; + }; + return $filters.updateMenus(); +}; + +pandora.ui.documentFiltersInnerPanel = function() { + var that = Ox.SplitPanel({ + elements: [ + { + element: pandora.$ui.documentFilters[1], + size: pandora.user.ui.filterSizes[1] + }, + { + element: pandora.$ui.documentFilters[2] + }, + { + element: pandora.$ui.documentFilters[3], + size: pandora.user.ui.filterSizes[3] + } + ], + orientation: 'horizontal' + }); + return that; +}; + + diff --git a/static/js/documentFilterForm.js b/static/js/documentFilterForm.js index 2d0992a6b..577375c04 100644 --- a/static/js/documentFilterForm.js +++ b/static/js/documentFilterForm.js @@ -42,7 +42,7 @@ pandora.ui.documentFilterForm = function(options) { view: pandora.user.ui.collectionView } : null, sortKeys: pandora.site.documentSortKeys, - value: Ox.clone(mode == 'collection' ? collection.query : pandora.user.ui.documentFind, true), + value: Ox.clone(mode == 'collection' ? collection.query : pandora.user.ui.findDocuments, true), viewKeys: pandora.site.collectionViews }) .css(mode == 'embed' ? {} : {padding: '16px'}) @@ -87,7 +87,7 @@ pandora.ui.documentFilterForm = function(options) { }); */ } else { - pandora.UI.set({find: Ox.clone(that.$filter.options('value'), true)}); + pandora.UI.set({findDocuments: Ox.clone(that.$filter.options('value'), true)}); pandora.$ui.findElement.updateElement(); } }; diff --git a/static/js/documentToolbar.js b/static/js/documentToolbar.js index 347fc2dfd..ef12a8560 100644 --- a/static/js/documentToolbar.js +++ b/static/js/documentToolbar.js @@ -64,7 +64,7 @@ pandora.ui.documentToolbar = function() { } }) that.append( - pandora.$ui.findDocumentsElement = pandora.ui.findDocumentsElement(function(data) { + pandora.$ui.findElement= pandora.ui.findDocumentsElement(function(data) { var key = data.key, value = data.value, conditions; diff --git a/static/js/filterDialog.js b/static/js/filterDialog.js index 88be1d557..3e5b7b465 100644 --- a/static/js/filterDialog.js +++ b/static/js/filterDialog.js @@ -42,7 +42,12 @@ pandora.ui.filterDialog = function() { } }) ], - content: pandora.$ui.filterForm = pandora.ui.filterForm({mode: 'find'}), + content: pandora.$ui.filterForm = (pandora.user.ui.section == 'documents' + ? pandora.ui.documentFilterForm + : pandora.ui.filterForm + )({ + mode: 'find' + }), maxWidth: 648 + Ox.UI.SCROLLBAR_SIZE, minHeight: 264, minWidth: 648 + Ox.UI.SCROLLBAR_SIZE, diff --git a/static/js/findDocumentsElement.js b/static/js/findDocumentsElement.js index e8fcfea77..ad7efcb13 100644 --- a/static/js/findDocumentsElement.js +++ b/static/js/findDocumentsElement.js @@ -35,26 +35,39 @@ pandora.ui.findDocumentsElement = function() { ] : [], [ $findSelect = Ox.Select({ id: 'select', - items: pandora.site.documentKeys.filter(function(key) { - return key.find; - }).map(function(key) { + items: [].concat( + pandora.site.documentKeys.filter(function(key) { + return key.find; + }).map(function(key) { return { id: key.id, title: Ox._('Find: {0}', [Ox._(key.title)]) }; }), + [{}, { + id: 'advanced', + title: Ox._('Find: Advanced...') + }] + ), + overlap: 'right', value: findKey, width: 128 }) .bindEvent({ change: function(data) { - //pandora.$ui.mainMenu.checkItem('findMenu_find_' + data.value); - $findInput.options({ - autocomplete: autocompleteFunction(), - placeholder: '' - }).focusInput(true); - previousFindKey = data.value; + if (data.value == 'advanced') { + that.updateElement(); + pandora.$ui.mainMenu.checkItem('findMenu_find_' + previousFindKey); + pandora.$ui.filterDialog = pandora.ui.filterDialog().open(); + } else { + //pandora.$ui.mainMenu.checkItem('findMenu_find_' + data.value); + $findInput.options({ + autocomplete: autocompleteFunction(), + placeholder: '' + }).focusInput(true); + previousFindKey = data.value; + } } }), $findInput = Ox.Input({ @@ -77,7 +90,7 @@ pandora.ui.findDocumentsElement = function() { focus: function(data) { if ($findSelect.value() == 'advanced') { if (hasPressedClear) { - pandora.UI.set({find: pandora.site.user.ui.find}); + pandora.UI.set({findDocuments: pandora.site.user.ui.findDocuments}); that.updateElement(); hasPressedClear = false; } diff --git a/static/js/pandora.js b/static/js/pandora.js index 571e58a1b..0962c235a 100644 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -342,6 +342,15 @@ appPanel type: Ox.isArray(key.type) ? key.type[0] : key.type }; }), + documentFilters: data.site.documentKeys.filter(function(key) { + return key.filter; + }).map(function(key) { + return { + id: key.id, + title: key.title, + type: Ox.isArray(key.type) ? key.type[0] : key.type + }; + }), findKeys: data.site.itemKeys.filter(function(key) { return key.find; }), diff --git a/static/js/utils.js b/static/js/utils.js index fdcd7c63f..fff8f9234 100644 --- a/static/js/utils.js +++ b/static/js/utils.js @@ -2626,6 +2626,7 @@ pandora.signin = function(data) { }); pandora.user.ui._list = pandora.getListState(pandora.user.ui.find); pandora.user.ui._filterState = pandora.getFilterState(pandora.user.ui.find); + pandora.user.ui._documentFilterState = pandora.getDocumentFilterState(pandora.user.ui.findDocuments); pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); pandora.user.ui._collection = pandora.getCollectionState(pandora.user.ui.findDocuments); pandora.user.ui._findDocumentsState = pandora.getFindDocumentsState(pandora.user.ui.findDocuments); @@ -2642,6 +2643,7 @@ pandora.signout = function(data) { pandora.user = data.user; pandora.user.ui._list = pandora.getListState(pandora.user.ui.find); pandora.user.ui._filterState = pandora.getFilterState(pandora.user.ui.find); + pandora.user.ui._documentFilterState = pandora.getDocumentFilterState(pandora.user.ui.findDocuments); pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); pandora.user.ui._collection = pandora.getCollectionState(pandora.user.ui.findDocuments); pandora.user.ui._findDocumentsState = pandora.getFindDocumentsState(pandora.user.ui.findDocuments); @@ -3396,6 +3398,7 @@ pandora.wait = function(id, callback, timeout) { } return state; }; + function getState(find, key) { var index, state = ''; if (find.operator == '&') { @@ -3429,12 +3432,10 @@ pandora.wait = function(id, callback, timeout) { if (find.operator == '&') { // number of conditions that are not list or filters conditions = find.conditions.length - - !!pandora.user.ui._collection; - /* - - pandora.user.ui._filterState.filter(function(filter) { + - !!pandora.user.ui._collection + - pandora.user.ui._documentFilterState.filter(function(filter) { return filter.index > -1; }).length; - */ // indices of non-advanced find queries indices = pandora.site.documentKeys.map(function(findKey) { return oneCondition(find.conditions, findKey.id, '='); @@ -3456,16 +3457,62 @@ pandora.wait = function(id, callback, timeout) { key: 'advanced', value: '' }; - /* Ox.forEach(pandora.user.ui.documentFilters, function(key) { if (everyCondition(find.conditions, key, '==')) { state.key = '*'; return false; } }); - */ } return state; }; + pandora.getDocumentFilterState = function(find) { + // A filter is selected if exactly one condition in an & query or every + // condition in an | query has the filter id as key and "==" as operator + return pandora.user.ui.documentFilters.map(function(filter) { + // FIXME: cant index be an empty array, instead of -1? + var key = filter.id, + state = {index: -1, find: Ox.clone(find, true), selected: []}; + if (find.operator == '&') { + // include conditions where all subconditions match + state.index = oneCondition(find.conditions, key, '==', true); + if (state.index > -1) { + state.selected = find.conditions[state.index].conditions + ? find.conditions[state.index].conditions.map(function(condition) { + return condition.value; + }) + : [find.conditions[state.index].value]; + } + } else { + if (everyCondition(find.conditions, key, '==')) { + state.index = Ox.range(find.conditions.length); + state.selected = find.conditions.map(function(condition) { + return condition.value; + }); + } + } + if (state.selected.length) { + if (Ox.isArray(state.index)) { + // every condition in an | query matches this filter + state.find = {conditions: [], operator: ''}; + } else { + // one condition in an & query matches this filter + state.find.conditions.splice(state.index, 1); + if ( + state.find.conditions.length == 1 + && state.find.conditions[0].conditions + ) { + // unwrap single remaining bracketed query + state.find = { + conditions: state.find.conditions[0].conditions, + operator: state.find.conditions[0].operator + }; + } + } + } + return state; + }); + }; + }());