diff --git a/resources/assets/src/js/__tests__/skinlib.test.js b/resources/assets/src/js/__tests__/skinlib.test.js deleted file mode 100644 index 5a55b776..00000000 --- a/resources/assets/src/js/__tests__/skinlib.test.js +++ /dev/null @@ -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 = ` -
-
-
- `; - 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 = ` -
-
-
- `; - const renderSkinlib = require(modulePath).renderSkinlib; - - renderSkinlib([]); - expect($('#skinlib-container').html()).toBe( - '

general.noResult

' - ); - 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 = ` -

-
- - `; - 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 = ` -
-
-
-
- - `; - const updateBreadCrumb = require(modulePath).updateBreadCrumb; - - updateBreadCrumb(); - expect($('#filter-indicator').html().replace(/\s/g, '')).toBe( - 'general.skinskinlib.filter.skin' - ); - - $.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 = ` -
- `; - 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 = ` - - `; - 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 = ` - - - `; - 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 = ` -
- `; - 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 = ` - - `; - - 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 = ` -
- -
- `; - - $('#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 = ` - - `; - 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 = ` - - - `; - 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 = '
'; - 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 = ` -
5
- - - `; - 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 = ''; - 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 = ` - skinlib.setAsPrivate - skinlib.setAsPublic - `; - 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(); - }); -}); diff --git a/resources/assets/src/js/skinlib/index.js b/resources/assets/src/js/skinlib/index.js deleted file mode 100644 index ec718c94..00000000 --- a/resources/assets/src/js/skinlib/index.js +++ /dev/null @@ -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( - '

' + - trans('general.noResult') + - '

' - ); - } 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 ` -
-
- -
- -
-
- `; -} - -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(` - - `); - } -} - -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') + ` - ${ trans('skinlib.filter.' + $.skinlib.filter) } - `); - } - - 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, - }; -} diff --git a/resources/assets/src/js/skinlib/operations.js b/resources/assets/src/js/skinlib/operations.js deleted file mode 100644 index e4723fe2..00000000 --- a/resources/assets/src/js/skinlib/operations.js +++ /dev/null @@ -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, - }; -} diff --git a/resources/assets/src/js/skinlib/upload.js b/resources/assets/src/js/skinlib/upload.js deleted file mode 100644 index a5104bba..00000000 --- a/resources/assets/src/js/skinlib/upload.js +++ /dev/null @@ -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( - ' ' + 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 }; -} diff --git a/resources/assets/src/stylus/general.styl b/resources/assets/src/stylus/general.styl deleted file mode 100644 index 1ddfbfd5..00000000 --- a/resources/assets/src/stylus/general.styl +++ /dev/null @@ -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; -} diff --git a/resources/assets/src/stylus/skinlib.styl b/resources/assets/src/stylus/skinlib.styl deleted file mode 100644 index 1dc217bd..00000000 --- a/resources/assets/src/stylus/skinlib.styl +++ /dev/null @@ -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; -} diff --git a/resources/views/common/manage-panel.tpl b/resources/views/common/manage-panel.tpl deleted file mode 100644 index b1360aa4..00000000 --- a/resources/views/common/manage-panel.tpl +++ /dev/null @@ -1,18 +0,0 @@ -
- {{-- Texture Manage Panel --}} -
-

{{ $title }}

-
-
-

{{ $message }}

-
- - -