123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import { Model } from 'objection'
- import { get, reduce, reverse } from 'lodash-es'
- import { DateTime, Duration } from 'luxon'
- import { Locale } from './locales.mjs'
- import { Page } from './pages.mjs'
- import { User } from './users.mjs'
- import { Tag } from './tags.mjs'
- /**
- * Page History model
- */
- export class PageHistory extends Model {
- static get tableName() { return 'pageHistory' }
- static get jsonSchema () {
- return {
- type: 'object',
- required: ['path', 'title'],
- properties: {
- id: {type: 'integer'},
- path: {type: 'string'},
- hash: {type: 'string'},
- title: {type: 'string'},
- description: {type: 'string'},
- publishState: {type: 'string'},
- publishStartDate: {type: 'string'},
- publishEndDate: {type: 'string'},
- content: {type: 'string'},
- contentType: {type: 'string'},
- createdAt: {type: 'string'}
- }
- }
- }
- static get relationMappings() {
- return {
- tags: {
- relation: Model.ManyToManyRelation,
- modelClass: Tag,
- join: {
- from: 'pageHistory.id',
- through: {
- from: 'pageHistoryTags.pageId',
- to: 'pageHistoryTags.tagId'
- },
- to: 'tags.id'
- }
- },
- page: {
- relation: Model.BelongsToOneRelation,
- modelClass: Page,
- join: {
- from: 'pageHistory.pageId',
- to: 'pages.id'
- }
- },
- author: {
- relation: Model.BelongsToOneRelation,
- modelClass: User,
- join: {
- from: 'pageHistory.authorId',
- to: 'users.id'
- }
- }
- }
- }
- $beforeInsert() {
- this.createdAt = new Date().toISOString()
- }
- /**
- * Create Page Version
- */
- static async addVersion(opts) {
- await WIKI.db.pageHistory.query().insert({
- action: opts.historyData?.action ?? 'updated',
- affectedFields: JSON.stringify(opts.historyData?.affectedFields ?? []),
- alias: opts.alias,
- config: JSON.stringify(opts.config ?? {}),
- authorId: opts.authorId,
- content: opts.content,
- contentType: opts.contentType,
- description: opts.description,
- editor: opts.editor,
- hash: opts.hash,
- icon: opts.icon,
- locale: opts.locale,
- pageId: opts.id,
- path: opts.path,
- publishEndDate: opts.publishEndDate?.toISO(),
- publishStartDate: opts.publishStartDate?.toISO(),
- publishState: opts.publishState,
- reason: opts.historyData?.reason,
- relations: JSON.stringify(opts.relations ?? []),
- render: opts.render,
- scripts: JSON.stringify(opts.scripts ?? {}),
- siteId: opts.siteId,
- title: opts.title,
- toc: JSON.stringify(opts.toc ?? []),
- versionDate: opts.versionDate
- })
- }
- /**
- * Get Page Version
- */
- static async getVersion({ pageId, versionId }) {
- const version = await WIKI.db.pageHistory.query()
- .column([
- 'pageHistory.path',
- 'pageHistory.title',
- 'pageHistory.description',
- 'pageHistory.isPublished',
- 'pageHistory.publishStartDate',
- 'pageHistory.publishEndDate',
- 'pageHistory.content',
- 'pageHistory.contentType',
- 'pageHistory.createdAt',
- 'pageHistory.action',
- 'pageHistory.authorId',
- 'pageHistory.pageId',
- 'pageHistory.versionDate',
- {
- versionId: 'pageHistory.id',
- editor: 'pageHistory.editorKey',
- locale: 'pageHistory.locale',
- authorName: 'author.name'
- }
- ])
- .joinRelated('author')
- .where({
- 'pageHistory.id': versionId,
- 'pageHistory.pageId': pageId
- }).first()
- if (version) {
- return {
- ...version,
- updatedAt: version.createdAt || null,
- tags: []
- }
- } else {
- return null
- }
- }
- /**
- * Get History Trail of a Page
- */
- static async getHistory({ pageId, offsetPage = 0, offsetSize = 100 }) {
- const history = await WIKI.db.pageHistory.query()
- .column([
- 'pageHistory.id',
- 'pageHistory.path',
- 'pageHistory.authorId',
- 'pageHistory.action',
- 'pageHistory.versionDate',
- {
- authorName: 'author.name'
- }
- ])
- .joinRelated('author')
- .where({
- 'pageHistory.pageId': pageId
- })
- .orderBy('pageHistory.versionDate', 'desc')
- .page(offsetPage, offsetSize)
- let prevPh = null
- const upperLimit = (offsetPage + 1) * offsetSize
- if (history.total >= upperLimit) {
- prevPh = await WIKI.db.pageHistory.query()
- .column([
- 'pageHistory.id',
- 'pageHistory.path',
- 'pageHistory.authorId',
- 'pageHistory.action',
- 'pageHistory.versionDate',
- {
- authorName: 'author.name'
- }
- ])
- .joinRelated('author')
- .where({
- 'pageHistory.pageId': pageId
- })
- .orderBy('pageHistory.versionDate', 'desc')
- .offset((offsetPage + 1) * offsetSize)
- .limit(1)
- .first()
- }
- return {
- trail: reduce(reverse(history.results), (res, ph) => {
- let actionType = 'edit'
- let valueBefore = null
- let valueAfter = null
- if (!prevPh && history.total < upperLimit) {
- actionType = 'initial'
- } else if (get(prevPh, 'path', '') !== ph.path) {
- actionType = 'move'
- valueBefore = get(prevPh, 'path', '')
- valueAfter = ph.path
- }
- res.unshift({
- versionId: ph.id,
- authorId: ph.authorId,
- authorName: ph.authorName,
- actionType,
- valueBefore,
- valueAfter,
- versionDate: ph.versionDate
- })
- prevPh = ph
- return res
- }, []),
- total: history.total
- }
- }
- /**
- * Purge history older than X
- *
- * @param {String} olderThan ISO 8601 Duration
- */
- static async purge (olderThan) {
- const dur = Duration.fromISO(olderThan)
- const olderThanISO = DateTime.utc().minus(dur)
- await WIKI.db.pageHistory.query().where('versionDate', '<', olderThanISO.toISO()).del()
- }
- }
|