Skip to content

Commit

Permalink
refactor: All asynchronous public methods should return a Promise
Browse files Browse the repository at this point in the history
  • Loading branch information
wa0x6e committed Dec 24, 2022
1 parent 70c67a1 commit 64ce7b1
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 55 deletions.
116 changes: 63 additions & 53 deletions src/CalHeatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ export default class CalHeatmap {
helpers: Helpers;

constructor() {
// Default settings
// Default options
this.options = new Options();

// Init the helpers with the default settings
// Init the helpers with the default options
this.helpers = createHelpers(this.options);
this.templateCollection = new TemplateCollection(
this.helpers,
Expand Down Expand Up @@ -80,11 +80,12 @@ export default class CalHeatmap {
/**
* Setup and paint the calendar with the given options
*
* @param {Object} settings Options
* @return {boolean} True, unless there's an error
* @param {Object} options The Options object
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
paint(settings: DeepPartial<OptionsType>): boolean {
this.options.init(settings);
paint(options?: DeepPartial<OptionsType>): Promise<unknown> {
this.options.init(options);

// Refresh the helpers with the correct options
this.helpers = createHelpers(this.options);
Expand All @@ -93,9 +94,7 @@ export default class CalHeatmap {
try {
validate(this.templateCollection, this.options.options);
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
return false;
return Promise.reject(error);
}

this.calendarPainter.setup();
Expand All @@ -109,87 +108,92 @@ export default class CalHeatmap {
this.options.options.range,
),
);
this.calendarPainter.paint();

this.fill();

return true;
return Promise.allSettled([
this.calendarPainter.paint(),
this.fill(),
]);
}

/**
* Add a new subDomainTemplate
*
* @since 4.0.0
* @param {Array<SubDomainTemplate> | SubDomainTemplate} templates
* @param {SubDomainTemplate[] | SubDomainTemplate} templates
* A single, or an array of SubDomainTemplate object
* @return void
*/
addTemplates(templates: Template | Template[]) {
addTemplates(templates: Template | Template[]): void {
this.templateCollection.add(templates);
}

/**
* Shift the calendar by n domains forward
*
* @param {number} Number of domain interval to shift
* @param {number} n Number of domain intervals to shift forward
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
next(n: number = 1) {
next(n: number = 1): Promise<unknown> {
const loadDirection = this.navigator.loadNewDomains(
this.createDomainCollection(this.domainCollection.max, n + 1).slice(n),
ScrollDirection.SCROLL_FORWARD,
);
const promise = this.calendarPainter.paint(loadDirection);
// @TODO: Update only newly inserted domains
this.fill();

return promise;
return Promise.allSettled([
this.calendarPainter.paint(loadDirection),
this.fill(),
]);
}

/**
* Shift the calendar by n domains backward
*
* @param {number} Number of domain interval to shift
* @param {number} n Number of domain intervals to shift backward
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
previous(n: number = 1) {
previous(n: number = 1): Promise<unknown> {
const loadDirection = this.navigator.loadNewDomains(
this.createDomainCollection(this.domainCollection.min, -n),
ScrollDirection.SCROLL_BACKWARD,
);
const promise = this.calendarPainter.paint(loadDirection);
// @TODO: Update only newly inserted domains
this.fill();

return promise;
return Promise.allSettled([
this.calendarPainter.paint(loadDirection),
this.fill(),
]);
}

/**
* Jump directly to a specific date
*
* JumpTo will scroll the calendar until the wanted domain with the specified
* date is visible. Unless you set reset to true, the wanted domain
* will not necessarily be the first (leftmost) domain of the calendar.
* will not necessarily be the first domain of the calendar.
*
* @param Date date Jump to the domain containing that date
* @param {Date} date Jump to the domain containing that date
* @param {boolean} reset Whether the wanted domain
* should be the first domain of the calendar
* @param {boolean} True of the calendar was scrolled
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
jumpTo(date: Date, reset: boolean = false) {
const loadDirection = this.navigator.jumpTo(date, reset);
const promise = this.calendarPainter.paint(loadDirection);
// @TODO: Update only newly inserted domains
this.fill();

return promise;
jumpTo(date: Date, reset: boolean = false): Promise<unknown> {
return Promise.allSettled([
this.calendarPainter.paint(this.navigator.jumpTo(date, reset)),
this.fill(),
]);
}

/**
* Fill the calendar with some data
* Fill the calendar with the given data
*
* @param {object|string} dataSource The calendar's datasource,
* same type as this.options.data.source
* @param {Object|string} dataSource The calendar's datasource,
* same type as `options.data.source`
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
fill(dataSource = this.options.options.data.source): void {
fill(dataSource = this.options.options.data.source): Promise<unknown> {
const { options } = this.options;
const template = this.templateCollection;
const endDate = this.helpers.DateHelper.intervals(
Expand All @@ -204,24 +208,29 @@ export default class CalHeatmap {
endDate,
);

dataPromise.then((data: any) => {
this.domainCollection.fill(
data,
options.data,
this.domainCollection.min,
endDate,
template.get(options.domain.type)!.extractUnit,
template.get(options.subDomain.type)!.extractUnit,
);
this.populator.populate();
return new Promise((resolve, reject) => {
dataPromise.then((data: any) => {
this.domainCollection.fill(
data,
options.data,
this.domainCollection.min,
endDate,
template.get(options.domain.type)!.extractUnit,
template.get(options.subDomain.type)!.extractUnit,
);
this.populator.populate();
resolve(null);
}, (error) => {
reject(error);
});
});
}

/**
* Listener for all events
*
* @since 4.0.0
* @param {string} eventName Name of the event to listen to
* @param {string} eventName Name of the event to listen to
* @param {function} Callback function to execute on event trigger
* @return void
*/
Expand All @@ -233,7 +242,8 @@ export default class CalHeatmap {
* Destroy the calendar
*
* @since 3.3.6
* @return Promise
* @return A Promise, which will fulfill once all the underlying asynchronous
* tasks settle, whether resolved or rejected.
*/
destroy(): Promise<unknown> {
return this.calendarPainter.destroy();
Expand Down
4 changes: 4 additions & 0 deletions src/calendar/CalendarPainter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ export default class CalendarPainter {
}

destroy(): Promise<unknown> {
if (!this.root) {
return Promise.resolve();
}

this.legendPainter.destroy();
this.tooltip.destroy();

Expand Down
4 changes: 2 additions & 2 deletions src/options/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,10 +306,10 @@ export default class Options {
return true;
}

init(settings: any): void {
init(opts: any): void {
this.options = {
// eslint-disable-next-line arrow-body-style
...mergeWith(this.options, settings, (objValue, srcValue) => {
...mergeWith(this.options, opts, (objValue, srcValue) => {
return Array.isArray(srcValue) ? srcValue : undefined;
}),
};
Expand Down
Loading

0 comments on commit 64ce7b1

Please sign in to comment.