| // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| // use this file except in compliance with the License. You may obtain a copy of |
| // the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| // License for the specific language governing permissions and limitations under |
| // the License. |
| |
| define([ |
| 'app', |
| 'api', |
| 'addons/documents/index-results/actiontypes', |
| 'addons/documents/header/header.actiontypes', |
| 'addons/documents/resources', |
| 'addons/documents/mango/mango.helper' |
| ], |
| |
| function (app, FauxtonAPI, ActionTypes, HeaderActionTypes, Documents, MangoHelper) { |
| var Stores = {}; |
| |
| /*TODO: |
| remove header code, add delete, clean up pagination tests |
| */ |
| |
| Stores.IndexResultsStore = FauxtonAPI.Store.extend({ |
| |
| initialize: function () { |
| this.reset(); |
| }, |
| |
| reset: function () { |
| this._collection = []; |
| this.clearSelectedItems(); |
| this._isLoading = false; |
| this._textEmptyIndex = 'No Index Created Yet!'; |
| this._typeOfIndex = 'view'; |
| this._lastQuery = null; |
| this._bulkDeleteDocCollection = null; |
| }, |
| |
| clearSelectedItems: function () { |
| this._selectedItems = {}; |
| }, |
| |
| newResults: function (options) { |
| this._collection = options.collection; |
| this.clearSelectedItems(); |
| |
| this._bulkDeleteDocCollection = options.bulkCollection; |
| |
| if (options.textEmptyIndex) { |
| this._textEmptyIndex = options.textEmptyIndex; |
| } |
| |
| if (options.typeOfIndex) { |
| this._typeOfIndex = options.typeOfIndex; |
| } |
| |
| if (options.query) { |
| this._lastQuery = options.query; |
| } |
| }, |
| |
| getTypeOfIndex: function () { |
| return this._typeOfIndex; |
| }, |
| |
| getLastQuery: function () { |
| return this._lastQuery; |
| }, |
| |
| isEditable: function (doc) { |
| if (!this._collection) { |
| return false; |
| } |
| |
| if (doc && this.isGhostDoc(doc)) { |
| return false; |
| } |
| |
| if (doc && !doc.get('_id')) { |
| return false; |
| } |
| |
| if (!this._collection.isEditable) { |
| return false; |
| } |
| |
| return this._collection.isEditable(); |
| }, |
| |
| isGhostDoc: function (doc) { |
| // ghost docs are empty results where all properties were |
| // filtered away by mango |
| return !doc || !doc.attributes || !Object.keys(doc.attributes).length; |
| }, |
| |
| isDeletable: function (doc) { |
| if (this.isGhostDoc(doc)) { |
| return false; |
| } |
| |
| return doc.isBulkDeletable(); |
| }, |
| |
| getCollection: function () { |
| return this._collection; |
| }, |
| |
| getDocContent: function (originalDoc) { |
| var doc = originalDoc.toJSON(); |
| |
| if (this._allCollapsed) { |
| return JSON.stringify({id: doc.id, rev: doc._rev}, null, ' '); |
| } |
| |
| return JSON.stringify(doc, null, ' '); |
| }, |
| |
| getDocId: function (doc) { |
| |
| if (!_.isUndefined(doc.id)) { |
| return doc.id; |
| } |
| |
| if (doc.get('key')) { |
| return doc.get('key').toString(); |
| } |
| |
| return ''; |
| }, |
| |
| getMangoDocContent: function (originalDoc) { |
| var doc = originalDoc.toJSON(); |
| |
| delete doc.ddoc; |
| delete doc.name; |
| |
| if (this._allCollapsed) { |
| return ''; |
| } |
| |
| return JSON.stringify(doc, null, ' '); |
| }, |
| |
| getMangoDoc: function (doc, index) { |
| var selector, |
| header; |
| |
| if (doc.get('def') && doc.get('def').fields) { |
| |
| header = MangoHelper.getIndexName(doc); |
| |
| return { |
| content: this.getMangoDocContent(doc), |
| header: header, |
| id: doc.getId(), |
| keylabel: '', |
| url: doc.isFromView() ? doc.url('app') : doc.url('web-index'), |
| isDeletable: this.isDeletable(doc), |
| isEditable: this.isEditable(doc) |
| }; |
| } |
| |
| // we filtered away our content with the fields param |
| return { |
| content: ' ', |
| header: header, |
| id: this.getDocId(doc) + index, |
| keylabel: '', |
| url: this.isEditable(doc) ? doc.url('app') : null, |
| isDeletable: this.isDeletable(doc), |
| isEditable: this.isEditable(doc) |
| }; |
| |
| }, |
| |
| filterOutGeneratedMangoDocs: function (doc) { |
| if (doc.get && typeof doc.get === 'function') { |
| return doc.get('language') !== 'query'; |
| } |
| |
| return doc.language !== 'query'; |
| }, |
| |
| getResults: function () { |
| var hasDeletableDoc; |
| var res; |
| var collection; |
| |
| var filteredCollection = this._collection.filter(this.filterOutGeneratedMangoDocs); |
| |
| // Table sytle view |
| if (this.getIsTableView()) { |
| collection = this._collection.toJSON().filter(this.filterOutGeneratedMangoDocs); |
| return this.getTableViewData(collection); |
| } |
| |
| // JSON style views |
| res = this._collection |
| .filter(this.filterOutGeneratedMangoDocs) |
| .map(function (doc, i) { |
| if (doc.get('def') || this.isGhostDoc(doc)) { |
| return this.getMangoDoc(doc, i); |
| } |
| return { |
| content: this.getDocContent(doc), |
| id: this.getDocId(doc), |
| header: this.getDocId(doc), |
| keylabel: doc.isFromView() ? 'key' : 'id', |
| url: this.getDocId(doc) ? doc.url('app') : null, |
| isDeletable: this.isDeletable(doc), |
| isEditable: this.isEditable(doc) |
| }; |
| }, this); |
| |
| hasDeletableDoc = this.getHasDeletableDoc(res); |
| |
| return { |
| hasDeletableDoc: hasDeletableDoc, |
| results: res |
| }; |
| }, |
| |
| getPseudoSchema: function (data) { |
| var cache = []; |
| |
| data.forEach(function (el) { |
| Object.keys(el).forEach(function (k) { |
| cache.push(k); |
| }); |
| }); |
| |
| cache = _.uniq(cache); |
| |
| // always begin with _id |
| var i = cache.indexOf('_id'); |
| if (i !== -1) { |
| cache.splice(i, 1); |
| cache.unshift('_id'); |
| } |
| |
| return cache; |
| }, |
| |
| // filter out cruft and JSONify strings |
| normalizeTableData: function (data) { |
| // include_docs enabled |
| if (data[0] && data[0].doc && data[0].doc._rev) { |
| return data.map(function (el) { |
| el = el.doc; |
| return el; |
| }); |
| } |
| |
| return data; |
| }, |
| |
| getTableViewData: function (data) { |
| var res; |
| var schema; |
| var database; |
| |
| data = this.normalizeTableData(data); |
| schema = this.getPseudoSchema(data); |
| database = this.getDatabase().safeID(); |
| |
| res = this._collection |
| .filter(this.filterOutGeneratedMangoDocs) |
| .map(function (doc) { |
| |
| return { |
| content: doc.toJSON(), |
| id: this.getDocId(doc), |
| header: '', |
| keylabel: '', |
| url: this.getDocId(doc) ? doc.url('app') : null, |
| isDeletable: this.isDeletable(doc), |
| isEditable: this.isEditable(doc) |
| }; |
| }, this); |
| |
| return { |
| hasDeletableDoc: this.getHasDeletableDoc(res), |
| schema: schema, |
| results: res |
| }; |
| }, |
| |
| getHasDeletableDoc: function (data) { |
| var found = false; |
| var length = data.length; |
| var i; |
| // use a for loop here as we can end it once we found the first id |
| for (i = 0; i < length; i++) { |
| |
| if (data[i].isDeletable) { |
| found = true; |
| break; |
| } |
| } |
| |
| return found; |
| }, |
| |
| hasResults: function () { |
| if (this.isLoading()) { return this.isLoading(); } |
| return this._collection.length > 0; |
| }, |
| |
| isLoading: function () { |
| return this._isLoading; |
| }, |
| |
| selectDoc: function (id) { |
| if (!id || id === '_all_docs') { |
| return; |
| } |
| |
| if (!this._selectedItems[id]) { |
| this._selectedItems[id] = true; |
| } else { |
| delete this._selectedItems[id]; |
| } |
| }, |
| |
| selectListOfDocs: function (ids) { |
| this.clearSelectedItems(); |
| _.each(ids, function (id) { |
| this.selectDoc(id); |
| }, this); |
| }, |
| |
| selectAllDocuments: function () { |
| this.clearSelectedItems(); |
| this._collection.each(function (doc) { |
| if (!doc.isBulkDeletable()) { |
| return; |
| } |
| this.selectDoc(doc.id); |
| }, this); |
| }, |
| |
| toggleSelectAllDocuments: function () { |
| if (this.areAllDocumentsSelected()) { |
| return this.clearSelectedItems(); |
| } |
| |
| return this.selectAllDocuments(); |
| }, |
| |
| areAllDocumentsSelected: function () { |
| var filtered; |
| |
| if (this._collection.length === 0) { |
| return false; |
| } |
| |
| filtered = this._collection.filter(function (doc) { |
| return doc.isBulkDeletable(); |
| }); |
| |
| return Object.keys(this._selectedItems).length === filtered.length; |
| }, |
| |
| getSelectedItemsLength: function () { |
| return Object.keys(this._selectedItems).length; |
| }, |
| |
| getDatabase: function () { |
| return this._collection.database; |
| }, |
| |
| getTextEmptyIndex: function () { |
| return this._textEmptyIndex; |
| }, |
| |
| setbulkDeleteDocCollection: function (bulkDeleteDocCollection) { |
| this._bulkDeleteDocCollection = bulkDeleteDocCollection; |
| }, |
| |
| createBulkDeleteFromSelected: function () { |
| var items = _.map(_.keys(this._selectedItems), function (id) { |
| var doc = this._collection.get(id); |
| |
| return { |
| _id: doc.id, |
| _rev: doc.get('_rev'), |
| _deleted: true |
| }; |
| }, this); |
| |
| var bulkDelete = new this._bulkDeleteDocCollection(items, { |
| databaseId: this.getDatabase().safeID() |
| }); |
| |
| return bulkDelete; |
| }, |
| |
| canSelectAll: function () { |
| var length = this._collection.length; |
| |
| if (this._collection.get && this._collection.get('_all_docs')) { |
| length = length - 1; |
| } |
| |
| return length > this.getSelectedItemsLength(); |
| }, |
| |
| canDeselectAll: function () { |
| return this.getSelectedItemsLength() > 0; |
| }, |
| |
| getSelectedItems: function () { |
| return this._selectedItems; |
| }, |
| |
| hasSelectedItem: function () { |
| return this.getSelectedItemsLength() > 0; |
| }, |
| |
| collapseAllDocs: function () { |
| this.disableTableView(); |
| |
| this._allCollapsed = true; |
| }, |
| |
| unCollapseAllDocs: function () { |
| this.disableTableView(); |
| |
| this._allCollapsed = false; |
| }, |
| |
| enableTableView: function () { |
| this._allCollapsed = false; |
| this._tableView = true; |
| }, |
| |
| disableTableView: function () { |
| this._allCollapsed = false; |
| this._tableView = false; |
| }, |
| |
| getIsTableView: function () { |
| return this._tableView; |
| }, |
| |
| getCurrentViewType: function () { |
| |
| if (this._tableView) { |
| return 'table'; |
| } |
| |
| if (this._allCollapsed) { |
| return 'collapsed'; |
| } |
| |
| return 'expanded'; |
| }, |
| |
| clearResultsBeforeFetch: function () { |
| if (this._collection && this._collection.reset) { |
| this._collection.reset(); |
| } |
| this._isLoading = true; |
| }, |
| |
| resultsResetFromFetch: function () { |
| this._isLoading = false; |
| }, |
| |
| dispatch: function (action) { |
| switch (action.type) { |
| case ActionTypes.INDEX_RESULTS_NEW_RESULTS: |
| this.newResults(action.options); |
| break; |
| case ActionTypes.INDEX_RESULTS_RESET: |
| this.resultsResetFromFetch(); |
| break; |
| case ActionTypes.INDEX_RESULTS_SELECT_DOC: |
| this.selectDoc(action.id); |
| break; |
| case ActionTypes.INDEX_RESULTS_SELECT_LIST_OF_DOCS: |
| this.selectListOfDocs(action.ids); |
| break; |
| case ActionTypes.INDEX_RESULTS_CLEAR_RESULTS: |
| this.clearResultsBeforeFetch(); |
| break; |
| case ActionTypes.INDEX_RESULTS_SELECT_ALL_DOCUMENTS: |
| this.selectAllDocuments(); |
| break; |
| case ActionTypes.INDEX_RESULTS_TOOGLE_SELECT_ALL_DOCUMENTS: |
| this.toggleSelectAllDocuments(); |
| break; |
| case HeaderActionTypes.COLLAPSE_DOCUMENTS: |
| this.collapseSelectedDocs(); |
| break; |
| case HeaderActionTypes.EXPAND_DOCUMENTS: |
| this.unCollapseSelectedDocs(); |
| break; |
| case HeaderActionTypes.COLLAPSE_ALL_DOCUMENTS: |
| this.collapseAllDocs(); |
| break; |
| case HeaderActionTypes.EXPAND_ALL_DOCUMENTS: |
| this.unCollapseAllDocs(); |
| break; |
| case HeaderActionTypes.DISABLE_TABLE_VIEW: |
| this.disableTableView(); |
| break; |
| case HeaderActionTypes.ENABLE_TABLE_VIEW: |
| this.enableTableView(); |
| break; |
| |
| default: |
| return; |
| // do nothing |
| } |
| |
| this.triggerChange(); |
| } |
| |
| }); |
| |
| Stores.indexResultsStore = new Stores.IndexResultsStore(); |
| |
| Stores.indexResultsStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.indexResultsStore.dispatch); |
| |
| return Stores; |
| |
| }); |