Просмотр исходного кода

kill View Registry, move to plugin system, viewDefTransformers

Adam Shaw 7 лет назад
Родитель
Сommit
0b084cfd5a

+ 5 - 3
src/Calendar.ts

@@ -29,7 +29,6 @@ import PointerDragging, { PointerDragEvent } from './dnd/PointerDragging'
 import EventDragging from './interactions/EventDragging'
 import { buildViewSpecs, ViewSpecHash, ViewSpec } from './structs/view-spec'
 import { PluginSystem, PluginDef } from './plugin-system'
-import * as exportHooks from './exports'
 import CalendarComponent from './CalendarComponent'
 
 
@@ -517,6 +516,8 @@ export default class Calendar {
 
 
   handleOptions(options) {
+    let pluginHooks = this.pluginSystem.hooks
+
     this.defaultAllDayEventDuration = createDuration(options.defaultAllDayEventDuration)
     this.defaultTimedEventDuration = createDuration(options.defaultTimedEventDuration)
     this.delayedRerender = this.buildDelayedRerender(options.rerenderDelay)
@@ -534,8 +535,9 @@ export default class Calendar {
 
     // ineffecient to do every time?
     this.viewSpecs = buildViewSpecs(
-      (exportHooks as any).views,
-      this.optionsManager
+      pluginHooks.viewConfigs,
+      this.optionsManager,
+      pluginHooks.viewDefTransformers
     )
 
     // ineffecient to do every time?

+ 0 - 15
src/ViewRegistry.ts

@@ -1,15 +0,0 @@
-import * as exportHooks from './exports'
-
-
-export const viewHash = {};
-(exportHooks as any).views = viewHash
-
-
-export function defineView(viewType: string, viewConfig) {
-  viewHash[viewType] = viewConfig
-}
-
-
-export function getViewConfig(viewType: string) {
-  return viewHash[viewType]
-}

+ 20 - 14
src/agenda/config.ts

@@ -1,19 +1,25 @@
-import { defineView } from '../ViewRegistry'
+import { createPlugin } from '../plugin-system'
 import AgendaView from './AgendaView'
 
-defineView('agenda', {
-  class: AgendaView,
-  allDaySlot: true,
-  slotDuration: '00:30:00',
-  slotEventOverlap: true // a bad name. confused with overlap/constraint system
-})
+export default createPlugin({
+  viewConfigs: {
 
-defineView('agendaDay', {
-  type: 'agenda',
-  duration: { days: 1 }
-})
+    agenda: {
+      class: AgendaView,
+      allDaySlot: true,
+      slotDuration: '00:30:00',
+      slotEventOverlap: true // a bad name. confused with overlap/constraint system
+    },
+
+    agendaDay: {
+      type: 'agenda',
+      duration: { days: 1 }
+    },
+
+    agendaWeek: {
+      type: 'agenda',
+      duration: { weeks: 1 }
+    }
 
-defineView('agendaWeek', {
-  type: 'agenda',
-  duration: { weeks: 1 }
+  }
 })

+ 21 - 15
src/basic/config.ts

@@ -1,21 +1,27 @@
-import { defineView } from '../ViewRegistry'
+import { createPlugin } from '../plugin-system'
 import BasicView from './BasicView'
 
-defineView('basic', BasicView)
+export default createPlugin({
+  viewConfigs: {
 
-defineView('basicDay', {
-  type: 'basic',
-  duration: { days: 1 }
-})
+    basic: BasicView,
 
-defineView('basicWeek', {
-  type: 'basic',
-  duration: { weeks: 1 }
-})
+    basicDay: {
+      type: 'basic',
+      duration: { days: 1 }
+    },
+
+    basicWeek: {
+      type: 'basic',
+      duration: { weeks: 1 }
+    },
+
+    month: {
+      type: 'basic',
+      monthMode: true,
+      duration: { months: 1 }, // important for prev/next
+      fixedWeekCount: true
+    }
 
-defineView('month', {
-  type: 'basic',
-  monthMode: true,
-  duration: { months: 1 }, // important for prev/next
-  fixedWeekCount: true
+  }
 })

+ 1 - 1
src/component/DateComponent.ts

@@ -1,6 +1,6 @@
 import Component, { ComponentContext } from './Component'
 import { EventStore } from '../structs/event-store'
-import { EventRenderRange, hasBgRendering } from './event-rendering'
+import { EventRenderRange } from './event-rendering'
 import { DateSpan } from '../structs/date-span'
 import { EventInstanceHash } from '../structs/event'
 import { rangeContainsRange } from '../datelib/date-range'

+ 2 - 2
src/exports.ts

@@ -92,7 +92,6 @@ export { default as Component, ComponentContext } from './component/Component'
 export { default as DateComponent, Seg, EventSegUiInteractionState } from './component/DateComponent'
 export { default as Calendar, dateClickApiTransformer, DateClickApi, DateSelectionApi } from './Calendar'
 export { default as View, ViewProps } from './View'
-export { defineView, getViewConfig } from './ViewRegistry'
 export { default as FgEventRenderer } from './component/renderers/FgEventRenderer'
 export { default as FillRenderer } from './component/renderers/FillRenderer'
 export { default as AgendaView, buildDayTable as buildAgendaDayTable } from './agenda/AgendaView'
@@ -105,7 +104,8 @@ export { default as DayGrid, DayGridSeg } from './basic/DayGrid'
 export { default as BasicView, buildDayTable as buildBasicDayTable } from './basic/BasicView'
 export { default as ListView } from './list/ListView'
 export { default as DateProfileGenerator, DateProfile } from './DateProfileGenerator'
-export { ViewSpec } from './structs/view-spec'
+export { ViewDef } from './structs/view-def'
+export { ViewSpec, ViewDefTransformer } from './structs/view-spec'
 export { DateSpan } from './structs/date-span'
 
 export { DateMarker, addDays, startOfDay, addMs, diffWholeWeeks, diffWholeDays, diffDayAndTime, isValidDate } from './datelib/marker'

+ 32 - 26
src/list/config.ts

@@ -1,33 +1,39 @@
-import { defineView } from '../ViewRegistry'
+import { createPlugin } from '../plugin-system'
 import ListView from './ListView'
 
-defineView('list', {
-  class: ListView,
-  buttonTextKey: 'list', // what to lookup in locale files
-  listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
-})
+export default createPlugin({
+  viewConfigs: {
 
-defineView('listDay', {
-  type: 'list',
-  duration: { days: 1 },
-  listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header
-})
+    list: {
+      class: ListView,
+      buttonTextKey: 'list', // what to lookup in locale files
+      listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
+    },
 
-defineView('listWeek', {
-  type: 'list',
-  duration: { weeks: 1 },
-  listDayFormat: { weekday: 'long' }, // day-of-week is more important
-  listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' }
-})
+    listDay: {
+      type: 'list',
+      duration: { days: 1 },
+      listDayFormat: { weekday: 'long' } // day-of-week is all we need. full date is probably in header
+    },
 
-defineView('listMonth', {
-  type: 'list',
-  duration: { month: 1 },
-  listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
-})
+    listWeek: {
+      type: 'list',
+      duration: { weeks: 1 },
+      listDayFormat: { weekday: 'long' }, // day-of-week is more important
+      listDayAltFormat: { month: 'long', day: 'numeric', year: 'numeric' }
+    },
+
+    listMonth: {
+      type: 'list',
+      duration: { month: 1 },
+      listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
+    },
+
+    listYear: {
+      type: 'list',
+      duration: { year: 1 },
+      listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
+    }
 
-defineView('listYear', {
-  type: 'list',
-  duration: { year: 1 },
-  listDayAltFormat: { weekday: 'long' } // day-of-week is nice-to-have
+  }
 })

+ 8 - 3
src/main.ts

@@ -2,9 +2,6 @@ import * as exportHooks from './exports'
 
 // for intentional side-effects
 import './theme/config'
-import './basic/config'
-import './agenda/config'
-import './list/config'
 
 import './event-sources/array-event-source'
 import './event-sources/func-event-source'
@@ -12,4 +9,12 @@ import './event-sources/json-feed-event-source'
 
 import './structs/recurring-event-simple'
 
+import BasicPlugin from './basic/config'
+import AgendaPlugin from './agenda/config'
+import ListPlugin from './list/config'
+
+import Calendar from './Calendar'
+
+Calendar.defaultPlugins.push(BasicPlugin, AgendaPlugin, ListPlugin)
+
 export = exportHooks

+ 16 - 3
src/plugin-system.ts

@@ -4,6 +4,9 @@ import { eventDragMutationMassager } from './interactions/EventDragging'
 import { eventDefMutationApplier } from './structs/event-mutation'
 import { dateClickApiTransformer, dateSelectionApiTransformer } from './Calendar'
 import { dateSelectionTransformer } from './interactions/DateSelecting'
+import { ViewConfigInputHash } from './structs/view-config'
+import { assignTo } from './util/object'
+import { ViewDefTransformer } from './structs/view-spec'
 
 // TODO: easier way to add new hooks? need to update a million things
 
@@ -16,6 +19,8 @@ export interface PluginDefInput {
   dateSelectionTransformers?: dateSelectionTransformer[]
   dateClickApiTransformers?: dateClickApiTransformer[]
   dateSelectionApiTransformers?: dateSelectionApiTransformer[]
+  viewConfigs?: ViewConfigInputHash
+  viewDefTransformers?: ViewDefTransformer[]
 }
 
 export interface PluginHooks {
@@ -26,6 +31,8 @@ export interface PluginHooks {
   dateSelectionTransformers: dateSelectionTransformer[]
   dateClickApiTransformers: dateClickApiTransformer[]
   dateSelectionApiTransformers: dateSelectionApiTransformer[]
+  viewConfigs: ViewConfigInputHash // TODO: parse before gets to this step?
+  viewDefTransformers: ViewDefTransformer[]
 }
 
 export interface PluginDef extends PluginHooks {
@@ -45,7 +52,9 @@ export function createPlugin(input: PluginDefInput): PluginDef {
     eventDefMutationAppliers: input.eventDefMutationAppliers || [],
     dateSelectionTransformers: input.dateSelectionTransformers || [],
     dateClickApiTransformers: input.dateClickApiTransformers || [],
-    dateSelectionApiTransformers: input.dateSelectionApiTransformers || []
+    dateSelectionApiTransformers: input.dateSelectionApiTransformers || [],
+    viewConfigs: input.viewConfigs || {},
+    viewDefTransformers: input.viewDefTransformers || []
   }
 }
 
@@ -62,7 +71,9 @@ export class PluginSystem {
       eventDefMutationAppliers: [],
       dateSelectionTransformers: [],
       dateClickApiTransformers: [],
-      dateSelectionApiTransformers: []
+      dateSelectionApiTransformers: [],
+      viewConfigs: {},
+      viewDefTransformers: []
     }
     this.addedHash = {}
   }
@@ -89,6 +100,8 @@ function combineHooks(hooks0: PluginHooks, hooks1: PluginHooks): PluginHooks {
     eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
     dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
     dateClickApiTransformers: hooks0.dateClickApiTransformers.concat(hooks1.dateClickApiTransformers),
-    dateSelectionApiTransformers: hooks0.dateSelectionApiTransformers.concat(hooks1.dateSelectionApiTransformers)
+    dateSelectionApiTransformers: hooks0.dateSelectionApiTransformers.concat(hooks1.dateSelectionApiTransformers),
+    viewConfigs: assignTo({}, hooks0.viewConfigs, hooks1.viewConfigs),
+    viewDefTransformers: hooks0.viewDefTransformers.concat(hooks1.viewDefTransformers)
   }
 }

+ 28 - 14
src/structs/view-spec.ts

@@ -26,17 +26,19 @@ export interface ViewSpec {
 
 export type ViewSpecHash = { [viewType: string]: ViewSpec }
 
-export function buildViewSpecs(defaultInputs: ViewConfigInputHash, optionsManager: OptionsManager): ViewSpecHash {
+export type ViewDefTransformer = (viewDef: ViewDef, overrides) => ViewDef
+
+export function buildViewSpecs(defaultInputs: ViewConfigInputHash, optionsManager: OptionsManager, defTransformers: ViewDefTransformer[]): ViewSpecHash {
   let defaultConfigs = parseViewConfigs(defaultInputs)
   let overrideConfigs = parseViewConfigs(optionsManager.overrides.views)
   let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs)
 
   return mapHash(viewDefs, function(viewDef) {
-    return buildViewSpec(viewDef, overrideConfigs, optionsManager)
+    return buildViewSpec(viewDef, overrideConfigs, optionsManager, defTransformers)
   })
 }
 
-function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, optionsManager: OptionsManager): ViewSpec {
+function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, optionsManager: OptionsManager, defTransformers: ViewDefTransformer[]): ViewSpec {
   let durationInput =
     viewDef.overrides.duration ||
     viewDef.defaults.duration ||
@@ -83,6 +85,28 @@ function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, option
     }
   }
 
+  let overrides = assignTo(
+    {},
+    optionsManager.overrides,
+    singleUnitOverrides,
+    viewDef.overrides,
+    optionsManager.dynamicOverrides
+  )
+
+  // we do this really late because we want to pass in the overrides
+  // NOTE: can't change 'type' because already grabbed buttonTextMap/buttonTextKey
+  for (let defTransformer of defTransformers) {
+    viewDef = defTransformer(viewDef, overrides)
+  }
+
+  let defaults = assignTo(
+    {},
+    globalDefaults,
+    viewDef.defaults,
+    optionsManager.dirDefaults,
+    optionsManager.localeDefaults,
+  )
+
   return {
     type: viewDef.type,
     class: viewDef.class,
@@ -90,17 +114,7 @@ function buildViewSpec(viewDef: ViewDef, overrideConfigs: ViewConfigHash, option
     durationUnit,
     singleUnit,
 
-    options: assignTo(
-      {},
-      globalDefaults,
-      viewDef.defaults,
-      optionsManager.dirDefaults,
-      optionsManager.localeDefaults,
-      optionsManager.overrides,
-      singleUnitOverrides,
-      viewDef.overrides,
-      optionsManager.dynamicOverrides
-    ),
+    options: assignTo(defaults, overrides), // can be destructive to defaults
 
     buttonTextOverride:
       queryButtonText(optionsManager.dynamicOverrides) ||

+ 7 - 4
tests/automated/legacy/custom-view-class.js

@@ -52,9 +52,14 @@ describe('custom view class', function() {
     spyOn(CustomView.prototype, 'renderDateSelection').and.callThrough()
     spyOn(CustomView.prototype, 'unrenderDateSelection').and.callThrough()
 
-    FullCalendar.views.custom = CustomView
-
     initCalendar({
+      plugins: [
+        FullCalendar.createPlugin({
+          viewConfigs: {
+            custom: CustomView
+          }
+        })
+      ],
       defaultView: 'custom',
       defaultDate: '2014-12-25', // will end up being a single-day view
       events: [
@@ -82,8 +87,6 @@ describe('custom view class', function() {
     currentCalendar.unselect()
 
     expect(CustomView.prototype.unrenderDateSelection).toHaveBeenCalled()
-
-    delete FullCalendar.views.custom
   })
 
 })

+ 14 - 10
tests/automated/legacy/custom-view-duration.js

@@ -350,22 +350,26 @@ describe('custom view', function() {
     })
 
     it('falls back to view name when view lacks metadata', function() {
+      // also sorta tests plugin system
 
       class CrazyView extends FullCalendar.View {
       }
 
-      FullCalendar.views.crazy = CrazyView
+      initCalendar({
+        plugins: [
+          FullCalendar.createPlugin({
+            viewConfigs: {
+              crazy: CrazyView
+            }
+          })
+        ],
+        header: {
+          center: 'crazy,month'
+        },
+        defaultView: 'crazy'
+      })
 
-      var options = {
-        views: {}
-      }
-      options.header = {
-        center: 'crazy,month'
-      }
-      options.defaultView = 'crazy'
-      initCalendar(options)
       expect($('.fc-crazy-button')).toHaveText('crazy')
-      delete FullCalendar.views.crazy
     })
   })
 })

+ 14 - 8
tests/automated/legacy/views-specific-options.js

@@ -125,9 +125,14 @@ describe('view-specific options', function() {
     class SuperBasicView extends FullCalendar.BasicView {
     }
 
-    FullCalendar.views.superBasic = SuperBasicView
-
     initCalendar({
+      plugins: [
+        FullCalendar.createPlugin({
+          viewConfigs: {
+            superBasic: SuperBasicView
+          }
+        })
+      ],
       views: {
         basic: {
           titleFormat: function() { return 'special!!!' }
@@ -140,8 +145,6 @@ describe('view-specific options', function() {
       month: 'special!!!',
       basicDay: 'special!!!'
     })
-
-    delete FullCalendar.views.superBasic
   })
 
   it('can implicitly target an old-school View subclass', function() {
@@ -150,9 +153,14 @@ describe('view-specific options', function() {
     function SuperBasicView() { BasicView.apply(this, arguments) }
     SuperBasicView.prototype = Object.create(BasicView.prototype)
 
-    FullCalendar.views.superBasic = SuperBasicView
-
     initCalendar({
+      plugins: [
+        FullCalendar.createPlugin({
+          viewConfigs: {
+            superBasic: SuperBasicView
+          }
+        })
+      ],
       views: {
         basic: {
           titleFormat: function() { return 'special!!!' }
@@ -165,8 +173,6 @@ describe('view-specific options', function() {
       month: 'special!!!',
       basicDay: 'special!!!'
     })
-
-    delete FullCalendar.views.superBasic
   })
 
 })