diff --git a/resources/assets/src/js/__tests__/.editorconfig b/resources/assets/src/js/__tests__/.editorconfig
deleted file mode 100644
index 0382a6f8..00000000
--- a/resources/assets/src/js/__tests__/.editorconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-# http://editorconfig.org
-
-[*.js]
-indent_size = 2
diff --git a/resources/assets/src/js/__tests__/admin.test.js b/resources/assets/src/js/__tests__/admin.test.js
deleted file mode 100644
index 7b567805..00000000
--- a/resources/assets/src/js/__tests__/admin.test.js
+++ /dev/null
@@ -1,1202 +0,0 @@
-/* eslint no-unused-vars: "off" */
-
-const $ = require('jquery');
-window.$ = window.jQuery = $;
-
-jest.useFakeTimers();
-
-describe('tests for "customize" module', () => {
- const modulePath = '../admin/customize';
-
- it('change skin preview after switching color', () => {
- window.current_skin = 'skin-blue';
- window.showAjaxError = jest.fn();
- document.body.className = window.current_skin;
- document.body.innerHTML = `
-
`;
-
- require(modulePath);
- $('#layout-skins-list [data-skin]').click();
-
- expect($('body').hasClass('skin-blue')).toBe(false);
- expect($('body').hasClass('skin-purple')).toBe(true);
- expect(window.current_skin).toBe('skin-purple');
- });
-
- it('submit information of skin', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject(new Error));
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.current_skin = '';
- window.showAjaxError = jest.fn();
-
- document.body.innerHTML = '';
- const submitColor = require(modulePath);
-
- await submitColor();
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/customize?action=color',
- dataType: 'json',
- data: { color_scheme: '' }
- });
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await submitColor();
- expect(toastr.warning).toBeCalledWith('warning');
-
- await submitColor();
- expect(window.showAjaxError).toBeCalled();
- });
-});
-
-describe('tests for "players" module', () => {
- const modulePath = '../admin/players';
-
- // TODO: test initializing players table
-
- it('show "change player texture" modal dialog', () => {
- const trans = jest.fn(key => key);
- const showModal = jest.fn();
- window.trans = trans;
- window.showModal = showModal;
-
- const changeTexture = require(modulePath).changeTexture;
- changeTexture(1, 'name');
- const args = showModal.mock.calls[0];
- expect(args.includes('admin.changePlayerTexture')).toBe(true);
- expect(args.includes('default')).toBe(true);
- });
-
- it('change player preference', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject(new Error));
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.showAjaxError = jest.fn();
-
- document.body.innerHTML = `
-
- `;
- $('select').on('change', require(modulePath).changePreference);
-
- await $('select').val('slim').trigger('change');
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/players?action=preference',
- dataType: 'json',
- data: {
- pid: '1',
- preference: 'slim'
- }
- });
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await $('select').trigger('change');
- expect(toastr.warning).toBeCalledWith('warning');
-
- await $('select').trigger('change');
- expect(window.showAjaxError).toBeCalled();
- });
-
- it('submit changed texture information', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const modal = jest.fn();
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.$.fn.modal = modal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
-
-
-
-
- `;
- const ajaxChangeTexture = require(modulePath).ajaxChangeTexture;
-
- await ajaxChangeTexture(1);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/players?action=texture',
- dataType: 'json',
- data: { pid: 1, model: 'default', tid: '1' }
- });
- expect(document.getElementById('shouldBeRemoved')).toBeNull();
- expect(document.getElementById('shouldNotBeRemoved')).not.toBeNull();
- expect(modal).toBeCalledWith('hide');
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
- expect($('img').attr('src')).toBe('preview/64/1.png');
-
- await ajaxChangeTexture(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await ajaxChangeTexture(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change player name', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockImplementationOnce(() => Promise.reject())
- .mockImplementationOnce(options => {
- options.inputValidator('newName');
- return Promise.resolve('newName');
- });
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- const changePlayerName = require(modulePath).changePlayerName;
-
- await changePlayerName(1, 'oldName');
- expect(fetch).not.toBeCalled();
-
- await changePlayerName(1, 'oldName');
- expect(swal).toBeCalledWith(expect.objectContaining({
- text: 'admin.changePlayerNameNotice',
- input: 'text',
- inputValue: 'oldName'
- }));
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/players?action=name',
- dataType: 'json',
- data: { pid: 1, name: 'newName' }
- });
- expect($('tr#1 > td:nth-child(3)').text()).toBe('newName');
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await changePlayerName(1, 'oldName');
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changePlayerName(1, 'oldName');
- expect(showAjaxError).toBeCalled();
- });
-
- it('change owner', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject(new Error));
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn().mockReturnValue(Promise.resolve(2));
- const debounce = jest.fn(fn => fn);
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.debounce = debounce;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
-
- `;
- const changeOwner = require(modulePath).changeOwner;
-
- await changeOwner(1, 'oldName');
- expect(debounce).toBeCalled();
- expect(swal).toBeCalledWith({
- html: 'admin.changePlayerOwner
',
- input: 'number',
- inputValue: '1',
- showCancelButton: true
- });
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/players?action=owner',
- dataType: 'json',
- data: { pid: 1, uid: 2 }
- });
- await changeOwner(1, 'oldName');
- expect($('tr#1 > td:nth-child(2)').text()).toBe('2');
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await changeOwner(1, 'oldName');
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changeOwner(1, 'oldName');
- expect(showAjaxError).toBeCalled();
- });
-
- it('show nickname in swal', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ user: { nickname: 'name' } }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const trans = jest.fn(key => key);
- window.fetch = fetch;
- window.url = url;
- window.trans = trans;
-
- document.body.innerHTML = `
-
-
- `;
- const { showNicknameInSwal } = require(modulePath);
-
- await showNicknameInSwal();
- expect(fetch).not.toBeCalled();
-
- $('input').val('-8');
- await showNicknameInSwal();
- expect(fetch).not.toBeCalled();
-
- $('input').val('8');
- await showNicknameInSwal();
- expect(fetch).toBeCalledWith({
- type: 'GET',
- url: 'admin/user/8',
- dataType: 'json'
- });
- expect($('div').html().includes('name'));
-
- await showNicknameInSwal();
- expect($('div').html().includes('admin.noSuchUser'));
- });
-
- it('delete player', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve());
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- const deletePlayer = require(modulePath).deletePlayer;
-
- await deletePlayer(1);
- expect(fetch).not.toBeCalled();
-
- await deletePlayer(1);
- expect(swal).toBeCalledWith({
- text: 'admin.deletePlayerNotice',
- type: 'warning',
- showCancelButton: true
- });
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/players?action=delete',
- dataType: 'json',
- data: { pid: 1 }
- });
- expect(document.getElementById('1')).toBeNull();
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await deletePlayer(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await deletePlayer(1);
- expect(showAjaxError).toBeCalled();
- });
-});
-
-describe('tests for "plugins" module', () => {
- const modulePath = '../admin/plugins';
-
- // TODO: test initializing plugins table
-
- it('enable a plugin', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ requirements: [] }))
- .mockReturnValueOnce(Promise.resolve({ requirements: [] }))
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({
- isRequirementsSatisfied: false,
- requirements: { 'a': '^1.1.0', 'b': '^2.1.0', 'c': '^3.3.0' },
- unsatisfiedRequirements: { 'c': '^3.3.0' }
- }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'notice', reason: ['reason1', 'reason2'] }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve());
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const reloadTable = jest.fn();
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.swal = swal;
- window.toastr = toastr;
- window.showAjaxError = showAjaxError;
- $.pluginsTable = {
- ajax: {
- reload: reloadTable
- }
- };
-
- const enablePlugin = require(modulePath).enablePlugin;
-
- await enablePlugin('plugin');
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/plugins/manage?action=requirements&name=plugin',
- dataType: 'json'
- });
- expect(swal).toBeCalledWith({
- text: 'admin.noDependenciesNotice',
- type: 'warning',
- showCancelButton: true
- });
- expect(fetch.mock.calls.length).toBe(1);
-
- await enablePlugin('plugin');
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/plugins/manage?action=enable&name=plugin',
- dataType: 'json'
- });
- expect(swal).not.toBeCalledWith({ type: 'warning' });
- expect(toastr.success).toBeCalledWith('success');
- expect(reloadTable).toBeCalledWith(null, false);
-
- await enablePlugin('plugin');
- expect(swal).toBeCalledWith({ type: 'warning', html: 'notice
' });
-
- await enablePlugin('plugin');
- expect(showAjaxError).toBeCalled();
- });
-
- it('disable a plugin', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const reloadTable = jest.fn();
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.showAjaxError = showAjaxError;
- $.pluginsTable = {
- ajax: {
- reload: reloadTable
- }
- };
-
- const disablePlugin = require(modulePath).disablePlugin;
-
- await disablePlugin('plugin');
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/plugins/manage?action=disable&name=plugin',
- dataType: 'json'
- });
- expect(swal).not.toBeCalledWith({ type: 'warning' });
- expect(toastr.success).toBeCalledWith('success');
- expect(reloadTable).toBeCalledWith(null, false);
-
- await disablePlugin('plugin');
- expect(swal).toBeCalledWith({ type: 'warning', html: 'warning' });
-
- await disablePlugin('plugin');
- expect(showAjaxError).toBeCalled();
- });
-
- it('delete a plugin', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const reloadTable = jest.fn();
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve());
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.showAjaxError = showAjaxError;
- $.pluginsTable = {
- ajax: {
- reload: reloadTable
- }
- };
- window.swal = swal;
-
- const deletePlugin = require(modulePath).deletePlugin;
-
- await deletePlugin('plugin');
- expect(fetch).not.toBeCalled();
-
- await deletePlugin('plugin');
- expect(swal).toBeCalledWith({
- text: 'admin.confirmDeletion',
- type: 'warning',
- showCancelButton: true
- });
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/plugins/manage?action=delete&name=plugin',
- dataType: 'json'
- });
- expect(swal).not.toBeCalledWith({ type: 'warning' });
- expect(toastr.success).toBeCalledWith('success');
- expect(reloadTable).toBeCalledWith(null, false);
-
- await deletePlugin('plugin');
- expect(swal).toBeCalledWith({ type: 'warning', html: 'warning' });
-
- await deletePlugin('plugin');
- expect(showAjaxError).toBeCalled();
- });
-});
-
-describe('tests for "update" module', () => {
- const modulePath = '../admin/update';
-
- it('download updates', async () => {
- const fetch = jest.fn()
- .mockImplementationOnce(({ beforeSend }) => {
- beforeSend && beforeSend();
- return Promise.resolve({
- file_size: 5000
- });
- })
- .mockImplementationOnce(() => Promise.resolve())
- .mockImplementationOnce(() => Promise.resolve({ msg: 'ok' }))
- .mockImplementationOnce(() => Promise.reject())
- .mockImplementationOnce(({ beforeSend }) => {
- beforeSend && beforeSend();
- return Promise.resolve({
- file_size: 5000
- });
- })
- .mockImplementationOnce(() => Promise.resolve())
- .mockImplementationOnce(() => Promise.resolve({ msg: 'ok' }));
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const modal = jest.fn();
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.resolve())
- .mockReturnValueOnce(Promise.reject());
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.swal = swal;
- window.showAjaxError = jest.fn();
- $.fn.modal = modal;
-
- document.body.innerHTML = `
-
-
-
-
-
- `;
-
- const downloadUpdates = require(modulePath).downloadUpdates;
-
- await downloadUpdates();
- expect(fetch).toBeCalledWith(expect.objectContaining({
- url: 'admin/update/download?action=prepare-download',
- type: 'GET',
- dataType: 'json',
- }));
- expect($('#update-button').prop('disabled')).toBe(true);
- expect($('#file-size').html()).toBe('5000');
- expect(modal).toBeCalledWith({
- backdrop: 'static',
- keyboard: false
- });
- expect(fetch).toBeCalledWith({
- url: 'admin/update/download?action=start-download',
- type: 'POST',
- dataType: 'json'
- });
- expect($('.modal-title').html().includes('admin.extracting')).toBe(true);
- expect($('.modal-body').html().includes('admin.downloadCompleted')).toBe(true);
- expect(swal).toBeCalledWith({ type: 'success', html: 'ok' });
- expect(url).toBeCalledWith('/');
-
- await downloadUpdates();
- expect(window.showAjaxError).toBeCalled();
-
- await downloadUpdates();
- expect(url).toBeCalledWith('/');
- });
-
- it('download progress polling', async () => {
- const fetch = jest.fn().mockReturnValueOnce(Promise.resolve({ size: 50 }));
- const url = jest.fn(path => path);
- window.fetch = fetch;
- window.url = url;
-
- document.body.innerHTML = `
-
-
- `;
-
- const { progressPolling } = require(modulePath);
- await progressPolling(100)();
- expect(fetch).toBeCalledWith({
- url: 'admin/update/download?action=get-file-size',
- type: 'GET'
- });
- expect($('#imported-progress').html()).toBe('50.00');
- expect($('.progress-bar').css('width')).toBe('50%');
- expect($('.progress-bar').attr('aria-valuenow')).toBe('50.00');
- });
-
- it('check for updates', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({
- available: false,
- latest: '1.1.4'
- }))
- .mockReturnValueOnce(Promise.resolve({
- available: true,
- latest: '5.1.4'
- }));
- const url = jest.fn(path => path);
-
- window.fetch = fetch;
- window.url = url;
-
- document.body.innerHTML = `
- Check Update
- `;
-
- const checkForUpdates = require(modulePath).checkForUpdates;
-
- await checkForUpdates();
- expect($('#target').html()).toBe(
- ' Check Update'
- );
-
- await checkForUpdates();
- expect($('#target').html()).toBe(
- ' Check Update'+
- 'v5.1.4'
- );
- });
-});
-
-describe('tests for "users" module', () => {
- const modulePath = '../admin/users';
-
- // TODO: test initializing users table
-
- it('change user email', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockImplementationOnce(() => Promise.reject())
- .mockImplementationOnce(options => {
- options.inputValidator('a@b.c');
- return Promise.resolve('a@b.c');
- });
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- const changeUserEmail = require(modulePath).changeUserEmail;
-
- await changeUserEmail(1);
- expect(fetch).not.toBeCalled();
-
- await changeUserEmail(1);
- expect(swal).toBeCalledWith(expect.objectContaining({
- text: 'admin.newUserEmail',
- showCancelButton: true,
- input: 'text',
- inputValue: 'd@e.f'
- }));
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=email',
- dataType: 'json',
- data: { uid: 1, email: 'a@b.c' }
- });
- expect($('tr > td:nth-child(2)').text()).toBe('a@b.c');
- expect(toastr.success).toBeCalledWith('success');
-
- await changeUserEmail(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changeUserEmail(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change user nick name', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockImplementationOnce(() => Promise.reject())
- .mockImplementationOnce(options => {
- options.inputValidator('foo');
- return Promise.resolve('foo');
- });
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- const changeUserNickName = require(modulePath).changeUserNickName;
-
- await changeUserNickName(1);
- expect(fetch).not.toBeCalled();
-
- await changeUserNickName(1);
- expect(swal).toBeCalledWith(expect.objectContaining({
- text: 'admin.newUserNickname',
- showCancelButton: true,
- input: 'text',
- inputValue: 'hhh'
- }));
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=nickname',
- dataType: 'json',
- data: { uid: 1, nickname: 'foo' }
- });
- expect($('tr > td:nth-child(3)').text()).toBe('foo');
- expect(toastr.success).toBeCalledWith('success');
-
- await changeUserNickName(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changeUserNickName(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change user password', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve('secret'));
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- const changeUserPwd = require(modulePath).changeUserPwd;
-
- await changeUserPwd(1);
- expect(fetch).not.toBeCalled();
-
- await changeUserPwd(1);
- expect(swal).toBeCalledWith(expect.objectContaining({
- text: 'admin.newUserPassword',
- showCancelButton: true,
- input: 'password',
- }));
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=password',
- dataType: 'json',
- data: { uid: 1, password: 'secret' }
- });
- expect(toastr.success).toBeCalledWith('success');
-
- await changeUserPwd(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changeUserPwd(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change user score', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- const changeUserScore = require(modulePath).changeUserScore;
-
- await changeUserScore('user-1', 50);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=score',
- dataType: 'json',
- data: { uid: '1', score: 50 }
- });
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- await changeUserScore('user-1', 50);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await changeUserScore('user-1', 50);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change ban status', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({
- errno: 0,
- msg: 'success',
- permission: 0
- }))
- .mockReturnValueOnce(Promise.resolve({
- errno: 0,
- msg: 'success',
- permission: -1
- }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- await require(modulePath).changeBanStatus(1);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=ban',
- dataType: 'json',
- data: { uid: 1 }
- });
- expect($('#ban-1').attr('data')).toBe('normal');
- expect($('#ban-1').text()).toBe('admin.ban');
- expect($('.status').text()).toBe('admin.normal');
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- document.body.innerHTML = `
-
- `;
- await require(modulePath).changeBanStatus(1);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=ban',
- dataType: 'json',
- data: { uid: 1 }
- });
- expect($('#ban-1').attr('data')).toBe('banned');
- expect($('#ban-1').text()).toBe('admin.unban');
- expect($('.status').text()).toBe('admin.banned');
-
- await require(modulePath).changeBanStatus(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await require(modulePath).changeBanStatus(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('change admin status', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({
- errno: 0,
- msg: 'success',
- permission: 0
- }))
- .mockReturnValueOnce(Promise.resolve({
- errno: 0,
- msg: 'success',
- permission: 1
- }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = `
-
- `;
- await require(modulePath).changeAdminStatus(1);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=admin',
- dataType: 'json',
- data: { uid: 1 }
- });
- expect($('#admin-1').attr('data')).toBe('normal');
- expect($('#admin-1').text()).toBe('admin.setAdmin');
- expect($('.status').text()).toBe('admin.normal');
- expect(toastr.warning).not.toBeCalled();
- expect(toastr.success).toBeCalledWith('success');
-
- document.body.innerHTML = `
-
- `;
- await require(modulePath).changeAdminStatus(1);
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=admin',
- dataType: 'json',
- data: { uid: 1 }
- });
- expect($('#admin-1').attr('data')).toBe('admin');
- expect($('#admin-1').text()).toBe('admin.unsetAdmin');
- expect($('.status').text()).toBe('admin.admin');
-
- await require(modulePath).changeAdminStatus(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await require(modulePath).changeAdminStatus(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('delete a user', async () => {
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ errno: 0, msg: 'success' }))
- .mockReturnValueOnce(Promise.resolve({ errno: 1, msg: 'warning' }))
- .mockReturnValueOnce(Promise.reject());
- const url = jest.fn(path => path);
- const toastr = {
- success: jest.fn(),
- warning: jest.fn()
- };
- const trans = jest.fn(key => key);
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve());
- const showAjaxError = jest.fn();
- window.fetch = fetch;
- window.url = url;
- window.toastr = toastr;
- window.trans = trans;
- window.swal = swal;
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = '
';
- const deleteUserAccount = require(modulePath).deleteUserAccount;
-
- await deleteUserAccount(1);
- expect(fetch).not.toBeCalled();
-
- await deleteUserAccount(1);
- expect(swal).toBeCalledWith({
- text: 'admin.deleteUserNotice',
- type: 'warning',
- showCancelButton: true
- });
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'admin/users?action=delete',
- dataType: 'json',
- data: { uid: 1 }
- });
- expect(document.getElementById('user-1')).toBeNull();
-
- await deleteUserAccount(1);
- expect(toastr.warning).toBeCalledWith('warning');
-
- await deleteUserAccount(1);
- expect(showAjaxError).toBeCalled();
- });
-
- it('"input" element should be focused out when press enter key', () => {
- document.body.innerHTML = `
-
- `;
-
- require(modulePath);
-
- $('.score').focus();
- const event = $.Event('keypress');
- event.which = 13;
- $('.score').trigger(event);
-
- expect($('.score').is(':focus')).toBe(false);
- });
-});
-
-describe('tests for "common" module', () => {
- const modulePath = '../admin/common';
-
- it('send feedbacks', async () => {
- const fetch = jest.fn()
- .mockReturnValue(Promise.resolve({ errno: 0, msg: 'Recorded.' }));
-
- $.fn.dataTable = { defaults: {}, ext: { errMode: '' } };
- window.document.cookie = '';
- window.fetch = fetch;
- window.blessing = {
- site_name: 'inm',
- base_url: 'http://tdkr.mur',
- version: '8.1.0'
- };
-
- const { sendFeedback } = require(modulePath);
-
- await sendFeedback();
- expect(fetch).toBeCalledWith({
- url: 'https://work.prinzeugen.net/statistics/feedback',
- type: 'POST',
- dataType: 'json',
- data: { site_name: 'inm', site_url: 'http://tdkr.mur', version: '8.1.0' }
- });
- expect(window.document.cookie).not.toBe('');
-
- await sendFeedback();
- expect(fetch).toHaveBeenCalledTimes(1);
- });
-
- it('handle DataTables AJAX error', () => {
- const { handleDataTablesAjaxError } = require(modulePath);
- const showModal = jest.fn();
- window.trans = jest.fn(t => t);
- window.showModal = showModal;
- $.fn.dataTable = { defaults: {}, ext: { errMode: '' } };
-
- handleDataTablesAjaxError(undefined, undefined, '{}');
- expect(showModal).not.toBeCalled();
-
- handleDataTablesAjaxError(undefined, undefined, null, {
- responseText: 'error'
- });
- expect(showModal).toBeCalledWith(
- 'error',
- 'general.fatalError',
- 'danger'
- );
- });
-});
diff --git a/resources/assets/src/js/__tests__/common.test.js b/resources/assets/src/js/__tests__/common.test.js
deleted file mode 100644
index f83412b4..00000000
--- a/resources/assets/src/js/__tests__/common.test.js
+++ /dev/null
@@ -1,244 +0,0 @@
-/* eslint no-unused-vars: "off" */
-
-const $ = require('jquery');
-window.jQuery = window.$ = $;
-
-describe('tests for "i18n" module', () => {
- const modulePath = '../common/i18n';
-
- it('load locales', () => {
- window.isEmpty = obj => !obj; // Just for test
- const loadLocales = require(modulePath).loadLocales;
-
- $.locales = {
- en: { text: 'text', nested: { sth: ':sth here!' } }
- };
-
- loadLocales();
- expect($.currentLocale).toEqual({ text: 'text', nested: { sth: ':sth here!' } });
- });
-
- it('get translated text', () => {
- const trans = require(modulePath).trans;
-
- $.currentLocale = undefined; // Should load locale automatically
- $.locales = {
- en: { text: 'text', nested: { sth: ':sth here!' } }
- };
-
- expect(trans('text')).toBe('text');
- expect(trans('text.nothing')).toBe('text.nothing');
- expect(trans('nested.sth')).toBe(':sth here!');
- expect(trans('nested.sth', { sth: 'abc' })).toBe('abc here!');
- });
-});
-
-jest.useFakeTimers();
-
-describe('tests for "logout" module', () => {
- const modulePath = '../common/logout';
-
- it('logout', async () => {
- const swal = jest.fn()
- .mockReturnValueOnce(Promise.reject())
- .mockReturnValueOnce(Promise.resolve());
- const trans = jest.fn(key => key);
- const fetch = jest.fn()
- .mockReturnValueOnce(Promise.resolve({ msg: 'success' }))
- .mockReturnValueOnce(Promise.reject());
- const showAjaxError = jest.fn();
- window.swal = swal;
- window.trans = trans;
- window.fetch = fetch;
- window.url = jest.fn(path => path);
- window.showAjaxError = showAjaxError;
-
- document.body.innerHTML = '';
- require(modulePath);
-
- await $('button').click();
- expect(fetch).not.toBeCalled();
-
- await $('button').click();
- expect(swal).toBeCalledWith({
- text: 'general.confirmLogout',
- type: 'warning',
- showCancelButton: true,
- confirmButtonText: 'general.confirm',
- cancelButtonText: 'general.cancel'
- });
- expect(fetch).toBeCalledWith({
- type: 'POST',
- url: 'auth/logout',
- dataType: 'json'
- });
- jest.runAllTimers();
- expect(url).toBeCalled();
-
- await $('button').click();
- expect(swal).toBeCalledWith({ type: 'success', html: 'success' });
-
- await $('button').click();
- expect(showAjaxError).toBeCalled();
- });
-});
-
-jest.useRealTimers();
-
-describe('tests for "notify" module', () => {
- const modulePath = '../common/notify';
-
- it('show message', () => {
- document.body.innerHTML = '';
-
- const showMsg = require(modulePath).showMsg;
-
- showMsg('msg1');
- expect($('div').hasClass('a-class')).toBe(false);
- expect($('div').hasClass('callout')).toBe(true);
- expect($('div').hasClass('callout-info')).toBe(true);
- expect($('div').html()).toBe('msg1');
-
- showMsg('msg2', 'warning');
- expect($('div').hasClass('callout-info')).toBe(false);
- expect($('div').hasClass('callout')).toBe(true);
- expect($('div').hasClass('callout-warning')).toBe(true);
- expect($('div').html()).toBe('msg2');
- });
-
- it('show ajax error', () => {
- window.trans = jest.fn(key => key);
- $.fn.modal = jest.fn();
-
- const showAjaxError = require(modulePath).showAjaxError;
-
- showAjaxError({ responseText: 'error' });
- expect(window.trans).toBeCalledWith('general.fatalError');
- });
-
- it('show modal dialog', () => {
- const modal = jest.fn();
- $.fn.modal = modal;
-
- const showModal = require(modulePath).showModal;
- showModal('');
- expect(modal).toBeCalled();
- });
-});
-
-describe('tests for "polyfill" module', () => {
- const modulePath = '../common/polyfill';
-
- String.prototype.includes = undefined;
- String.prototype.endsWith = undefined;
- require(modulePath);
-
- it('String#includes', () => {
- expect('blessing-skin'.includes('skin')).toBe(true);
- expect('blessing-skin'.includes('server')).toBe(false);
- expect('blessing-skin'.includes('skin', 9)).toBe(true);
- expect('blessing-skin'.includes('blessing', 9)).toBe(false);
- });
-
- it('String#endsWith', () => {
- expect('blessing-skin'.endsWith('skin')).toBe(true);
- expect('blessing-skin'.endsWith('server')).toBe(false);
- expect('blessing-skin'.endsWith('blessing', 8)).toBe(true);
- });
-});
-
-describe('tests for "utils" module', () => {
- const modulePath = '../common/utils';
-
- window.blessing = {
- version: ''
- };
-
- it('check a variable if it is empty', () => {
- const isEmpty = require(modulePath).isEmpty;
-
- expect(isEmpty()).toBe(true);
- expect(isEmpty(null)).toBe(true);
- expect(isEmpty(undefined)).toBe(true);
- expect(isEmpty(0)).toBe(false);
- expect(isEmpty(false)).toBe(false);
- expect(isEmpty('')).toBe(true);
- expect(isEmpty({})).toBe(true);
- expect(isEmpty({ sth: '' })).toBe(false);
- expect(isEmpty([])).toBe(true);
- expect(isEmpty([1])).toBe(false);
- expect(isEmpty('something')).toBe(false);
- expect(isEmpty(Symbol())).toBe(true);
- });
-
- it('fake fetch', () => {
- $.ajax = jest.fn();
- const fetch = require(modulePath).fetch;
- const xhr = fetch({ type: 'GET' });
-
- expect($.ajax).toBeCalledWith({ type: 'GET' });
- expect(Object.getPrototypeOf(xhr)).toBe(Promise.prototype);
- });
-
- it('make a debounced function', done => {
- const func = jest.fn();
- const debounce = require(modulePath).debounce;
- const debounced = debounce(func, 100);
-
- debounced();
- debounced();
-
- setTimeout(() => {
- expect(func.mock.calls.length).toBe(1);
- done();
- }, 100);
- jest.runAllTimers();
-
- expect(() => debounce(func, 'string')).toThrow();
- expect(() => debounce('not a function', 100)).toThrow();
- });
-
- it('get a absolute url', () => {
- window.blessing = { base_url: 'http://localhost' };
- const url = require(modulePath).url;
-
- expect(url()).toBe('http://localhost/');
- expect(url('test')).toBe('http://localhost/test');
- expect(url('/test')).toBe('http://localhost/test');
- });
-
- it('get argument from query string', () => {
- const { getQueryString } = require(modulePath);
-
- Object.defineProperty(window.location, 'search', {
- value: '?key1=val1',
- writable: true
- });
- expect(getQueryString('key1')).toBe('val1');
- expect(getQueryString('key2')).toBeUndefined();
- expect(getQueryString('key2', 'val2')).toBe('val2');
- window.location.search = '?key1=val1&key2=val2';
- expect(getQueryString('key2', 'val2')).toBe('val2');
- });
-
- it('test `isMobileBrowserScrolling` function', () => {
- const { isMobileBrowserScrolling } = require(modulePath);
- expect(isMobileBrowserScrolling()).toBe(false);
-
- $.cachedWindowWidth = 50;
- $.cachedWindowHeight = 50;
- expect(isMobileBrowserScrolling()).toBe(false);
-
- $.cachedWindowWidth = 60;
- $.cachedWindowHeight = 0;
- expect(isMobileBrowserScrolling()).toBe(false);
-
- $.cachedWindowWidth = 0;
- $.cachedWindowHeight = 50;
- expect(isMobileBrowserScrolling()).toBe(true);
- expect(isMobileBrowserScrolling()).toBe(true); // For the second condition
-
- $.lastWindowHeight = 60;
- expect(isMobileBrowserScrolling()).toBe(false);
- });
-});
diff --git a/resources/assets/src/js/admin/customize.js b/resources/assets/src/js/admin/customize.js
deleted file mode 100644
index 53e49823..00000000
--- a/resources/assets/src/js/admin/customize.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* global current_skin:true */
-
-'use strict';
-
-$('#layout-skins-list [data-skin]').click(function (e) {
- e.preventDefault();
- const skin_name = $(this).data('skin');
- $('body').removeClass(current_skin).addClass(skin_name);
- current_skin = skin_name;
-});
-
-async function submitColor() {
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/customize?action=color'),
- dataType: 'json',
- data: { color_scheme: current_skin }
- });
- errno === 0 ? toastr.success(msg) : toastr.warning(msg);
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-$('#color-submit').click(submitColor);
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = submitColor;
-}
diff --git a/resources/assets/src/js/admin/players.js b/resources/assets/src/js/admin/players.js
deleted file mode 100644
index c423833c..00000000
--- a/resources/assets/src/js/admin/players.js
+++ /dev/null
@@ -1,288 +0,0 @@
-'use strict';
-
-if ($('#player-table').length === 1) {
- $(document).ready(initPlayersTable);
-}
-
-function initPlayersTable() {
- const specificUid = getQueryString('uid');
- const query = specificUid ? `?uid=${specificUid}` : '';
-
- $('#player-table').DataTable({
- ajax: url(`admin/player-data${query}`),
- scrollY: ($('.content-wrapper').height() - $('.content-header').outerHeight()) * 0.7,
- fnDrawCallback: () => $('[data-toggle="tooltip"]').tooltip(),
- columnDefs: playersTableColumnDefs
- }).on('xhr.dt', handleDataTablesAjaxError);
-}
-
-const playersTableColumnDefs = [
- {
- targets: 0,
- data: 'pid',
- width: '1%'
- },
- {
- targets: 1,
- data: 'uid',
- render: (data, type, row) => `${data}`
- },
- {
- targets: 2,
- data: 'player_name'
- },
- {
- targets: 3,
- data: 'preference',
- render: data => {
- return `
- `;
- }
- },
- {
- targets: 4,
- searchable: false,
- orderable: false,
- render: (data, type, row) => ['steve', 'alex', 'cape'].reduce((html, type) => {
- const currentTypeTid = row[`tid_${type}`];
- const imageId = `${row.pid}-${currentTypeTid}`;
-
- if (currentTypeTid === 0) {
- return html + `
`;
- } else {
- return html + `
-
-
- `;
- }
- }, '')
- },
- {
- targets: 5,
- data: 'last_modified'
- },
- {
- targets: 6,
- searchable: false,
- orderable: false,
- render: (data, type, row) => `
-
-
-
-
- ${trans('admin.deletePlayer')}`
- }
-];
-
-async function changePreference() {
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/players?action=preference'),
- dataType: 'json',
- data: {
- pid: $(this).parent().parent().attr('id'),
- preference: $(this).val()
- }
- });
- errno === 0 ? toastr.success(msg) : toastr.warning(msg);
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-function changeTexture(pid, playerName) {
- const dom = `
-
-
-
-
-
-
-
-
`;
-
- showModal(dom, trans('admin.changePlayerTexture', { 'player': playerName }), 'default', {
- callback: `ajaxChangeTexture(${pid})`
- });
- return;
-}
-
-async function ajaxChangeTexture(pid) {
- // Remove interference of modal which is hide
- $('.modal').each(function () {
- if ($(this).css('display') === 'none') $(this).remove();
- });
-
- const model = $('#model').val();
- const tid = $('#tid').val();
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/players?action=texture'),
- dataType: 'json',
- data: { pid: pid, model: model, tid: tid }
- });
- if (errno === 0) {
- $(`#${pid}-${model}`).attr('src', url(`preview/64/${tid}.png`));
- $('.modal').modal('hide');
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changePlayerName(pid, oldName) {
- const dom = $(`tr#${pid} > td:nth-child(3)`);
- let newPlayerName;
-
- try {
- newPlayerName = await swal({
- text: trans('admin.changePlayerNameNotice'),
- input: 'text',
- inputValue: oldName,
- inputValidator: name => (new Promise((resolve, reject) => {
- name ? resolve() : reject(trans('admin.emptyPlayerName'));
- }))
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/players?action=name'),
- dataType: 'json',
- data: { pid: pid, name: newPlayerName }
- });
- if (errno === 0) {
- dom.text(newPlayerName);
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-function changeOwner(pid) {
- const dom = $(`#${pid} > td:nth-child(2)`);
- let owner = 0;
-
- swal({
- html: `${trans('admin.changePlayerOwner')}
`,
- input: 'number',
- inputValue: dom.text(),
- showCancelButton: true
- }).then(async uid => {
- owner = uid;
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/players?action=owner'),
- dataType: 'json',
- data: { pid, uid }
- });
- if (errno === 0) {
- dom.text(owner);
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
- });
-
- $('.swal2-input').on('input', debounce(showNicknameInSwal, 350));
-}
-
-async function showNicknameInSwal() {
- const uid = $('.swal2-input').val();
-
- if (isNaN(uid) || uid <= 0)
- return;
-
- try {
- const { user } = await fetch({
- type: 'GET',
- url: url(`admin/user/${uid}`),
- dataType: 'json'
- });
- $('.swal2-content').html(
- trans('admin.changePlayerOwner') +
- '' +
- trans('admin.targetUser', { nickname: user.nickname }) +
- ''
- );
- } catch (error) {
- $('.swal2-content').html(`
- ${trans('admin.changePlayerOwner')}
- ${trans('admin.noSuchUser')}
- `);
- }
-}
-
-async function deletePlayer(pid) {
- try {
- await swal({
- text: trans('admin.deletePlayerNotice'),
- type: 'warning',
- showCancelButton: true
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/players?action=delete'),
- dataType: 'json',
- data: { pid: pid }
- });
- if (errno === 0) {
- $(`tr#${pid}`).remove();
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- initPlayersTable,
- changeOwner,
- showNicknameInSwal,
- deletePlayer,
- changeTexture,
- changePlayerName,
- changePreference,
- ajaxChangeTexture,
- };
-}
diff --git a/resources/assets/src/js/admin/plugins.js b/resources/assets/src/js/admin/plugins.js
deleted file mode 100644
index ed0a6136..00000000
--- a/resources/assets/src/js/admin/plugins.js
+++ /dev/null
@@ -1,178 +0,0 @@
-'use strict';
-
-if ($('#plugin-table').length === 1) {
- $(document).ready(initPluginsTable);
-}
-
-function initPluginsTable() {
- $.pluginsTable = $('#plugin-table').DataTable({
- ajax: url('admin/plugins/data'),
- fnDrawCallback: () => $('[data-toggle="tooltip"]').tooltip(),
- columnDefs: pluginsTableColumnDefs
- }).on('xhr.dt', handleDataTablesAjaxError);
-}
-
-const pluginsTableColumnDefs = [
- {
- targets: 0,
- data: 'title'
- },
- {
- targets: 1,
- data: 'description',
- orderable: false,
- width: '35%'
- },
- {
- targets: 2,
- data: 'author',
- render: data => isEmpty(data.url) ? data.author : `${data.author}`
- },
- {
- targets: 3,
- data: 'version',
- orderable: false
- },
- {
- targets: 4,
- data: 'dependencies',
- searchable: false,
- orderable: false,
- render: data => {
- if (data.requirements.length === 0) {
- return `${trans('admin.noDependencies')}`;
- }
-
- let result = data.isRequirementsSatisfied ? '' : `${trans('admin.whyDependencies')}
`;
-
- for (const name in data.requirements) {
- const constraint = data.requirements[name];
- const color = (name in data.unsatisfiedRequirements) ? 'red' : 'green';
-
- result += `${name}: ${constraint}
`;
- }
-
- return result;
- }
- },
- {
- targets: 5,
- data: 'status'
- },
- {
- targets: 6,
- data: 'operations',
- searchable: false,
- orderable: false,
- render: (data, type, row) => {
- let toggleButton, configViewButton;
-
- if (data.enabled) {
- toggleButton = `${trans('admin.disablePlugin')}`;
- } else {
- toggleButton = `${trans('admin.enablePlugin')}`;
- }
-
- if (data.enabled && data.hasConfigView) {
- configViewButton = `${trans('admin.configurePlugin')}`;
- } else {
- configViewButton = `${trans('admin.configurePlugin')}`;
- }
-
- const deletePluginButton = `${trans('admin.deletePlugin')}`;
-
- return toggleButton + configViewButton + deletePluginButton;
- }
- }
-];
-
-async function enablePlugin(name) {
- try {
- const { requirements } = await fetch({
- type: 'POST',
- url: url(`admin/plugins/manage?action=requirements&name=${name}`),
- dataType: 'json'
- });
-
- if (requirements.length === 0) {
- await swal({
- text: trans('admin.noDependenciesNotice'),
- type: 'warning',
- showCancelButton: true
- });
- }
-
- const { errno, msg, reason } = await fetch({
- type: 'POST',
- url: url(`admin/plugins/manage?action=enable&name=${name}`),
- dataType: 'json'
- });
-
- if (errno === 0) {
- toastr.success(msg);
-
- $.pluginsTable.ajax.reload(null, false);
- } else {
- swal({ type: 'warning', html: `${msg}
` });
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function disablePlugin(name) {
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url(`admin/plugins/manage?action=disable&name=${name}`),
- dataType: 'json'
- });
- if (errno === 0) {
- toastr.success(msg);
-
- $.pluginsTable.ajax.reload(null, false);
- } else {
- swal({ type: 'warning', html: msg });
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function deletePlugin(name) {
- try {
- await swal({
- text: trans('admin.confirmDeletion'),
- type: 'warning',
- showCancelButton: true
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url(`admin/plugins/manage?action=delete&name=${name}`),
- dataType: 'json'
- });
- if (errno === 0) {
- toastr.success(msg);
-
- $.pluginsTable.ajax.reload(null, false);
- } else {
- swal({ type: 'warning', html: msg });
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- initPluginsTable,
- deletePlugin,
- enablePlugin,
- disablePlugin,
- };
-}
diff --git a/resources/assets/src/js/admin/users.js b/resources/assets/src/js/admin/users.js
deleted file mode 100644
index b01c7a04..00000000
--- a/resources/assets/src/js/admin/users.js
+++ /dev/null
@@ -1,346 +0,0 @@
-'use strict';
-
-if ($('#user-table').length === 1) {
- $(document).ready(initUsersTable);
-}
-
-function initUsersTable() {
- const specificUid = getQueryString('uid');
- const query = specificUid ? `?uid=${specificUid}` : '';
-
- $('#user-table').DataTable({
- ajax: url(`admin/user-data${query}`),
- scrollY: ($('.content-wrapper').height() - $('.content-header').outerHeight()) * 0.7,
- fnDrawCallback: () => $('[data-toggle="tooltip"]').tooltip(),
- rowCallback: (row, data) => $(row).attr('id', `user-${data.uid}`),
- columnDefs: usersTableColumnDefs
- }).on('xhr.dt', handleDataTablesAjaxError);
-}
-
-const userPermissions = {
- '-1': 'banned',
- '0': 'normal',
- '1': 'admin',
- '2': 'superAdmin'
-};
-
-const usersTableColumnDefs = [
- {
- targets: 0,
- data: 'uid',
- width: '1%'
- },
- {
- targets: 1,
- data: 'email'
- },
- {
- targets: 2,
- data: 'nickname'
- },
- {
- targets: 3,
- data: 'score',
- render: data => ``
- },
- {
- targets: 4,
- data: 'players_count',
- searchable: false,
- orderable: false,
- render: (data, type, row) => `${data}`
- },
- {
- targets: 5,
- data: 'permission',
- className: 'status',
- render: data => trans('admin.' + userPermissions[data])
- },
- {
- targets: 6,
- data: 'register_at'
- },
- {
- targets: 7,
- data: 'operations',
- searchable: false,
- orderable: false,
- render: renderUsersTableOperations
- }
-];
-
-function renderUsersTableOperations(currentUserPermission, type, row) {
- let adminOption = '', bannedOption = '', deleteUserButton;
-
- if (row.permission !== 2) {
- // Only SUPER admins are allowed to set/unset admins
- if (currentUserPermission === 2) {
- const adminStatus = row.permission === 1 ? 'admin' : 'normal';
- adminOption = `
- ${ adminStatus === 'admin' ? trans('admin.unsetAdmin') : trans('admin.setAdmin') }
- `;
- }
-
- const banStatus = row.permission === -1 ? 'banned' : 'normal';
- bannedOption = `
- ${ banStatus === 'banned' ? trans('admin.unban') : trans('admin.ban') }
- `;
- }
-
- if (currentUserPermission === 2) {
- if (row.permission === 2) {
- deleteUserButton = `${trans('admin.deleteUser')}`;
- } else {
- deleteUserButton = `${trans('admin.deleteUser')}`;
- }
- } else {
- if (row.permission === 1 || row.permission === 2) {
- deleteUserButton = `${trans('admin.deleteUser')}`;
- } else {
- deleteUserButton = `${trans('admin.deleteUser')}`;
- }
- }
-
- return `
-
-
-
-
- ${deleteUserButton}`;
-}
-
-async function changeUserEmail(uid) {
- const dom = $(`tr#user-${uid} > td:nth-child(2)`);
- let newUserEmail = '';
-
- try {
- newUserEmail = await swal({
- text: trans('admin.newUserEmail'),
- showCancelButton: true,
- input: 'text',
- inputValue: dom.text(),
- inputValidator: value => (new Promise((resolve, reject) => {
- value ? resolve() : reject(trans('auth.emptyEmail'));
- }))
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/users?action=email'),
- dataType: 'json',
- data: { uid: uid, email: newUserEmail }
- });
-
- if (errno === 0) {
- dom.text(newUserEmail);
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changeUserNickName(uid) {
- const dom = $(`tr#user-${uid} > td:nth-child(3)`);
- let newNickName = '';
-
- try {
- newNickName = await swal({
- text: trans('admin.newUserNickname'),
- showCancelButton: true,
- input: 'text',
- inputValue: dom.text(),
- inputValidator: value => (new Promise((resolve, reject) => {
- value ? resolve() : reject(trans('auth.emptyNickname'));
- }))
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/users?action=nickname'),
- dataType: 'json',
- data: { uid: uid, nickname: newNickName }
- });
- if (errno === 0) {
- dom.text(newNickName);
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changeUserPwd(uid) {
- let password;
- try {
- password = await swal({
- text: trans('admin.newUserPassword'),
- showCancelButton: true,
- input: 'password',
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/users?action=password'),
- dataType: 'json',
- data: { uid: uid, password: password }
- });
- errno === 0 ? toastr.success(msg) : toastr.warning(msg);
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changeUserScore(uid, score) {
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/users?action=score'),
- dataType: 'json',
- // Handle id formatted as '#user-1234'
- data: { uid: uid.slice(5), score: score }
- });
- errno === 0 ? toastr.success(msg) : toastr.warning(msg);
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changeBanStatus(uid) {
- try {
- const { errno, msg, permission } = await fetch({
- type: 'POST',
- url: url('admin/users?action=ban'),
- dataType: 'json',
- data: { uid: uid }
- });
-
- if (errno === 0) {
- const dom = $(`#ban-${uid}`);
-
- if (dom.attr('data') === 'banned') {
- dom.text(trans('admin.ban')).attr('data', 'normal');
- } else {
- dom.text(trans('admin.unban')).attr('data', 'banned');
- }
-
- $(`#user-${uid} > td.status`).text(
- permission === -1 ? trans('admin.banned') : trans('admin.normal')
- );
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function changeAdminStatus(uid) {
- try {
- const { errno, msg, permission } = await fetch({
- type: 'POST',
- url: url('admin/users?action=admin'),
- dataType: 'json',
- data: { uid: uid }
- });
-
- if (errno === 0) {
- const dom = $(`#admin-${uid}`);
-
- if (dom.attr('data') === 'admin') {
- dom.text(trans('admin.setAdmin')).attr('data', 'normal');
- } else {
- dom.text(trans('admin.unsetAdmin')).attr('data', 'admin');
- }
-
- $(`#user-${uid} > td.status`).text(
- (permission === 1) ? trans('admin.admin') : trans('admin.normal')
- );
-
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-async function deleteUserAccount(uid) {
- try {
- await swal({
- text: trans('admin.deleteUserNotice'),
- type: 'warning',
- showCancelButton: true
- });
- } catch (error) {
- return;
- }
-
- try {
- const { errno, msg } = await fetch({
- type: 'POST',
- url: url('admin/users?action=delete'),
- dataType: 'json',
- data: { uid: uid }
- });
-
- if (errno === 0) {
- $('tr#user-' + uid).remove();
- toastr.success(msg);
- } else {
- toastr.warning(msg);
- }
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-$('body').on('keypress', '.score', function(event){
- // Change score when Enter key is pressed
- if (event.which === 13) {
- $(this).blur();
- changeUserScore($(this).parent().parent().attr('id'), $(this).val());
- }
-});
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- initUsersTable,
- changeUserPwd,
- changeBanStatus,
- changeUserEmail,
- changeUserScore,
- changeAdminStatus,
- deleteUserAccount,
- changeUserNickName,
- };
-}
diff --git a/resources/assets/src/js/common/i18n.js b/resources/assets/src/js/common/i18n.js
deleted file mode 100644
index 6671fde9..00000000
--- a/resources/assets/src/js/common/i18n.js
+++ /dev/null
@@ -1,56 +0,0 @@
-'use strict';
-
-$.locales = Object.create(null);
-$.currentLocale = Object.create(null);
-
-/**
- * Load current selected language.
- *
- * @return void
- */
-function loadLocales() {
- for (const lang in $.locales) {
- if (!isEmpty($.locales[lang])) {
- $.currentLocale = $.locales[lang] || Object.create(null);
- }
- }
-}
-
-/**
- * Translate according to given key.
- *
- * @param {string} key
- * @param {dict} parameters
- * @return {string}
- */
-function trans(key, parameters = {}) {
- if (isEmpty($.currentLocale)) {
- loadLocales();
- }
-
- const segments = key.split('.');
- let temp = $.currentLocale || {};
-
- for (const i in segments) {
- if (isEmpty(temp[segments[i]])) {
- return key;
- } else {
- temp = temp[segments[i]];
- }
- }
-
- for (const i in parameters) {
- if (!isEmpty(parameters[i])) {
- temp = temp.replace(':'+i, parameters[i]);
- }
- }
-
- return temp;
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- trans,
- loadLocales,
- };
-}
diff --git a/resources/assets/src/js/common/layout.js b/resources/assets/src/js/common/layout.js
deleted file mode 100644
index 886b725a..00000000
--- a/resources/assets/src/js/common/layout.js
+++ /dev/null
@@ -1,26 +0,0 @@
-'use strict';
-
-$.defaultPaginatorConfig = {
- visiblePages: 5,
- currentPage: 1,
- first: '«',
- prev: '‹',
- next: '›',
- last: '»',
- page: '{{page}}',
- wrapper: ''
-};
-
-$(document).ready(() => {
- $('input').iCheck({
- radioClass: 'iradio_square-blue',
- checkboxClass: 'icheckbox_square-blue'
- });
-
- $('[data-toggle="tooltip"]').tooltip();
-
- swal.setDefaults({
- confirmButtonText: trans('general.confirm'),
- cancelButtonText: trans('general.cancel')
- });
-});
diff --git a/resources/assets/src/js/common/logout.js b/resources/assets/src/js/common/logout.js
deleted file mode 100644
index efba28cf..00000000
--- a/resources/assets/src/js/common/logout.js
+++ /dev/null
@@ -1,36 +0,0 @@
-'use strict';
-
-async function confirmLogout() {
- try {
- await swal({
- text: trans('general.confirmLogout'),
- type: 'warning',
- showCancelButton: true,
- confirmButtonText: trans('general.confirm'),
- cancelButtonText: trans('general.cancel')
- });
- } catch (error) {
- return;
- }
-
- try {
- const { msg } = await logout();
- setTimeout(() => window.location = url(), 1000);
- swal({
- type: 'success',
- html: msg
- });
- } catch (error) {
- showAjaxError(error);
- }
-}
-
-function logout() {
- return fetch({
- type: 'POST',
- url: url('auth/logout'),
- dataType: 'json'
- });
-}
-
-$('#logout-button').click(confirmLogout);
diff --git a/resources/assets/src/js/common/notify.js b/resources/assets/src/js/common/notify.js
deleted file mode 100644
index 02abae7a..00000000
--- a/resources/assets/src/js/common/notify.js
+++ /dev/null
@@ -1,78 +0,0 @@
-'use strict';
-
-/**
- * Show message to div#msg with level
- *
- * @param {string} msg
- * @param {string} type
- * @return {void}
- */
-function showMsg(msg, type = 'info') {
- $('[id=msg]').removeClass().addClass('callout').addClass(`callout-${type}`).html(msg);
-}
-
-/**
- * Show modal if error occured when sending an ajax request.
- *
- * @param {object} json
- * @return {void}
- */
-function showAjaxError(json) {
- if (typeof json === 'string') {
- return console.warn(json);
- }
-
- if (! json.responseText) {
- return console.warn('Empty Ajax response body.');
- }
-
- showModal(json.responseText.replace(/\n/g, '
'), trans('general.fatalError'), 'danger');
-}
-
-/**
- * Show a bootstrap modal.
- *
- * @param {string} msg Modal content
- * @param {string} title Modal title
- * @param {string} type Modal type, default|info|success|warning|error
- * @param {object} options All $.fn.modal options, plus { btnText, callback, destroyOnClose }
- * @return {void}
- */
-function showModal(msg, title = 'Message', type = 'default', options = {}) {
- const btnType = (type !== 'default') ? 'btn-outline' : 'btn-primary';
- const btnText = options.btnText || 'OK';
- const onClick = (options.callback === undefined) ? 'data-dismiss="modal"' : `onclick="${options.callback}"`;
- const destroyOnClose = (options.destroyOnClose === false) ? false : true;
-
- const dom = `
- `;
-
- $(dom).on('hidden.bs.modal', function () {
- destroyOnClose && $(this).remove();
- }).modal(options);
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- showMsg,
- showModal,
- showAjaxError,
- };
-}
diff --git a/resources/assets/src/js/common/polyfill.js b/resources/assets/src/js/common/polyfill.js
deleted file mode 100644
index 4c39123b..00000000
--- a/resources/assets/src/js/common/polyfill.js
+++ /dev/null
@@ -1,22 +0,0 @@
-'use strict';
-
-// polyfill of String.prototype.includes
-if (!String.prototype.includes) {
- String.prototype.includes = function(search) {
- // Copied from core-js
- return !!~this.indexOf(search, arguments.length > 1 ? arguments[1] : undefined);
- };
-}
-
-// polyfill of String.prototype.endsWith
-if (!String.prototype.endsWith) {
- String.prototype.endsWith = function (searchString, position) {
- const subjectString = this.toString();
- if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
- position = subjectString.length;
- }
- position -= searchString.length;
- const lastIndex = subjectString.lastIndexOf(searchString, position);
- return lastIndex !== -1 && lastIndex === position;
- };
-}
diff --git a/resources/assets/src/js/common/skinview3d.js b/resources/assets/src/js/common/skinview3d.js
deleted file mode 100644
index d2d096f3..00000000
--- a/resources/assets/src/js/common/skinview3d.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/* global skinview3d */
-
-// TODO: Help wanted. This file needs to be tested.
-
-$.msp = {};
-$.msp.handles = {};
-$.msp.control = null;
-$.msp.config = {
- domElement: document.getElementById('preview-3d-container'),
- slim: false,
- width: $('#preview-3d-container').width(),
- height: $('#preview-3d-container').height(),
- skinUrl: '',
- capeUrl: ''
-};
-
-function initSkinViewer(cameraPositionZ = 70) {
- disposeSkinViewer();
-
- $.msp.viewer = new skinview3d.SkinViewer($.msp.config);
- $.msp.viewer.camera.position.z = cameraPositionZ;
-
- $.msp.viewer.animation = new skinview3d.CompositeAnimation();
-
- // Init all available animations and pause them
- $.msp.handles.walk = $.msp.viewer.animation.add(skinview3d.WalkingAnimation);
- $.msp.handles.run = $.msp.viewer.animation.add(skinview3d.RunningAnimation);
- $.msp.handles.rotate = $.msp.viewer.animation.add(skinview3d.RotatingAnimation);
- $.msp.handles.run.paused = true;
-
- $.msp.control = skinview3d.createOrbitControls($.msp.viewer);
-}
-
-function applySkinViewerConfig(config) {
- config = config || $.msp.config;
-
- for (const key in config) {
- $.msp.viewer[key] = config[key];
- }
-}
-
-function disposeSkinViewer() {
- if ($.msp.viewer instanceof skinview3d.SkinViewer) {
- $.msp.viewer.dispose();
- $.msp.handles = {};
- $.msp.control = undefined;
- }
-}
-
-function registerAnimationController() {
- $('.fa-pause').click(function () {
- $.msp.viewer.animationPaused = !$.msp.viewer.animationPaused;
- $(this).toggleClass('fa-pause').toggleClass('fa-play');
- });
-
- $('.fa-forward').click(function () {
- $.msp.handles.run.paused = !$.msp.handles.run.paused;
- $.msp.handles.walk.paused = !$.msp.handles.run.paused;
- });
-
- $('.fa-repeat').click(() => ($.msp.handles.rotate.paused = !$.msp.handles.rotate.paused));
- $('.fa-stop').click(() => {
- initSkinViewer();
-
- // Pause all animations respectively
- for (const key in $.msp.handles) {
- $.msp.handles[key].paused = true;
- }
- });
-}
-
-function registerWindowResizeHandler() {
- $(window).resize(function () {
- $.msp.viewer.width = $('#preview-3d-container').width();
- $.msp.viewer.height = $('#preview-3d-container').height();
- });
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = { initSkinViewer, applySkinViewerConfig, registerAnimationController, registerWindowResizeHandler };
-}
diff --git a/resources/assets/src/js/common/utils.js b/resources/assets/src/js/common/utils.js
deleted file mode 100644
index f20044d5..00000000
--- a/resources/assets/src/js/common/utils.js
+++ /dev/null
@@ -1,158 +0,0 @@
-'use strict';
-
-console.log(
- `%c Blessing Skin %c v${blessing.version} %c Made with %c<3%c by printempw.%c https://blessing.studio`,
- 'color:#fadfa3;background:#030307;padding:5px 0;margin:10px 0;',
- 'background:#fadfa3;padding:5px 0;',
- 'font-style:italic;',
- 'color:red;',
- 'font-style:italic;', ''
-);
-
-/**
- * Check if given value is empty.
- *
- * @param {any} obj
- * @return {Boolean}
- */
-function isEmpty(obj) {
-
- // null and undefined are "empty"
- if (obj == null) return true; // eslint-disable-line eqeqeq
-
- if (typeof (obj) === 'number' || typeof (obj) === 'boolean') return false;
-
- // Assume if it has a length property with a non-zero value
- // that that property is correct.
- if (obj.length > 0) return false;
- if (obj.length === 0) return true;
-
- // If it isn't an object at this point
- // it is empty, but it can't be anything *but* empty
- // Is it empty? Depends on your application.
- if (typeof obj !== 'object') return true;
-
- // Otherwise, does it have any properties of its own?
- // Note that this doesn't handle
- // toString and valueOf enumeration bugs in IE < 9
- for (const key in obj) {
- if (hasOwnProperty.call(obj, key)) return false;
- }
-
- return true;
-}
-
-/**
- * A fake fetch API. Returns Promises.
- *
- * @param {array} option Same as options of jQuery.ajax()
- * @return {Promise}
- */
-function fetch(option) {
- return Promise.resolve($.ajax(option));
-}
-
-/**
- * Get parameters in query string with key.
- *
- * @param {string} key
- * @param {string} defaultValue
- * @return {string}
- */
-function getQueryString(key, defaultValue) {
- const result = location.search.match(new RegExp('[?&]'+key+'=([^&]+)','i'));
-
- if (result === null || result.length < 1){
- return defaultValue;
- } else {
- return result[1];
- }
-}
-
-/**
- * Check if the `resize` event is fired by scrolling on a mobile browser
- * whose address bar (e.g. Chrome) will hide automatically when scrolling.
- *
- * @return {Boolean}
- */
-function isMobileBrowserScrolling() {
- const currentWindowWidth = $(window).width();
- const currentWindowHeight = $(window).height();
-
- if ($.cachedWindowWidth === undefined) {
- $.cachedWindowWidth = currentWindowWidth;
- }
-
- if ($.cachedWindowHeight === undefined) {
- $.cachedWindowHeight = currentWindowHeight;
- }
-
- const isWidthChanged = (currentWindowWidth !== $.cachedWindowWidth);
- const isHeightChanged = (currentWindowHeight !== $.cachedWindowHeight);
-
- // If the window width & height changes simultaneously, the resize can't be fired by scrolling.
- if (isWidthChanged && isHeightChanged) {
- return false;
- }
-
- // If only width was changed, it also can't be.
- if (isWidthChanged) {
- return false;
- }
-
- // If width didn't change but height changed ?
- if (isHeightChanged) {
- const last = $.lastWindowHeight;
- $.lastWindowHeight = currentWindowHeight;
-
- if (last === undefined || currentWindowHeight === last) {
- return true;
- }
- }
-
- // If both width & height did not change
- return false;
-}
-
-/**
- * Return a debounced function
- *
- * @param {Function} func
- * @param {number} delay
- * @param {Array} args
- * @param {Object} context
- */
-function debounce(func, delay, args = [], context = undefined) {
- if (isNaN(delay) || typeof func !== 'function') {
- throw new Error('Arguments type of function "debounce" is incorrect!');
- }
-
- let timer = null;
- return function () {
- clearTimeout(timer);
- timer = setTimeout(() => {
- func.apply(context, args);
- }, delay);
- };
-}
-
-function url(relativeUri = '') {
- blessing.base_url = blessing.base_url || '';
-
- if (relativeUri[0] !== '/') {
- relativeUri = '/' + relativeUri;
- }
-
- return blessing.base_url + relativeUri;
-}
-
-if (process.env.NODE_ENV === 'test') {
- module.exports = {
- url,
- fetch,
- isEmpty,
- debounce,
- getQueryString,
- isMobileBrowserScrolling,
- };
-}
diff --git a/resources/assets/src/js/index.js b/resources/assets/src/js/index.js
index 95feb8e0..7d5063ad 100644
--- a/resources/assets/src/js/index.js
+++ b/resources/assets/src/js/index.js
@@ -3,3 +3,12 @@ import './i18n';
import './net';
import './layout';
import './logout';
+
+console.log(
+ `%c Blessing Skin %c v${blessing.version} %c Made with %c<3%c by printempw.%c https://blessing.studio`,
+ 'color:#fadfa3;background:#030307;padding:5px 0;margin:10px 0;',
+ 'background:#fadfa3;padding:5px 0;',
+ 'font-style:italic;',
+ 'color:red;',
+ 'font-style:italic;', ''
+);