import * as moment from "moment"; import { DayEvent } from "./"; import * as WPAPI from "../../Core/WPAPI"; import EventStore from "./EventStore"; interface EventQueryResult { events: DayEvent[]; } /** * A cache for querying against events */ const eventCache = new Map(); /** * A cache by event ID */ const flatEventCache: DayEvent[] = []; /** * A store listing all months that have been queried before. */ const queried = new Set(); /** * Holds a set of queries that are outstanding by month. */ const queriesInProgress = new Map>(); /** * Adds the given events to the cache of events at the given month. */ export function addToCache(month: number, events: DayEvent[]) { let cache = eventCache.get(month); if (!cache) { cache = []; eventCache.set(month, cache); } // TODO: filter out events with IDs we've already seen? cache.push(...events); flatEventCache.push(...events); } /** * Queries for events at the given month, potentially hitting the server. */ export function queryEvents(month: number): Promise { // Are we currently querying for these events somewhere else? const existing = queriesInProgress.get(month); if (existing) { return existing; } // Have we already issued a query for this month? if (queried.has(month)) { return Promise.resolve(eventCache.get(month)); } // We hadn't before, but we have now. queried.add(month); // Define the bounds of the query as the start/end of the month const start = monthNumberToMoment(month); const end = start.clone() .endOf("month"); // The WordPress API call const request = WPAPI.request("query_events", { afterTime: start.utc().unix(), beforeTime: end.utc().unix() }) as Promise>; // Handle the results of the API call const query = request .then(response => response.result.events) .then(events => { for (const event of events) { event.visible = true; } addToCache(month, events); return eventCache.get(month); }); // If anyone else tries to query this same month before we're done // they should get the same Promise object back. queriesInProgress.set(month, query); return query; } export function yearMonthToMonthNumber(year: number, month: number) { return year * 12 + month; } export function momentToMonthNumber(moment: moment.Moment) { return yearMonthToMonthNumber(moment.year(), moment.month()); } export function monthNumberToMoment(monthNumber: number) { const year = Math.floor(monthNumber / 12); const month = monthNumber % 12; return moment.utc() .year(year) .month(month) .startOf("month"); } EventStore.listen("showOnlyEvents", (ids?: number[]) => { if (ids) { for (const event of flatEventCache) { if (ids.includes(event.id)) { event.visible = true; } else { event.visible = false; } } } else { for (const event of flatEventCache) { event.visible = true; } } });