From 069eab1f630407d69042c3d30568bb6754ce696f Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Sun, 29 Dec 2019 13:33:05 +0100 Subject: [PATCH] Add user editing support to user view model --- css/main.css | 2 +- helpers/utils.php | 4 +- index.php | 8 +- js/src/userviewmodel.js | 53 ++++++++++++- js/test/fixtures/main-authorized.html | 8 +- js/test/userviewmodel.test.js | 104 +++++++++++++++++++++++++- utils/handleuser.php | 4 +- 7 files changed, 169 insertions(+), 14 deletions(-) diff --git a/css/main.css b/css/main.css index 460dd3a..a006cc7 100644 --- a/css/main.css +++ b/css/main.css @@ -356,7 +356,7 @@ button > * { border: 1px solid #888; } -#user-menu.menu-hidden { +#user-menu.menu-hidden, a.menu-hidden { display: none; } diff --git a/helpers/utils.php b/helpers/utils.php index 4df8d9c..2524e4c 100644 --- a/helpers/utils.php +++ b/helpers/utils.php @@ -91,7 +91,9 @@ */ private static function exitWithStatus($isError, $extra = NULL) { $output = []; - $output["error"] = $isError; + if ($isError) { + $output["error"] = true; + } if (!empty($extra)) { foreach ($extra as $key => $value) { $output[$key] = $value; diff --git a/index.php b/index.php index 52a4785..e4fd8d5 100644 --- a/index.php +++ b/index.php @@ -61,7 +61,7 @@
<?= $lang['user'] ?> user->login) ?>
@@ -133,10 +133,10 @@
isAdmin()): ?> - - + + - +
diff --git a/js/src/userviewmodel.js b/js/src/userviewmodel.js index c8b9519..283256f 100644 --- a/js/src/userviewmodel.js +++ b/js/src/userviewmodel.js @@ -18,6 +18,7 @@ */ import { lang as $, auth } from './initializer.js'; +import UserDialogModel from './userdialogmodel.js'; import ViewModel from './viewmodel.js'; import uSelect from './select.js'; import uUser from './user.js'; @@ -36,14 +37,29 @@ export default class UserViewModel extends ViewModel { /** @type {uUser[]} */ userList: [], /** @type {string} */ - currentUserId: '0' + currentUserId: '0', + // click handlers + /** @type {function} */ + onUserEdit: null, + /** @type {function} */ + onUserAdd: null, + /** @type {function} */ + onPasswordChange: null }); + this.setClickHandlers(); /** @type HTMLSelectElement */ const listEl = document.querySelector('#user'); + this.editEl = this.getBoundElement('onUserEdit'); this.select = new uSelect(listEl, $._('suser'), `- ${$._('allusers')} -`); this.state = state; } + setClickHandlers() { + this.model.onUserEdit = () => this.showDialog('edit'); + this.model.onUserAdd = () => this.showDialog('add'); + this.model.onPasswordChange = () => this.showDialog('pass'); + } + /** * @return {UserViewModel} */ @@ -78,6 +94,7 @@ export default class UserViewModel extends ViewModel { this.onChanged('currentUserId', (listValue) => { this.state.showAllUsers = listValue === uSelect.allValue; this.state.currentUser = this.model.userList.find((_user) => _user.listValue === listValue) || null; + UserViewModel.setMenuVisible(this.editEl, this.state.currentUser !== null && !this.state.currentUser.isEqualTo(auth.user)); }); state.onChanged('showLatest', (showLatest) => { if (showLatest) { @@ -88,4 +105,38 @@ export default class UserViewModel extends ViewModel { }); } + showDialog(action) { + const vm = new UserDialogModel(this, action); + vm.init(); + } + + /** + * @param {uUser} newUser + */ + onUserAdded(newUser) { + this.model.userList.push(newUser); + this.model.userList.sort((a, b) => ((a.login > b.login) ? 1 : -1)); + } + + onUserDeleted() { + const index = this.model.userList.indexOf(this.state.currentUser); + this.state.currentUser = null; + if (index !== -1) { + this.model.userList.splice(index, 1); + if (this.model.userList.length) { + this.model.currentUserId = this.model.userList[index].listValue; + } else { + this.model.currentUserId = '0'; + } + } + } + + static setMenuVisible(el, visible) { + if (visible) { + el.classList.remove('menu-hidden'); + } else { + el.classList.add('menu-hidden'); + } + } + } diff --git a/js/test/fixtures/main-authorized.html b/js/test/fixtures/main-authorized.html index c7e54e2..e209fea 100644 --- a/js/test/fixtures/main-authorized.html +++ b/js/test/fixtures/main-authorized.html @@ -5,7 +5,7 @@
User testUser
@@ -80,9 +80,9 @@
- Add user - Edit user - Edit track + Add user + Edit user + Edit track
diff --git a/js/test/userviewmodel.test.js b/js/test/userviewmodel.test.js index f93165e..3a7fbac 100644 --- a/js/test/userviewmodel.test.js +++ b/js/test/userviewmodel.test.js @@ -33,16 +33,22 @@ describe('UserViewModel tests', () => { let users; /** @type {HTMLSelectElement} */ let userEl; + let userEditEl; + let userAddEl; + let userPassEl; let vm; beforeEach((done) => { - Fixture.load('main.html') + Fixture.load('main-authorized.html') .then(() => done()) .catch((e) => done.fail(e)); }); beforeEach(() => { userEl = document.querySelector('#user'); + userEditEl = document.querySelector('#edituser'); + userAddEl = document.querySelector('#adduser'); + userPassEl = document.querySelector('#user-pass'); config.reinitialize(); lang.init(config); lang.strings['suser'] = 'select user'; @@ -211,4 +217,100 @@ describe('UserViewModel tests', () => { }, 100); }); + it('should show user edit dialog on button click', (done) => { + // given + spyOn(vm, 'showDialog'); + // when + vm.bindAll(); + userEditEl.click(); + // then + setTimeout(() => { + expect(vm.showDialog).toHaveBeenCalledWith('edit'); + done(); + }, 100); + }); + + it('should show user add dialog on button click', (done) => { + // given + spyOn(vm, 'showDialog'); + // when + vm.bindAll(); + userAddEl.click(); + // then + setTimeout(() => { + expect(vm.showDialog).toHaveBeenCalledWith('add'); + done(); + }, 100); + }); + + it('should show password change dialog on button click', (done) => { + // given + spyOn(vm, 'showDialog'); + // when + vm.bindAll(); + userPassEl.click(); + // then + setTimeout(() => { + expect(vm.showDialog).toHaveBeenCalledWith('pass'); + done(); + }, 100); + }); + + it('should add new user to user list in alphabetic order', () => { + // given + user1 = new uUser(1, 'b'); + user2 = new uUser(2, 'a'); + vm.model.userList = [ user1 ]; + // when + vm.onUserAdded(user2); + // then + expect(vm.model.userList.length).toBe(2); + expect(vm.model.userList[0]).toBe(user2); + }); + + it('should remove current user from user list and set new current user id', () => { + // given + vm.model.userList = [ user1, user2 ]; + vm.state.currentUser = user1; + vm.model.currentUserId = user1.listValue; + // when + vm.onUserDeleted(); + // then + expect(vm.model.userList.length).toBe(1); + expect(vm.model.currentUserId).toBe(user2.listValue); + expect(vm.state.currentUser).toBe(null); + }); + + it('should remove last remaining element from user list and set empty user id', () => { + // given + vm.model.userList = [ user1 ]; + vm.state.currentUser = user1; + vm.model.currentUserId = user1.listValue; + // when + vm.onUserDeleted(); + // then + expect(vm.model.userList.length).toBe(0); + expect(vm.model.currentUserId).toBe('0'); + expect(vm.state.currentUser).toBe(null); + }); + + it('show hide element', () => { + // given + const element = document.createElement('div'); + // when + UserViewModel.setMenuVisible(element, false); + // then + expect(element.classList.contains('menu-hidden')).toBe(true); + }); + + it('show shown hidden element', () => { + // given + const element = document.createElement('div'); + element.classList.add('menu-hidden'); + // when + UserViewModel.setMenuVisible(element, true); + // then + expect(element.classList.contains('menu-hidden')).toBe(false); + }); + }); diff --git a/utils/handleuser.php b/utils/handleuser.php index 854778b..ab135ef 100644 --- a/utils/handleuser.php +++ b/utils/handleuser.php @@ -30,7 +30,7 @@ $lang = (new uLang(uConfig::$lang))->getStrings(); - if (!$auth->isAuthenticated() || !$auth->isAdmin() || $auth->user->login == $login || empty($action) || empty($login)) { + if (!$auth->isAuthenticated() || !$auth->isAdmin() || $auth->user->login === $login || empty($action) || empty($login)) { uUtils::exitWithError($lang["servererror"]); } @@ -45,7 +45,7 @@ if (empty($pass) || ($userId = uUser::add($login, $pass)) === false) { uUtils::exitWithError($lang["servererror"]); } else { - $data = [ 'userid' => $userId ]; + $data = [ 'id' => $userId ]; } break;