Reuse <Modal> component

This commit is contained in:
Pig Fang 2019-11-28 21:35:27 +08:00
parent 991475041b
commit aada1148fb
10 changed files with 168 additions and 307 deletions

View File

@ -1,58 +1,38 @@
<template>
<div
<modal
id="modal-add-player"
class="modal fade"
tabindex="-1"
role="dialog"
:title="$t('user.player.add-player')"
:ok-button-text="$t('general.submit')"
flex-footer
@confirm="addPlayer"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 v-t="'user.player.add-player'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table class="table">
<tbody>
<tr>
<td v-t="'general.player.player-name'" class="key" />
<td class="value">
<input v-model="name" class="form-control" type="text">
</td>
</tr>
</tbody>
</table>
<div class="callout callout-info">
<ul class="m-0 p-0 pl-3">
<li>{{ rule }}</li>
<li>{{ length }}</li>
</ul>
</div>
</div>
<div class="modal-footer d-flex justify-content-between">
<button class="btn btn-default" data-dismiss="modal">
{{ $t('general.close') }}
</button>
<button class="btn btn-primary" data-test="addPlayer" @click="addPlayer">
{{ $t('general.submit') }}
</button>
</div>
</div>
<table class="table">
<tbody>
<tr>
<td v-t="'general.player.player-name'" class="key" />
<td class="value">
<input v-model="name" class="form-control" type="text">
</td>
</tr>
</tbody>
</table>
<div class="callout callout-info">
<ul class="m-0 p-0 pl-3">
<li>{{ rule }}</li>
<li>{{ length }}</li>
</ul>
</div>
</div>
</modal>
</template>
<script>
import Modal from './Modal.vue'
export default {
name: 'AddPlayerDialog',
components: {
Modal,
},
data() {
return {
name: '',
@ -67,7 +47,6 @@ export default {
{ name: this.name },
)
if (code === 0) {
$('#modal-add-player').modal('hide')
this.$message.success(message)
this.$emit('add')
} else {

View File

@ -1,61 +1,51 @@
<template>
<div
<modal
id="modal-use-as"
class="modal fade"
tabindex="-1"
role="dialog"
ref="modal"
:title="$t('user.closet.use-as.title')"
:ok-button-text="$t('general.submit')"
flex-footer
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 v-t="'user.closet.use-as.title'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
<template v-if="players.length !== 0">
<div v-for="player in players" :key="player.pid" class="player-item">
<label class="model-label" :for="player.pid">
<input
v-model="selected"
type="radio"
name="player"
:value="player.pid"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<template v-if="players.length !== 0">
<div v-for="player in players" :key="player.pid" class="player-item">
<label class="model-label" :for="player.pid">
<input
v-model="selected"
type="radio"
name="player"
:value="player.pid"
>
<img :src="avatarUrl(player)" width="35" height="35">
<span>{{ player.name }}</span>
</label>
</div>
</template>
<p v-else v-t="'user.closet.use-as.empty'" />
</div>
<div class="modal-footer d-flex justify-content-between">
<a
v-if="allowAdd"
v-t="'user.closet.use-as.add'"
data-toggle="modal"
data-target="#modal-add-player"
class="btn btn-default"
href="#"
/>
<button class="btn btn-primary" data-test="submit" @click="submit">
{{ $t('general.submit') }}
</button>
</div>
<img :src="avatarUrl(player)" width="35" height="35">
<span>{{ player.name }}</span>
</label>
</div>
</div>
</div>
</template>
<p v-else v-t="'user.closet.use-as.empty'" />
<template #footer>
<a
v-if="allowAdd"
v-t="'user.closet.use-as.add'"
data-toggle="modal"
data-target="#modal-add-player"
class="btn btn-default"
href="#"
/>
<button class="btn btn-primary" data-test="submit" @click="submit">
{{ $t('general.submit') }}
</button>
</template>
</modal>
</template>
<script>
import $ from 'jquery'
import Modal from './Modal.vue'
export default {
name: 'ApplyToPlayerDialog',
components: {
Modal,
},
props: {
skin: Number,
cape: Number,

View File

@ -62,60 +62,35 @@
</template>
</vue-good-table>
<div
<modal
id="modal-change-texture"
class="modal fade"
tabindex="-1"
role="dialog"
:title="$t('admin.changeTexture')"
@confirm="changeTexture"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 v-t="'admin.changeTexture'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label v-t="'admin.textureType'" />
<select v-model="textureChanges.type" class="form-control">
<option v-t="'general.skin'" value="skin" />
<option v-t="'general.cape'" value="cape" />
</select>
</div>
<div class="form-group">
<label>TID</label>
<input
v-model.number="textureChanges.tid"
class="form-control"
type="text"
:placeholder="$t('admin.pidNotice')"
>
</div>
</div>
<div class="modal-footer d-flex justify-content-between">
<button class="btn btn-default" data-dismiss="modal">
{{ $t('general.close') }}
</button>
<button class="btn btn-primary" data-test="changeTexture" @click="changeTexture">
{{ $t('general.submit') }}
</button>
</div>
</div>
<div class="form-group">
<label v-t="'admin.textureType'" />
<select v-model="textureChanges.type" class="form-control">
<option v-t="'general.skin'" value="skin" />
<option v-t="'general.cape'" value="cape" />
</select>
</div>
</div>
<div class="form-group">
<label>TID</label>
<input
v-model.number="textureChanges.tid"
class="form-control"
type="text"
:placeholder="$t('admin.pidNotice')"
>
</div>
</modal>
</div>
</template>
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import Modal from '../../components/Modal.vue'
import tableOptions from '../../components/mixins/tableOptions'
import serverTable from '../../components/mixins/serverTable'
import emitMounted from '../../components/mixins/emitMounted'
@ -123,6 +98,7 @@ import emitMounted from '../../components/mixins/emitMounted'
export default {
name: 'PlayersManagement',
components: {
Modal,
VueGoodTable,
},
mixins: [
@ -189,7 +165,6 @@ export default {
if (code === 0) {
player[`tid_${type}`] = tid
this.$message.success(message)
$('.modal').modal('hide')
} else {
this.$message.warning(message)
}

View File

@ -49,60 +49,31 @@
</template>
</vue-good-table>
<div
id="modal-create"
class="modal fade"
tabindex="-1"
role="dialog"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 v-t="'user.oauth.create'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table class="table">
<tbody>
<tr>
<td v-t="'user.oauth.name'" class="key" />
<td class="value">
<input v-model="name" class="form-control" type="text">
</td>
</tr>
<tr>
<td v-t="'user.oauth.redirect'" class="key" />
<td class="value">
<input v-model="callback" class="form-control" type="text">
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer d-flex justify-content-between">
<button class="btn btn-default" data-dismiss="modal">
{{ $t('general.close') }}
</button>
<button class="btn btn-primary" data-test="create" @click="create">
{{ $t('general.submit') }}
</button>
</div>
</div>
</div>
</div>
<modal id="modal-create" :title="$t('user.oauth.create')" @confirm="create">
<table class="table">
<tbody>
<tr>
<td v-t="'user.oauth.name'" class="key" />
<td class="value">
<input v-model="name" class="form-control" type="text">
</td>
</tr>
<tr>
<td v-t="'user.oauth.redirect'" class="key" />
<td class="value">
<input v-model="callback" class="form-control" type="text">
</td>
</tr>
</tbody>
</table>
</modal>
</div>
</template>
<script>
import { VueGoodTable } from 'vue-good-table'
import 'vue-good-table/dist/vue-good-table.min.css'
import Modal from '../../components/Modal.vue'
import tableOptions from '../../components/mixins/tableOptions'
import emitMounted from '../../components/mixins/emitMounted'
import { walkFetch, init } from '../../scripts/net'
@ -110,6 +81,7 @@ import { walkFetch, init } from '../../scripts/net'
export default {
name: 'OAuthApps',
components: {
Modal,
VueGoodTable,
},
mixins: [
@ -160,7 +132,6 @@ export default {
redirect: this.callback,
})
if (client.id) {
$('#modal-create').modal('hide')
this.clients.unshift(client)
} else {
this.$message.warning(client.message)

View File

@ -114,49 +114,24 @@
<add-player-dialog @add="fetchPlayers" />
<div
<modal
id="modal-clear-texture"
class="modal fade"
tabindex="-1"
role="dialog"
:title="$t('user.chooseClearTexture')"
@confirm="clearTexture"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 v-t="'user.chooseClearTexture'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<label class="form-group">
<input v-model="clear.skin" type="checkbox"> {{ $t('general.skin') }}
</label>
<br>
<label class="form-group">
<input v-model="clear.cape" type="checkbox"> {{ $t('general.cape') }}
</label>
</div>
<div class="modal-footer d-flex justify-content-between">
<button class="btn btn-default" data-dismiss="modal">
{{ $t('general.close') }}
</button>
<button class="btn btn-primary" data-test="clearTexture" @click="clearTexture">
{{ $t('general.submit') }}
</button>
</div>
</div>
</div>
</div>
<label class="form-group">
<input v-model="clear.skin" type="checkbox"> {{ $t('general.skin') }}
</label>
<br>
<label class="form-group">
<input v-model="clear.cape" type="checkbox"> {{ $t('general.cape') }}
</label>
</modal>
</div>
</template>
<script>
import Modal from '../../components/Modal.vue'
import AddPlayerDialog from '../../components/AddPlayerDialog.vue'
import emitMounted from '../../components/mixins/emitMounted'
@ -164,6 +139,7 @@ export default {
name: 'Players',
components: {
AddPlayerDialog,
Modal,
Previewer: () => import('../../components/Previewer.vue'),
},
mixins: [
@ -259,7 +235,6 @@ export default {
this.clear,
)
if (code === 0) {
$('.modal').modal('hide')
this.$message.success(message)
const player = this.players.find(({ pid }) => pid === this.selected)
Object.keys(this.clear)

View File

@ -157,65 +157,51 @@
</div>
</div>
<div
id="modal-delete-account"
class="modal fade"
tabindex="-1"
role="dialog"
>
<form class="modal-dialog" data-test="deleteAccount" @submit.prevent="deleteAccount">
<div class="modal-content bg-danger">
<div class="modal-header">
<h4 v-t="'user.profile.delete.modal-title'" class="modal-title" />
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-once v-html="nl2br($t('user.profile.delete.modal-notice'))" />
<br>
<input
v-model="deleteConfirm"
type="password"
class="form-control"
:placeholder="$t('user.profile.delete.password')"
required
>
<br>
</div>
<div class="modal-footer d-flex justify-content-between">
<button
v-t="'general.close'"
type="button"
class="btn btn-outline-light"
data-dismiss="modal"
/>
<button
v-t="'general.submit'"
type="submit"
class="btn btn-outline-light"
/>
</div>
</div>
</form>
</div>
<form data-test="deleteAccount" @submit.prevent="deleteAccount">
<modal
id="modal-delete-account"
type="danger"
:title="$t('user.profile.delete.modal-title')"
flex-footer
>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-once v-html="nl2br($t('user.profile.delete.modal-notice'))" />
<br>
<input
v-model="deleteConfirm"
type="password"
class="form-control"
:placeholder="$t('user.profile.delete.password')"
required
>
<template #footer>
<button
v-t="'general.close'"
type="button"
class="btn btn-outline-light"
data-dismiss="modal"
/>
<button
v-t="'general.submit'"
type="submit"
class="btn btn-outline-light"
/>
</template>
</modal>
</form>
</div>
</template>
<script>
import EmailVerification from '../../components/EmailVerification.vue'
import Modal from '../../components/Modal.vue'
import emitMounted from '../../components/mixins/emitMounted'
export default {
name: 'Profile',
components: {
EmailVerification,
Modal,
},
mixins: [
emitMounted,

View File

@ -1,6 +1,7 @@
import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { flushPromises } from '../utils'
import Modal from '@/components/Modal.vue'
import AddPlayerDialog from '@/components/AddPlayerDialog.vue'
window.blessing.extra = {
@ -9,16 +10,15 @@ window.blessing.extra = {
}
test('add player', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get.mockResolvedValueOnce([])
Vue.prototype.$http.post
.mockResolvedValueOnce({ code: 1, message: 'fail' })
.mockResolvedValue({ code: 0, message: 'ok' })
const wrapper = mount(AddPlayerDialog)
const button = wrapper.find('[data-test=addPlayer]')
const modal = wrapper.find(Modal)
wrapper.find('input[type="text"]').setValue('the-new')
button.trigger('click')
modal.vm.$emit('confirm')
expect(Vue.prototype.$http.post).toBeCalledWith(
'/user/player/add',
{ name: 'the-new' },
@ -27,7 +27,7 @@ test('add player', async () => {
expect(wrapper.text()).not.toContain('the-new')
expect(Vue.prototype.$message.warning).toBeCalledWith('fail')
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(wrapper.emitted().add).toBeDefined()
expect(Vue.prototype.$message.success).toBeCalledWith('ok')

View File

@ -2,6 +2,7 @@ import Vue from 'vue'
import { mount } from '@vue/test-utils'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
import Modal from '@/components/Modal.vue'
import Players from '@/views/admin/Players.vue'
test('fetch data after initializing', () => {
@ -16,7 +17,6 @@ test('fetch data after initializing', () => {
})
test('change texture', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get.mockResolvedValue({
data: [
{ pid: 1, tid_skin: 0 },
@ -28,12 +28,12 @@ test('change texture', async () => {
const wrapper = mount(Players)
await flushPromises()
const button = wrapper.find('[data-test=changeTexture]')
const modal = wrapper.find(Modal)
wrapper.findAll('.btn-default').trigger('click')
wrapper.find('.modal-body input').setValue('5')
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(Vue.prototype.$http.post).toBeCalledWith(
'/admin/players?action=texture',
@ -41,10 +41,9 @@ test('change texture', async () => {
pid: 1, tid: 5, type: 'skin',
},
)
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(wrapper.html()).toContain('/preview/64/5.png')
expect($).toBeCalledWith('.modal')
})
test('change player name', async () => {

View File

@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils'
import { MessageBoxData } from 'element-ui/types/message-box'
import { flushPromises } from '../../utils'
import { walkFetch } from '@/scripts/net'
import Modal from '@/components/Modal.vue'
import OAuth from '@/views/user/OAuth.vue'
jest.mock('@/scripts/net', () => ({
@ -20,7 +21,6 @@ test('basic render', async () => {
})
test('create app', async () => {
Object.assign(window, { $: () => ({ modal() {} }) })
Vue.prototype.$http.get.mockResolvedValue([])
Vue.prototype.$http.post
.mockResolvedValueOnce({ message: 'fail' })
@ -28,14 +28,14 @@ test('create app', async () => {
const wrapper = mount(OAuth)
await flushPromises()
const button = wrapper.find('[data-test=create]')
const modal = wrapper.find(Modal)
const inputs = wrapper.findAll('.value')
inputs.at(0).find('input')
.setValue('name')
inputs.at(1).find('input')
.setValue('https://example.com/')
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(Vue.prototype.$http.post).toBeCalledWith(
'/oauth/clients',
@ -43,7 +43,7 @@ test('create app', async () => {
)
expect(Vue.prototype.$message.warning).toBeCalledWith('fail')
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(wrapper.text()).toContain('name')
})

View File

@ -153,21 +153,7 @@ test('toggle preview mode', () => {
expect(wrapper.text()).toContain('user.player.texture-empty')
})
test('add player', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get.mockResolvedValueOnce({ data: [] })
Vue.prototype.$http.post.mockResolvedValue({ code: 0 })
const wrapper = mount(Players)
const button = wrapper.find('[data-test=addPlayer]')
wrapper.find('input[type="text"]').setValue('the-new')
button.trigger('click')
await flushPromises()
expect(Vue.prototype.$http.get).toBeCalledTimes(2)
})
test('clear texture', async () => {
window.$ = jest.fn(() => ({ modal() {} }))
Vue.prototype.$http.get
.mockResolvedValueOnce({
data: [
@ -183,22 +169,22 @@ test('clear texture', async () => {
.mockResolvedValue({ code: 0, message: 'ok' })
const wrapper = mount(Players)
await flushPromises()
const button = wrapper.find('[data-test=clearTexture]')
const modal = wrapper.find('#modal-clear-texture')
wrapper.find('.player').trigger('click')
button.trigger('click')
modal.vm.$emit('confirm')
expect(Vue.prototype.$http.post).not.toBeCalled()
wrapper.findAll('input[type="checkbox"]').at(0)
.setChecked()
button.trigger('click')
modal.vm.$emit('confirm')
expect(Vue.prototype.$http.post).toBeCalledWith(
'/user/player/texture/clear/1',
{
skin: true, cape: false,
},
)
button.trigger('click')
modal.vm.$emit('confirm')
await flushPromises()
expect(Vue.prototype.$message.success).toBeCalledWith('ok')
})