Commit d14e6e6a authored by Clement Ho's avatar Clement Ho

Merge branch 'multiple-assignees-fe-sidebar' into multiple-assignees-issue-board-sidebar

parents 4e473119 d3f7e156
......@@ -79,6 +79,9 @@ export default {
renderAssignee(index) {
return !this.showLess || (index < this.defaultRenderCount && this.showLess);
},
avatarUrl(user) {
return user.avatarUrl || user.avatar_url;
},
assigneeUrl(user) {
return `${this.rootPath}${user.username}`;
},
......@@ -118,7 +121,7 @@ export default {
width="24"
class="avatar avatar-inline s24"
:alt="assigneeAlt(user)"
:src="user.avatarUrl"
:src="avatarUrl(user)"
/>
<span class="author">
{{ user.name }}
......@@ -158,7 +161,7 @@ export default {
width="32"
class="avatar avatar-inline s32"
:alt="assigneeAlt(firstUser)"
:src="firstUser.avatarUrl"
:src="avatarUrl(firstUser)"
/>
<span class="author">
{{ firstUser.name }}
......@@ -185,7 +188,7 @@ export default {
width="32"
class="avatar avatar-inline s32"
:alt="assigneeAlt(user)"
:src="user.avatarUrl"
:src="avatarUrl(user)"
/>
</a>
</div>
......
/* global Flash */
import AssigneeTitle from './assignee_title';
import Assignees from './assignees';
......@@ -20,39 +22,45 @@ export default {
'assignee-title': AssigneeTitle,
assignees: Assignees,
},
computed: {
numberOfAssignees() {
return this.store.selectedUserIds.length;
},
},
methods: {
assignSelf() {
// Notify gl dropdown that we are now assigning to current user
this.$el.parentElement.dispatchEvent(new Event('assignYourself'));
this.mediator.assignYourself();
this.saveUsers();
this.saveAssignees();
},
saveUsers() {
saveAssignees() {
this.loading = true;
function setLoadingFalse() {
this.loading = false;
}
const setLoadingFalseWrapper = setLoadingFalse.bind(this);
this.mediator.saveSelectedUsers(this.field)
.then(setLoadingFalseWrapper)
.catch(setLoadingFalseWrapper);
this.mediator.saveAssignees(this.field)
.then(setLoadingFalse.bind(this))
.catch(() => {
setLoadingFalse();
return new Flash('Error occurred when saving assignees');
});
},
},
created() {
this.removeAssignee = this.store.removeAssignee.bind(this.store);
this.addAssignee = this.store.addAssignee.bind(this.store);
this.removeAllAssignees = this.store.removeAllAssignees.bind(this.store);
// Get events from glDropdown
eventHub.$on('sidebar.removeUser', this.store.removeUserId.bind(this.store));
eventHub.$on('sidebar.addUser', this.store.addUserId.bind(this.store));
eventHub.$on('sidebar.removeAllUsers', this.store.removeAllUserIds.bind(this.store));
eventHub.$on('sidebar.saveUsers', this.saveUsers);
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$on('sidebar.saveAssignees', this.saveAssignees);
},
beforeDestroy() {
eventHub.$off('sidebar.removeAssignee', this.removeAssignee);
eventHub.$off('sidebar.addAssignee', this.addAssignee);
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
beforeMount() {
this.field = this.$el.dataset.field;
......@@ -60,15 +68,14 @@ export default {
template: `
<div>
<assignee-title
:number-of-assignees="store.selectedUserIds.length"
:number-of-assignees="store.assignees.length"
:loading="loading"
:editable="store.editable"
/>
<assignees
class="value"
v-if="!loading"
:root-path="store.rootPath"
:users="store.renderedUsers"
:users="store.assignees"
@assign-self="assignSelf"
/>
</div>
......
......@@ -15,33 +15,22 @@ export default class SidebarMediator {
}
assignYourself() {
this.store.addUserId(this.store.currentUserId);
this.store.addAssignee(this.store.currentUser);
}
saveSelectedUsers(field) {
return new Promise((resolve, reject) => {
const selected = this.store.selectedUserIds;
saveAssignees(field) {
const selected = this.store.assignees.map((u) => u.id);
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
this.service.update(field, selected.length === 0 ? [0] : selected)
.then((response) => {
const data = response.json();
this.store.processUserData(data);
resolve();
})
.catch(() => {
reject();
return new Flash('Error occurred when saving users');
});
});
// If there are no ids, that means we have to unassign (which is id = 0)
// And it only accepts an array, hence [0]
return this.service.update(field, selected.length === 0 ? [0] : selected);
}
fetch() {
this.service.get()
.then((response) => {
const data = response.json();
this.store.processUserData(data);
this.store.processAssigneeData(data);
this.store.processTimeTrackingData(data);
})
.catch(() => new Flash('Error occured when fetching sidebar data'));
......
export default class SidebarStore {
constructor(store) {
if (!SidebarStore.singleton) {
const { currentUserId, rootPath, editable } = store;
this.currentUserId = currentUserId;
const { currentUser, rootPath, editable } = store;
this.currentUser = currentUser;
this.rootPath = rootPath;
this.editable = editable;
this.timeEstimate = 0;
this.totalTimeSpent = 0;
this.humanTimeEstimate = '';
this.humanTimeSpent = '';
this.selectedUserIds = [];
this.renderedUsers = [];
this.assignees = [];
SidebarStore.singleton = this;
}
......@@ -18,17 +17,9 @@ export default class SidebarStore {
return SidebarStore.singleton;
}
processUserData(data) {
processAssigneeData(data) {
if (data.assignees) {
this.renderedUsers = data.assignees.map(a => {
a.avatarUrl = a.avatar_url;
delete a.avatar_url;
return a;
});
this.removeAllUserIds();
this.renderedUsers.map(u => this.addUserId(u.id));
this.assignees = data.assignees;
}
}
......@@ -39,18 +30,23 @@ export default class SidebarStore {
this.humanTimeSpent = data.human_time_spent;
}
addUserId(id) {
// Prevent duplicate user id's from being added
if (this.selectedUserIds.indexOf(id) === -1) {
this.selectedUserIds.push(id);
addAssignee(assignee) {
if (!this.findAssignee(assignee)) {
this.assignees.push(assignee);
}
}
removeUserId(id) {
this.selectedUserIds = this.selectedUserIds.filter(uid => uid !== id);
findAssignee(findAssignee) {
return this.assignees.filter(assignee => assignee.id === findAssignee.id)[0];
}
removeAssignee(removeAssignee) {
if (removeAssignee) {
this.assignees = this.assignees.filter(assignee => assignee.id !== removeAssignee.id);
}
}
removeAllUserIds() {
this.selectedUserIds = [];
removeAllAssignees() {
this.assignees = [];
}
}
......@@ -219,7 +219,7 @@
gl.sidebarOptions = {
endpoint: "#{issuable_json_path(issuable)}",
editable: #{can_edit_issuable ? true : false},
currentUserId: #{current_user.id},
currentUser: #{current_user.to_json(only: [:username, :id, :name], methods: :avatar_url)},
rootPath: "#{root_path}"
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment