Skip to content

Commit

Permalink
isLoading refactoring. fixes #5896. solves #5729
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Dec 17, 2020
1 parent 6daf22a commit 386b303
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 19 deletions.
2 changes: 1 addition & 1 deletion packages-premium
5 changes: 5 additions & 0 deletions packages/common/src/global-plugins.ts
Expand Up @@ -9,6 +9,8 @@ import { handleDateProfile } from './dates-set'
import { handleEventStore } from './event-crud'
import { isArraysEqual } from './util/array'
import { removeElement } from './util/dom-manip'
import { computeEventSourcesLoading } from './reducers/eventSources'
import { CalendarDataManagerState } from './reducers/data-types'

/*
this array is exposed on the root namespace so that UMD plugins can add to it.
Expand All @@ -21,6 +23,9 @@ export const globalPlugins: PluginDef[] = [ // TODO: make a const?
simpleRecurringEventsPlugin,
changeHandlerPlugin,
createPlugin({ // misc...
isLoadingFuncs: [
(state: CalendarDataManagerState) => computeEventSourcesLoading(state.eventSources),
],
contentTypeHandlers: {
html: () => ({ render: injectHtml }),
domNodes: () => ({ render: injectDomNodes }),
Expand Down
4 changes: 3 additions & 1 deletion packages/common/src/plugin-system-struct.ts
Expand Up @@ -21,14 +21,15 @@ import { ElementDraggingClass } from './interactions/ElementDragging'
import { ComponentChildren } from './vdom'
import { ScrollGridImpl } from './scrollgrid/ScrollGridImpl'
import { ContentTypeHandlers } from './common/render-hook'
import { GenericRefiners, GenericListenerRefiners } from './options'
import { GenericRefiners, GenericListenerRefiners, Dictionary } from './options'
import { CalendarData } from './reducers/data-types'

// TODO: easier way to add new hooks? need to update a million things

export interface PluginDefInput {
deps?: PluginDef[]
reducers?: ReducerFunc[]
isLoadingFuncs?: ((state: Dictionary) => boolean)[]
contextInit?: (context: CalendarContext) => void
eventRefiners?: GenericRefiners // why not an array like others?
eventDefMemberAdders?: EventDefMemberAdder[]
Expand Down Expand Up @@ -65,6 +66,7 @@ export interface PluginDefInput {

export interface PluginHooks {
reducers: ReducerFunc[]
isLoadingFuncs: ((state: Dictionary) => boolean)[]
contextInit: ((context: CalendarContext) => void)[]
eventRefiners: GenericRefiners
eventDefMemberAdders: EventDefMemberAdder[]
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/plugin-system.ts
Expand Up @@ -9,6 +9,7 @@ export function createPlugin(input: PluginDefInput): PluginDef {
id: guid(),
deps: input.deps || [],
reducers: input.reducers || [],
isLoadingFuncs: input.isLoadingFuncs || [],
contextInit: [].concat(input.contextInit || []),
eventRefiners: input.eventRefiners || {},
eventDefMemberAdders: input.eventDefMemberAdders || [],
Expand Down Expand Up @@ -48,6 +49,7 @@ function buildPluginHooks(pluginDefs: PluginDef[], globalDefs: PluginDef[]): Plu
let isAdded: { [pluginId: string]: boolean } = {}
let hooks: PluginHooks = {
reducers: [],
isLoadingFuncs: [],
contextInit: [],
eventRefiners: {},
eventDefMemberAdders: [],
Expand Down Expand Up @@ -119,6 +121,7 @@ export function buildBuildPluginHooks() { // memoizes
function combineHooks(hooks0: PluginHooks, hooks1: PluginHooks): PluginHooks {
return {
reducers: hooks0.reducers.concat(hooks1.reducers),
isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
contextInit: hooks0.contextInit.concat(hooks1.contextInit),
eventRefiners: { ...hooks0.eventRefiners, ...hooks1.eventRefiners },
eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
Expand Down
30 changes: 19 additions & 11 deletions packages/common/src/reducers/CalendarDataManager.ts
Expand Up @@ -15,7 +15,7 @@ import { reduceViewType } from './view-type'
import { getInitialDate, reduceCurrentDate } from './current-date'
import { reduceDynamicOptionOverrides } from './options'
import { reduceDateProfile } from './date-profile'
import { reduceEventSources, initEventSources, reduceEventSourcesNewTimeZone, computeEventSourceLoadingLevel } from './eventSources'
import { reduceEventSources, initEventSources, reduceEventSourcesNewTimeZone, computeEventSourcesLoading } from './eventSources'
import { reduceEventStore, rezoneEventStoreDates } from './eventStore'
import { reduceDateSelection } from './date-selection'
import { reduceSelectedEvent } from './selected-event'
Expand Down Expand Up @@ -147,7 +147,6 @@ export class CalendarDataManager {
businessHours: this.parseContextBusinessHours(calendarContext), // weird to have this in state
eventSources,
eventUiBases: {},
loadingLevel: computeEventSourceLoadingLevel(eventSources),
eventStore: createEmptyEventStore(),
renderableEventStore: createEmptyEventStore(),
dateSelection: null,
Expand All @@ -162,7 +161,7 @@ export class CalendarDataManager {
__assign(initialState, reducer(null, null, contextAndState))
}

if (initialState.loadingLevel) {
if (computeIsLoading(initialState, calendarContext)) {
this.emitter.trigger('loading', true) // NOT DRY
}

Expand Down Expand Up @@ -237,21 +236,18 @@ export class CalendarDataManager {
}

let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext)
let eventSourceLoadingLevel = computeEventSourceLoadingLevel(eventSources)
let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext)
let isEventsLoading = computeEventSourcesLoading(eventSources) // BAD. also called in this func in computeIsLoading

let renderableEventStore =
(eventSourceLoadingLevel && !currentViewData.options.progressiveEventRendering) ?
(isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
(state.renderableEventStore || eventStore) : // try from previous state
eventStore

let { eventUiSingleBase, selectionConfig } = this.buildViewUiProps(calendarContext) // will memoize obj
let eventUiBySource = this.buildEventUiBySource(eventSources)
let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource)

let prevLoadingLevel = state.loadingLevel || 0
let loadingLevel = eventSourceLoadingLevel

let newState: CalendarDataManagerState = {
dynamicOptionOverrides,
currentViewType,
Expand All @@ -262,7 +258,6 @@ export class CalendarDataManager {
renderableEventStore,
selectionConfig,
eventUiBases,
loadingLevel,
businessHours: this.parseContextBusinessHours(calendarContext), // will memoize obj
dateSelection: reduceDateSelection(state.dateSelection, action),
eventSelection: reduceSelectedEvent(state.eventSelection, action),
Expand All @@ -275,10 +270,13 @@ export class CalendarDataManager {
__assign(newState, reducer(state, action, contextAndState)) // give the OLD state, for old value
}

let wasLoading = computeIsLoading(state, calendarContext)
let isLoading = computeIsLoading(newState, calendarContext)

// TODO: use propSetHandlers in plugin system
if (!prevLoadingLevel && loadingLevel) {
if (!wasLoading && isLoading) {
emitter.trigger('loading', true)
} else if (prevLoadingLevel && !loadingLevel) {
} else if (wasLoading && !isLoading) {
emitter.trigger('loading', false)
}

Expand Down Expand Up @@ -646,6 +644,16 @@ function buildViewUiProps(calendarContext: CalendarContext) {
}
}

function computeIsLoading(state: CalendarDataManagerState, context: CalendarContext) {
for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
if (isLoadingFunc(state)) {
return true
}
}

return false
}

function parseContextBusinessHours(calendarContext: CalendarContext) {
return parseBusinessHours(calendarContext.options.businessHours, calendarContext)
}
Expand Down
1 change: 0 additions & 1 deletion packages/common/src/reducers/data-types.ts
Expand Up @@ -23,7 +23,6 @@ export interface CalendarDataManagerState {
businessHours: EventStore
eventSources: EventSourceHash
eventUiBases: EventUiHash
loadingLevel: number
eventStore: EventStore
renderableEventStore: EventStore
dateSelection: DateSpan | null
Expand Down
8 changes: 3 additions & 5 deletions packages/common/src/reducers/eventSources.ts
Expand Up @@ -76,16 +76,14 @@ export function reduceEventSourcesNewTimeZone(eventSources: EventSourceHash, dat
)
}

export function computeEventSourceLoadingLevel(eventSources: EventSourceHash): number {
let cnt = 0

export function computeEventSourcesLoading(eventSources: EventSourceHash): boolean {
for (let sourceId in eventSources) {
if (eventSources[sourceId].isFetching) {
cnt += 1
return true
}
}

return cnt
return false
}

function addSources(
Expand Down

0 comments on commit 386b303

Please sign in to comment.