Support changing texture model from skinlib

This commit is contained in:
Pig Fang 2018-08-16 17:42:54 +08:00
parent f83d5850a1
commit bf8ec12645
9 changed files with 189 additions and 5 deletions

View File

@ -295,6 +295,35 @@ class SkinlibController extends Controller
}
} // @codeCoverageIgnore
public function model(Request $request) {
$user = Auth::user();
$data = $this->validate($request, [
'tid' => 'required|integer',
'model' => 'required|in:steve,alex,cape'
]);
$t = Texture::find($request->input('tid'));
if (! $t)
return json(trans('skinlib.non-existent'), 1);
if ($t->uploader != $user->uid && !$user->isAdmin())
return json(trans('skinlib.no-permission'), 1);
$duplicate = Texture::where('hash', $t->hash)
->where('type', $request->input('model'))
->where('tid', '<>', $t->tid)
->first();
if ($duplicate && $duplicate->public) {
return json(trans('skinlib.model.duplicate', ['name' => $duplicate->name]), 1);
}
$t->type = $request->input('model');
$t->save();
return json(trans('skinlib.model.success', ['model' => $data['model']]), 0);
}
/**
* Check Uploaded Files
*

View File

@ -55,7 +55,7 @@
<td v-t="'skinlib.show.name'"></td>
<td>{{ name }}
<small v-if="uploader === currentUid || admin">
<a href="#" @click="changeTextureName" v-t="'skinlib.show.edit-name'"></a>
<a href="#" @click="changeTextureName" v-t="'skinlib.show.edit'"></a>
</small>
</td>
</tr>
@ -64,6 +64,9 @@
<td>
<template v-if="type === 'cape'">{{ $t('general.cape') }}</template>
<template v-else>{{ type }}</template>
<small v-if="uploader === currentUid || admin">
<a href="#" @click="changeModel" v-t="'skinlib.show.edit'"></a>
</small>
</td>
</tr>
<tr>
@ -253,6 +256,34 @@ export default {
toastr.warning(msg);
}
},
async changeModel() {
const { dismiss, value } = await swal({
text: this.$t('skinlib.setNewTextureModel'),
input: 'select',
inputValue: this.type,
inputOptions: {
steve: 'Steve',
alex: 'Alex',
cape: this.$t('general.cape')
},
showCancelButton: true,
inputClass: 'form-control'
});
if (dismiss) {
return;
}
const { errno, msg } = await this.$http.post(
'/skinlib/model',
{ tid: this.tid, model: value }
);
if (errno === 0) {
this.type = value;
toastr.success(msg);
} else {
toastr.warning(msg);
}
},
async togglePrivacy() {
const { dismiss } = await swal({
text: this.public

View File

@ -249,6 +249,38 @@ test('change texture name', async () => {
expect(wrapper.vm.name).toBe('new-name');
});
test('change texture model', async () => {
Vue.prototype.$http.get.mockResolvedValue({ type: 'steve' });
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValue({ errno: 0, msg: '0' });
jest.spyOn(toastr, 'warning');
swal.mockResolvedValueOnce({ dismiss: 1 })
.mockResolvedValue({ value: 'alex' });
const wrapper = mount(Show, {
mocks: {
$route: ['/skinlib/show/1', '1']
},
stubs: { previewer }
});
const button = wrapper.findAll('small').at(1).find('a');
button.trigger('click');
expect(Vue.prototype.$http.post).not.toBeCalled();
button.trigger('click');
await flushPromises();
expect(Vue.prototype.$http.post).toBeCalledWith(
'/skinlib/model',
{ tid: 1, model: 'alex' }
);
expect(toastr.warning).toBeCalledWith('1');
button.trigger('click');
await flushPromises();
expect(wrapper.vm.type).toBe('alex');
});
test('toggle privacy', async () => {
Vue.prototype.$http.get.mockResolvedValue({ public: true });
Vue.prototype.$http.post

View File

@ -70,6 +70,7 @@ skinlib:
setPublicNotice: Sure to set this as public texture?
setPrivateNotice: Sure to set this as private texture?
deleteNotice: Are you sure to delete this texture?
setNewTextureModel: "Please select a new texture model:"
upload:
texture-name: Texture Name
texture-type: Texture Type
@ -85,7 +86,7 @@ skinlib:
likes: People who like this
detail: Details
name: Texture Name
edit-name: Edit Name
edit: Edit
model: Applicable Model
download-raw: Click to download raw texture
size: File Size

View File

@ -85,10 +85,14 @@ privacy:
change-privacy: Change Privacy
set-as-private: Set as Private
set-as-public: Set as Public
success: The texture was setted to :privacy successfully.
success: The texture was set to :privacy successfully.
rename:
success: The texture was renamed to :name successfully.
model:
success: The texture's model was changed to :model successfully.
duplicate: "The same texture available for the chosen model already exists in skinlib (Name: :tid). You can add it to your closet directly."
no-permission: You aren't the uploader of this texture.
non-existent: Non-existent texture.

View File

@ -72,6 +72,7 @@ skinlib:
setPublicNotice: 要将此材质设置为公开吗?
setPrivateNotice: 要将此材质设置为私有吗?
deleteNotice: 真的要删除此材质吗?
setNewTextureModel: 请选择新的材质适用模型:
upload:
texture-name: 材质名称
texture-type: 材质类型
@ -87,7 +88,7 @@ skinlib:
likes: 收藏人数
detail: 详细信息
name: 名称
edit-name: 修改名称
edit: 修改
model: 适用模型
download-raw: 右键另存为即可下载原始皮肤文件
size: 文件大小

View File

@ -89,5 +89,9 @@ privacy:
rename:
success: 材质名称已被成功设置为 :name
model:
success: 材质的适用模型已被修改为 :model
duplicate: 已经有人上传过适用于该模型的相同材质了,直接去皮肤库收藏使用吧(名称::tid
no-permission: 你不是这个材质的上传者哦
non-existent: 材质不存在

View File

@ -86,7 +86,7 @@ Route::group(['prefix' => 'skinlib'], function ()
{
Route::get ('/upload', 'SkinlibController@upload');
Route::post('/upload', 'SkinlibController@handleUpload');
Route::post('/model', 'SkinlibController@model');
Route::post('/rename', 'SkinlibController@rename');
Route::post('/privacy', 'SkinlibController@privacy');
Route::post('/delete', 'SkinlibController@delete');

View File

@ -895,4 +895,86 @@ class SkinlibControllerTest extends TestCase
]);
$this->assertEquals('new_name', Texture::find($texture->tid)->name);
}
public function testModel()
{
$uploader = factory(User::class)->create();
$other = factory(User::class)->create();
$texture = factory(Texture::class)->create(['uploader' => $uploader->uid]);
// Non-existed texture
$this->actAs($uploader)
->postJson('/skinlib/model', [
'tid' => -1,
'model' => 'alex'
])
->assertJson([
'errno' => 1,
'msg' => trans('skinlib.non-existent')
]);
// Other user should not be able to change model
$this->actAs($other)
->postJson('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->assertJson([
'errno' => 1,
'msg' => trans('skinlib.no-permission')
]);
// Administrators should be able to change model
$this->actAs('admin')
->postJson('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->assertJson([
'errno' => 0,
'msg' => trans('skinlib.model.success', ['model' => 'alex'])
]);
$this->assertEquals('alex', Texture::find($texture->tid)->type);
// Uploader should be able to change model
$this->actAs($uploader)
->postJson('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'steve'
])
->assertJson([
'errno' => 0,
'msg' => trans('skinlib.model.success', ['model' => 'steve'])
]);
$this->assertEquals('steve', Texture::find($texture->tid)->type);
$duplicate = factory(Texture::class, 'alex')->create([
'uploader' => $other->uid,
'hash' => $texture->hash
]);
// Should fail if there is already a texture with same hash and chosen model
$this->actAs($uploader)
->postJson('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->assertJson([
'errno' => 1,
'msg' => trans('skinlib.model.duplicate', ['name' => $duplicate->name])
]);
// Allow private texture
$duplicate->public = false;
$duplicate->save();
$this->actAs($uploader)
->postJson('/skinlib/model', [
'tid' => $texture->tid,
'model' => 'alex'
])
->assertJson([
'errno' => 0,
'msg' => trans('skinlib.model.success', ['model' => 'alex'])
]);
}
}