0281a30fb4
closes https://github.com/TryGhost/Team/issues/2463 - it merges the similar history events by adding additional properties to the events data - `skip` was added to the current event when the next event is similar to it, so that the event isn't output on the frontend - `count` was added to the last item of the similar events and it's used for outputting the number of repeated similar events
133 lines
3.9 KiB
JavaScript
133 lines
3.9 KiB
JavaScript
import moment from 'moment-timezone';
|
|
import {Resource} from 'ember-could-get-used-to-this';
|
|
import {TrackedArray} from 'tracked-built-ins';
|
|
import {action} from '@ember/object';
|
|
import {didCancel, task} from 'ember-concurrency';
|
|
import {inject as service} from '@ember/service';
|
|
import {tracked} from '@glimmer/tracking';
|
|
|
|
export default class HistoryEventFetcher extends Resource {
|
|
@service ajax;
|
|
@service ghostPaths;
|
|
@service store;
|
|
|
|
@tracked data = new TrackedArray([]);
|
|
@tracked isLoading = false;
|
|
@tracked isError = false;
|
|
@tracked errorMessage = null;
|
|
@tracked hasReachedEnd = false;
|
|
|
|
cursor = null;
|
|
|
|
get value() {
|
|
return {
|
|
isLoading: this.isLoading,
|
|
isError: this.isError,
|
|
errorMessage: this.errorMessage,
|
|
data: this.data,
|
|
loadNextPage: this.loadNextPage,
|
|
hasReachedEnd: this.hasReachedEnd
|
|
};
|
|
}
|
|
|
|
async setup() {
|
|
this.cursor = moment.utc().format('YYYY-MM-DD HH:mm:ss');
|
|
let filter = `created_at:<'${this.cursor}'`;
|
|
|
|
if (this.args.named.filter) {
|
|
filter += `+${this.args.named.filter}`;
|
|
}
|
|
|
|
try {
|
|
await this.loadEventsTask.perform({filter});
|
|
} catch (e) {
|
|
if (!didCancel(e)) {
|
|
// re-throw the non-cancelation error
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
@action
|
|
loadNextPage() {
|
|
// NOTE: assumes data is always ordered by created_at desc
|
|
const lastEvent = this.data[this.data.length - 1];
|
|
|
|
if (!lastEvent?.created_at) {
|
|
this.hasReachedEnd = true;
|
|
return;
|
|
}
|
|
|
|
const cursor = moment.utc(lastEvent.created_at).format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
if (cursor === this.cursor) {
|
|
this.hasReachedEnd = true;
|
|
return;
|
|
}
|
|
|
|
this.cursor = cursor;
|
|
let filter = `created_at:<'${this.cursor}'`;
|
|
|
|
if (this.args.named.filter) {
|
|
filter += `+${this.args.named.filter}`;
|
|
}
|
|
|
|
this.loadEventsTask.perform({filter});
|
|
}
|
|
|
|
@task
|
|
*loadEventsTask(queryParams) {
|
|
try {
|
|
this.isLoading = true;
|
|
|
|
const url = this.ghostPaths.url.api('actions');
|
|
const data = Object.assign({}, queryParams, {
|
|
include: 'actor,resource',
|
|
limit: this.args.named.pageSize
|
|
});
|
|
const {actions} = yield this.ajax.request(url, {data});
|
|
|
|
if (actions.length < data.limit) {
|
|
this.hasReachedEnd = true;
|
|
}
|
|
|
|
let count = 1;
|
|
|
|
actions.reverse().forEach((a, index) => {
|
|
const nextAction = actions[index + 1] || null;
|
|
|
|
// depending on the similarity, add additional properties to be used on the frontend for grouping
|
|
// skip - used for hiding the event on the frontend
|
|
// count - the number of similar events which is added to the last item
|
|
if (nextAction || (!nextAction && actions[index - 1].skip)) {
|
|
if (nextAction && a.resource_id === nextAction.resource_id && a.event === nextAction.event) {
|
|
a.skip = true;
|
|
count += 1;
|
|
} else {
|
|
if (count > 1) {
|
|
a.count = count.toString();
|
|
count = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
a.context = JSON.parse(a.context);
|
|
});
|
|
|
|
this.data.push(...actions.reverse());
|
|
} catch (e) {
|
|
this.isError = true;
|
|
|
|
const errorMessage = e.payload?.errors?.[0]?.message;
|
|
if (errorMessage) {
|
|
this.errorMessage = errorMessage;
|
|
}
|
|
|
|
// TODO: log to Sentry
|
|
console.error(e); // eslint-disable-line
|
|
} finally {
|
|
this.isLoading = false;
|
|
}
|
|
}
|
|
}
|