class RolesViewController extends TimeCardsViewController { constructor(element) { super(element); this.roleCells = { }; this.resourceDependencies = { user: { user_role: "r" }, user_samerole: { user: "r"/*, project_user: "r"*/ }, user_all: { user_samerole: "r" }, card: { project: "r", //Technically not necessary because any user should always have at least read-only access to their own projects. card_category: "r" }, project_assigned: { project: "r" //Technically not necessary because any user should always have at least read-only access to their own projects. }, project_all: { project_assigned: "r" //Technically not necessary because any user should always have at least read-only access to their own projects. }, project_user: { project: "r" //A user may assign their own projects to other users, therefore project_all is not necessarily necessary. Also this is technically not necessary because any user should always have at least read-only access to their own projects. }, project_user_tariff: { project_user: "r" }, report_project: { project: "r" //Technically not necessary because any user should always have at least read-only access to their own projects. }, period: { card: "r" }, period_all: { period: "r" } }; TimeCards.dataManager.addDataListener("user_role", null, this.onRoleUpdate.bind(this)); } viewDidLoad() { this.rolesTableController.addEventListener("cellselected", this.onCellSelected.bind(this)); this.newRoleCell = new TableViewCell(); this.newRoleCell.titleLabel.innerText = "New Role"; //Index the permissions table. var permissionSelects = this.permissionsTable.querySelectorAll("input[type=\"radio\"].permission-radio"); this.resourceKeys = [ ]; for (var i = 0; i < permissionSelects.length; i++) { if (this.resourceKeys.indexOf(permissionSelects[i].name) == -1) { this.resourceKeys.push(permissionSelects[i].name); } } } /** * Data listener callback for the DataManager. */ onRoleUpdate(roleId, role, sortedBefore) { if (!role) { //Handle the deleted role. if (!(roleId in this.roleCells)) { return; } var roleCell = this.roleCells[roleId]; this.rolesTableController.removeCell(roleCell); delete this.roleCells[roleId]; } else if (!(roleId in this.roleCells)) { //Handle the added role. var roleCell = new TableViewCell(); roleCell.titleLabel.innerText = role.name; roleCell.role = role; this.rolesTableController.addCell(roleCell, 0, sortedBefore ? this.roleCells[sortedBefore] : null); this.roleCells[roleId] = roleCell; //Immediately select the added role if this is the role that was just created. //We assume that the first incoming new role is the one created by the interface. //This is because it is unlikely that two roles are created simultaneously. if (this.waitingForRoleCreation) { this.waitingForRoleCreation = false; this.rolesTableController.selectCell(roleCell); } } else { //Handle the changed role. var roleCell = this.roleCells[roleId]; roleCell.titleLabel = role.name; roleCell.role = role; //Re-add to keep the sorting in case of a name change. this.rolesTableController.addCell(roleCell, 0, sortedBefore ? this.roleCells[sortedBefore] : null); //Update the displayed data if the changed role is the currently selected one. if (this.selectedRole && this.selectedRole.role_id == roleId) { this.setRoleData(role); } } } onCellSelected(event) { if (!event.cell) { this.roleSettingsSheet.style.display = "none"; this.selectedRole = null; } else { //Hide the new project cell if another cell was selected. if (this.isNewRole && event.cell != this.newRoleCell) { this.onDeleteButtonPressed(event); } this.setRoleData(event.cell.role); this.roleSettingsSheet.style.display = ""; } } /** * Reads the permission radio buttons and assembles them into an object. */ gatherPermissionData() { var permissions = { }; for (var i = 0; i < this.resourceKeys.length; i++) { var resourceKey = this.resourceKeys[i]; var noRightsRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resourceKey + "\"].no-rights"); var readRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resourceKey + "\"].read"); var writeRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resourceKey + "\"].write"); var permission = (writeRadio.checked ? "w" : (readRadio.checked ? "r" : null)); if (permission) { permissions[resourceKey] = permission; } } return permissions; } setRoleData(role) { this.selectedRole = role; this.roleNameField.value = role.name; //Populate the permissions table. for (var i = 0; i < this.resourceKeys.length; i++) { if (this.resourceKeys[i] in role.permissions) { this.setPermission(this.resourceKeys[i], role.permissions[this.resourceKeys[i]]); } else { this.setPermission(this.resourceKeys[i], false); } } //Hide the delete button if this is the session user's role. //If this is the case, also disable the radio buttons. var radioButtons = this.permissionsTable.querySelectorAll("input[type=\"radio\"].permission-radio"); for (var i = 0; i < radioButtons.length; i++) { radioButtons[i].disabled = (Authentication.currentUser.id_role == role.role_id); } if (Authentication.currentUser.id_role == role.role_id) { this.deleteRoleButton.disabled = true; this.ownRoleInformation.style.display = ""; } else { this.deleteRoleButton.disabled = false; this.ownRoleInformation.style.display = "none"; } this.updatePermissions(); } respectDependencies(resource) { //Just return if there are no dependencies. if (!(resource in this.resourceDependencies)) { return; } var dependencies = this.resourceDependencies[resource]; for (var dependency in dependencies) { var type = dependencies[dependency]; var dependencyRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + dependency + "\"]." + (type == "w" ? "write" : "read")); var noRightsRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + dependency + "\"].no-rights"); var readRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + dependency + "\"].read"); //Check if the dependency is not already met. if (!(dependency in this.selectedRole.permissions) || (type == "w" && this.selectedRole.permissions[dependency] == "r")) { if (this.selectedRole.permissions[resource]) { this.setPermission(dependency, type); } } if (resource in this.selectedRole.permissions) { noRightsRadio.disabled = true; if (type == "w") { readRadio.disabled = true; } } else { noRightsRadio.disabled = false; if (type == "w") { readRadio.disabled = false; } } } } setPermission(resource, type = false) { var noRightsRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resource + "\"].no-rights"); var readRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resource + "\"].read"); var writeRadio = this.permissionsTable.querySelector("input[type=\"radio\"].permission-radio[name=\"" + resource + "\"].write"); noRightsRadio.checked = false; readRadio.checked = false; writeRadio.checked = false; if (!type) { noRightsRadio.checked = true; } else if (type == "r") { readRadio.checked = true; } else if (type == "w") { writeRadio.checked = true; } if (type) { this.selectedRole.permissions[resource] = type; } else { delete this.selectedRole.permissions[resource]; } //Only check the dependencies when the type is "r" or "w". this.respectDependencies(resource); } /** * Takes the input and puts it into an object which will then be sent to the server. */ saveRole() { if (this.roleNameField.value && this.roleNameField.value.length > 0) { var role = { name: this.roleNameField.value, permissions: this.gatherPermissionData() }; if (this.isNewRole) { if (!this.waitingForRoleCreation) { TimeCards.dataManager.store("user_role", role); this.waitingForRoleCreation = true; } } else { TimeCards.dataManager.store("user_role", this.selectedRole.role_id, role); } } } onFieldChanged(event) { this.saveRole(); } onPermissionRadioChanged(event) { this.setPermission(event.currentTarget.name, (event.currentTarget.className.indexOf("no-rights") != -1 ? false : (event.currentTarget.className.indexOf("read") != -1 ? "r" : (event.currentTarget.className.indexOf("write") != -1 ? "w" : false)))); this.saveRole(); } onDeleteButtonPressed(event) { if (this.isNewRole) { this.isNewRole = false; this.rolesTableController.removeCell(this.newRoleCell); } else { //TODO: Add a confirmation dialog where the user has to decide what happens to the users of the role to delete. TimeCards.dataManager.store("user_role", this.selectedRole.role_id, null); } } onCreateButtonPressed(event) { this.isNewRole = true; this.newRoleCell.role = { name: "", permissions: { } }; this.rolesTableController.addCell(this.newRoleCell); this.rolesTableController.selectCell(this.newRoleCell); this.roleNameField.focus(); } } UIKit.registerViewControllerType(RolesViewController);