Merge "Allow teams to be added to the permission list for private stories"
This commit is contained in:
commit
28b4809425
@ -123,6 +123,7 @@
|
||||
<td colspan="2">
|
||||
<input id="user"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Click to add a user"
|
||||
ng-model="asyncUser"
|
||||
typeahead-wait-ms="200"
|
||||
|
@ -106,6 +106,7 @@
|
||||
<td colspan="2">
|
||||
<input id="user"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Click to add a user"
|
||||
ng-model="asyncUser"
|
||||
typeahead-wait-ms="200"
|
||||
|
@ -24,7 +24,7 @@ angular.module('sb.story').controller('StoryDetailController',
|
||||
Story, Project, Branch, creator, tasks, Task, DSCacheFactory,
|
||||
User, $q, storyboardApiBase, SessionModalService, moment,
|
||||
$document, $anchorScroll, $timeout, $location, currentUser,
|
||||
enableEditableComments, Tags, worklists) {
|
||||
enableEditableComments, Tags, worklists, Team) {
|
||||
'use strict';
|
||||
|
||||
var pageSize = Preference.get('story_detail_page_size');
|
||||
@ -532,51 +532,82 @@ angular.module('sb.story').controller('StoryDetailController',
|
||||
};
|
||||
|
||||
/**
|
||||
* User typeahead search method.
|
||||
* User/team typeahead search method.
|
||||
*/
|
||||
$scope.searchUsers = function (value, array) {
|
||||
var userIds = array.map(function(user){return user.id;});
|
||||
$scope.searchActors = function (value, users, teams) {
|
||||
var userIds = users.map(function(user){return user.id;});
|
||||
var teamIds = teams.map(function(team){return team.id;});
|
||||
var deferred = $q.defer();
|
||||
var usersDeferred = $q.defer();
|
||||
var teamsDeferred = $q.defer();
|
||||
|
||||
User.browse({full_name: value, limit: 10},
|
||||
function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(result) {
|
||||
if (userIds.indexOf(result.id) === -1) {
|
||||
result.name = result.full_name;
|
||||
result.type = 'user';
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
deferred.resolve(results);
|
||||
usersDeferred.resolve(results);
|
||||
}
|
||||
);
|
||||
Team.browse({name: value, limit: 10},
|
||||
function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(result) {
|
||||
if (teamIds.indexOf(result.id) === -1) {
|
||||
result.type = 'team';
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
teamsDeferred.resolve(results);
|
||||
}
|
||||
);
|
||||
|
||||
var searches = [teamsDeferred.promise, usersDeferred.promise];
|
||||
$q.all(searches).then(function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(promise) {
|
||||
angular.forEach(promise, function(result) {
|
||||
results.push(result);
|
||||
});
|
||||
});
|
||||
deferred.resolve(results);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the user name.
|
||||
* Add a new user or team to one of the permission levels.
|
||||
*/
|
||||
$scope.formatUserName = function (model) {
|
||||
if (!!model) {
|
||||
return model.name;
|
||||
$scope.addActor = function (model) {
|
||||
if (model.type === 'user') {
|
||||
$scope.story.users.push(model);
|
||||
} else if (model.type === 'team') {
|
||||
$scope.story.teams.push(model);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new user to one of the permission levels.
|
||||
*/
|
||||
$scope.addUser = function (model) {
|
||||
$scope.story.users.push(model);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a user from one of the permission levels.
|
||||
* Remove a user from the permissions.
|
||||
*/
|
||||
$scope.removeUser = function (model) {
|
||||
var idx = $scope.story.users.indexOf(model);
|
||||
$scope.story.users.splice(idx, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a team from the permissions.
|
||||
*/
|
||||
$scope.removeTeam = function(model) {
|
||||
var idx = $scope.story.teams.indexOf(model);
|
||||
$scope.story.teams.splice(idx, 1);
|
||||
};
|
||||
|
||||
// ###################################################################
|
||||
// Task Management
|
||||
// ###################################################################
|
||||
|
@ -19,7 +19,7 @@
|
||||
*/
|
||||
angular.module('sb.story').controller('StoryModalController',
|
||||
function ($scope, $modalInstance, params, Project, Story, Task, User,
|
||||
$q, CurrentUser) {
|
||||
Team, $q, CurrentUser) {
|
||||
'use strict';
|
||||
|
||||
var currentUser = CurrentUser.resolve();
|
||||
@ -29,7 +29,8 @@ angular.module('sb.story').controller('StoryModalController',
|
||||
currentUser.then(function(user) {
|
||||
$scope.story = new Story({
|
||||
title: '',
|
||||
users: [user]
|
||||
users: [user],
|
||||
teams: []
|
||||
});
|
||||
});
|
||||
|
||||
@ -164,49 +165,80 @@ angular.module('sb.story').controller('StoryModalController',
|
||||
};
|
||||
|
||||
/**
|
||||
* User typeahead search method.
|
||||
* User/team typeahead search method.
|
||||
*/
|
||||
$scope.searchUsers = function (value, array) {
|
||||
$scope.searchActors = function (value, users, teams) {
|
||||
var userIds = users.map(function(user){return user.id;});
|
||||
var teamIds = teams.map(function(team){return team.id;});
|
||||
var deferred = $q.defer();
|
||||
var usersDeferred = $q.defer();
|
||||
var teamsDeferred = $q.defer();
|
||||
|
||||
User.browse({full_name: value, limit: 10},
|
||||
function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(result) {
|
||||
if (array.indexOf(result.id) === -1) {
|
||||
if (userIds.indexOf(result.id) === -1) {
|
||||
result.name = result.full_name;
|
||||
result.type = 'user';
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
deferred.resolve(results);
|
||||
usersDeferred.resolve(results);
|
||||
}
|
||||
);
|
||||
Team.browse({name: value, limit: 10},
|
||||
function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(result) {
|
||||
if (teamIds.indexOf(result.id) === -1) {
|
||||
result.type = 'team';
|
||||
results.push(result);
|
||||
}
|
||||
});
|
||||
teamsDeferred.resolve(results);
|
||||
}
|
||||
);
|
||||
|
||||
var searches = [teamsDeferred.promise, usersDeferred.promise];
|
||||
$q.all(searches).then(function(searchResults) {
|
||||
var results = [];
|
||||
angular.forEach(searchResults, function(promise) {
|
||||
angular.forEach(promise, function(result) {
|
||||
results.push(result);
|
||||
});
|
||||
});
|
||||
deferred.resolve(results);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the user name.
|
||||
* Add a new user or team to one of the permission levels.
|
||||
*/
|
||||
$scope.formatUserName = function (model) {
|
||||
if (!!model) {
|
||||
return model.name;
|
||||
$scope.addActor = function (model) {
|
||||
if (model.type === 'user') {
|
||||
$scope.story.users.push(model);
|
||||
} else if (model.type === 'team') {
|
||||
$scope.story.teams.push(model);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new user to one of the permission levels.
|
||||
*/
|
||||
$scope.addUser = function (model) {
|
||||
$scope.story.users.push(model);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a user from one of the permission levels.
|
||||
* Remove a user from the permissions.
|
||||
*/
|
||||
$scope.removeUser = function (model) {
|
||||
var idx = $scope.story.users.indexOf(model);
|
||||
$scope.story.users.splice(idx, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a team from the permissions.
|
||||
*/
|
||||
$scope.removeTeam = function(model) {
|
||||
var idx = $scope.story.teams.indexOf(model);
|
||||
$scope.story.teams.splice(idx, 1);
|
||||
};
|
||||
})
|
||||
;
|
||||
|
@ -187,31 +187,43 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-sm-offset-3"
|
||||
<div class="col-md-6 col-md-offset-3"
|
||||
ng-show="story.private">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Users that can see this story</th>
|
||||
<th>Teams and Users that can see this story</th>
|
||||
<th class="text-right">
|
||||
<small>
|
||||
<a href
|
||||
ng-click="showAddUser = !showAddUser">
|
||||
<i class="fa fa-plus" ng-if="!showAddUser"></i>
|
||||
<i class="fa fa-minus" ng-if="showAddUser"></i>
|
||||
Add User
|
||||
Add Team or User
|
||||
</a>
|
||||
</small>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="team in story.teams">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-sb-team"></i>
|
||||
{{ team.name }}
|
||||
<a class="close"
|
||||
ng-click="removeTeam(team)"
|
||||
ng-show="story.teams.length > 1 || story.users.length > 0">
|
||||
×
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="user in story.users">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-sb-user"></i>
|
||||
{{user.full_name}}
|
||||
<a class="close"
|
||||
ng-click="removeUser(user)"
|
||||
ng-show="story.users.length > 1">
|
||||
ng-show="story.users.length > 1 || story.teams.length > 0">
|
||||
×
|
||||
</a>
|
||||
</td>
|
||||
@ -220,15 +232,16 @@
|
||||
<td colspan="2">
|
||||
<input id="user"
|
||||
type="text"
|
||||
placeholder="Click to add a user"
|
||||
autocomplete="off"
|
||||
placeholder="Click to add a team or user"
|
||||
ng-model="asyncUser"
|
||||
typeahead-wait-ms="200"
|
||||
typeahead-editable="false"
|
||||
typeahead="user as user.full_name for user in
|
||||
searchUsers($viewValue, story.users)"
|
||||
typeahead="actor as actor.name for actor in
|
||||
searchActors($viewValue, story.users, story.teams)"
|
||||
typeahead-loading="loadingUsers"
|
||||
typeahead-input-formatter="formatUserName($model)"
|
||||
typeahead-on-select="addUser($model)"
|
||||
typeahead-on-select="addActor($model)"
|
||||
typeahead-template-url="/inline/actor-typeahead-item.html"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
</td>
|
||||
@ -275,6 +288,14 @@
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/ng-template" id="/inline/actor-typeahead-item.html">
|
||||
<a tabindex="-1">
|
||||
<i ng-class="'fa fa-sb-' + match.model.type"></i>
|
||||
<span ng-bind-html="match.model.name | typeaheadHighlight:query"></span>
|
||||
</a>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Template for the list of relevant worklists -->
|
||||
<script type="text/ng-template" id="/inline/worklists.html">
|
||||
<table class="table table-striped table-condensed">
|
||||
|
@ -64,53 +64,69 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-sm-offset-3"
|
||||
ng-show="story.private">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Users that can see this story</th>
|
||||
<th class="text-right">
|
||||
<small>
|
||||
<a href
|
||||
ng-click="showAddUser = !showAddUser">
|
||||
<i class="fa fa-plus" ng-if="!showAddUser"></i>
|
||||
<i class="fa fa-minus" ng-if="showAddUser"></i>
|
||||
Add User
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3"
|
||||
ng-show="story.private">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Teams and Users that can see this story</th>
|
||||
<th class="text-right">
|
||||
<small>
|
||||
<a href
|
||||
ng-click="showAddUser = !showAddUser">
|
||||
<i class="fa fa-plus" ng-if="!showAddUser"></i>
|
||||
<i class="fa fa-minus" ng-if="showAddUser"></i>
|
||||
Add Team or User
|
||||
</a>
|
||||
</small>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="team in story.teams">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-sb-team"></i>
|
||||
{{ team.name }}
|
||||
<a class="close"
|
||||
ng-click="removeTeam(team)"
|
||||
ng-show="story.teams.length > 1 || story.users.length > 0">
|
||||
×
|
||||
</a>
|
||||
</small>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="user in story.users">
|
||||
<td colspan="2">
|
||||
{{user.full_name}}
|
||||
<a class="close"
|
||||
ng-click="removeUser(user)">
|
||||
×
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="showAddUser">
|
||||
<td colspan="2">
|
||||
<input id="user"
|
||||
type="text"
|
||||
placeholder="Click to add a user"
|
||||
ng-model="asyncUser"
|
||||
typeahead-wait-ms="200"
|
||||
typeahead-editable="false"
|
||||
typeahead="user as user.full_name for user in
|
||||
searchUsers($viewValue, story.users)"
|
||||
typeahead-loading="loadingUsers"
|
||||
typeahead-input-formatter="formatUserName($model)"
|
||||
typeahead-on-select="addUser($model)"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="user in story.users">
|
||||
<td colspan="2">
|
||||
<i class="fa fa-sb-user"></i>
|
||||
{{user.full_name}}
|
||||
<a class="close"
|
||||
ng-click="removeUser(user)"
|
||||
ng-show="story.users.length > 1 || story.teams.length > 0">
|
||||
×
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="showAddUser">
|
||||
<td colspan="2">
|
||||
<input id="user"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Click to add a team or user"
|
||||
ng-model="asyncUser"
|
||||
typeahead-wait-ms="200"
|
||||
typeahead-editable="false"
|
||||
typeahead="actor as actor.name for actor in
|
||||
searchActors($viewValue, story.users, story.teams)"
|
||||
typeahead-loading="loadingUsers"
|
||||
typeahead-on-select="addActor($model)"
|
||||
typeahead-template-url="/inline/actor-typeahead-item.html"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -163,6 +179,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="text/ng-template" id="/inline/actor-typeahead-item.html">
|
||||
<a tabindex="-1">
|
||||
<i ng-class="'fa fa-sb-' + match.model.type"></i>
|
||||
<span ng-bind-html="match.model.name | typeaheadHighlight:query"></span>
|
||||
</a>
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Template for story metadata -->
|
||||
<script type="text/ng-template" id="/inline/task_row.html">
|
||||
<td>
|
||||
|
Loading…
Reference in New Issue
Block a user