diff --git a/app/coffee/modules/admin/roles.coffee b/app/coffee/modules/admin/roles.coffee index b14effb2..cbd45d1a 100644 --- a/app/coffee/modules/admin/roles.coffee +++ b/app/coffee/modules/admin/roles.coffee @@ -64,16 +64,36 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil loadProject: -> return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project + @scope.$emit('project:loaded', project) @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) return project + loadExternalUserRole: (roles) -> + roles = roles.map (role) -> + role.external_user = false + + return role + + public_permission = { + "name": "External User", + "permissions": @scope.project.public_permissions, + "external_user": true + } + + roles.push(public_permission) + + return roles + loadRoles: -> - return @rs.roles.list(@scope.projectId).then (data) => - @scope.roles = data - @scope.role = @scope.roles[0] - return data + return @rs.roles.list(@scope.projectId) + .then @loadExternalUserRole + .then (roles) => + @scope.roles = roles + @scope.role = @scope.roles[0] + + return roles loadInitialData: -> promise = @repo.resolve({pslug: @params.pslug}).then (data) => @@ -256,7 +276,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) ->
<%- permission.description %>
- checked="checked"<% } %>/> + disabled="disabled"<% } %> <% if(permission.active) { %>checked="checked"<% } %>/>
Yes No @@ -279,10 +299,23 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) -> setActivePermissions = (permissions) -> return _.map(permissions, (x) -> _.extend({}, x, {active: x["key"] in role.permissions})) + isPermissionEditable = (permission, role, project) -> + if role.external_user && + !project.is_private && + permission.key.indexOf("view_") == 0 + return false + else + return true + setActivePermissionsPerCategory = (category) -> - return _.map(category, (x) -> - _.extend({}, x, { - activePermissions: _.filter(x["permissions"], "active").length + return _.map(category, (cat) -> + cat.permissions = cat.permissions.map (permission) -> + permission.editable = isPermissionEditable(permission, role, $scope.project) + + return permission + + _.extend({}, cat, { + activePermissions: _.filter(cat["permissions"], "active").length }) ) @@ -366,10 +399,11 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) -> return activePermissions target = angular.element(event.currentTarget) + $scope.role.permissions = getActivePermissions() - onSuccess = (role) -> - categories = generateCategoriesFromRole(role) + onSuccess = () -> + categories = generateCategoriesFromRole($scope.role) categoryId = target.parents(".category-config").data("id") renderResume(target.parents(".category-config"), categories[categoryId]) $rootscope.$broadcast("projects:reload") @@ -381,7 +415,14 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) -> target.prop "checked", !target.prop("checked") $scope.role.permissions = getActivePermissions() - $repo.save($scope.role).then onSuccess, onError + if $scope.role.external_user + $scope.project.public_permissions = $scope.role.permissions + $scope.project.anon_permissions = $scope.role.permissions.filter (permission) -> + return permission.indexOf("view_") == 0 + + $repo.save($scope.project).then onSuccess, onError + else + $repo.save($scope.role).then onSuccess, onError $scope.$on "$destroy", -> $el.off() diff --git a/app/coffee/modules/common/history.coffee b/app/coffee/modules/common/history.coffee index fcd1d961..c7ab11d5 100644 --- a/app/coffee/modules/common/history.coffee +++ b/app/coffee/modules/common/history.coffee @@ -258,7 +258,7 @@ HistoryDirective = ($log, $loading, $qqueue, $template, $confirm) -> deleteCommentDate: moment(comment.delete_comment_date).format("DD MMM YYYY HH:mm") if comment.delete_comment_date deleteCommentUser: comment.delete_comment_user.name if comment.delete_comment_user?.name activityId: comment.id - canDeleteComment: comment.user.pk == $scope.user.id or $scope.project.my_permissions.indexOf("modify_project") > -1 + canDeleteComment: comment.user.pk == $scope.user?.id or $scope.project.my_permissions.indexOf("modify_project") > -1 }) renderChange = (change) -> diff --git a/app/coffee/modules/taskboard/sortable.coffee b/app/coffee/modules/taskboard/sortable.coffee index 16aa5020..57f99711 100644 --- a/app/coffee/modules/taskboard/sortable.coffee +++ b/app/coffee/modules/taskboard/sortable.coffee @@ -36,47 +36,52 @@ module = angular.module("taigaBacklog") TaskboardSortableDirective = ($repo, $rs, $rootscope) -> link = ($scope, $el, $attrs) -> - oldParentScope = null - newParentScope = null - itemEl = null - tdom = $el + bindOnce $scope, "project", (project) -> + # If the user has not enough permissions we don't enable the sortable + if not (project.my_permissions.indexOf("modify_us") > -1) + return - deleteElement = (itemEl) -> - # Completelly remove item and its scope from dom - itemEl.scope().$destroy() - itemEl.off() - itemEl.remove() + oldParentScope = null + newParentScope = null + itemEl = null + tdom = $el - tdom.sortable({ - handle: ".taskboard-task-inner", - dropOnEmpty: true - connectWith: ".taskboard-tasks-box" - revert: 400 - }) + deleteElement = (itemEl) -> + # Completelly remove item and its scope from dom + itemEl.scope().$destroy() + itemEl.off() + itemEl.remove() - tdom.on "sortstop", (event, ui) -> - parentEl = ui.item.parent() - itemEl = ui.item - itemTask = itemEl.scope().task - itemIndex = itemEl.index() - newParentScope = parentEl.scope() + tdom.sortable({ + handle: ".taskboard-task-inner", + dropOnEmpty: true + connectWith: ".taskboard-tasks-box" + revert: 400 + }) - oldUsId = if oldParentScope.us then oldParentScope.us.id else null - oldStatusId = oldParentScope.st.id - newUsId = if newParentScope.us then newParentScope.us.id else null - newStatusId = newParentScope.st.id + tdom.on "sortstop", (event, ui) -> + parentEl = ui.item.parent() + itemEl = ui.item + itemTask = itemEl.scope().task + itemIndex = itemEl.index() + newParentScope = parentEl.scope() - if newStatusId != oldStatusId or newUsId != oldUsId - deleteElement(itemEl) + oldUsId = if oldParentScope.us then oldParentScope.us.id else null + oldStatusId = oldParentScope.st.id + newUsId = if newParentScope.us then newParentScope.us.id else null + newStatusId = newParentScope.st.id - $scope.$apply -> - $rootscope.$broadcast("taskboard:task:move", itemTask, newUsId, newStatusId, itemIndex) + if newStatusId != oldStatusId or newUsId != oldUsId + deleteElement(itemEl) - ui.item.find('a').removeClass('noclick') + $scope.$apply -> + $rootscope.$broadcast("taskboard:task:move", itemTask, newUsId, newStatusId, itemIndex) - tdom.on "sortstart", (event, ui) -> - oldParentScope = ui.item.parent().scope() - ui.item.find('a').addClass('noclick') + ui.item.find('a').removeClass('noclick') + + tdom.on "sortstart", (event, ui) -> + oldParentScope = ui.item.parent().scope() + ui.item.find('a').addClass('noclick') $scope.$on "$destroy", -> $el.off() diff --git a/app/coffee/modules/team/main.coffee b/app/coffee/modules/team/main.coffee index 69830a2f..9bc9b57a 100644 --- a/app/coffee/modules/team/main.coffee +++ b/app/coffee/modules/team/main.coffee @@ -69,18 +69,18 @@ class TeamController extends mixOf(taiga.Controller, taiga.PageMixin) loadMembers: -> return @rs.memberships.list(@scope.projectId, {}, false).then (data) => currentUser = @auth.getUser() - if not currentUser.photo? + if currentUser? and not currentUser.photo? currentUser.photo = "/images/unnamed.png" @scope.currentUser = _.find data, (membership) => - return membership.user == currentUser.id + return currentUser? and membership.user == currentUser.id @scope.totals = {} _.forEach data, (membership) => @scope.totals[membership.user] = 0 @scope.memberships = _.filter data, (membership) => - if membership.user && membership.user != currentUser.id && membership.is_user_active + if membership.user && (not currentUser? or membership.user != currentUser.id) && membership.is_user_active return membership for membership in @scope.memberships diff --git a/app/coffee/modules/wiki/main.coffee b/app/coffee/modules/wiki/main.coffee index 381c4848..8aad38e7 100644 --- a/app/coffee/modules/wiki/main.coffee +++ b/app/coffee/modules/wiki/main.coffee @@ -238,6 +238,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $ $el.on "mouseup", ".view-wiki-content", (event) -> target = angular.element(event.target) return if getSelectedText() + return if not isEditable() return if target.is('a') return if target.is('pre') diff --git a/app/partials/admin/admin-project-profile.jade b/app/partials/admin/admin-project-profile.jade index 6ee7c272..b504ceb9 100644 --- a/app/partials/admin/admin-project-profile.jade +++ b/app/partials/admin/admin-project-profile.jade @@ -40,16 +40,14 @@ div.wrapper(tg-project-profile, ng-controller="ProjectProfileController as ctrl" tg-privacy-settings-inputs div.privacy-settings div - input.hidden(type="radio", disabled="disabled") + input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="false") label.trans-button(for="public-project") span Public Project div - input.hidden(type="radio", checked="checked", disabled="disabled") + input.privacy-project(type="radio", name="private-project", ng-model="project.is_private", ng-value="true") label.trans-button(for="private-project") span Private Project - p All projects are private during Taiga's beta period. - button.button-green.submit-button(type="submit", title="Save") Save a.delete-project(href="", title="Delete this project", ng-click="ctrl.openDeleteLightbox()") Delete this project diff --git a/app/partials/admin/admin-roles.jade b/app/partials/admin/admin-roles.jade index 52dc954f..2899d960 100644 --- a/app/partials/admin/admin-roles.jade +++ b/app/partials/admin/admin-roles.jade @@ -8,28 +8,33 @@ div.wrapper.roles(ng-controller="RolesController as ctrl", section.main.admin-roles.admin-common .header-with-actions include ../includes/components/mainTitle - .action-buttons + .action-buttons(ng-if="!role.external_user") a.button-red.delete-role(href="", title="Delete", ng-click="ctrl.delete()") span Delete - div(tg-edit-role) - .edit-role - input(type="text", value="{{ role.name }}") - a.save.icon.icon-floppy(href="", title="Save") + div(ng-if="!role.external_user") + div(tg-edit-role) + .edit-role + input(type="text", value="{{ role.name }}") + a.save.icon.icon-floppy(href="", title="Save") + p.total + span.role-name(title="{{ role.members_count }} members with this role") {{ role.name }} + a.edit-value.icon.icon-edit + + div.any-computable-role(ng-hide="anyComputableRole") Be careful, no role in your project will be able to estimate the point value for user stories + + div.general-category + | When enabled, members assigned to this role will be able to estimate the point value for user stories + div.check + input(type="checkbox", ng-model="role.computable", ng-change="ctrl.setComputable()") + div + span.check-text.check-yes Yes + span.check-text.check-no No + + div(ng-if="role.external_user") p.total - span.role-name(title="{{ role.members_count }} members with this role") {{ role.name }} - a.edit-value.icon.icon-edit - - div.any-computable-role(ng-hide="anyComputableRole") Be careful, no role in your project will be able to estimate the point value for user stories - - div.general-category - | When enabled, members assigned to this role will be able to estimate the point value for user stories - div.check - input(type="checkbox", ng-model="role.computable", ng-change="ctrl.setComputable()") - div - span.check-text.check-yes Yes - span.check-text.check-no No + span.role-name {{ role.name }} div(tg-role-permissions, ng-model="role") diff --git a/app/partials/includes/modules/team/team-table.jade b/app/partials/includes/modules/team/team-table.jade index 9ee2279c..f4e0c739 100644 --- a/app/partials/includes/modules/team/team-table.jade +++ b/app/partials/includes/modules/team/team-table.jade @@ -27,7 +27,7 @@ section.table-team.basic-table div.popover.attribute-explanation span Total Points - div.hero(tg-team-current-user, stats="stats", currentuser="currentUser", projectid="projectId", issuesEnabled="issuesEnabled", tasksenabled="tasksEnabled", wikienabled="wikiEnabled") + div.hero(tg-team-current-user, stats="stats", currentuser="currentUser", projectid="projectId", issuesEnabled="issuesEnabled", tasksenabled="tasksEnabled", wikienabled="wikiEnabled", ng-if="::currentUser") h2(ng-show="memberships.length") span Team > diff --git a/app/partials/project/project-menu.jade b/app/partials/project/project-menu.jade index 9b70ae09..ea56ff56 100644 --- a/app/partials/project/project-menu.jade +++ b/app/partials/project/project-menu.jade @@ -44,6 +44,7 @@ div(class="menu-container") span(class="icon icon-settings") span(class="item") Admin <% } %> + <% if (user) { %> div(class="user") div(class="user-settings") ul(class="popover") @@ -61,3 +62,4 @@ div(class="menu-container") a(href="" title="Logout" class="logout") Logout a(href="" title="User preferences" class="avatar" id="nav-user-settings") img(src="{{ user.photo }}" alt="{{ user.full_name_display }}") + <% } %> diff --git a/app/styles/layout/wiki.scss b/app/styles/layout/wiki.scss index 9bb55308..48cb40ab 100644 --- a/app/styles/layout/wiki.scss +++ b/app/styles/layout/wiki.scss @@ -24,10 +24,6 @@ position: relative; .view-wiki-content { &:hover { - .wysiwyg { - background: $whitish; - cursor: pointer; - } .edit { opacity: 1; top: -1.5rem; @@ -67,4 +63,12 @@ top: .4rem; } } + &.editable { + &:hover { + .wysiwyg { + background: $whitish; + cursor: pointer; + } + } + } } diff --git a/app/styles/modules/admin/admin-project-profile.scss b/app/styles/modules/admin/admin-project-profile.scss index 0339fc66..cefec654 100644 --- a/app/styles/modules/admin/admin-project-profile.scss +++ b/app/styles/modules/admin/admin-project-profile.scss @@ -21,14 +21,15 @@ .privacy-settings { display: flex; margin-bottom: 2rem; - div { + > div { flex-basis: 0; flex-grow: 1; + overflow: hidden; + position: relative; &:first-child { margin-right: .5rem; } } - // TODO: This should change when public projects available label { @extend %title; border: 1px solid $gray-light; @@ -39,14 +40,22 @@ span { color: $gray-light; } - // &:hover { - // border: 1px solid $fresh-taiga; - // } } - input:checked+label { + } + .privacy-project { + cursor: pointer; + height: 500px; + left: -10px; + opacity: 0; + position: absolute; + top: -10px; + width: 500px; + z-index: 999; + } + .privacy-project:checked { + + label { background: $fresh-taiga; border: 1px solid $fresh-taiga; - cursor: default; span { color: $white; } diff --git a/app/styles/modules/admin/admin-roles.scss b/app/styles/modules/admin/admin-roles.scss index 58203d80..daa55c21 100644 --- a/app/styles/modules/admin/admin-roles.scss +++ b/app/styles/modules/admin/admin-roles.scss @@ -101,5 +101,11 @@ opacity: 0; } } + input:disabled { + cursor: auto; + + div { + background-color: #ccc; + } + } } }