Refactors view management in calendar component
Introduces ViewSelectorManager to handle view state and UI interactions Separates view logic from configuration management Adds explicit tracking of current calendar view Enhances view selection and state management Improves modularity and separation of concerns
This commit is contained in:
parent
c1e0da056c
commit
29ba0bfa37
6 changed files with 162 additions and 123 deletions
|
|
@ -1,119 +0,0 @@
|
|||
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
||||
import { Configuration } from '../configurations/CalendarConfig';
|
||||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
|
||||
|
||||
export class ViewManager {
|
||||
private eventBus: IEventBus;
|
||||
private config: Configuration;
|
||||
private currentView: CalendarView = 'week';
|
||||
private buttonListeners: Map<Element, EventListener> = new Map();
|
||||
|
||||
constructor(eventBus: IEventBus, config: Configuration) {
|
||||
this.eventBus = eventBus;
|
||||
this.config = config;
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
private setupEventListeners(): void {
|
||||
this.setupEventBusListeners();
|
||||
this.setupButtonHandlers();
|
||||
}
|
||||
|
||||
|
||||
private setupEventBusListeners(): void {
|
||||
this.eventBus.on(CoreEvents.INITIALIZED, () => {
|
||||
this.initializeView();
|
||||
});
|
||||
|
||||
this.eventBus.on(CoreEvents.DATE_CHANGED, () => {
|
||||
this.refreshCurrentView();
|
||||
});
|
||||
}
|
||||
|
||||
private setupButtonHandlers(): void {
|
||||
this.setupButtonGroup('swp-view-button[data-view]', 'data-view', (value) => {
|
||||
if (this.isValidView(value)) {
|
||||
this.changeView(value as CalendarView);
|
||||
}
|
||||
});
|
||||
|
||||
// NOTE: Workweek preset buttons are now handled by WorkweekPresetsManager
|
||||
}
|
||||
|
||||
|
||||
private setupButtonGroup(selector: string, attribute: string, handler: (value: string) => void): void {
|
||||
const buttons = document.querySelectorAll(selector);
|
||||
buttons.forEach(button => {
|
||||
const clickHandler = (event: Event) => {
|
||||
event.preventDefault();
|
||||
const value = button.getAttribute(attribute);
|
||||
if (value) {
|
||||
handler(value);
|
||||
}
|
||||
};
|
||||
button.addEventListener('click', clickHandler);
|
||||
this.buttonListeners.set(button, clickHandler);
|
||||
});
|
||||
}
|
||||
|
||||
private getViewButtons(): NodeListOf<Element> {
|
||||
return document.querySelectorAll('swp-view-button[data-view]');
|
||||
}
|
||||
|
||||
|
||||
private initializeView(): void {
|
||||
this.updateAllButtons();
|
||||
this.emitViewRendered();
|
||||
}
|
||||
|
||||
private changeView(newView: CalendarView): void {
|
||||
if (newView === this.currentView) return;
|
||||
|
||||
const previousView = this.currentView;
|
||||
this.currentView = newView;
|
||||
|
||||
this.updateAllButtons();
|
||||
|
||||
this.eventBus.emit(CoreEvents.VIEW_CHANGED, {
|
||||
previousView,
|
||||
currentView: newView
|
||||
});
|
||||
}
|
||||
private updateAllButtons(): void {
|
||||
this.updateButtonGroup(
|
||||
this.getViewButtons(),
|
||||
'data-view',
|
||||
this.currentView
|
||||
);
|
||||
|
||||
// NOTE: Workweek button states are now managed by WorkweekPresetsManager
|
||||
}
|
||||
|
||||
private updateButtonGroup(buttons: NodeListOf<Element>, attribute: string, activeValue: string): void {
|
||||
buttons.forEach(button => {
|
||||
const buttonValue = button.getAttribute(attribute);
|
||||
if (buttonValue === activeValue) {
|
||||
button.setAttribute('data-active', 'true');
|
||||
} else {
|
||||
button.removeAttribute('data-active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private emitViewRendered(): void {
|
||||
this.eventBus.emit(CoreEvents.VIEW_RENDERED, {
|
||||
view: this.currentView
|
||||
});
|
||||
}
|
||||
|
||||
private refreshCurrentView(): void {
|
||||
this.emitViewRendered();
|
||||
}
|
||||
|
||||
private isValidView(view: string): view is CalendarView {
|
||||
return ['day', 'week', 'month'].includes(view);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
152
src/managers/ViewSelectorManager.ts
Normal file
152
src/managers/ViewSelectorManager.ts
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import { CalendarView, IEventBus } from '../types/CalendarTypes';
|
||||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
import { Configuration } from '../configurations/CalendarConfig';
|
||||
|
||||
/**
|
||||
* ViewSelectorManager - Manages view selector UI and state
|
||||
*
|
||||
* RESPONSIBILITY:
|
||||
* ===============
|
||||
* This manager owns all logic related to the <swp-view-selector> UI element.
|
||||
* It follows the principle that each functional UI element has its own manager.
|
||||
*
|
||||
* RESPONSIBILITIES:
|
||||
* - Handles button clicks on swp-view-button elements
|
||||
* - Manages current view state (day/week/month)
|
||||
* - Validates view values
|
||||
* - Emits VIEW_CHANGED and VIEW_RENDERED events
|
||||
* - Updates button UI states (data-active attributes)
|
||||
*
|
||||
* EVENT FLOW:
|
||||
* ===========
|
||||
* User clicks button → changeView() → validate → update state → emit event → update UI
|
||||
*
|
||||
* IMPLEMENTATION STATUS:
|
||||
* ======================
|
||||
* - Week view: FULLY IMPLEMENTED
|
||||
* - Day view: NOT IMPLEMENTED (button exists but no rendering)
|
||||
* - Month view: NOT IMPLEMENTED (button exists but no rendering)
|
||||
*
|
||||
* SUBSCRIBERS:
|
||||
* ============
|
||||
* - GridRenderer: Uses view parameter (currently only supports 'week')
|
||||
* - Future: DayRenderer, MonthRenderer when implemented
|
||||
*/
|
||||
export class ViewSelectorManager {
|
||||
private eventBus: IEventBus;
|
||||
private config: Configuration;
|
||||
private buttonListeners: Map<Element, EventListener> = new Map();
|
||||
|
||||
constructor(eventBus: IEventBus, config: Configuration) {
|
||||
this.eventBus = eventBus;
|
||||
this.config = config;
|
||||
|
||||
this.setupButtonListeners();
|
||||
this.setupEventListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup click listeners on all view selector buttons
|
||||
*/
|
||||
private setupButtonListeners(): void {
|
||||
const buttons = document.querySelectorAll('swp-view-button[data-view]');
|
||||
|
||||
buttons.forEach(button => {
|
||||
const clickHandler = (event: Event) => {
|
||||
event.preventDefault();
|
||||
const view = button.getAttribute('data-view');
|
||||
if (view && this.isValidView(view)) {
|
||||
this.changeView(view as CalendarView);
|
||||
}
|
||||
};
|
||||
|
||||
button.addEventListener('click', clickHandler);
|
||||
this.buttonListeners.set(button, clickHandler);
|
||||
});
|
||||
|
||||
// Initialize button states
|
||||
this.updateButtonStates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup event bus listeners
|
||||
*/
|
||||
private setupEventListeners(): void {
|
||||
this.eventBus.on(CoreEvents.INITIALIZED, () => {
|
||||
this.initializeView();
|
||||
});
|
||||
|
||||
this.eventBus.on(CoreEvents.DATE_CHANGED, () => {
|
||||
this.refreshCurrentView();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the active view
|
||||
*/
|
||||
private changeView(newView: CalendarView): void {
|
||||
if (newView === this.config.currentView) {
|
||||
return; // No change
|
||||
}
|
||||
|
||||
const previousView = this.config.currentView;
|
||||
this.config.currentView = newView;
|
||||
|
||||
// Update button UI states
|
||||
this.updateButtonStates();
|
||||
|
||||
// Emit event for subscribers
|
||||
this.eventBus.emit(CoreEvents.VIEW_CHANGED, {
|
||||
previousView,
|
||||
currentView: newView
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update button states (data-active attributes)
|
||||
*/
|
||||
private updateButtonStates(): void {
|
||||
const buttons = document.querySelectorAll('swp-view-button[data-view]');
|
||||
|
||||
buttons.forEach(button => {
|
||||
const buttonView = button.getAttribute('data-view');
|
||||
|
||||
if (buttonView === this.config.currentView) {
|
||||
button.setAttribute('data-active', 'true');
|
||||
} else {
|
||||
button.removeAttribute('data-active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize view on INITIALIZED event
|
||||
*/
|
||||
private initializeView(): void {
|
||||
this.updateButtonStates();
|
||||
this.emitViewRendered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit VIEW_RENDERED event
|
||||
*/
|
||||
private emitViewRendered(): void {
|
||||
this.eventBus.emit(CoreEvents.VIEW_RENDERED, {
|
||||
view: this.config.currentView
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh current view on DATE_CHANGED event
|
||||
*/
|
||||
private refreshCurrentView(): void {
|
||||
this.emitViewRendered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if string is a valid CalendarView type
|
||||
*/
|
||||
private isValidView(view: string): view is CalendarView {
|
||||
return ['day', 'week', 'month'].includes(view);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue