feat: tags autocomplete in page properties

This commit is contained in:
NGPixel 2020-02-02 16:24:27 -05:00
parent a1e0e4f27a
commit f4e3fd0954
5 changed files with 80 additions and 7 deletions

View File

@ -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>

View File

@ -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
*/ */

View File

@ -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

View File

@ -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 => ({

View File

@ -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}%`)