Skip to content

Commit

Permalink
Merge pull request #187 from CityOfDetroit/feature.182.2
Browse files Browse the repository at this point in the history
Support custom event/filter background colors
  • Loading branch information
jedgar1mx authored Mar 20, 2024
2 parents a33a1f4 + 21a9b7b commit 2656c7a
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 2 deletions.
98 changes: 96 additions & 2 deletions src/components/organisms/Calendar/Calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,44 @@ class Calendar extends HTMLElement {
// eslint-disable-next-line no-console
console.error(`Failed to parse list of events:\n${eventsJSON}`);
}
events = this.applyEventPropertyRules(events);
const eventSource = {
id: 'eventsArray',
events: events,
};
return eventSource;
}

/**
* Apply additional event properties as defined by event
* property rules supplied in the `event-property-rules` attribute.
*
* @param {Object[]} events - An array of pre-parsed
* event objects. See https://fullcalendar.io/docs/event-parsing.
* @returns {Object[]} An array of pre-parsed event objects.
*/
applyEventPropertyRules(events) {
const eventPropertyRules = this.getEventPropertyRules();
for (const property in eventPropertyRules) {
events = events.map((event) => {
const eventPropertyValue = event[property];
if (
!Object.prototype.hasOwnProperty.call(
eventPropertyRules[property],
eventPropertyValue,
)
) {
return event;
}
return {
...event,
...eventPropertyRules[property][eventPropertyValue],
};
});
}
return events;
}

/**
* Replaces the 'eventsArray' event source with a new event source.
*
Expand Down Expand Up @@ -132,7 +163,6 @@ class Calendar extends HTMLElement {
* @param {string} [newFiltersJSON=null] - A JSON serialized array of event filter definitions.
* If null, filters will be fetched from the 'event-filters' attribute on the
* component instead.
* @returns void
*/
buildEventFilters(newFiltersJSON = null) {
const calendarFilterElt = this.shadowRoot.getElementById('calendarFilters');
Expand Down Expand Up @@ -164,7 +194,6 @@ class Calendar extends HTMLElement {
* @param {HTMLElement} calendarFilterElt - An HTML element to be used
* as the container for the event filter created.
* @param {Object} filter - A single event filter object.
* @returns void
*/
buildEventFilter(calendarFilterElt, filter) {
switch (filter.type) {
Expand Down Expand Up @@ -198,6 +227,8 @@ class Calendar extends HTMLElement {
const radioButtonLabel = document.createElement('label');
radioButtonLabel.setAttribute('for', value);
radioButtonLabel.classList.add('btn', 'btn-primary');
const eventRule = this.getEventPropertyRule(filter.key, value);
this.applyFilterPropertyRule(radioButtonLabel, eventRule);
radioButtonLabel.innerText = value;
radioButtonContainer.appendChild(radioButtonLabel);
radioFiltersContainer.appendChild(radioButtonContainer);
Expand All @@ -214,6 +245,31 @@ class Calendar extends HTMLElement {
}
}

/**
* Applies necessary styles based on the event property rule supplied.
*
* @param {HTMLElement} filterElement - The HTML element where the filter
* property rule will be applied.
* @param {Object} eventPropertyRule - An event property rule to be used as
* the filter property.
*/
applyFilterPropertyRule(filterElement, eventPropertyRule) {
for (const property in eventPropertyRule) {
switch (property) {
case 'backgroundColor': {
filterElement.style.backgroundColor = eventPropertyRule[property];
break;
}
default: {
// TODO: Introduce proper error logging.
// eslint-disable-next-line no-console
console.warn(`Ignoring unsupported filter property: ${property}`);
return;
}
}
}
}

/**
* Handles filter element events by filter down events to the
* user-selected criteria.
Expand All @@ -237,6 +293,44 @@ class Calendar extends HTMLElement {
this.updateEventArraySource(JSON.stringify(events));
}

/**
* Get an event/filter property and value for a given event/filter key and
* value.
* @param {string} eventKey - The event key used to filter down filters
* and events for rules.
* @param {string} eventKeyValue - The value at the sepcified event key
* used to filter down filters and events for rules.
* @returns Object - An event property rule consisting of
* property keys and values to be applied to events and filters.
*/
getEventPropertyRule(eventKey, eventKeyValue) {
const rules = this.getEventPropertyRules();
return rules[eventKey][eventKeyValue] ?? {};
}

/**
* Get all the event property rules from the `event-property-rules`
* attribute.
* @returns Object - All event property rules.
*/
getEventPropertyRules() {
const eventPropertyRulesJSON = this.getAttribute('event-property-rules');
if (!eventPropertyRulesJSON) {
return {};
}
let eventPropertyRules = {};
try {
eventPropertyRules = JSON.parse(eventPropertyRulesJSON ?? '{}');
} catch (error) {
// TODO: Introduce proper error logging.
// eslint-disable-next-line no-console
console.error(
`Failed to parse event property rules:\n${eventPropertyRulesJSON}`,
);
}
return eventPropertyRules;
}

attributeChangedCallback(name, oldValue, newValue) {
if (name in Calendar.observedAttributeCbs) {
this.handleObservedAttribute(
Expand Down
33 changes: 33 additions & 0 deletions src/stories/calendar.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ export default {
}
}`,
},
eventPropertyRules: {
control: { type: 'text' },
description: `A JSON object of event properties to be applied to events matching
a specific criteria. The keys and value of the object correspond to keys and
values of the event and filters where the properties are applied. The object
associated with each key is a list of event properties and their values
as defined in https://fullcalendar.io/docs/event-object.
The rules should take the following form:
{
event_field_key: {
event_field_key_value: {
backgroundColor: '#000',
}
}
}
`,
},
},
args: {
events: JSON.stringify([
Expand Down Expand Up @@ -60,6 +77,19 @@ export default {
],
},
}),
eventPropertyRules: JSON.stringify({
location: {
'Say Detroit Play Center': {
backgroundColor: '#ff6c37',
},
'Senior Facility': {
backgroundColor: '#1f71bf',
},
'Detroit Housing Commission': {
backgroundColor: '#1ed760',
},
},
}),
},
};

Expand All @@ -70,6 +100,9 @@ const Template = (args) => {
if (args.eventFilters) {
calendarElt.setAttribute('event-filters', args.eventFilters);
}
if (args.eventPropertyRules) {
calendarElt.setAttribute('event-property-rules', args.eventPropertyRules);
}
return calendarElt;
};

Expand Down

0 comments on commit 2656c7a

Please sign in to comment.