Remove unused files
This commit is contained in:
parent
deda5cf11c
commit
71cd20052b
|
|
@ -1,659 +0,0 @@
|
|||
/* eslint no-unused-vars: "off" */
|
||||
|
||||
const $ = require('jquery');
|
||||
window.$ = window.jQuery = $;
|
||||
|
||||
window.getQueryString = jest.fn((key, defaultValue) => defaultValue);
|
||||
|
||||
describe('tests for "index" module', () => {
|
||||
const modulePath = '../skinlib/index';
|
||||
|
||||
it('initialize skin library', () => {
|
||||
const fetch = jest.fn().mockReturnValue(Promise.resolve({ items: [] }));
|
||||
const url = jest.fn(path => path);
|
||||
const trans = jest.fn(key => key);
|
||||
const showAjaxError = jest.fn();
|
||||
window.fetch = fetch;
|
||||
window.url = url;
|
||||
window.trans = trans;
|
||||
window.showAjaxError = showAjaxError;
|
||||
$.fn.jqPaginator = jest.fn();
|
||||
const { initSkinlib } = require(modulePath);
|
||||
|
||||
initSkinlib();
|
||||
expect(fetch).not.toBeCalled();
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div id="skinlib-container"></div>
|
||||
<div id="skinlib-paginator"></div>
|
||||
<div class="sort"></div>
|
||||
`;
|
||||
initSkinlib();
|
||||
expect(fetch).toBeCalled();
|
||||
});
|
||||
|
||||
it('render skin library', () => {
|
||||
const trans = jest.fn(key => key);
|
||||
const url = jest.fn(path => path);
|
||||
const jqPaginator = jest.fn();
|
||||
window.trans = trans;
|
||||
window.url = url;
|
||||
$.fn.jqPaginator = jqPaginator;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="overlay"></div>
|
||||
<div id="skinlib-container"></div>
|
||||
<div id="skinlib-paginator"></div>
|
||||
`;
|
||||
const renderSkinlib = require(modulePath).renderSkinlib;
|
||||
|
||||
renderSkinlib([]);
|
||||
expect($('#skinlib-container').html()).toBe(
|
||||
'<p style="text-align: center; margin: 30px 0;">general.noResult</p>'
|
||||
);
|
||||
expect($('#skinlib-paginator').css('display')).toBe('none');
|
||||
expect($('.overlay').css('display')).toBe('none');
|
||||
|
||||
renderSkinlib([{
|
||||
tid: 1,
|
||||
name: 'name',
|
||||
type: 'steve',
|
||||
public: false
|
||||
}]);
|
||||
expect($('#skinlib-paginator').css('display')).not.toBe('none');
|
||||
expect($('.item').attr('tid')).toBe('1');
|
||||
expect($('.item-body > img').attr('src')).toBe('preview/1.png');
|
||||
expect($('.texture-name > span').attr('title')).toBe('name');
|
||||
expect($('.texture-name > span > small').text()).toBe('skinlib.filter.steve');
|
||||
expect($('a.more.like').attr('title')).toBe('skinlib.anonymous');
|
||||
expect($('a.more.like').hasClass('liked')).toBe(false);
|
||||
expect($('a.more.like').hasClass('anonymous')).toBe(true);
|
||||
expect($('small.more').hasClass('hide')).toBe(false);
|
||||
expect($('small.private-label').text().trim()).toBe('skinlib.private');
|
||||
|
||||
renderSkinlib([{
|
||||
tid: 1,
|
||||
name: 'name',
|
||||
type: 'steve',
|
||||
public: false,
|
||||
liked: true
|
||||
}]);
|
||||
expect($('a.more.like').attr('title')).toBe('skinlib.removeFromCloset');
|
||||
expect($('a.more.like').hasClass('liked')).toBe(true);
|
||||
expect($('a.more.like').hasClass('anonymous')).toBe(false);
|
||||
expect($('small.more').hasClass('hide')).toBe(false);
|
||||
expect($('small.private-label').text().trim()).toBe('skinlib.private');
|
||||
|
||||
renderSkinlib([{
|
||||
tid: 1,
|
||||
name: 'name',
|
||||
type: 'steve',
|
||||
public: false,
|
||||
liked: false
|
||||
}]);
|
||||
expect($('a.more.like').attr('title')).toBe('skinlib.addToCloset');
|
||||
expect($('a.more.like').hasClass('liked')).toBe(false);
|
||||
expect($('a.more.like').hasClass('anonymous')).toBe(false);
|
||||
expect($('small.more').hasClass('hide')).toBe(false);
|
||||
expect($('small.private-label').text().trim()).toBe('skinlib.private');
|
||||
|
||||
renderSkinlib([{
|
||||
tid: 1,
|
||||
name: 'name',
|
||||
type: 'steve',
|
||||
public: true,
|
||||
liked: false
|
||||
}]);
|
||||
expect($('small.more').hasClass('hide')).toBe(true);
|
||||
});
|
||||
|
||||
it('update paginator', () => {
|
||||
const trans = jest.fn(key => key);
|
||||
const jqPaginator = jest.fn();
|
||||
window.trans = trans;
|
||||
$.fn.jqPaginator = jqPaginator;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<p class="pagination"></p>
|
||||
<div id="skinlib-paginator"></div>
|
||||
<select class="pagination"></select>
|
||||
`;
|
||||
const updatePaginator = require(modulePath).updatePaginator;
|
||||
|
||||
updatePaginator(2, 2);
|
||||
expect(trans).toBeCalledWith('general.pagination', { page: 2, total: 2 });
|
||||
expect(jqPaginator).toBeCalledWith(expect.objectContaining({
|
||||
currentPage: 2,
|
||||
totalPages: 2
|
||||
}));
|
||||
expect($('option').length).toBe(2);
|
||||
expect($('option[value=1]').prop('selected')).toBe(false);
|
||||
expect($('option[value=2]').prop('selected')).toBe(true);
|
||||
|
||||
$('#skinlib-paginator').html('something');
|
||||
updatePaginator(2, 2);
|
||||
expect(jqPaginator).toBeCalledWith('option', {
|
||||
currentPage: 2,
|
||||
totalPages: 2
|
||||
});
|
||||
});
|
||||
|
||||
it('update breadcrumb', () => {
|
||||
const trans = jest.fn(key => key);
|
||||
const jqPaginator = jest.fn();
|
||||
window.trans = trans;
|
||||
$.fn.jqPaginator = jqPaginator;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div id="filter-indicator"></div>
|
||||
<div id="uploader-indicator"></div>
|
||||
<div id="sort-indicator"></div>
|
||||
<div id="search-indicator"></div>
|
||||
<input id="navbar-search-input" />
|
||||
`;
|
||||
const updateBreadCrumb = require(modulePath).updateBreadCrumb;
|
||||
|
||||
updateBreadCrumb();
|
||||
expect($('#filter-indicator').html().replace(/\s/g, '')).toBe(
|
||||
'general.skin<small>skinlib.filter.skin</small>'
|
||||
);
|
||||
|
||||
$.skinlib.filter = 'cape';
|
||||
updateBreadCrumb();
|
||||
expect($('#filter-indicator').html()).toBe('general.cape');
|
||||
|
||||
expect($('#uploader-indicator').html()).toBe('skinlib.filter.allUsers');
|
||||
$.skinlib.uploader = 1;
|
||||
updateBreadCrumb();
|
||||
expect(trans).toBeCalledWith('skinlib.filter.uploader', { uid: 1 });
|
||||
expect($('#uploader-indicator').html()).toBe('skinlib.filter.uploader');
|
||||
|
||||
expect($('#sort-indicator').html()).toBe('skinlib.sort.time');
|
||||
|
||||
$.skinlib.keyword = '%20q';
|
||||
updateBreadCrumb();
|
||||
expect(trans).lastCalledWith(
|
||||
'general.searchResult',
|
||||
{ keyword: ' q' }
|
||||
);
|
||||
expect($('#search-indicator').html()).toBe('general.searchResult');
|
||||
expect($('#navbar-search-input').val()).toBe(' q');
|
||||
});
|
||||
|
||||
it('reload skin library', async () => {
|
||||
const fetch = jest.fn().mockReturnValueOnce(Promise.resolve({
|
||||
items: []
|
||||
})).mockReturnValueOnce(Promise.reject());
|
||||
const url = jest.fn(path => path);
|
||||
const showAjaxError = jest.fn();
|
||||
window.fetch = fetch;
|
||||
window.url = url;
|
||||
window.showAjaxError = showAjaxError;
|
||||
document.body.innerHTML = `
|
||||
<div id="skinlib-paginator"></div>
|
||||
`;
|
||||
const reloadSkinlib = require(modulePath).reloadSkinlib;
|
||||
window.history.pushState = jest.fn();
|
||||
|
||||
await reloadSkinlib();
|
||||
expect(fetch).toBeCalledWith(expect.objectContaining({
|
||||
type: 'GET',
|
||||
url: 'skinlib/data',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
page: 2,
|
||||
filter: 'cape',
|
||||
sort: 'time',
|
||||
uploader: 1,
|
||||
keyword: '%20q'
|
||||
}
|
||||
}));
|
||||
|
||||
await reloadSkinlib();
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
|
||||
it('update query string', () => {
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
document.body.innerHTML = `
|
||||
<ul>
|
||||
<li class="locale" data-code="zh_CN"><a></a></li>
|
||||
<li class="locale" data-code="en"><a></a></li>
|
||||
</ul>
|
||||
`;
|
||||
const updateUrlQueryString = require(modulePath).updateUrlQueryString;
|
||||
window.history.pushState = jest.fn();
|
||||
|
||||
const query = 'page=2&filter=cape&sort=time&uploader=1&keyword=%2520q';
|
||||
|
||||
updateUrlQueryString();
|
||||
expect(window.history.pushState).toBeCalledWith(
|
||||
null,
|
||||
null,
|
||||
'skinlib?' + query);
|
||||
expect($('li[data-code=zh_CN] > a').prop('href')).toBe(`?lang=zh_CN&${query}`);
|
||||
expect($('li[data-code=en] > a').prop('href')).toBe(`?lang=en&${query}`);
|
||||
});
|
||||
|
||||
it('change page', () => {
|
||||
document.body.innerHTML = `
|
||||
<div class="overlay" style="display: none"></div>
|
||||
<select class="pagination">
|
||||
<option value="2"></option>
|
||||
</select>
|
||||
`;
|
||||
const { onPageChange } = require(modulePath);
|
||||
onPageChange(1, 'init');
|
||||
expect($.skinlib.page).toBe(1);
|
||||
|
||||
//onPageChange(2);
|
||||
$('select').trigger('change');
|
||||
expect($('div').css('display')).not.toBe('none');
|
||||
expect($.skinlib.page).toBe(2);
|
||||
});
|
||||
|
||||
it('update filter', () => {
|
||||
document.body.innerHTML = `
|
||||
<div data-filter="skin"></div>
|
||||
`;
|
||||
const { updateFilter } = require(modulePath);
|
||||
updateFilter.call($('div'), new Event('click'));
|
||||
expect($.skinlib.filter).toBe('skin');
|
||||
|
||||
$('div').data('filter', 'uploader').data('uid', 4);
|
||||
updateFilter.call($('div'), new Event('click'));
|
||||
expect($.skinlib.uploader).toBe(4);
|
||||
});
|
||||
|
||||
it('change sort type', () => {
|
||||
const fetch = jest.fn().mockReturnValue(Promise.resolve());
|
||||
window.fetch = fetch;
|
||||
document.body.innerHTML = `
|
||||
<a class="sort" data-sort="likes"></a>
|
||||
`;
|
||||
|
||||
require(modulePath);
|
||||
$('a').click();
|
||||
expect(fetch).toBeCalled();
|
||||
expect($.skinlib.sort).toBe('likes');
|
||||
});
|
||||
|
||||
it('search texture', async () => {
|
||||
const fetch = jest.fn().mockReturnValue(Promise.resolve());
|
||||
window.fetch = fetch;
|
||||
document.body.innerHTML = `
|
||||
<form id="search-form">
|
||||
<input id="navbar-search-input" name="q" value="keyword">
|
||||
</form>
|
||||
`;
|
||||
|
||||
$('#search-form').trigger('submit');
|
||||
expect(fetch).toBeCalled();
|
||||
expect($.skinlib.keyword).toBe('keyword');
|
||||
});
|
||||
});
|
||||
|
||||
describe('tests for "operations" module', () => {
|
||||
const modulePath = '../skinlib/operations';
|
||||
|
||||
it('toggle liked', async () => {
|
||||
const fetch = jest.fn().mockReturnValue(Promise.resolve());
|
||||
const swal = jest.fn().mockReturnValue(Promise.resolve());
|
||||
const url = jest.fn(path => path);
|
||||
window.fetch = fetch;
|
||||
window.swal = swal;
|
||||
window.url = url;
|
||||
document.body.innerHTML = `
|
||||
<a tid="5" class="anonymous"></a>
|
||||
`;
|
||||
const { toggleLiked } = require(modulePath);
|
||||
|
||||
await toggleLiked.call($('a'));
|
||||
expect(fetch).not.toBeCalled();
|
||||
|
||||
$('a').removeClass('anonymous');
|
||||
const originGetJson = $.getJSON;
|
||||
$.getJSON = jest.fn();
|
||||
await toggleLiked.call($('a'));
|
||||
expect($.getJSON).toBeCalled();
|
||||
$.getJSON = originGetJson;
|
||||
|
||||
$('a').addClass('liked');
|
||||
await toggleLiked.call($('a'));
|
||||
expect(fetch).toBeCalled();
|
||||
});
|
||||
|
||||
it('add to closet', async () => {
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn(option => {
|
||||
option.inputValidator('custom');
|
||||
return Promise.resolve('custom');
|
||||
});
|
||||
window.swal = swal;
|
||||
$.getJSON = jest.fn((option, cb) => {
|
||||
cb({ name: 'name' });
|
||||
});
|
||||
|
||||
const addToCloset = require(modulePath).addToCloset;
|
||||
|
||||
await addToCloset(1);
|
||||
expect($.getJSON.mock.calls[0][0]).toBe('skinlib/info/1');
|
||||
expect(swal).toBeCalledWith(expect.objectContaining({
|
||||
title: 'skinlib.setItemName',
|
||||
inputValue: 'name',
|
||||
input: 'text',
|
||||
showCancelButton: true,
|
||||
}));
|
||||
});
|
||||
|
||||
it('add to closet (by ajax)', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
|
||||
.mockReturnValueOnce(Promise.reject());
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn().mockReturnValue(Promise.resolve());
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
const showAjaxError = jest.fn();
|
||||
window.showAjaxError = showAjaxError;
|
||||
$.fn.modal = modal;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<div class="modal" style="display: none" id="shouldBeRemoved"></div>
|
||||
<div class="modal" id="shouldNotBeRemoved"></div>
|
||||
`;
|
||||
const ajaxAddToCloset = require(modulePath).ajaxAddToCloset;
|
||||
|
||||
await ajaxAddToCloset(1, 'name');
|
||||
expect(document.getElementById('shouldBeRemoved')).toBeNull();
|
||||
expect(document.getElementById('shouldNotBeRemoved')).not.toBeNull();
|
||||
expect(fetch).toBeCalledWith({
|
||||
type: 'POST',
|
||||
url: 'user/closet/add',
|
||||
dataType: 'json',
|
||||
data: { tid: 1, name: 'name' }
|
||||
});
|
||||
expect(swal).toBeCalledWith({ type: 'success', html: 'success' });
|
||||
expect(modal).toBeCalledWith('hide');
|
||||
|
||||
await ajaxAddToCloset(1, 'name');
|
||||
expect(toastr.warning).toBeCalledWith('warning');
|
||||
|
||||
await ajaxAddToCloset(1, 'name');
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
|
||||
it('remove from closet', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
|
||||
.mockReturnValueOnce(Promise.reject());
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn()
|
||||
.mockReturnValueOnce(Promise.reject())
|
||||
.mockReturnValueOnce(Promise.resolve());
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
const showAjaxError = jest.fn();
|
||||
window.showAjaxError = showAjaxError;
|
||||
|
||||
const removeFromCloset = require(modulePath).removeFromCloset;
|
||||
|
||||
await removeFromCloset(1);
|
||||
expect(fetch).not.toBeCalled();
|
||||
|
||||
await removeFromCloset(1);
|
||||
expect(swal).toBeCalledWith({
|
||||
text: 'user.removeFromClosetNotice',
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonColor: '#d33'
|
||||
});
|
||||
expect(fetch).toBeCalledWith({
|
||||
type: 'POST',
|
||||
url: '/user/closet/remove',
|
||||
dataType: 'json',
|
||||
data: { tid: 1 }
|
||||
});
|
||||
expect(swal).toBeCalledWith({ type: 'success', html: 'success' });
|
||||
|
||||
await removeFromCloset(1);
|
||||
expect(toastr.warning).toBeCalledWith('warning');
|
||||
|
||||
await removeFromCloset(1);
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
|
||||
it('change texture name', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
|
||||
.mockReturnValueOnce(Promise.reject());
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn()
|
||||
.mockImplementationOnce(() => Promise.reject())
|
||||
.mockImplementationOnce(option => {
|
||||
option.inputValidator('new-name');
|
||||
return Promise.resolve('new-name');
|
||||
});
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
const showAjaxError = jest.fn();
|
||||
window.showAjaxError = showAjaxError;
|
||||
|
||||
document.body.innerHTML = '<div id="name"></div>';
|
||||
const changeTextureName = require(modulePath).changeTextureName;
|
||||
|
||||
await changeTextureName(1, 'oldName');
|
||||
expect(fetch).not.toBeCalled();
|
||||
|
||||
await changeTextureName(1, 'oldName');
|
||||
expect(swal).toBeCalledWith(expect.objectContaining({
|
||||
text: 'skinlib.setNewTextureName',
|
||||
input: 'text',
|
||||
inputValue: 'oldName',
|
||||
showCancelButton: true,
|
||||
}));
|
||||
expect(fetch).toBeCalledWith({
|
||||
type: 'POST',
|
||||
url: 'skinlib/rename',
|
||||
dataType: 'json',
|
||||
data: { tid: 1, new_name: 'new-name' }
|
||||
});
|
||||
expect($('div').text()).toBe('new-name');
|
||||
expect(toastr.success).toBeCalledWith('success');
|
||||
|
||||
await changeTextureName(1, 'oldName');
|
||||
expect(toastr.warning).toBeCalledWith('warning');
|
||||
|
||||
await changeTextureName(1, 'oldName');
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
|
||||
it('update texture status', () => {
|
||||
window.trans = jest.fn(key => key);
|
||||
document.body.innerHTML = `
|
||||
<div id="likes">5</div>
|
||||
<a tid="1"></a>
|
||||
<a id="1"></a>
|
||||
`;
|
||||
const updateTextureStatus = require(modulePath).updateTextureStatus;
|
||||
|
||||
updateTextureStatus(1, 'add');
|
||||
expect($('a[tid=1]').attr('onclick')).toBe('removeFromCloset(1);');
|
||||
expect($('a[tid=1]').attr('title')).toBe('skinlib.removeFromCloset');
|
||||
expect($('a[tid=1]').hasClass('liked')).toBe(true);
|
||||
expect($('#1').attr('onclick')).toBe('removeFromCloset(1);');
|
||||
expect($('#1').html()).toBe('skinlib.removeFromCloset');
|
||||
expect($('div').html()).toBe('6');
|
||||
|
||||
updateTextureStatus(1, 'remove');
|
||||
expect($('a[tid=1]').attr('onclick')).toBe('addToCloset(1);');
|
||||
expect($('a[tid=1]').attr('title')).toBe('skinlib.addToCloset');
|
||||
expect($('a[tid=1]').hasClass('liked')).toBe(false);
|
||||
expect($('#1').attr('onclick')).toBe('addToCloset(1);');
|
||||
expect($('#1').html()).toBe('skinlib.addToCloset');
|
||||
expect($('div').html()).toBe('5');
|
||||
});
|
||||
|
||||
it('click changing privacy button', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValue(Promise.resolve({ errno: 0, msg: 'success' }));
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn().mockReturnValue(Promise.resolve());
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
|
||||
document.body.innerHTML = '<a class="private-label"></a>';
|
||||
require(modulePath);
|
||||
|
||||
await $('a').click();
|
||||
expect(swal).toBeCalledWith({
|
||||
text: 'skinlib.setPublicNotice',
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
});
|
||||
expect(document.getElementsByTagName('a').length).toBe(0);
|
||||
});
|
||||
|
||||
it('change privacy', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success', public: false }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success', public: true }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
|
||||
.mockReturnValueOnce(Promise.reject());
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn().mockReturnValue(Promise.resolve());
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
const showAjaxError = jest.fn();
|
||||
window.showAjaxError = showAjaxError;
|
||||
|
||||
document.body.innerHTML = `
|
||||
<a id="1">skinlib.setAsPrivate</a>
|
||||
<a id="2">skinlib.setAsPublic</a>
|
||||
`;
|
||||
const changePrivacy = require(modulePath).changePrivacy;
|
||||
|
||||
await changePrivacy(1);
|
||||
expect(fetch).toBeCalledWith({
|
||||
type: 'POST',
|
||||
url: 'skinlib/privacy',
|
||||
dataType: 'json',
|
||||
data: { tid: 1 }
|
||||
});
|
||||
expect(toastr.warning).not.toBeCalled();
|
||||
expect(toastr.success).toBeCalledWith('success');
|
||||
expect($('#1').html()).toBe('skinlib.setAsPublic');
|
||||
|
||||
await changePrivacy(1);
|
||||
expect($('#2').html()).toBe('skinlib.setAsPrivate');
|
||||
|
||||
await changePrivacy(1);
|
||||
expect(toastr.warning).toBeCalledWith('warning');
|
||||
|
||||
await changePrivacy(1);
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
|
||||
it('delete texture', async () => {
|
||||
const fetch = jest.fn()
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
|
||||
.mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
|
||||
.mockReturnValueOnce(Promise.reject());
|
||||
window.fetch = fetch;
|
||||
const url = jest.fn(path => path);
|
||||
window.url = url;
|
||||
const trans = jest.fn(key => key);
|
||||
window.trans = trans;
|
||||
const swal = jest.fn()
|
||||
.mockReturnValueOnce(Promise.reject())
|
||||
.mockReturnValueOnce(Promise.resolve());
|
||||
window.swal = swal;
|
||||
const modal = jest.fn();
|
||||
const toastr = {
|
||||
success: jest.fn(),
|
||||
warning: jest.fn()
|
||||
};
|
||||
window.toastr = toastr;
|
||||
const showAjaxError = jest.fn();
|
||||
window.showAjaxError = showAjaxError;
|
||||
|
||||
const deleteTexture = require(modulePath).deleteTexture;
|
||||
|
||||
await deleteTexture(1);
|
||||
expect(fetch).not.toBeCalled();
|
||||
|
||||
await deleteTexture(1);
|
||||
expect(swal).toBeCalledWith({
|
||||
text: 'skinlib.deleteNotice',
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
});
|
||||
expect(fetch).toBeCalledWith({
|
||||
type: 'POST',
|
||||
url: 'skinlib/delete',
|
||||
dataType: 'json',
|
||||
data: { tid: 1 }
|
||||
});
|
||||
expect(swal).toBeCalledWith({ type: 'success', html: 'success' });
|
||||
expect(url).toBeCalledWith('skinlib');
|
||||
|
||||
await deleteTexture(1);
|
||||
expect(swal).toBeCalledWith({ type: 'warning', html: 'warning' });
|
||||
|
||||
await deleteTexture(1);
|
||||
expect(showAjaxError).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
$.skinlib = {
|
||||
page: getQueryString('page', 1),
|
||||
filter: getQueryString('filter', 'skin'),
|
||||
sort: getQueryString('sort', 'time'),
|
||||
uploader: getQueryString('uploader', 0),
|
||||
keyword: decodeURI(getQueryString('keyword', ''))
|
||||
};
|
||||
|
||||
$(document).ready(initSkinlib);
|
||||
|
||||
$('body').on('change', 'select.pagination', function () {
|
||||
onPageChange(parseInt($(this).val()));
|
||||
});
|
||||
|
||||
$('.filter').click(updateFilter);
|
||||
|
||||
$('body').on('click', '.sort', function (e) {
|
||||
e.preventDefault();
|
||||
$.skinlib.sort = $(this).data('sort');
|
||||
|
||||
console.log('Sort by ' + $.skinlib.sort);
|
||||
reloadSkinlib();
|
||||
});
|
||||
|
||||
$('body').on('submit', '#search-form', function (e) {
|
||||
e.preventDefault();
|
||||
$.skinlib.keyword = $('#navbar-search-input').val();
|
||||
|
||||
console.log('Search keyword: ' + $.skinlib.keyword);
|
||||
reloadSkinlib();
|
||||
});
|
||||
|
||||
function initSkinlib() {
|
||||
if ($('#skinlib-container').length !== 0) {
|
||||
// Initially render skinlib
|
||||
requestSkinlibData().then(result => {
|
||||
renderSkinlib(result.items);
|
||||
|
||||
updatePaginator(
|
||||
$.skinlib.page,
|
||||
result.total_pages || 1
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function renderSkinlib(items) {
|
||||
const container = $('#skinlib-container').html('');
|
||||
|
||||
if (items.length === 0) {
|
||||
$('#skinlib-paginator').hide();
|
||||
|
||||
container.html(
|
||||
'<p style="text-align: center; margin: 30px 0;">' +
|
||||
trans('general.noResult') +
|
||||
'</p>'
|
||||
);
|
||||
} else {
|
||||
$('#skinlib-paginator').show();
|
||||
|
||||
container.html(items.reduce((carry, item) => carry + renderSkinlibItemComponent(item), ''));
|
||||
}
|
||||
|
||||
$('.overlay').hide();
|
||||
}
|
||||
|
||||
async function reloadSkinlib() {
|
||||
try {
|
||||
const result = await requestSkinlibData();
|
||||
|
||||
$('.overlay').show();
|
||||
renderSkinlib(result.items);
|
||||
|
||||
updatePaginator($.skinlib.page, result.total_pages || 1);
|
||||
|
||||
updateUrlQueryString();
|
||||
updateBreadCrumb();
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
function requestSkinlibData() {
|
||||
return fetch({
|
||||
type: 'GET',
|
||||
url: url('skinlib/data'),
|
||||
dataType: 'json',
|
||||
data: $.skinlib,
|
||||
error: showAjaxError
|
||||
});
|
||||
}
|
||||
|
||||
function renderSkinlibItemComponent(item) {
|
||||
let title = '';
|
||||
let anonymous = '';
|
||||
const liked = item.liked ? 'liked' : '';
|
||||
|
||||
if (item.liked === undefined) {
|
||||
// If user haven't logged in
|
||||
title = trans('skinlib.anonymous');
|
||||
anonymous = 'anonymous';
|
||||
} else {
|
||||
title = item.liked ? trans('skinlib.removeFromCloset') : trans('skinlib.addToCloset');
|
||||
}
|
||||
|
||||
return `<a href="${ url('skinlib/show/' + item.tid) }">
|
||||
<div class="item" tid="${ item.tid }">
|
||||
<div class="item-body">
|
||||
<img src="${ url('preview/' + item.tid + '.png') }">
|
||||
</div>
|
||||
|
||||
<div class="item-footer">
|
||||
<p class="texture-name">
|
||||
<span title="${ item.name }">${ item.name }
|
||||
<small>${ trans('skinlib.filter.' + item.type) }</small>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<a title="${title}" class="more like ${liked} ${anonymous}" tid="${ item.tid }" href="javascript:;" data-placement="top" data-toggle="tooltip"><i class="fa fa-heart"></i></a>
|
||||
|
||||
<small class="more private-label ${(!item.public) ? '' : 'hide'}" tid="${ item.tid }">
|
||||
${ trans('skinlib.private') }
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
function updatePaginator(currentPage, totalPages) {
|
||||
$.skinlib.page = currentPage;
|
||||
|
||||
$('p.pagination').text(trans('general.pagination', {
|
||||
page: currentPage,
|
||||
total: totalPages
|
||||
}));
|
||||
|
||||
const paginator = $('#skinlib-paginator');
|
||||
|
||||
if (paginator.html().length === 0) {
|
||||
// init paginator
|
||||
$('#skinlib-paginator').jqPaginator($.extend({}, $.defaultPaginatorConfig, {
|
||||
currentPage: parseInt(currentPage),
|
||||
totalPages: parseInt(totalPages),
|
||||
onPageChange: onPageChange
|
||||
}));
|
||||
} else {
|
||||
$('#skinlib-paginator').jqPaginator('option', {
|
||||
currentPage: parseInt(currentPage),
|
||||
totalPages: parseInt(totalPages)
|
||||
});
|
||||
}
|
||||
|
||||
const pageSelectElement = $('select.pagination').html('');
|
||||
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
pageSelectElement.append(`
|
||||
<option value="${i}" ${ (i === currentPage) ? 'selected' : '' }>${i}</option>
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFilter(e) {
|
||||
e.preventDefault();
|
||||
const selectedFilter = $(this).data('filter');
|
||||
|
||||
if (selectedFilter === 'uploader') {
|
||||
$.skinlib.uploader = $(this).data('uid');
|
||||
console.log('Show items uploaded by uid ' + $.skinlib.uploader);
|
||||
} else {
|
||||
$.skinlib.filter = selectedFilter;
|
||||
console.log('Filter by ' + $.skinlib.filter);
|
||||
}
|
||||
|
||||
reloadSkinlib();
|
||||
}
|
||||
|
||||
function onPageChange(page, type) {
|
||||
$.skinlib.page = page;
|
||||
updateBreadCrumb();
|
||||
|
||||
if (type === 'init') {
|
||||
console.log('Init paginator', page);
|
||||
} else {
|
||||
$('.overlay').show();
|
||||
reloadSkinlib();
|
||||
|
||||
console.log('Rendering page', page);
|
||||
}
|
||||
}
|
||||
|
||||
function updateUrlQueryString() {
|
||||
const query = $.param($.skinlib);
|
||||
|
||||
window.history.pushState(null, null, url(`skinlib?${ query }`));
|
||||
|
||||
$('li.locale').each(function () {
|
||||
$(this).find('a').prop('href', `?lang=${ $(this).data('code') }&${ query }`);
|
||||
});
|
||||
}
|
||||
|
||||
function updateBreadCrumb() {
|
||||
if ($.skinlib.filter === 'cape') {
|
||||
$('#filter-indicator').html(trans('general.cape'));
|
||||
} else {
|
||||
$('#filter-indicator').html(trans('general.skin') + `<small>
|
||||
${ trans('skinlib.filter.' + $.skinlib.filter) }
|
||||
</small>`);
|
||||
}
|
||||
|
||||
if ($.skinlib.uploader !== 0) {
|
||||
$('#uploader-indicator').html(trans('skinlib.filter.uploader', { uid: $.skinlib.uploader }));
|
||||
} else {
|
||||
$('#uploader-indicator').html(trans('skinlib.filter.allUsers'));
|
||||
}
|
||||
|
||||
$('#sort-indicator').html(trans('skinlib.sort.' + $.skinlib.sort));
|
||||
|
||||
if ($.skinlib.keyword !== '') {
|
||||
$('#search-indicator').text(trans('general.searchResult', {
|
||||
keyword: decodeURI($.skinlib.keyword)
|
||||
}));
|
||||
|
||||
$('#navbar-search-input').val(decodeURI($.skinlib.keyword));
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
module.exports = {
|
||||
initSkinlib,
|
||||
renderSkinlib,
|
||||
reloadSkinlib,
|
||||
updatePaginator,
|
||||
updateBreadCrumb,
|
||||
updateUrlQueryString,
|
||||
onPageChange,
|
||||
updateFilter,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
$(document).on('click', '.more.like', toggleLiked);
|
||||
|
||||
function toggleLiked() {
|
||||
const tid = $(this).attr('tid');
|
||||
|
||||
if ($(this).hasClass('anonymous'))
|
||||
return;
|
||||
|
||||
if ($(this).hasClass('liked')) {
|
||||
removeFromCloset(tid);
|
||||
} else {
|
||||
addToCloset(tid);
|
||||
}
|
||||
}
|
||||
|
||||
function addToCloset(tid) {
|
||||
$.getJSON(url(`skinlib/info/${tid}`), async ({ name }) => {
|
||||
try {
|
||||
const result = await swal({
|
||||
title: trans('skinlib.setItemName'),
|
||||
inputValue: name,
|
||||
input: 'text',
|
||||
showCancelButton: true,
|
||||
inputValidator: value => (new Promise((resolve, reject) => {
|
||||
value ? resolve() : reject(trans('skinlib.emptyItemName'));
|
||||
}))
|
||||
});
|
||||
ajaxAddToCloset(tid, result);
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function ajaxAddToCloset(tid, name) {
|
||||
// Remove interference of modal which is hide
|
||||
$('.modal').each(function () {
|
||||
return ($(this).css('display') === 'none') ? $(this).remove() : null;
|
||||
});
|
||||
|
||||
try {
|
||||
const { errno, msg } = await fetch({
|
||||
type: 'POST',
|
||||
url: url('user/closet/add'),
|
||||
dataType: 'json',
|
||||
data: { tid: tid, name: name }
|
||||
});
|
||||
|
||||
if (errno === 0) {
|
||||
swal({ type: 'success', html: msg });
|
||||
|
||||
$('.modal').modal('hide');
|
||||
updateTextureStatus(tid, 'add');
|
||||
} else {
|
||||
toastr.warning(msg);
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function removeFromCloset(tid) {
|
||||
try {
|
||||
await swal({
|
||||
text: trans('user.removeFromClosetNotice'),
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonColor: '#d33'
|
||||
});
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { errno, msg } = await fetch({
|
||||
type: 'POST',
|
||||
url: url('/user/closet/remove'),
|
||||
dataType: 'json',
|
||||
data: { tid: tid }
|
||||
});
|
||||
|
||||
if (errno === 0) {
|
||||
swal({ type: 'success', html: msg });
|
||||
|
||||
updateTextureStatus(tid, 'remove');
|
||||
} else {
|
||||
toastr.warning(msg);
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function changeTextureName(tid, oldName) {
|
||||
let newTextureName = '';
|
||||
|
||||
try {
|
||||
newTextureName = await swal({
|
||||
text: trans('skinlib.setNewTextureName'),
|
||||
input: 'text',
|
||||
inputValue: oldName,
|
||||
showCancelButton: true,
|
||||
inputValidator: value => (new Promise((resolve, reject) => {
|
||||
value ? resolve() : reject(trans('skinlib.emptyNewTextureName'));
|
||||
}))
|
||||
});
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { errno, msg } = await fetch({
|
||||
type: 'POST',
|
||||
url: url('skinlib/rename'),
|
||||
dataType: 'json',
|
||||
data: { tid: tid, new_name: newTextureName }
|
||||
});
|
||||
|
||||
if (errno === 0) {
|
||||
$('#name').text(newTextureName);
|
||||
toastr.success(msg);
|
||||
} else {
|
||||
toastr.warning(msg);
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update button action & likes of texture.
|
||||
*
|
||||
* @param {number} tid
|
||||
* @param {'add'|'remove'} action
|
||||
* @return {null}
|
||||
*/
|
||||
function updateTextureStatus(tid, action) {
|
||||
const likes = parseInt($('#likes').html()) + (action === 'add' ? 1 : -1);
|
||||
action = (action === 'add') ? 'removeFromCloset' : 'addToCloset';
|
||||
|
||||
$(`a[tid=${tid}]`)
|
||||
.attr('onclick', `${action}(${tid});`)
|
||||
.attr('title', trans(`skinlib.${action}`))
|
||||
.toggleClass('liked');
|
||||
$(`#${tid}`)
|
||||
.attr('onclick', `${action}(${tid});`)
|
||||
.html(trans(`skinlib.${action}`));
|
||||
$('#likes').html(likes);
|
||||
}
|
||||
|
||||
$(document).on('click', '.private-label', async function () {
|
||||
try {
|
||||
await swal({
|
||||
text: trans('skinlib.setPublicNotice'),
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
});
|
||||
|
||||
changePrivacy($(this).attr('tid'));
|
||||
$(this).remove();
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
});
|
||||
|
||||
async function changePrivacy(tid) {
|
||||
try {
|
||||
const result = await fetch({
|
||||
type: 'POST',
|
||||
url: url('skinlib/privacy'),
|
||||
dataType: 'json',
|
||||
data: { tid: tid }
|
||||
});
|
||||
const { errno, msg } = result;
|
||||
|
||||
if (errno === 0) {
|
||||
toastr.success(msg);
|
||||
|
||||
if (!result.public) {
|
||||
$(`a:contains("${trans('skinlib.setAsPrivate')}")`).html(trans('skinlib.setAsPublic'));
|
||||
} else {
|
||||
$(`a:contains("${trans('skinlib.setAsPublic')}")`).html(trans('skinlib.setAsPrivate'));
|
||||
}
|
||||
} else {
|
||||
toastr.warning(msg);
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTexture(tid) {
|
||||
try {
|
||||
await swal({
|
||||
text: trans('skinlib.deleteNotice'),
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
});
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { errno, msg } = await fetch({
|
||||
type: 'POST',
|
||||
url: url('skinlib/delete'),
|
||||
dataType: 'json',
|
||||
data: { tid: tid }
|
||||
});
|
||||
|
||||
if (errno === 0) {
|
||||
await swal({ type: 'success', html: msg });
|
||||
window.location = url('skinlib');
|
||||
} else {
|
||||
swal({ type: 'warning', html: msg });
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
module.exports = {
|
||||
toggleLiked,
|
||||
addToCloset,
|
||||
changePrivacy,
|
||||
deleteTexture,
|
||||
ajaxAddToCloset,
|
||||
removeFromCloset,
|
||||
changeTextureName,
|
||||
updateTextureStatus,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
/* global initSkinViewer, defaultSteveSkin, defaultAlexSkin */
|
||||
|
||||
// TODO: Help wanted. This file needs to be tested.
|
||||
|
||||
'use strict';
|
||||
|
||||
function initUploadListeners() {
|
||||
if (trans('vendor.fileinput') !== 'vendor.fileinput') {
|
||||
$.fn.fileinputLocales[blessing.locale] = trans('vendor.fileinput');
|
||||
}
|
||||
|
||||
$('body')
|
||||
.on('change', '#file', () => handleFiles())
|
||||
.on('ifToggled', '#type-cape', () => handleFiles())
|
||||
.on('change', '#skin-type', function () {
|
||||
if ($('#file').prop('files').length === 0) {
|
||||
$.msp.config.slim = ($(this).val() === 'alex');
|
||||
$.msp.config.skinUrl = getDefaultSkin();
|
||||
initSkinViewer();
|
||||
}
|
||||
handleFiles();
|
||||
})
|
||||
.on('ifToggled', '#type-skin', function () {
|
||||
$(this).prop('checked') ? $('#skin-type').show() : $('#skin-type').hide();
|
||||
})
|
||||
.on('ifToggled', '#private', function () {
|
||||
$(this).prop('checked') ? $('#msg').show() : $('#msg').hide();
|
||||
});
|
||||
|
||||
$(document).ready(() => {
|
||||
$.msp.config.skinUrl = defaultSteveSkin;
|
||||
initSkinViewer();
|
||||
$('[for="private"]').tooltip();
|
||||
});
|
||||
}
|
||||
|
||||
// Real-time preview
|
||||
function handleFiles(files, type) {
|
||||
|
||||
files = files || $('#file').prop('files');
|
||||
type = type || $('#type-cape').prop('checked') ? 'cape' : 'skin';
|
||||
|
||||
if (files.length > 0) {
|
||||
const file = files[0];
|
||||
|
||||
if (file.type === 'image/png' || file.type === 'image/x-png') {
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function () {
|
||||
const img = new Image();
|
||||
|
||||
img.onload = () => {
|
||||
const $name = $('#name');
|
||||
|
||||
if (type === 'cape') {
|
||||
$.msp.config.skinUrl = getDefaultSkin();
|
||||
|
||||
if (img.width / img.height === 2) {
|
||||
$.msp.config.capeUrl = img.src;
|
||||
} else {
|
||||
$.msp.config.capeUrl = null;
|
||||
toastr.warning(trans('skinlib.badCapeSize'));
|
||||
}
|
||||
} else {
|
||||
// Check skin size
|
||||
if (img.width === img.height || img.width / img.height === 2) {
|
||||
$.msp.config.skinUrl = img.src;
|
||||
$.msp.config.capeUrl = null;
|
||||
} else {
|
||||
$.msp.config.skinUrl = getDefaultSkin();
|
||||
toastr.warning(trans('skinlib.badSkinSize'));
|
||||
}
|
||||
}
|
||||
|
||||
$.msp.config.slim = ($('#skin-type').val() === 'alex');
|
||||
|
||||
initSkinViewer();
|
||||
|
||||
if ($name.val() === '' || $name.val() === $name.attr('data-last-file-name')) {
|
||||
// Remove png extension in filename
|
||||
const fileName = file.name.replace(/\.[Pp][Nn][Gg]$/, '');
|
||||
|
||||
$name.attr('data-last-file-name', fileName);
|
||||
$name.val(fileName);
|
||||
}
|
||||
};
|
||||
|
||||
img.onerror = () => toastr.warning(trans('skinlib.fileExtError'));
|
||||
|
||||
img.src = this.result;
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
toastr.warning(trans('skinlib.encodingError'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultSkin() {
|
||||
return $('#skin-type').val() === 'alex' ? defaultAlexSkin : defaultSteveSkin;
|
||||
}
|
||||
|
||||
function upload() {
|
||||
const form = new FormData();
|
||||
const file = $('#file').prop('files')[0];
|
||||
|
||||
form.append('name', $('#name').val());
|
||||
form.append('file', file);
|
||||
form.append('public', ! $('#private').prop('checked'));
|
||||
|
||||
if ($('#type-skin').prop('checked')) {
|
||||
form.append('type', $('#skin-type').val());
|
||||
} else if ($('#type-cape').prop('checked')) {
|
||||
form.append('type', 'cape');
|
||||
} else {
|
||||
return toastr.info(trans('skinlib.emptyTextureType'));
|
||||
}
|
||||
|
||||
(function validate(form, file, callback) {
|
||||
if (file === undefined) {
|
||||
toastr.info(trans('skinlib.emptyUploadFile'));
|
||||
$('#file').focus();
|
||||
} else if ($('#name').val() === '') {
|
||||
toastr.info(trans('skinlib.emptyTextureName'));
|
||||
$('#name').focus();
|
||||
} else if (file.type !== 'image/png') {
|
||||
toastr.warning(trans('skinlib.fileExtError'));
|
||||
$('#file').focus();
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
})(form, file, async () => {
|
||||
try {
|
||||
const { errno, msg, tid } = await fetch({
|
||||
type: 'POST',
|
||||
url: url('skinlib/upload'),
|
||||
contentType: false,
|
||||
dataType: 'json',
|
||||
data: form,
|
||||
processData: false,
|
||||
beforeSend: () => {
|
||||
$('#upload-button').html(
|
||||
'<i class="fa fa-spinner fa-spin"></i> ' + trans('skinlib.uploading')
|
||||
).prop('disabled', 'disabled');
|
||||
}
|
||||
});
|
||||
|
||||
if (errno === 0) {
|
||||
const redirect = function () {
|
||||
toastr.info(trans('skinlib.redirecting'));
|
||||
|
||||
setTimeout(() => {
|
||||
window.location = url(`skinlib/show/${tid}`);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
// Always redirect
|
||||
swal({
|
||||
type: 'success',
|
||||
html: msg
|
||||
}).then(redirect, redirect);
|
||||
} else {
|
||||
await swal({
|
||||
type: 'warning',
|
||||
html: msg
|
||||
});
|
||||
$('#upload-button').html(trans('skinlib.upload')).prop('disabled', '');
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
$('#upload-button').html(trans('skinlib.upload')).prop('disabled', '');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
module.exports = { upload, initUploadListeners };
|
||||
}
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
font_stack = Ubuntu, 'Segoe UI', 'Microsoft Yahei', 'Microsoft Jhenghei', sans-serif;
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ubuntu';
|
||||
src: url('../fonts/ubuntu.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Minecraft';
|
||||
src: url('../fonts/minecraft.eot');
|
||||
src: url('../fonts/minecraft.eot') format('embedded-opentype'),
|
||||
url('../fonts/minecraft.woff2') format('woff2'),
|
||||
url('../fonts/minecraft.woff') format('woff'),
|
||||
url('../fonts/minecraft.ttf') format('truetype'),
|
||||
url('../fonts/minecraft.svg#minecraft') format('svg');
|
||||
}
|
||||
|
||||
body, h1, h2, h3, h4, h5, h6, .logo {
|
||||
font-family: font_stack !important;
|
||||
}
|
||||
|
||||
.swal2-modal, .swal2-content {
|
||||
font-family: font_stack;
|
||||
font-weight: 400 !important;
|
||||
}
|
||||
|
||||
.swal2-modal h2 {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
/* fucking webkit autofill */
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0px 1000px #fff inset !important;
|
||||
}
|
||||
|
||||
.login-page {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: block;
|
||||
background: #EFF1F0;
|
||||
box-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
||||
border-radius: 2px;
|
||||
float: left;
|
||||
position: relative;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
cursor: pointer;
|
||||
width: 210px;
|
||||
height: 196px;
|
||||
|
||||
-webkit-transition: box-shadow 0.1s ease-in-out 0s;
|
||||
-moz-transition: box-shadow 0.1s ease-in-out 0s;
|
||||
-o-transition: box-shadow 0.1s ease-in-out 0s;
|
||||
-ms-transition: box-shadow 0.1s ease-in-out 0s;
|
||||
transition: box-shadow 0.1s ease-in-out 0s;
|
||||
}
|
||||
|
||||
.item-body {
|
||||
height: 166px;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
margin-left: 30px;
|
||||
margin-top: 16px;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 756px) {
|
||||
.item {
|
||||
width: 45%;
|
||||
margin-right: 5%;
|
||||
}
|
||||
|
||||
.item-body > img {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.texture-name {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item-body > img {
|
||||
margin-left: 30%;
|
||||
}
|
||||
|
||||
.texture-name {
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
#preview-3d-container {
|
||||
min-height: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
#preview-3d-container canvas {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.texture-name {
|
||||
width: 65%;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
|
||||
.item-selected {
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
|
||||
}
|
||||
|
||||
.item-footer {
|
||||
background: #50b3ec;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
height: 30px;
|
||||
padding: 3px 8px;
|
||||
|
||||
.more {
|
||||
float: right;
|
||||
margin-left: 6px;
|
||||
margin-right: 3px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.more:hover {
|
||||
color: #dadada;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.operations {
|
||||
display: inline; float: right;
|
||||
|
||||
i {
|
||||
padding: .5em .5em;
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
i:hover {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.skin2d {
|
||||
float: right;
|
||||
max-height: 64px;
|
||||
width: 64px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#preview-2d-container > p {
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
}
|
||||
|
||||
#toast-container > div {
|
||||
opacity: 1;
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
|
||||
filter: "alpha(opacity=100)";
|
||||
}
|
||||
|
||||
.captcha {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.box-footer > p {
|
||||
margin: 6px 15px 5px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
|
||||
.wrapper .main-header .navbar .dropdown-menu li.locale {
|
||||
a {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #e1e3e9;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
/* hide the text on mobile phone pages */
|
||||
.description-text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.key {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.value {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
td[class='key'], td[class='value'] {
|
||||
border-top: 0 !important;
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
@import "general.styl";
|
||||
|
||||
.navbar-nav {
|
||||
.user-menu .user-image {
|
||||
border-radius: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
.main-header #navbar-search-input.form-control {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.item {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.item-body > img {
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.texture-name {
|
||||
width: 65%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-footer {
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.like:hover,
|
||||
.liked {
|
||||
color: #e0353b;
|
||||
}
|
||||
}
|
||||
|
||||
.model-label {
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
label.pull-right {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
div.likes {
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
color: #3e3e3e;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
div.likes:hover,
|
||||
div.likes:active,
|
||||
div.likes:focus,
|
||||
div.likes:active:focus {
|
||||
background-color: #fff;
|
||||
border-color: #fff;
|
||||
color: #e0353b;
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.table > tbody > tr > td {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
select.pagination {
|
||||
padding-left: 0;
|
||||
margin: 0 20px 0 0;
|
||||
border-radius: 4px;
|
||||
padding: 5.5px 14px;
|
||||
}
|
||||
|
||||
.overlay span {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -40px;
|
||||
margin-top: 25px;
|
||||
color: #000;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#skinlib-container {
|
||||
min-height: 20em;
|
||||
}
|
||||
|
||||
.private-label {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.dropdown-menu .divider {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<div class="box box-danger">
|
||||
{{-- Texture Manage Panel --}}
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ $title }}</h3>
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<p>{{ $message }}</p>
|
||||
</div><!-- /.box-body -->
|
||||
|
||||
<div class="box-footer">
|
||||
@if ($texture->public == "1")
|
||||
<a onclick="changePrivacy({{ $texture->tid }});" class="btn btn-warning">@lang('skinlib.privacy.set-as-private')</a>
|
||||
@else
|
||||
<a onclick="changePrivacy({{ $texture->tid }});" class="btn btn-warning">@lang('skinlib.privacy.set-as-public')</a>
|
||||
@endif
|
||||
<a onclick="deleteTexture({{ $texture->tid }});" class="btn btn-danger pull-right">@lang('skinlib.show.delete-texture')</a>
|
||||
</div><!-- /.box-footer -->
|
||||
</div><!-- /.box -->
|
||||
Loading…
Reference in New Issue
Block a user