From ab463fcae183f16ebc8a8a0616601c7893505eff Mon Sep 17 00:00:00 2001 From: Nick Date: Mon, 2 Sep 2019 18:32:33 -0400 Subject: [PATCH] feat: tags on page fetch + pageLinks table schema --- client/themes/default/components/page.vue | 6 +- server/db/migrations-sqlite/2.0.0-beta.293.js | 13 +++ server/db/migrations/2.0.0-beta.293.js | 19 ++++ server/models/pages.js | 102 +++++++++++------- server/views/page.pug | 2 +- 5 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 server/db/migrations-sqlite/2.0.0-beta.293.js create mode 100644 server/db/migrations/2.0.0-beta.293.js diff --git a/client/themes/default/components/page.vue b/client/themes/default/components/page.vue index 7927e9a9..ed389de8 100644 --- a/client/themes/default/components/page.vue +++ b/client/themes/default/components/page.vue @@ -77,11 +77,11 @@ label color='teal lighten-5' v-for='(tag, idx) in tags' - :href='`/t/` + tag.slug' - :key='tag.slug' + :href='`/t/` + tag.tag' + :key='tag.tag' ) v-icon(color='teal', left, small) mdi-label - span.teal--text.text--darken-2 {{tag.text}} + span.teal--text.text--darken-2 {{tag.title}} v-card.mb-5 .pa-5 diff --git a/server/db/migrations-sqlite/2.0.0-beta.293.js b/server/db/migrations-sqlite/2.0.0-beta.293.js new file mode 100644 index 00000000..85fb8666 --- /dev/null +++ b/server/db/migrations-sqlite/2.0.0-beta.293.js @@ -0,0 +1,13 @@ +exports.up = knex => { + return knex.schema + .createTable('pageLinks', table => { + table.increments('id').primary() + table.integer('sourcePageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') + table.integer('targetPageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') + }) +} + +exports.down = knex => { + return knex.schema + .dropTableIfExists('pageLinks') +} diff --git a/server/db/migrations/2.0.0-beta.293.js b/server/db/migrations/2.0.0-beta.293.js new file mode 100644 index 00000000..dd8339f6 --- /dev/null +++ b/server/db/migrations/2.0.0-beta.293.js @@ -0,0 +1,19 @@ +/* global WIKI */ + +exports.up = knex => { + const dbCompat = { + charset: (WIKI.config.db.type === `mysql` || WIKI.config.db.type === `mariadb`) + } + return knex.schema + .createTable('pageLinks', table => { + if (dbCompat.charset) { table.charset('utf8mb4') } + table.increments('id').primary() + table.integer('sourcePageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') + table.integer('targetPageId').unsigned().references('id').inTable('pages').onDelete('CASCADE') + }) +} + +exports.down = knex => { + return knex.schema + .dropTableIfExists('pageLinks') +} diff --git a/server/models/pages.js b/server/models/pages.js index e98dd22e..95644b52 100644 --- a/server/models/pages.js +++ b/server/models/pages.js @@ -63,6 +63,18 @@ module.exports = class Page extends Model { to: 'tags.id' } }, + links: { + relation: Model.ManyToManyRelation, + modelClass: Page, + join: { + from: 'pages.id', + through: { + from: 'pageLinks.sourcePageId', + to: 'pageLinks.targetPageId' + }, + to: 'pages.id' + } + }, author: { relation: Model.BelongsToOneRelation, modelClass: require('./users'), @@ -120,6 +132,12 @@ module.exports = class Page extends Model { publishEndDate: 'string', publishStartDate: 'string', render: 'string', + tags: [ + { + tag: 'string', + title: 'string' + } + ], title: 'string', toc: 'string', updatedAt: 'string' @@ -349,42 +367,53 @@ module.exports = class Page extends Model { static async getPageFromDb(opts) { const queryModeID = _.isNumber(opts) - return WIKI.models.pages.query() - .column([ - 'pages.*', - { - authorName: 'author.name', - authorEmail: 'author.email', - creatorName: 'creator.name', - creatorEmail: 'creator.email' - } - ]) - .joinRelation('author') - .joinRelation('creator') - .where(queryModeID ? { - 'pages.id': opts - } : { - 'pages.path': opts.path, - 'pages.localeCode': opts.locale - }) - // .andWhere(builder => { - // if (queryModeID) return - // builder.where({ - // 'pages.isPublished': true - // }).orWhere({ - // 'pages.isPublished': false, - // 'pages.authorId': opts.userId - // }) - // }) - // .andWhere(builder => { - // if (queryModeID) return - // if (opts.isPrivate) { - // builder.where({ 'pages.isPrivate': true, 'pages.privateNS': opts.privateNS }) - // } else { - // builder.where({ 'pages.isPrivate': false }) - // } - // }) - .first() + try { + return WIKI.models.pages.query() + .column([ + 'pages.*', + { + authorName: 'author.name', + authorEmail: 'author.email', + creatorName: 'creator.name', + creatorEmail: 'creator.email' + } + ]) + .joinRelation('author') + .joinRelation('creator') + .eagerAlgorithm(Model.JoinEagerAlgorithm) + .eager('tags(selectTags)', { + selectTags: builder => { + builder.select('tag', 'title') + } + }) + .where(queryModeID ? { + 'pages.id': opts + } : { + 'pages.path': opts.path, + 'pages.localeCode': opts.locale + }) + // .andWhere(builder => { + // if (queryModeID) return + // builder.where({ + // 'pages.isPublished': true + // }).orWhere({ + // 'pages.isPublished': false, + // 'pages.authorId': opts.userId + // }) + // }) + // .andWhere(builder => { + // if (queryModeID) return + // if (opts.isPrivate) { + // builder.where({ 'pages.isPrivate': true, 'pages.privateNS': opts.privateNS }) + // } else { + // builder.where({ 'pages.isPrivate': false }) + // } + // }) + .first() + } catch (err) { + WIKI.logger.warn(err) + throw err + } } static async savePageToCache(page) { @@ -402,6 +431,7 @@ module.exports = class Page extends Model { publishEndDate: page.publishEndDate, publishStartDate: page.publishStartDate, render: page.render, + tags: page.tags.map(t => _.pick(t, ['tag', 'title'])), title: page.title, toc: _.isString(page.toc) ? page.toc : JSON.stringify(page.toc), updatedAt: page.updatedAt diff --git a/server/views/page.pug b/server/views/page.pug index e3eb68da..83ca6328 100644 --- a/server/views/page.pug +++ b/server/views/page.pug @@ -13,7 +13,7 @@ block body path=page.path title=page.title description=page.description - tags=page.tags + :tags=page.tags created-at=page.createdAt updated-at=page.updatedAt author-name=page.authorName