Skip to content
Snippets Groups Projects
listcontroller.js 3.11 KiB
Newer Older
import m from 'mithril';
import Stream from 'mithril/stream';
import { ResourceHandler } from './auth';
import { debounce } from './utils';

export default class DatalistController {
Hermann's avatar
Hermann committed
  constructor(resource, query = {}, searchKeys = false) {
    this.handler = new ResourceHandler(resource, searchKeys);
    this.query = query || {};
Hermann's avatar
Hermann committed
    this.filter = null;
    // state pointer that is counted up every time the table is refreshed so
    // we can tell infinite scroll that the data-version has changed.
    this.stateCounter = Stream(0);
    this.debouncedSearch = debounce((search) => {
      this.setSearch(search);
      this.refresh();
      m.redraw();
    }, 100);
Hermann's avatar
Hermann committed
    // keep track of the total number of pages
    this.totalPages = null;
  refresh() {
    this.stateCounter(this.stateCounter() + 1);
  infiniteScrollParams(item) {
    return {
      item,
      pageData: pageNum => this.getPageData(pageNum),
      pageKey: pageNum => `${pageNum}-${this.stateCounter()}`,
    };
  }

  getPageData(pageNum) {
    // for some reason this is called before the object is instantiated.
    // check this and return nothing
Hermann's avatar
Hermann committed
    const query = Object.assign({}, this.query);
Hermann's avatar
Hermann committed
    query.max_results = 10;
    query.page = pageNum;
Hermann's avatar
Hermann committed
    query.where = { ...this.filter, ...this.query.where };
Hermann's avatar
Hermann committed
    // remove where again if it is empty
    if (Object.keys(query.where).length === 0) delete query.where;
Hermann's avatar
Hermann committed
    return new Promise((resolve) => {
      this.handler.get(query).then((data) => {
Hermann's avatar
Hermann committed
        // update total number of pages
        this.totalPages = Math.ceil(data._meta.total / 10);
Hermann's avatar
Hermann committed
        resolve(data._items);
  /*
   * Get all available pages
   */
  getFullList() {
    return new Promise((resolve) => {
      // get first page to refresh total page count
      this.getPageData(1).then((firstPage) => {
        const pages = { 1: firstPage };
        // save totalPages as a constant to avoid race condition with pages added during this
        // process
        const { totalPages } = this;
        console.log(totalPages);

        if (totalPages === 1) {
          resolve(firstPage);
        }

        // now fetch all the missing pages
        Array.from(new Array(totalPages - 1), (x, i) => i + 2).forEach((pageNum) => {
          this.getPageData(pageNum).then((newPage) => {
            pages[pageNum] = newPage;
            // look if all pages were collected
            const missingPages = Array.from(new Array(totalPages), (x, i) => i + 1).filter(i =>
              !(i in pages));
            console.log('missingPages', missingPages);
            if (missingPages.length === 0) {
              // collect all the so-far loaded pages in order (sorted keys)
              // and flatten them into 1 array
              resolve([].concat(...Object.keys(pages).sort().map(key => pages[key])));
            }
          });
        });
      });
    });
  }

  setSearch(search) {
    this.query.search = search;
Hermann's avatar
Hermann committed
  setFilter(filter) {
    this.filter = filter;
    this.refresh();
  }

  setQuery(query) {
Hermann's avatar
Hermann committed
    this.query = Object.assign({}, query, { search: this.query.search });