feat: reconnect links after page update
This commit is contained in:
parent
d89bf1ab71
commit
26842ab62b
@ -66,8 +66,9 @@
|
||||
v-list-item-subtitle.red--text.caption {{$t('admin:storage.lastSyncAttempt', { time: $options.filters.moment(tgt.lastAttempt, 'from') })}}
|
||||
v-list-item-action
|
||||
v-menu
|
||||
v-btn(slot='activator', icon)
|
||||
v-icon(color='red') mdi-information
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(icon, v-on='on')
|
||||
v-icon(color='red') mdi-information
|
||||
v-card(width='450')
|
||||
v-toolbar(flat, color='red', dark, dense) {{$t('admin:storage.errorMsg')}}
|
||||
v-card-text {{tgt.message}}
|
||||
|
@ -107,7 +107,7 @@
|
||||
|
||||
//- PAGE ACTIONS
|
||||
|
||||
template(v-if='isAuthenticated && path')
|
||||
template(v-if='isAuthenticated && path && mode !== `edit`')
|
||||
v-menu(offset-y, bottom, nudge-bottom='30', transition='slide-y-transition')
|
||||
template(v-slot:activator='{ on: menu }')
|
||||
v-tooltip(bottom)
|
||||
|
@ -114,6 +114,9 @@ module.exports = class Page extends Model {
|
||||
this.updatedAt = new Date().toISOString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache Schema
|
||||
*/
|
||||
static get cacheSchema() {
|
||||
return new JSBinType({
|
||||
id: 'uint',
|
||||
@ -142,6 +145,8 @@ module.exports = class Page extends Model {
|
||||
|
||||
/**
|
||||
* Inject page metadata into contents
|
||||
*
|
||||
* @returns {string} Page Contents with Injected Metadata
|
||||
*/
|
||||
injectMetadata () {
|
||||
return pageHelper.injectPageMetadata(this)
|
||||
@ -149,6 +154,8 @@ module.exports = class Page extends Model {
|
||||
|
||||
/**
|
||||
* Get the page's file extension based on content type
|
||||
*
|
||||
* @returns {string} File Extension
|
||||
*/
|
||||
getFileExtension() {
|
||||
switch (this.contentType) {
|
||||
@ -166,6 +173,7 @@ module.exports = class Page extends Model {
|
||||
*
|
||||
* @param {String} raw Raw file contents
|
||||
* @param {String} contentType Content Type
|
||||
* @returns {Object} Parsed Page Metadata with Raw Content
|
||||
*/
|
||||
static parseMetadata (raw, contentType) {
|
||||
let result
|
||||
@ -204,6 +212,12 @@ module.exports = class Page extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a New Page
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise of the Page Model Instance
|
||||
*/
|
||||
static async createPage(opts) {
|
||||
const dupCheck = await WIKI.models.pages.query().select('id').where('localeCode', opts.locale).where('path', opts.path).first()
|
||||
if (dupCheck) {
|
||||
@ -259,9 +273,22 @@ module.exports = class Page extends Model {
|
||||
})
|
||||
}
|
||||
|
||||
// -> Reconnect Links
|
||||
await WIKI.models.pages.reconnectLinks({
|
||||
locale: page.localeCode,
|
||||
path: page.path,
|
||||
mode: 'create'
|
||||
})
|
||||
|
||||
return page
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an Existing Page
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise of the Page Model Instance
|
||||
*/
|
||||
static async updatePage(opts) {
|
||||
const ogPage = await WIKI.models.pages.query().findById(opts.id)
|
||||
if (!ogPage) {
|
||||
@ -314,6 +341,12 @@ module.exports = class Page extends Model {
|
||||
return page
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an Existing Page
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async deletePage(opts) {
|
||||
let page
|
||||
if (_.has(opts, 'id')) {
|
||||
@ -344,8 +377,98 @@ module.exports = class Page extends Model {
|
||||
page
|
||||
})
|
||||
}
|
||||
|
||||
// -> Reconnect Links
|
||||
await WIKI.models.pages.reconnectLinks({
|
||||
locale: page.localeCode,
|
||||
path: page.path,
|
||||
mode: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnect links to new/updated/deleted page
|
||||
*
|
||||
* @param {Object} opts - Page parameters
|
||||
* @param {string} opts.path - Page Path
|
||||
* @param {string} opts.locale - Page Locale Code
|
||||
* @param {string} [opts.sourcePath] - Previous Page Path (move only)
|
||||
* @param {string} [opts.sourceLocale] - Previous Page Locale Code (move only)
|
||||
* @param {string} opts.mode - Page Update mode (new, move, delete)
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async reconnectLinks (opts) {
|
||||
const pageHref = `/${opts.locale}/${opts.path}`
|
||||
let replaceArgs = {
|
||||
from: '',
|
||||
to: ''
|
||||
}
|
||||
switch (opts.mode) {
|
||||
case 'create':
|
||||
replaceArgs.from = `<a href="${pageHref}" class="is-internal-link is-invalid-page">`
|
||||
replaceArgs.to = `<a href="${pageHref}" class="is-internal-link is-valid-page">`
|
||||
break
|
||||
case 'move':
|
||||
const prevPageHref = `/${opts.sourceLocale}/${opts.sourcePath}`
|
||||
replaceArgs.from = `<a href="${prevPageHref}" class="is-internal-link is-invalid-page">`
|
||||
replaceArgs.to = `<a href="${pageHref}" class="is-internal-link is-valid-page">`
|
||||
break
|
||||
case 'delete':
|
||||
replaceArgs.from = `<a href="${pageHref}" class="is-internal-link is-valid-page">`
|
||||
replaceArgs.to = `<a href="${pageHref}" class="is-internal-link is-invalid-page">`
|
||||
break
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
let affectedHashes = []
|
||||
// -> Perform replace and return affected page hashes (POSTGRES, MSSQL only)
|
||||
if (WIKI.config.db.type === 'postgres' || WIKI.config.db.type === 'mssql') {
|
||||
affectedHashes = await WIKI.models.pages.query()
|
||||
.returning('hash')
|
||||
.patch({
|
||||
render: WIKI.models.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to])
|
||||
})
|
||||
.whereIn('pages.id', function () {
|
||||
this.select('pageLinks.pageId').from('pageLinks').where({
|
||||
'pageLinks.path': opts.path,
|
||||
'pageLinks.localeCode': opts.locale
|
||||
})
|
||||
})
|
||||
.pluck('hash')
|
||||
} else {
|
||||
// -> Perform replace, then query affected page hashes (MYSQL, MARIADB, SQLITE only)
|
||||
await WIKI.models.pages.query()
|
||||
.patch({
|
||||
render: WIKI.models.knex.raw('REPLACE(??, ?, ?)', ['render', replaceArgs.from, replaceArgs.to])
|
||||
})
|
||||
.whereIn('pages.id', function () {
|
||||
this.select('pageLinks.pageId').from('pageLinks').where({
|
||||
'pageLinks.path': opts.path,
|
||||
'pageLinks.localeCode': opts.locale
|
||||
})
|
||||
})
|
||||
affectedHashes = await WIKI.models.pages.query()
|
||||
.column('hash')
|
||||
.whereIn('pages.id', function () {
|
||||
this.select('pageLinks.pageId').from('pageLinks').where({
|
||||
'pageLinks.path': opts.path,
|
||||
'pageLinks.localeCode': opts.locale
|
||||
})
|
||||
})
|
||||
.pluck('hash')
|
||||
}
|
||||
for (const hash of affectedHashes) {
|
||||
await WIKI.models.pages.deletePageFromCache({ hash })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the rendering of a page
|
||||
*
|
||||
* @param {Object} page Page Model Instance
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async renderPage(page) {
|
||||
const renderJob = await WIKI.scheduler.registerJob({
|
||||
name: 'render-page',
|
||||
@ -355,6 +478,12 @@ module.exports = class Page extends Model {
|
||||
return renderJob.finished
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an Existing Page from Cache if possible, from DB otherwise and save render to Cache
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise of the Page Model Instance
|
||||
*/
|
||||
static async getPage(opts) {
|
||||
// -> Get from cache first
|
||||
let page = await WIKI.models.pages.getPageFromCache(opts)
|
||||
@ -375,6 +504,12 @@ module.exports = class Page extends Model {
|
||||
return page
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an Existing Page from the Database
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise of the Page Model Instance
|
||||
*/
|
||||
static async getPageFromDb(opts) {
|
||||
const queryModeID = _.isNumber(opts)
|
||||
try {
|
||||
@ -426,6 +561,12 @@ module.exports = class Page extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a Page Model Instance to Cache
|
||||
*
|
||||
* @param {Object} page Page Model Instance
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async savePageToCache(page) {
|
||||
const cachePath = path.join(process.cwd(), `data/cache/${page.hash}.bin`)
|
||||
await fs.outputFile(cachePath, WIKI.models.pages.cacheSchema.encode({
|
||||
@ -448,6 +589,12 @@ module.exports = class Page extends Model {
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an Existing Page from Cache
|
||||
*
|
||||
* @param {Object} opts Page Properties
|
||||
* @returns {Promise} Promise of the Page Model Instance
|
||||
*/
|
||||
static async getPageFromCache(opts) {
|
||||
const pageHash = pageHelper.generateHash({ path: opts.path, locale: opts.locale, privateNS: opts.isPrivate ? 'TODO' : '' })
|
||||
const cachePath = path.join(process.cwd(), `data/cache/${pageHash}.bin`)
|
||||
@ -470,14 +617,32 @@ module.exports = class Page extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an Existing Page from Cache
|
||||
*
|
||||
* @param {Object} page Page Model Instance
|
||||
* @param {string} page.hash Hash of the Page
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async deletePageFromCache(page) {
|
||||
return fs.remove(path.join(process.cwd(), `data/cache/${page.hash}.bin`))
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the contents of the Cache
|
||||
*/
|
||||
static async flushCache() {
|
||||
return fs.emptyDir(path.join(process.cwd(), `data/cache`))
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate all pages from a source locale to the target locale
|
||||
*
|
||||
* @param {Object} opts Migration properties
|
||||
* @param {string} opts.sourceLocale Source Locale Code
|
||||
* @param {string} opts.targetLocale Target Locale Code
|
||||
* @returns {Promise} Promise with no value
|
||||
*/
|
||||
static async migrateToLocale({ sourceLocale, targetLocale }) {
|
||||
return WIKI.models.pages.query()
|
||||
.patch({
|
||||
@ -491,6 +656,12 @@ module.exports = class Page extends Model {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean raw HTML from content for use in search engines
|
||||
*
|
||||
* @param {string} rawHTML Raw HTML
|
||||
* @returns {string} Cleaned Content Text
|
||||
*/
|
||||
static cleanHTML(rawHTML = '') {
|
||||
return striptags(rawHTML || '')
|
||||
.replace(emojiRegex(), '')
|
||||
|
Loading…
Reference in New Issue
Block a user