Skip to content

Commit

Permalink
fix tests, import commonjs plugin, other stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed May 29, 2019
1 parent 02076c2 commit 9163210
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 270 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.8.0",
"eslint-plugin-standard": "^3.1.0",
"fast-deep-equal": "^2.0.1",
"glob": "^7.1.3",
"gulp": "^3.9.1",
"gulp-cssmin": "^0.1.7",
Expand All @@ -64,6 +65,7 @@
"moment-timezone": "^0.5.25",
"native-promise-only": "^0.8.1",
"rollup": "1.8.0",
"rollup-plugin-commonjs": "^9.0.0",
"rollup-plugin-multi-entry": "^2.1.0",
"rollup-plugin-node-resolve": "4.0.1",
"rollup-plugin-sourcemaps": "^0.4.2",
Expand Down
8 changes: 6 additions & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path'
import glob from 'glob'
import resolve from 'rollup-plugin-node-resolve'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import multiEntry from 'rollup-plugin-multi-entry'
import multiEntryArray from './rollup-plugin-multi-entry-array'
import sourcemaps from 'rollup-plugin-sourcemaps'
Expand Down Expand Up @@ -34,7 +35,10 @@ let watchOptions = {
}

function getDefaultPlugins() { // need to be instantiated each time
let plugins = [ resolve() ] // for tslib
let plugins = [
nodeResolve(), // for tslib
commonjs() // for fast-deep-equal import
]

if (isDev) {
plugins.push(sourcemaps()) // for reading/writing sourcemaps
Expand Down
159 changes: 52 additions & 107 deletions src/core/Calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import { Duration, createDuration, DurationInput } from './datelib/duration'
import reduce from './reducers/main'
import { parseDateSpan, DateSpanInput, DateSpan, buildDateSpanApi, DateSpanApi, buildDatePointApi, DatePointApi } from './structs/date-span'
import { memoize, memoizeOutput } from './util/memoize'
import { mapHash } from './util/object'
import { isObjectsSimilar, anyKeysRemoved, computeChangedProps, isValuesSimilar } from './util/object-similarity'
import { mapHash, isPropsEqual } from './util/object'
import { DateRangeInput } from './datelib/date-range'
import DateProfileGenerator from './DateProfileGenerator'
import { EventSourceInput, parseEventSource, EventSourceHash } from './structs/event-source'
Expand Down Expand Up @@ -55,11 +54,9 @@ export type DateSpanTransform = (dateSpan: DateSpan, calendar: Calendar) => any
export type CalendarInteraction = { destroy() }
export type CalendarInteractionClass = { new(calendar: Calendar): CalendarInteraction }

export type OptionChangeHandler = (propValue: any, calendar: Calendar) => void
export type OptionChangeHandler = (propValue: any, calendar: Calendar, deepEquals) => void
export type OptionChangeHandlerMap = { [propName: string]: OptionChangeHandler }

const OPTION_CMP_DEPTH = 2 // must be >= 2

export default class Calendar {

// global handler registry
Expand All @@ -80,7 +77,7 @@ export default class Calendar {
private buildTheme = memoize(buildTheme)
private buildEventUiSingleBase = memoize(this._buildEventUiSingleBase)
private buildSelectionConfig = memoize(this._buildSelectionConfig)
private buildEventUiBySource = memoizeOutput(buildEventUiBySource, isObjectsSimilar)
private buildEventUiBySource = memoizeOutput(buildEventUiBySource, isPropsEqual)
private buildEventUiBases = memoize(buildEventUiBases)

eventUiBases: EventUiHash // solely for validation system
Expand Down Expand Up @@ -495,84 +492,52 @@ export default class Calendar {
// Options
// -----------------------------------------------------------------------------------------------------------------

/*
Not meant for public API
*/
resetOptions(options) {
let changeHandlers = this.pluginSystem.hooks.optionChangeHandlers
let oldOptions = this.optionsManager.overrides
let oldNormalOptions = {}
let normalOptions = {}
let specialOptions = {}

for (let name in oldOptions) {
if (!changeHandlers[name]) {
oldNormalOptions[name] = oldOptions[name]
}
}

for (let name in options) {
if (changeHandlers[name]) {
specialOptions[name] = options[name]
} else {
normalOptions[name] = options[name]
}
}
setOption(name: string, val) {
this.mutateOptions({ [name]: val }, [], true)
}

this.batchRendering(() => { // for if both processOptions and special options want to rerender

if (anyKeysRemoved(oldNormalOptions, normalOptions)) {
this.processOptions(options, 'reset')
} else {
this.processOptions(
computeChangedProps(oldNormalOptions, normalOptions, OPTION_CMP_DEPTH) // depth 2 is enough to get props in header/footer
)
}
getOption(name: string) { // getter, used externally
return this.optionsManager.computed[name]
}

// handle special options last
for (let name in specialOptions) {
changeHandlers[name](specialOptions[name], this)
}
})

opt(name: string) { // getter, used internally
return this.optionsManager.computed[name]
}

/*
Not meant for public API. Won't give the same precedence that setOption does
*/
setOptions(options) {
let changeHandlers = this.pluginSystem.hooks.optionChangeHandlers
let oldOptions = this.optionsManager.overrides
let normalOptions = {}
let specialOptions = {}

for (let name in options) {
if (!isValuesSimilar(oldOptions[name], options[name], OPTION_CMP_DEPTH - 1)) {
if (changeHandlers[name]) {
specialOptions[name] = options[name]
} else {
normalOptions[name] = options[name]
}
}
}

this.batchRendering(() => { // for if both processOptions and special options want to rerender
viewOpt(name: string) { // getter, used internally
return this.viewOpts()[name]
}

this.processOptions(normalOptions)

// handle special options last
for (let name in specialOptions) {
changeHandlers[name](specialOptions[name], this)
}
})
viewOpts() {
return this.viewSpecs[this.state.viewType].options
}

processOptions(options, mode?: 'dynamic' | 'reset') {
/*
handles option changes (like a diff)
*/
mutateOptions(updates, removals: string[], isDynamic?: boolean, deepEquals?) {
let changeHandlers = this.pluginSystem.hooks.optionChangeHandlers
let normalUpdates = {}
let specialUpdates = {}
let oldDateEnv = this.dateEnv // do this before handleOptions
let isTimeZoneDirty = false
let isSizeDirty = false
let anyDifficultOptions = false
let anyDifficultOptions = Boolean(removals.length)

for (let name in options) {
for (let name in updates) {
if (changeHandlers[name]) {
specialUpdates[name] = updates[name]
} else {
normalUpdates[name] = updates[name]
}
}

for (let name in normalUpdates) {
if (/^(height|contentHeight|aspectRatio)$/.test(name)) {
isSizeDirty = true
} else if (/^(defaultDate|defaultView)$/.test(name)) {
Expand All @@ -586,20 +551,16 @@ export default class Calendar {
}
}

if (mode === 'reset') {
anyDifficultOptions = true
this.optionsManager.reset(options)
} else if (mode === 'dynamic') {
this.optionsManager.addDynamic(options) // takes higher precedence
} else {
this.optionsManager.add(options)
}
this.optionsManager.mutate(normalUpdates, removals, isDynamic)

if (anyDifficultOptions) {
this.handleOptions(this.optionsManager.computed) // only for "difficult" options

this.handleOptions(this.optionsManager.computed)
this.needsFullRerender = true
this.batchRendering(() => {
}

this.batchRendering(() => {

if (anyDifficultOptions) {

if (isTimeZoneDirty) {
this.dispatch({
Expand All @@ -616,35 +577,19 @@ export default class Calendar {
type: 'SET_VIEW_TYPE',
viewType: this.state.viewType
})
})
} if (isSizeDirty) {
this.updateSize()
}
}


setOption(name: string, val) {
this.processOptions({ [name]: val }, 'dynamic')
}

} else if (isSizeDirty) {
this.updateSize()
}

getOption(name: string) { // getter, used externally
return this.optionsManager.computed[name]
}


opt(name: string) { // getter, used internally
return this.optionsManager.computed[name]
}


viewOpt(name: string) { // getter, used internally
return this.viewOpts()[name]
}

// special updates
if (deepEquals) {
for (let name in specialUpdates) {
changeHandlers[name](specialUpdates[name], this, deepEquals)
}
}

viewOpts() {
return this.viewSpecs[this.state.viewType].options
})
}

/*
Expand Down Expand Up @@ -761,7 +706,7 @@ export default class Calendar {

if (dateOrRange) {
if ((dateOrRange as DateRangeInput).start && (dateOrRange as DateRangeInput).end) { // a range
this.optionsManager.addDynamic({ visibleRange: dateOrRange }) // will not rerender
this.optionsManager.mutate({ visibleRange: dateOrRange }, []) // will not rerender
this.handleOptions(this.optionsManager.computed) // ...but yuck
} else { // a date
dateMarker = this.dateEnv.createMarker(dateOrRange as DateInput) // just like gotoDate
Expand Down
17 changes: 6 additions & 11 deletions src/core/OptionsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,15 @@ export default class OptionsManager {
}


add(props) {
__assign(this.overrides, props)
this.compute()
}

mutate(updates, removals: string[], isDynamic?: boolean) {
let overrideHash = isDynamic ? this.dynamicOverrides : this.overrides

addDynamic(props) {
__assign(this.dynamicOverrides, props)
this.compute()
}
__assign(overrideHash, updates)

for (let propName of removals) {
delete overrideHash[propName]
}

reset(props) {
this.overrides = props
this.compute()
}

Expand Down
3 changes: 1 addition & 2 deletions src/core/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ export {
translateRect
} from './util/geom'

export { mapHash, filterHash } from './util/object'
export { isObjectsSimilar, isValuesSimilar } from './util/object-similarity'
export { mapHash, filterHash, isPropsEqual } from './util/object'

export {
findElements,
Expand Down
9 changes: 4 additions & 5 deletions src/core/option-change-handlers.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import { createPlugin } from './plugin-system'
import { Calendar } from './main'
import { hashValuesToArray } from './util/object'
import { isValuesSimilar } from './util/object-similarity'
import { EventSource } from './structs/event-source'

export default createPlugin({
optionChangeHandlers: {
events(events, calendar) {
handleEventSources([ events ], calendar)
events(events, calendar, deepEquals) {
handleEventSources([ events ], calendar, deepEquals)
},
eventSources: handleEventSources,
plugins: handlePlugins
}
})

function handleEventSources(inputs, calendar: Calendar) {
function handleEventSources(inputs, calendar: Calendar, deepEquals) {
let unfoundSources: EventSource[] = hashValuesToArray(calendar.state.eventSources)
let newInputs = []

for (let input of inputs) {
let inputFound = false

for (let i = 0; i < unfoundSources.length; i++) {
if (isValuesSimilar(unfoundSources[i]._raw, input, 2)) {
if (deepEquals(unfoundSources[i]._raw, input)) {
unfoundSources.splice(i, 1) // delete
inputFound = true
break
Expand Down

0 comments on commit 9163210

Please sign in to comment.