feat: tags autocomplete in page properties
This commit is contained in:
parent
a1e0e4f27a
commit
f4e3fd0954
@ -67,18 +67,32 @@
|
|||||||
v-divider
|
v-divider
|
||||||
v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d5` : `lighten-4`')
|
v-card-text.grey.pt-5(:class='darkMode ? `darken-3-d5` : `lighten-4`')
|
||||||
.overline.pb-5 {{$t('editor:props.categorization')}}
|
.overline.pb-5 {{$t('editor:props.categorization')}}
|
||||||
|
v-chip-group.radius-5.mb-5(column, v-if='tags && tags.length > 0')
|
||||||
|
v-chip(
|
||||||
|
v-for='tag of tags'
|
||||||
|
:key='`tag-` + tag'
|
||||||
|
close
|
||||||
|
label
|
||||||
|
color='teal'
|
||||||
|
text-color='teal lighten-5'
|
||||||
|
@click:close='removeTag(tag)'
|
||||||
|
) {{tag}}
|
||||||
v-combobox(
|
v-combobox(
|
||||||
chips
|
|
||||||
deletable-chips
|
|
||||||
:label='$t(`editor:props.tags`)'
|
:label='$t(`editor:props.tags`)'
|
||||||
outlined
|
outlined
|
||||||
multiple
|
|
||||||
v-model='tags'
|
v-model='tags'
|
||||||
:hint='$t(`editor:props.tagsHint`)'
|
:hint='$t(`editor:props.tagsHint`)'
|
||||||
|
:items='newTagSuggestions'
|
||||||
|
:loading='$apollo.queries.newTagSuggestions.loading'
|
||||||
persistent-hint
|
persistent-hint
|
||||||
clearable
|
deletable-chips
|
||||||
height='130'
|
hide-no-data
|
||||||
|
hide-selected
|
||||||
|
:search-input.sync='newTagSearch'
|
||||||
|
multiple
|
||||||
)
|
)
|
||||||
|
template(v-slot:selection='{ attrs, item, parent, selected }')
|
||||||
|
span
|
||||||
v-tab-item
|
v-tab-item
|
||||||
v-card-text
|
v-card-text
|
||||||
.overline.pb-5 {{$t('editor:props.publishState')}} #[v-chip.ml-3(label, color='grey', small, outlined).white--text coming soon]
|
.overline.pb-5 {{$t('editor:props.publishState')}} #[v-chip.ml-3(label, color='grey', small, outlined).white--text coming soon]
|
||||||
@ -243,6 +257,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { sync, get } from 'vuex-pathify'
|
import { sync, get } from 'vuex-pathify'
|
||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
/* global siteLangs, siteConfig */
|
/* global siteLangs, siteConfig */
|
||||||
|
|
||||||
@ -258,7 +273,10 @@ export default {
|
|||||||
isPublishStartShown: false,
|
isPublishStartShown: false,
|
||||||
isPublishEndShown: false,
|
isPublishEndShown: false,
|
||||||
pageSelectorShown: false,
|
pageSelectorShown: false,
|
||||||
namespaces: siteLangs.length ? siteLangs.map(ns => ns.code) : [siteConfig.lang]
|
namespaces: siteLangs.length ? siteLangs.map(ns => ns.code) : [siteConfig.lang],
|
||||||
|
newTag: '',
|
||||||
|
newTagSuggestions: [],
|
||||||
|
newTagSearch: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -291,6 +309,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
addTag () {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.tags.push(this.newTag)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeTag (tag) {
|
||||||
|
this.tags = _.without(this.tags, tag)
|
||||||
|
},
|
||||||
close() {
|
close() {
|
||||||
this.isShown = false
|
this.isShown = false
|
||||||
},
|
},
|
||||||
@ -301,6 +327,28 @@ export default {
|
|||||||
this.locale = locale
|
this.locale = locale
|
||||||
this.path = path
|
this.path = path
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
apollo: {
|
||||||
|
newTagSuggestions: {
|
||||||
|
query: gql`
|
||||||
|
query ($query: String!) {
|
||||||
|
pages {
|
||||||
|
searchTags (query: $query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables () {
|
||||||
|
return {
|
||||||
|
query: this.newTagSearch
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchPolicy: 'cache-first',
|
||||||
|
update: (data) => _.get(data, 'pages.searchTags', []),
|
||||||
|
skip () {
|
||||||
|
return !this.value || _.isEmpty(this.newTagSearch)
|
||||||
|
},
|
||||||
|
throttle: 500
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -129,6 +129,24 @@ module.exports = {
|
|||||||
async tags (obj, args, context, info) {
|
async tags (obj, args, context, info) {
|
||||||
return WIKI.models.tags.query().orderBy('tag', 'asc')
|
return WIKI.models.tags.query().orderBy('tag', 'asc')
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* SEARCH TAGS
|
||||||
|
*/
|
||||||
|
async searchTags (obj, args, context, info) {
|
||||||
|
const results = await WIKI.models.tags.query()
|
||||||
|
.column('tag')
|
||||||
|
.where(builder => {
|
||||||
|
builder.andWhere(builderSub => {
|
||||||
|
if (WIKI.config.db.type === 'postgres') {
|
||||||
|
builderSub.where('tag', 'ILIKE', `%${args.query}%`)
|
||||||
|
} else {
|
||||||
|
builderSub.where('tag', 'LIKE', `%${args.query}%`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.limit(5)
|
||||||
|
return results.map(r => r.tag)
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* FETCH PAGE TREE
|
* FETCH PAGE TREE
|
||||||
*/
|
*/
|
||||||
|
@ -41,6 +41,10 @@ type PageQuery {
|
|||||||
|
|
||||||
tags: [PageTag]! @auth(requires: ["manage:system", "read:pages"])
|
tags: [PageTag]! @auth(requires: ["manage:system", "read:pages"])
|
||||||
|
|
||||||
|
searchTags(
|
||||||
|
query: String!
|
||||||
|
): [String]! @auth(requires: ["manage:system", "read:pages"])
|
||||||
|
|
||||||
tree(
|
tree(
|
||||||
path: String
|
path: String
|
||||||
parent: Int
|
parent: Int
|
||||||
|
@ -53,6 +53,10 @@ module.exports = class Tag extends Model {
|
|||||||
static async associateTags ({ tags, page }) {
|
static async associateTags ({ tags, page }) {
|
||||||
let existingTags = await WIKI.models.tags.query().column('id', 'tag')
|
let existingTags = await WIKI.models.tags.query().column('id', 'tag')
|
||||||
|
|
||||||
|
// Format tags
|
||||||
|
|
||||||
|
tags = _.uniq(tags.map(t => t.toLowerCase()))
|
||||||
|
|
||||||
// Create missing tags
|
// Create missing tags
|
||||||
|
|
||||||
const newTags = _.filter(tags, t => !_.some(existingTags, ['tag', t])).map(t => ({
|
const newTags = _.filter(tags, t => !_.some(existingTags, ['tag', t])).map(t => ({
|
||||||
|
@ -30,7 +30,6 @@ module.exports = {
|
|||||||
if (opts.path) {
|
if (opts.path) {
|
||||||
builder.andWhere('path', 'like', `${opts.path}%`)
|
builder.andWhere('path', 'like', `${opts.path}%`)
|
||||||
}
|
}
|
||||||
// TODO: Add user permissions filtering
|
|
||||||
builder.andWhere(builderSub => {
|
builder.andWhere(builderSub => {
|
||||||
if (WIKI.config.db.type === 'postgres') {
|
if (WIKI.config.db.type === 'postgres') {
|
||||||
builderSub.where('title', 'ILIKE', `%${q}%`)
|
builderSub.where('title', 'ILIKE', `%${q}%`)
|
||||||
|
Loading…
Reference in New Issue
Block a user