1
0
mirror of https://github.com/ascribe/onion.git synced 2024-06-24 10:16:29 +02:00
onion/js/stores/edition_list_store.js
2016-01-18 14:15:19 +01:00

175 lines
6.8 KiB
JavaScript

'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');