mirror of
https://github.com/pinry/pinry.git
synced 2026-01-14 19:22:05 +01:00
Merge pull request #168 from pinry/feature/tag-auto-complete
close #161 Add tag auto-complete
This commit is contained in:
@@ -226,3 +226,10 @@ class BoardSerializer(serializers.HyperlinkedModelSerializer):
|
||||
)
|
||||
validated_data['submitter'] = user
|
||||
return super(BoardSerializer, self).create(validated_data)
|
||||
|
||||
|
||||
class TagAutoCompleteSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Tag
|
||||
fields = ('name', )
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import viewsets, mixins, routers
|
||||
from rest_framework.filters import SearchFilter, OrderingFilter
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
from taggit.models import Tag
|
||||
|
||||
from core import serializers as api
|
||||
from core.models import Image, Pin, Board
|
||||
@@ -49,8 +52,23 @@ class BoardAutoCompleteViewSet(
|
||||
pagination_class = None
|
||||
|
||||
|
||||
class TagAutoCompleteViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
|
||||
queryset = Tag.objects.all()
|
||||
serializer_class = api.TagAutoCompleteSerializer
|
||||
pagination_class = None
|
||||
|
||||
@method_decorator(cache_page(60 * 5))
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super(TagAutoCompleteViewSet, self).list(
|
||||
request,
|
||||
*args,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
drf_router = routers.DefaultRouter()
|
||||
drf_router.register(r'pins', PinViewSet)
|
||||
drf_router.register(r'images', ImageViewSet)
|
||||
drf_router.register(r'boards', BoardViewSet)
|
||||
drf_router.register(r'tags-auto-complete', TagAutoCompleteViewSet)
|
||||
drf_router.register(r'boards-auto-complete', BoardAutoCompleteViewSet)
|
||||
|
||||
@@ -258,7 +258,15 @@ const User = {
|
||||
},
|
||||
};
|
||||
|
||||
const Tag = {
|
||||
fetchList() {
|
||||
const url = `${API_PREFIX}tags-auto-complete/`;
|
||||
return axios.get(url);
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
Tag,
|
||||
Pin,
|
||||
Board,
|
||||
fetchPin,
|
||||
|
||||
@@ -38,21 +38,10 @@
|
||||
<script>
|
||||
import API from '../api';
|
||||
import ModelForm from '../utils/ModelForm';
|
||||
import AutoComplete from '../utils/AutoComplete';
|
||||
|
||||
const fields = ['name'];
|
||||
|
||||
function getFilteredOptions(options, filterText) {
|
||||
return options.filter(
|
||||
(option) => {
|
||||
const index = option.name
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.indexOf(filterText.toLowerCase());
|
||||
return index >= 0;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function getBoardFromResp(boardObject) {
|
||||
return { name: boardObject.name, value: boardObject.id };
|
||||
}
|
||||
@@ -62,7 +51,7 @@ function getAvailableOptions(vm, filter) {
|
||||
if (filter === '' || filter === null) {
|
||||
availableOptions = vm.allOptions;
|
||||
} else {
|
||||
availableOptions = getFilteredOptions(
|
||||
availableOptions = AutoComplete.getFilteredOptions(
|
||||
vm.allOptions, vm.form.name.value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,24 @@
|
||||
>
|
||||
</b-input>
|
||||
</b-field>
|
||||
<b-field label="Tags">
|
||||
<b-taginput
|
||||
v-model="pinModel.form.tags.value"
|
||||
:data="editorMeta.filteredTagOptions"
|
||||
autocomplete
|
||||
ellipsis
|
||||
icon="label"
|
||||
:allow-new="true"
|
||||
placeholder="Add a tag"
|
||||
@typing="getFilteredTags">
|
||||
<template slot-scope="props">
|
||||
<strong>{{ props.option }}</strong>
|
||||
</template>
|
||||
<template slot="empty">
|
||||
There are no items
|
||||
</template>
|
||||
</b-taginput>
|
||||
</b-field>
|
||||
<b-field label="Descripton"
|
||||
:type="pinModel.form.description.type"
|
||||
:message="pinModel.form.description.error">
|
||||
@@ -49,14 +67,6 @@
|
||||
>
|
||||
</b-input>
|
||||
</b-field>
|
||||
<b-field label="Tags">
|
||||
<b-taginput
|
||||
v-model="pinModel.form.tags.value"
|
||||
ellipsis
|
||||
icon="label"
|
||||
placeholder="Add a tag">
|
||||
</b-taginput>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column" v-if="!isEdit">
|
||||
<FilterSelect
|
||||
@@ -91,6 +101,7 @@ import FilterSelect from './FilterSelect.vue';
|
||||
import bus from '../utils/bus';
|
||||
import ModelForm from '../utils/ModelForm';
|
||||
import Loading from '../utils/Loading';
|
||||
import AutoComplete from '../utils/AutoComplete';
|
||||
|
||||
function isURLBlank(url) {
|
||||
return url !== null && url === '';
|
||||
@@ -133,13 +144,16 @@ export default {
|
||||
},
|
||||
boardId: null,
|
||||
boardOptions: [],
|
||||
tagOptions: [],
|
||||
editorMeta: {
|
||||
title: 'New Pin',
|
||||
filteredTagOptions: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.fetchBoardList();
|
||||
this.fetchTagList();
|
||||
if (this.isEdit) {
|
||||
this.editorMeta.title = 'Edit Pin';
|
||||
this.pinModel.form.url.value = this.existedPin.url;
|
||||
@@ -154,6 +168,25 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchTagList() {
|
||||
API.Tag.fetchList().then(
|
||||
(resp) => {
|
||||
this.tagOptions = resp.data;
|
||||
},
|
||||
);
|
||||
},
|
||||
getFilteredTags(text) {
|
||||
const filteredTagOptions = [];
|
||||
AutoComplete.getFilteredOptions(
|
||||
this.tagOptions,
|
||||
text,
|
||||
).forEach(
|
||||
(option) => {
|
||||
filteredTagOptions.push(option.name);
|
||||
},
|
||||
);
|
||||
this.editorMeta.filteredTagOptions = filteredTagOptions;
|
||||
},
|
||||
fetchBoardList() {
|
||||
API.Board.fetchFullList(this.username).then(
|
||||
(resp) => {
|
||||
|
||||
15
pinry-spa/src/components/utils/AutoComplete.js
Normal file
15
pinry-spa/src/components/utils/AutoComplete.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function getFilteredOptions(options, filterText) {
|
||||
return options.filter(
|
||||
(option) => {
|
||||
const index = option.name
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.indexOf(filterText.toLowerCase());
|
||||
return index >= 0;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
getFilteredOptions,
|
||||
};
|
||||
Reference in New Issue
Block a user