'use strict'; import React from 'react'; import { alt } from '../alt'; import EditionsListActions from '../actions/edition_list_actions'; class EditionListStore { constructor() { this.editionList = {}; this.isEditionListOpenForPieceId = {}; this.bindActions(EditionsListActions); } onUpdateEditionList({ pieceId, editionListOfPiece, page, pageSize, orderBy, orderAsc, count, filterBy, maxEdition }) { // if editionList for a specific piece does not exist yet, // just initialize a new array const pieceEditionList = this.editionList[pieceId] || []; /* Basically there are two modes an edition list can be updated. 1. The elements that have been requested from the server are not yet defined in the store => just assign them 2. The elements are already defined => merge current objects with the new ones from the server */ editionListOfPiece.forEach((updatedEdition, index) => { // this is the index formula for accessing an edition starting from a specific page const storeEditionIndex = (page - 1) * pageSize + index; // if edition already exists, just merge if (pieceEditionList[storeEditionIndex]) { pieceEditionList[storeEditionIndex] = React.addons.update(pieceEditionList[storeEditionIndex], { $merge: updatedEdition }); } else { // if does not exist, assign pieceEditionList[storeEditionIndex] = updatedEdition; } }); // Remove editions after specified max by finding the index of the first // edition larger than the max edition and using that to cut off the rest of the list if (typeof maxEdition === 'number') { const largerThanMaxIndex = pieceEditionList.findIndex(edition => edition.edition_number > maxEdition); if (largerThanMaxIndex !== -1) { // The API defines inflexible page buckets based on the page number // and page size, so we cannot just arbitrarily cut off the end of // a page and expect get the rest of it on the next pagination request. // Hence, we use the max edition index as a guide for which page to // cut off to so as to always provide complete pages. page = Math.ceil(largerThanMaxIndex / pageSize); // We only want to cut off the list if there are more editions than // there should be (ie. we're not already at the end of the editions) const totalPageSize = page * pageSize; if (pieceEditionList.length > totalPageSize) { pieceEditionList.length = totalPageSize; } } } const lastEdition = pieceEditionList[pieceEditionList.length - 1]; /** * page, pageSize, orderBy, orderAsc and count are specific to a single list of editions * therefore they need to be saved in relation to their parent-piece. * * Default values for both are set in the editon_list_actions. */ pieceEditionList.page = page; pieceEditionList.pageSize = pageSize; pieceEditionList.orderBy = orderBy; pieceEditionList.orderAsc = orderAsc; pieceEditionList.count = count; pieceEditionList.filterBy = filterBy; if (pieceEditionList.maxSeen == null || lastEdition.edition_number > pieceEditionList.maxSeen) { pieceEditionList.maxSeen = lastEdition.edition_number; } this.editionList[pieceId] = pieceEditionList; } /** * We often just have to refresh the edition list for a certain pieceId, * this method provides exactly that functionality without any side effects */ onRefreshEditionList({ pieceId, filterBy }) { const pieceEditionList = this.editionList[pieceId]; // It may happen that the user enters the site logged in already // through /editions // If he then tries to delete a piece/edition and this method is called, // we'll not be able to refresh his edition list since its not yet there. // Therefore we can just return, since there is no data to be refreshed if (!this.editionList[pieceId]) { return; } if (typeof filterBy !== 'object') { filterBy = pieceEditionList.filterBy; } const { maxSeen, orderAsc, orderBy, pageSize } = pieceEditionList; // to clear an array, david walsh recommends to just set it's length to zero // http://davidwalsh.name/empty-array pieceEditionList.length = 0; EditionsListActions .fetchEditionList({ pieceId, pageSize, orderBy, orderAsc, filterBy, maxSeen, page: 1 }) .catch(console.logGlobal); } onSelectEdition({ pieceId, editionId, toValue }) { this.editionList[pieceId].forEach((edition) => { // Taken from: http://stackoverflow.com/a/519157/1263876 if (typeof toValue !== 'undefined' && edition.id === editionId) { edition.selected = toValue; } else if(edition.id === editionId) { if(edition.selected) { edition.selected = false; } else { edition.selected = true; } } }); } onClearAllEditionSelections() { Object .keys(this.editionList) .forEach((pieceId) => { this.editionList[pieceId] .forEach((edition) => { try { delete edition.selected; } catch(err) {/* ignore and keep going */} }); }); } onToggleEditionList(pieceId) { this.isEditionListOpenForPieceId[pieceId] = { show: this.isEditionListOpenForPieceId[pieceId] ? !this.isEditionListOpenForPieceId[pieceId].show : true }; // When loading all editions of a piece, closing the table and then applying the filter // the merge fails, as the edition list is not refreshed when closed. // Therefore in the case of a filter application when closed, we need to reload the // edition list if (!this.isEditionListOpenForPieceId[pieceId].show) { // to clear an array, david walsh recommends to just set it's length to zero // http://davidwalsh.name/empty-array this.editionList[pieceId].length = 0; } } onCloseAllEditionLists() { this.isEditionListOpenForPieceId = {}; } } export default alt.createStore(EditionListStore, 'EditionListStore');