feat: page published state + comments localization
This commit is contained in:
parent
83b83a7510
commit
4855051d87
@ -3,7 +3,7 @@
|
||||
v-textarea#discussion-new(
|
||||
outlined
|
||||
flat
|
||||
placeholder='Write a new comment...'
|
||||
:placeholder='$t(`common:comments.newPlaceholder`)'
|
||||
auto-grow
|
||||
dense
|
||||
rows='3'
|
||||
@ -19,7 +19,7 @@
|
||||
outlined
|
||||
color='blue-grey darken-2'
|
||||
:background-color='$vuetify.theme.dark ? `grey darken-5` : `white`'
|
||||
placeholder='Your Name'
|
||||
:placeholder='$t(`common:comments.fieldName`)'
|
||||
hide-details
|
||||
dense
|
||||
autocomplete='name'
|
||||
@ -30,7 +30,7 @@
|
||||
outlined
|
||||
color='blue-grey darken-2'
|
||||
:background-color='$vuetify.theme.dark ? `grey darken-5` : `white`'
|
||||
placeholder='Your Email Address'
|
||||
:placeholder='$t(`common:comments.fieldEmail`)'
|
||||
hide-details
|
||||
type='email'
|
||||
dense
|
||||
@ -39,9 +39,11 @@
|
||||
)
|
||||
.d-flex.align-center.pt-3(v-if='permissions.write')
|
||||
v-icon.mr-1(color='blue-grey') mdi-language-markdown-outline
|
||||
.caption.blue-grey--text Markdown Format
|
||||
.caption.blue-grey--text {{$t('common:comments.markdownFormat')}}
|
||||
v-spacer
|
||||
.caption.mr-3(v-if='isAuthenticated') Posting as #[strong {{userDisplayName}}]
|
||||
.caption.mr-3(v-if='isAuthenticated')
|
||||
i18next(tag='span', path='common:comments.postingAs')
|
||||
strong(place='bold') {{userDisplayName}}
|
||||
v-btn(
|
||||
dark
|
||||
color='blue-grey darken-2'
|
||||
@ -49,7 +51,7 @@
|
||||
depressed
|
||||
)
|
||||
v-icon(left) mdi-comment
|
||||
span.text-none Post Comment
|
||||
span.text-none {{$t('common:comments.postComment')}}
|
||||
v-divider.mt-3(v-if='permissions.write')
|
||||
.pa-5.d-flex.align-center.justify-center(v-if='isLoading && !hasLoadedOnce')
|
||||
v-progress-circular(
|
||||
@ -58,7 +60,7 @@
|
||||
width='1'
|
||||
color='blue-grey'
|
||||
)
|
||||
.caption.blue-grey--text.pl-3: em Loading comments...
|
||||
.caption.blue-grey--text.pl-3: em {{$t('common:comments.loading')}}
|
||||
v-timeline(
|
||||
dense
|
||||
v-else-if='comments && comments.length > 0'
|
||||
@ -80,7 +82,7 @@
|
||||
v-icon.mr-3(small, @click='editComment(cm)') mdi-pencil
|
||||
v-icon(small, @click='deleteCommentConfirm(cm)') mdi-delete
|
||||
.comments-post-name.caption: strong {{cm.authorName}}
|
||||
.comments-post-date.overline.grey--text {{cm.createdAt | moment('from') }} #[em(v-if='cm.createdAt !== cm.updatedAt') - modified {{cm.updatedAt | moment('from') }}]
|
||||
.comments-post-date.overline.grey--text {{cm.createdAt | moment('from') }} #[em(v-if='cm.createdAt !== cm.updatedAt') - {{$t('common:comments.modified', { reldate: $options.filters.moment(cm.updatedAt, 'from') })}}]
|
||||
.comments-post-content.mt-3(v-if='commentEditId !== cm.id', v-html='cm.render')
|
||||
.comments-post-editcontent.mt-3(v-else)
|
||||
v-textarea(
|
||||
@ -103,7 +105,7 @@
|
||||
outlined
|
||||
)
|
||||
v-icon(left) mdi-close
|
||||
span.text-none Cancel
|
||||
span.text-none {{$t('common:action.cancel')}}
|
||||
v-btn(
|
||||
dark
|
||||
color='blue-grey darken-2'
|
||||
@ -111,16 +113,16 @@
|
||||
depressed
|
||||
)
|
||||
v-icon(left) mdi-comment
|
||||
span.text-none Update Comment
|
||||
.pt-5.text-center.body-2.blue-grey--text(v-else-if='permissions.write') Be the first to comment.
|
||||
.text-center.body-2.blue-grey--text(v-else) No comments yet.
|
||||
span.text-none {{$t('common:comments.updateComment')}}
|
||||
.pt-5.text-center.body-2.blue-grey--text(v-else-if='permissions.write') {{$t('common:comments.beFirst')}}
|
||||
.text-center.body-2.blue-grey--text(v-else) {{$t('common:comments.none')}}
|
||||
|
||||
v-dialog(v-model='deleteCommentDialogShown', max-width='500')
|
||||
v-card
|
||||
.dialog-header.is-red Confirm Delete
|
||||
.dialog-header.is-red {{$t('common:comments.deleteConfirmTitle')}}
|
||||
v-card-text.pt-5
|
||||
span Are you sure you want to permanently delete this comment?
|
||||
.caption: strong This action cannot be undone!
|
||||
span {{$t('common:comments.deleteWarn')}}
|
||||
.caption: strong {{$t('common:comments.deletePermanentWarn')}}
|
||||
v-card-chin
|
||||
v-spacer
|
||||
v-btn(text, @click='deleteCommentDialogShown = false') {{$t('common:actions.cancel')}}
|
||||
@ -298,7 +300,7 @@ export default {
|
||||
if (_.get(resp, 'data.comments.create.responseResult.succeeded', false)) {
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'success',
|
||||
message: 'New comment posted successfully.',
|
||||
message: this.$t('common:comments.postSuccess'),
|
||||
icon: 'check'
|
||||
})
|
||||
|
||||
@ -371,7 +373,7 @@ export default {
|
||||
this.isBusy = true
|
||||
try {
|
||||
if (this.commentEditContent.length < 2) {
|
||||
throw new Error('Comment is empty or too short!')
|
||||
throw new Error(this.$t('common:comments.contentMissingError'))
|
||||
}
|
||||
const resp = await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
@ -404,7 +406,7 @@ export default {
|
||||
if (_.get(resp, 'data.comments.update.responseResult.succeeded', false)) {
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'success',
|
||||
message: 'Comment was updated successfully.',
|
||||
message: this.$t('common:comments.updateSuccess'),
|
||||
icon: 'check'
|
||||
})
|
||||
|
||||
@ -470,7 +472,7 @@ export default {
|
||||
if (_.get(resp, 'data.comments.delete.responseResult.succeeded', false)) {
|
||||
this.$store.commit('showNotification', {
|
||||
style: 'success',
|
||||
message: 'Comment was deleted successfully.',
|
||||
message: this.$t('common:comments.deleteSuccess'),
|
||||
icon: 'check'
|
||||
})
|
||||
|
||||
|
@ -115,6 +115,14 @@ export default {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
publishStartDate: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
publishEndDate: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
scriptJs: {
|
||||
type: String,
|
||||
default: ''
|
||||
@ -196,6 +204,8 @@ export default {
|
||||
this.$store.set('page/id', this.pageId)
|
||||
this.$store.set('page/description', this.description)
|
||||
this.$store.set('page/isPublished', this.isPublished)
|
||||
this.$store.set('page/publishStartDate', this.publishStartDate)
|
||||
this.$store.set('page/publishEndDate', this.publishEndDate)
|
||||
this.$store.set('page/locale', this.locale)
|
||||
this.$store.set('page/path', this.path)
|
||||
this.$store.set('page/tags', this.tags)
|
||||
|
@ -136,12 +136,12 @@
|
||||
)
|
||||
v-spacer
|
||||
v-btn(
|
||||
flat=''
|
||||
text
|
||||
color='primary'
|
||||
@click='isPublishStartShown = false'
|
||||
) {{$t('common:actions.cancel')}}
|
||||
v-btn(
|
||||
flat=''
|
||||
text
|
||||
color='primary'
|
||||
@click='$refs.menuPublishStart.save(publishStartDate)'
|
||||
) {{$t('common:actions.ok')}}
|
||||
@ -177,12 +177,12 @@
|
||||
)
|
||||
v-spacer
|
||||
v-btn(
|
||||
flat=''
|
||||
text
|
||||
color='primary'
|
||||
@click='isPublishEndShown = false'
|
||||
) {{$t('common:actions.cancel')}}
|
||||
v-btn(
|
||||
flat=''
|
||||
text
|
||||
color='primary'
|
||||
@click='$refs.menuPublishEnd.save(publishEndDate)'
|
||||
) {{$t('common:actions.ok')}}
|
||||
|
@ -260,12 +260,14 @@
|
||||
v-icon(size='20') mdi-trash-can-outline
|
||||
span {{$t('common:header.delete')}}
|
||||
span {{$t('common:page.editPage')}}
|
||||
v-alert.mb-5(v-if='!isPublished', color='red', outlined, icon='mdi-minus-circle', dense)
|
||||
.caption {{$t('common:page.unpublishedWarning')}}
|
||||
.contents(ref='container')
|
||||
slot(name='contents')
|
||||
.comments-container#discussion(v-if='commentsEnabled && commentsPerms.read')
|
||||
.comments-header
|
||||
v-icon.mr-2(dark) mdi-comment-text-outline
|
||||
span Comments
|
||||
span {{$t('common:comments.title')}}
|
||||
.comments-main
|
||||
slot(name='comments')
|
||||
nav-footer
|
||||
@ -503,7 +505,7 @@ export default {
|
||||
this.$store.set('page/title', this.title)
|
||||
this.$store.set('page/updatedAt', this.updatedAt)
|
||||
if (this.effectivePermissions) {
|
||||
this.$store.set('page/effectivePermissions',JSON.parse(Buffer.from(this.effectivePermissions, 'base64').toString()))
|
||||
this.$store.set('page/effectivePermissions', JSON.parse(Buffer.from(this.effectivePermissions, 'base64').toString()))
|
||||
}
|
||||
|
||||
this.$store.set('page/mode', 'view')
|
||||
|
@ -3,37 +3,12 @@ const router = express.Router()
|
||||
const pageHelper = require('../helpers/page')
|
||||
const _ = require('lodash')
|
||||
const CleanCSS = require('clean-css')
|
||||
const moment = require('moment')
|
||||
|
||||
/* global WIKI */
|
||||
|
||||
const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/
|
||||
|
||||
const getPageEffectivePermissions = (req, page) => {
|
||||
return {
|
||||
comments: {
|
||||
read: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['read:comments'], page) : false,
|
||||
write: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['write:comments'], page) : false,
|
||||
manage: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['manage:comments'], page) : false
|
||||
},
|
||||
history: {
|
||||
read: WIKI.auth.checkAccess(req.user, ['read:history'], page)
|
||||
},
|
||||
source: {
|
||||
read: WIKI.auth.checkAccess(req.user, ['read:source'], page)
|
||||
},
|
||||
pages: {
|
||||
write: WIKI.auth.checkAccess(req.user, ['write:pages'], page),
|
||||
manage: WIKI.auth.checkAccess(req.user, ['manage:pages'], page),
|
||||
delete: WIKI.auth.checkAccess(req.user, ['delete:pages'], page),
|
||||
script: WIKI.auth.checkAccess(req.user, ['write:scripts'], page),
|
||||
style: WIKI.auth.checkAccess(req.user, ['write:styles'], page)
|
||||
},
|
||||
system: {
|
||||
manage: WIKI.auth.checkAccess(req.user, ['manage:system'], page)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Robots.txt
|
||||
*/
|
||||
@ -137,6 +112,9 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
|
||||
|
||||
pageArgs.tags = _.get(page, 'tags', [])
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
|
||||
|
||||
const injectCode = {
|
||||
css: WIKI.config.theming.injectCSS,
|
||||
head: WIKI.config.theming.injectHead,
|
||||
@ -145,7 +123,7 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
|
||||
|
||||
if (page) {
|
||||
// -> EDIT MODE
|
||||
if (!WIKI.auth.checkAccess(req.user, ['write:pages', 'manage:pages'], pageArgs)) {
|
||||
if (!(effectivePermissions.pages.write || effectivePermissions.pages.manage)) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.render('unauthorized', { action: 'edit' })
|
||||
}
|
||||
@ -166,7 +144,7 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
|
||||
page.content = Buffer.from(page.content).toString('base64')
|
||||
} else {
|
||||
// -> CREATE MODE
|
||||
if (!WIKI.auth.checkAccess(req.user, ['write:pages'], pageArgs)) {
|
||||
if (!effectivePermissions.pages.write) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.render('unauthorized', { action: 'create' })
|
||||
}
|
||||
@ -229,9 +207,6 @@ router.get(['/e', '/e/*'], async (req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = getPageEffectivePermissions(req, pageArgs)
|
||||
|
||||
res.render('editor', { page, injectCode, effectivePermissions })
|
||||
})
|
||||
|
||||
@ -262,7 +237,9 @@ router.get(['/h', '/h/*'], async (req, res, next) => {
|
||||
|
||||
pageArgs.tags = _.get(page, 'tags', [])
|
||||
|
||||
if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) {
|
||||
const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
|
||||
|
||||
if (!effectivePermissions.history.read) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.render('unauthorized', { action: 'history' })
|
||||
}
|
||||
@ -271,9 +248,6 @@ router.get(['/h', '/h/*'], async (req, res, next) => {
|
||||
_.set(res.locals, 'pageMeta.title', page.title)
|
||||
_.set(res.locals, 'pageMeta.description', page.description)
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = getPageEffectivePermissions(req, pageArgs)
|
||||
|
||||
res.render('history', { page, effectivePermissions })
|
||||
} else {
|
||||
res.redirect(`/${pageArgs.path}`)
|
||||
@ -346,16 +320,19 @@ router.get(['/s', '/s/*'], async (req, res, next) => {
|
||||
return res.redirect(`/s/${pageArgs.locale}/${pageArgs.path}`)
|
||||
}
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
|
||||
|
||||
_.set(res, 'locals.siteConfig.lang', pageArgs.locale)
|
||||
_.set(res, 'locals.siteConfig.rtl', req.i18n.dir() === 'rtl')
|
||||
|
||||
if (versionId > 0) {
|
||||
if (!WIKI.auth.checkAccess(req.user, ['read:history'], pageArgs)) {
|
||||
if (!effectivePermissions.history.read) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.render('unauthorized', { action: 'sourceVersion' })
|
||||
}
|
||||
} else {
|
||||
if (!WIKI.auth.checkAccess(req.user, ['read:source'], pageArgs)) {
|
||||
if (!effectivePermissions.source.read) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.render('unauthorized', { action: 'source' })
|
||||
}
|
||||
@ -376,9 +353,6 @@ router.get(['/s', '/s/*'], async (req, res, next) => {
|
||||
_.set(res.locals, 'pageMeta.title', page.title)
|
||||
_.set(res.locals, 'pageMeta.description', page.description)
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = getPageEffectivePermissions(req, pageArgs)
|
||||
|
||||
res.render('source', { page, effectivePermissions })
|
||||
}
|
||||
} else {
|
||||
@ -419,8 +393,11 @@ router.get('/*', async (req, res, next) => {
|
||||
})
|
||||
pageArgs.tags = _.get(page, 'tags', [])
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = WIKI.auth.getEffectivePermissions(req, pageArgs)
|
||||
|
||||
// -> Check User Access
|
||||
if (!WIKI.auth.checkAccess(req.user, ['read:pages'], pageArgs)) {
|
||||
if (!effectivePermissions.pages.read) {
|
||||
if (req.user.id === 2) {
|
||||
res.cookie('loginRedirect', req.path, {
|
||||
maxAge: 15 * 60 * 1000
|
||||
@ -442,6 +419,21 @@ router.get('/*', async (req, res, next) => {
|
||||
_.set(res.locals, 'pageMeta.title', page.title)
|
||||
_.set(res.locals, 'pageMeta.description', page.description)
|
||||
|
||||
// -> Check Publishing State
|
||||
let pageIsPublished = page.isPublished
|
||||
if (pageIsPublished && !_.isEmpty(page.publishStartDate)) {
|
||||
pageIsPublished = moment(page.publishStartDate).isSameOrBefore()
|
||||
}
|
||||
if (pageIsPublished && !_.isEmpty(page.publishEndDate)) {
|
||||
pageIsPublished = moment(page.publishEndDate).isSameOrAfter()
|
||||
}
|
||||
if (!pageIsPublished && !effectivePermissions.pages.write) {
|
||||
_.set(res.locals, 'pageMeta.title', 'Unauthorized')
|
||||
return res.status(403).render('unauthorized', {
|
||||
action: 'view'
|
||||
})
|
||||
}
|
||||
|
||||
// -> Build sidebar navigation
|
||||
let sdi = 1
|
||||
const sidebar = (await WIKI.models.navigation.getTree({ cache: true, locale: pageArgs.locale, groups: req.user.groups })).map(n => ({
|
||||
@ -499,9 +491,6 @@ router.get('/*', async (req, res, next) => {
|
||||
})
|
||||
}
|
||||
|
||||
// -> Effective Permissions
|
||||
const effectivePermissions = getPageEffectivePermissions(req, pageArgs)
|
||||
|
||||
// -> Render view
|
||||
res.render('page', {
|
||||
page,
|
||||
@ -516,7 +505,7 @@ router.get('/*', async (req, res, next) => {
|
||||
res.render('welcome', { locale: pageArgs.locale })
|
||||
} else {
|
||||
_.set(res.locals, 'pageMeta.title', 'Page Not Found')
|
||||
if (WIKI.auth.checkAccess(req.user, ['write:pages'], pageArgs)) {
|
||||
if (effectivePermissions.pages.write) {
|
||||
res.status(404).render('new', { path: pageArgs.path, locale: pageArgs.locale })
|
||||
} else {
|
||||
res.status(404).render('notfound', { action: 'view' })
|
||||
|
@ -380,5 +380,35 @@ module.exports = {
|
||||
WIKI.events.inbound.on('reloadAuthStrategies', () => {
|
||||
WIKI.auth.activateStrategies()
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all user permissions for a specific page
|
||||
*/
|
||||
getEffectivePermissions (req, page) {
|
||||
return {
|
||||
comments: {
|
||||
read: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['read:comments'], page) : false,
|
||||
write: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['write:comments'], page) : false,
|
||||
manage: WIKI.config.features.featurePageComments ? WIKI.auth.checkAccess(req.user, ['manage:comments'], page) : false
|
||||
},
|
||||
history: {
|
||||
read: WIKI.auth.checkAccess(req.user, ['read:history'], page)
|
||||
},
|
||||
source: {
|
||||
read: WIKI.auth.checkAccess(req.user, ['read:source'], page)
|
||||
},
|
||||
pages: {
|
||||
read: WIKI.auth.checkAccess(req.user, ['read:pages'], page),
|
||||
write: WIKI.auth.checkAccess(req.user, ['write:pages'], page),
|
||||
manage: WIKI.auth.checkAccess(req.user, ['manage:pages'], page),
|
||||
delete: WIKI.auth.checkAccess(req.user, ['delete:pages'], page),
|
||||
script: WIKI.auth.checkAccess(req.user, ['write:scripts'], page),
|
||||
style: WIKI.auth.checkAccess(req.user, ['write:styles'], page)
|
||||
},
|
||||
system: {
|
||||
manage: WIKI.auth.checkAccess(req.user, ['manage:system'], page)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ block body
|
||||
description=page.description
|
||||
:tags=page.tags
|
||||
:is-published=page.isPublished
|
||||
publish-start-date=page.publishStartDate
|
||||
publish-end-date=page.publishEndDate
|
||||
script-css=page.extra.css
|
||||
script-js=page.extra.js
|
||||
init-mode=page.mode
|
||||
|
Loading…
Reference in New Issue
Block a user