Rework skin library filter

This commit is contained in:
Pig Fang 2019-03-26 17:42:27 +08:00
parent 0876d41421
commit a1e38eec1f
7 changed files with 123 additions and 134 deletions

View File

@ -1,4 +1,6 @@
@import '~element-theme-chalk/src/button.scss';
@import '~element-theme-chalk/src/button-group.scss';
@import '~element-theme-chalk/src/input.scss';
@import '~element-theme-chalk/src/message.scss';
@import '~element-theme-chalk/src/message-box.scss';
@import '~element-theme-chalk/src/progress.scss';

View File

@ -1,9 +1,13 @@
import Vue from 'vue'
import Button from 'element-ui/lib/button'
import ButtonGroup from 'element-ui/lib/button-group'
import Input from 'element-ui/lib/input'
import Message from 'element-ui/lib/message'
import MessageBox from 'element-ui/lib/message-box'
Vue.use(Button)
Vue.use(ButtonGroup)
Vue.use(Input)
Vue.prototype.$message = Message
Vue.prototype.$msgbox = MessageBox

View File

@ -23,84 +23,39 @@
<div class="box box-default">
<div class="box-header">
<div class="form-group row">
<div class="col-md-4">
<label>
<input
v-model="filter"
type="radio"
name="filter"
value="skin"
>
{{ $t('skinlib.anyModels') }}
</label>&nbsp;
<label>
<input
v-model="filter"
type="radio"
name="filter"
value="steve"
>
Steve
</label>&nbsp;
<label>
<input
v-model="filter"
type="radio"
name="filter"
value="alex"
>
Alex
</label>&nbsp;
<label>
<input
v-model="filter"
type="radio"
name="filter"
value="cape"
>
{{ $t('general.cape') }}
</label>
</div>
<form class="col-md-4" @submit.prevent="fetchData">
<div class="input-group">
<input
v-model="keyword"
type="text"
:placeholder="$t('vendor.datatable.search')"
class="form-control"
>
<span class="input-group-btn">
<button class="btn btn-success" @click="fetchData">
{{ $t('general.submit') }}
</button>
</span>
</div>
<form class="col-md-6" @submit.prevent="fetchData">
<el-input
v-model="keyword"
:placeholder="$t('vendor.datatable.search')"
clearable
>
<el-select slot="prepend" v-model="filter" class="texture-type-select">
<el-option :label="$t('general.skin')" value="skin" />
<el-option label="Steve" value="steve" />
<el-option label="Alex" value="alex" />
<el-option :label="$t('general.cape')" value="cape" />
</el-select>
<el-button slot="append" data-test="btn-search" @click="fetchData">
{{ $t('general.submit') }}
</el-button>
</el-input>
</form>
<div class="col-md-4">
<div class="btn-group filter-btn">
<button
class="btn btn-primary dropdown-toggle"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
{{ $t('skinlib.sort.title') }} <span class="caret" />
</button>
<ul class="dropdown-menu">
<li><a v-t="'skinlib.sort.likes'" href="#" @click="sort = 'likes'" /></li>
<li><a v-t="'skinlib.sort.time'" href="#" @click="sort = 'time'" /></li>
</ul>
</div>
<a
v-if="currentUid"
class="btn btn-default btn-tail"
@click="uploader = currentUid"
>{{ $t('skinlib.seeMyUpload') }}</a>
<button class="btn btn-warning btn-tail" @click="reset">
{{ $t('skinlib.reset') }}
</button>
<div class="col-md-6 advanced-filter">
<el-button-group class="pull-right">
<el-button plain @click="sort = 'likes'">
{{ $t('skinlib.sort.likes') }}
</el-button>
<el-button plain @click="sort = 'time'">
{{ $t('skinlib.sort.time') }}
</el-button>
<el-button plain @click="uploader = currentUid">
{{ $t('skinlib.seeMyUpload') }}
</el-button>
<el-button type="info" plain @click="reset">
{{ $t('skinlib.reset') }}
</el-button>
</el-button-group>
</div>
</div>
</div>
@ -154,10 +109,17 @@
</template>
<script>
import Vue from 'vue'
import Paginate from 'vuejs-paginate'
import 'element-ui/lib/theme-chalk/select.css'
import Select from 'element-ui/lib/select'
import Option from 'element-ui/lib/option'
import { queryString } from '../../js/utils'
import SkinLibItem from '../../components/SkinLibItem.vue'
Vue.use(Select)
Vue.use(Option)
export default {
name: 'SkinLibrary',
components: {
@ -191,8 +153,7 @@ export default {
},
},
watch: {
filter(value) {
$(`[value="${value}"]`).iCheck('check')
filter() {
this.fetchData()
},
uploader() {
@ -202,17 +163,6 @@ export default {
this.fetchData()
},
},
created() {
let available = true
const origin = this.fetchData
this.fetchData = () => {
if (available) {
available = false
setTimeout(() => (available = true), 50)
origin()
}
}
},
beforeMount() {
this.fetchData()
},
@ -265,9 +215,12 @@ export default {
color #000
font-size 20px
@media (min-width: 768px)
.filter-btn
margin-left 25px
.texture-type-select
width 90px
.advanced-filter
@media (max-width 850px)
display none
.btn-tail
margin-left 6px

View File

@ -1,7 +1,10 @@
/* eslint-disable import/no-extraneous-dependencies */
import 'jest-extended'
import Vue from 'vue'
import { Button } from 'element-ui'
import {
Button,
Input,
} from 'element-ui'
window.blessing = {
base_url: '',
@ -37,6 +40,7 @@ Vue.prototype.$http = {
}
Vue.use(Button)
Vue.use(Input)
Vue.prototype.$message = {
info: jest.fn(),
success: jest.fn(),

View File

@ -1,7 +1,48 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { Button } from 'element-ui'
import List from '@/views/skinlib/List.vue'
jest.mock('element-ui/lib/select', () => ({
install(vue: typeof Vue) {
vue.component('ElSelect', {
render(h) {
return h('select', {
on: {
change: (event: Event) => this.$emit(
'change',
(event.target as HTMLSelectElement).value
),
},
attrs: {
value: this.value,
},
}, this.$slots.default)
},
props: {
value: String,
},
model: {
prop: 'value',
event: 'change',
},
})
},
}))
jest.mock('element-ui/lib/option', () => ({
install(vue: typeof Vue) {
vue.component('ElOption', {
render(h) {
return h('option', { attrs: { value: this.value } }, this.label)
},
props: {
label: String,
value: String,
},
})
},
}))
test('fetch data before mounting', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
@ -27,17 +68,13 @@ test('toggle texture type', () => {
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
})
window.$ = jest.fn(() => ({
iCheck() {},
}))
const wrapper = mount(List)
const select = wrapper.find({ name: 'ElSelect' })
const breadcrumb = wrapper.find('.breadcrumb')
jest.runAllTimers()
expect(breadcrumb.text()).toContain('skinlib.filter.skin')
wrapper.find('[value=steve]').setChecked()
jest.runAllTimers()
select.setValue('steve')
select.trigger('change')
expect(breadcrumb.text()).toContain('skinlib.filter.steve')
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',
@ -45,8 +82,8 @@ test('toggle texture type', () => {
filter: 'steve', uploader: 0, sort: 'time', keyword: '', page: 1,
}
)
wrapper.find('[value=alex]').setChecked()
jest.runAllTimers()
select.setValue('alex')
select.trigger('change')
expect(breadcrumb.text()).toContain('skinlib.filter.alex')
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',
@ -54,8 +91,8 @@ test('toggle texture type', () => {
filter: 'alex', uploader: 0, sort: 'time', keyword: '', page: 1,
}
)
wrapper.find('[value=cape]').setChecked()
jest.runAllTimers()
select.setValue('cape')
select.trigger('change')
expect(breadcrumb.text()).toContain('general.cape')
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',
@ -72,9 +109,10 @@ test('check specified uploader', async () => {
const wrapper = mount(List)
await wrapper.vm.$nextTick()
const breadcrumb = wrapper.find('.breadcrumb')
const button = wrapper.find('.btn-default')
jest.runAllTimers()
const button = wrapper
.find('.advanced-filter')
.findAll(Button)
.at(2)
expect(breadcrumb.text()).toContain('skinlib.filter.allUsers')
button.trigger('click')
@ -92,9 +130,9 @@ test('sort items', () => {
items: [], total_pages: 0, current_uid: 0,
})
const wrapper = mount(List)
const sortByLikes = wrapper.find('.dropdown-menu > li:nth-child(1) > a')
const sortByTime = wrapper.find('.dropdown-menu > li:nth-child(2) > a')
jest.runAllTimers()
const buttons = wrapper.find('.advanced-filter').findAll(Button)
const sortByLikes = buttons.at(0)
const sortByTime = buttons.at(1)
sortByLikes.trigger('click')
expect(Vue.prototype.$http.get).toBeCalledWith(
@ -104,7 +142,6 @@ test('sort items', () => {
}
)
expect(wrapper.text()).toContain('skinlib.sort.likes')
jest.runAllTimers()
sortByTime.trigger('click')
expect(Vue.prototype.$http.get).toBeCalledWith(
@ -121,10 +158,8 @@ test('search by keyword', () => {
items: [], total_pages: 0, current_uid: 0,
})
const wrapper = mount(List)
const searchBox = wrapper.find('input[type=text]')
jest.runAllTimers()
searchBox.setValue('a')
wrapper.setData({ keyword: 'a' })
wrapper.find('form').trigger('submit')
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',
@ -132,10 +167,9 @@ test('search by keyword', () => {
filter: 'skin', uploader: 0, sort: 'time', keyword: 'a', page: 1,
}
)
jest.runAllTimers()
searchBox.setValue('b')
wrapper.find('.input-group-btn > button').trigger('click')
wrapper.setData({ keyword: 'b' })
wrapper.find('[data-test="btn-search"]').trigger('click')
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',
{
@ -145,23 +179,18 @@ test('search by keyword', () => {
})
test('reset all filters', () => {
window.$ = jest.fn(() => ({
iCheck() {},
}))
Vue.prototype.$http.get.mockResolvedValue({
items: [], total_pages: 0, current_uid: 0,
})
const wrapper = mount(List)
jest.runAllTimers()
wrapper.find('input[value=cape]').setChecked()
jest.runAllTimers()
wrapper.find('input[type=text]').setValue('abc')
jest.runAllTimers()
wrapper.find('.dropdown-menu > li:nth-child(1) > a').trigger('click')
jest.runAllTimers()
wrapper.findAll('option').at(3)
.setSelected()
wrapper.setData({ keyword: 'abc' })
const buttons = wrapper.find('.advanced-filter').findAll(Button)
buttons.at(1).trigger('click')
Vue.prototype.$http.get.mockClear()
wrapper.find('.btn-warning').trigger('click')
buttons.at(3).trigger('click')
expect(Vue.prototype.$http.get).toBeCalledTimes(1)
})
@ -178,7 +207,6 @@ test('on page changed', () => {
items: [], total_pages: 0, current_uid: 0,
})
const wrapper = mount<Vue & { pageChanged(page: number): void }>(List)
jest.runAllTimers()
wrapper.vm.pageChanged(2)
expect(Vue.prototype.$http.get).toBeCalledWith(
'/skinlib/data',

View File

@ -47,8 +47,7 @@ skinlib:
emptyItemName: Empty texture name.
setNewTextureName: 'Please enter the new texture name:'
emptyNewTextureName: Empty new texture name.
anyModels: Any Models
seeMyUpload: Check My Upload
seeMyUpload: My Uploads
apply: Quick Apply
filter:
skin: (Any Model)
@ -59,7 +58,7 @@ skinlib:
allUsers: All Users
sort:
title: Sort
time: Newestly Uploaded
time: Latest
likes: Most Likes
badSkinSize: The size of selected skin file is not valid
badCapeSize: The size of selected cape file is not valid

View File

@ -47,8 +47,7 @@ skinlib:
emptyItemName: 你还没有填写要收藏的材质名称啊
anonymous: 请先登录
private: 私密
anyModels: 任意模型
seeMyUpload: 查看我上传的
seeMyUpload: 我上传的
apply: 立即使用
filter:
skin: (任意模型)