Skip to content

Commit 15e2cf5

Browse files
authored
Merge pull request #1647 from code-corps/1632-add-conversation-status-select
Add conversation status selector
2 parents 7dc7679 + 2c3455f commit 15e2cf5

File tree

17 files changed

+305
-105
lines changed

17 files changed

+305
-105
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Component from '@ember/component';
2+
3+
export default Component.extend({
4+
classNames: ['conversations__status-select', 'dropdown'],
5+
6+
showDropdown: false
7+
});

app/controllers/project/conversations.js

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import Controller from '@ember/controller';
22
import { set } from '@ember/object';
33

44
export default Controller.extend({
5+
queryParams: ['status'],
6+
status: 'open',
7+
8+
currentlyLoading: null,
9+
510
actions: {
611
close(conversation) {
712
set(conversation, 'status', 'closed');

app/routes/project/conversations.js

+20-5
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,23 @@ export default Route.extend(AuthenticatedRouteMixin, CanMixin, {
2121
}
2222
},
2323

24-
async model() {
24+
async model(params) {
2525
let project = this.modelFor('project');
2626
let projectId = get(project, 'id');
2727
let store = get(this, 'store');
28-
// peekAll returns a live array, so it will alse render any newly created
29-
// messages, causing the list to update properly on project.messages.new
30-
await store.query('conversation', { project_id: projectId });
31-
let conversations = store.peekAll('conversation');
28+
let conversations = await store.query('conversation', {
29+
project_id: projectId,
30+
status: params.status
31+
});
3232
return { conversations, project };
3333
},
3434

35+
queryParams: {
36+
status: {
37+
refreshModel: true
38+
}
39+
},
40+
3541
renderTemplate() {
3642
this.render('project/conversations', { into: 'application' });
3743
},
@@ -64,6 +70,15 @@ export default Route.extend(AuthenticatedRouteMixin, CanMixin, {
6470
this._super(...arguments);
6571
get(this, 'conversations').activate();
6672
return true;
73+
},
74+
75+
loading(transition) {
76+
let controller = this.controllerFor('project.conversations');
77+
controller.set('currentlyLoading', true);
78+
transition.promise.finally(() => {
79+
controller.set('currentlyLoading', false);
80+
this.transitionTo('project.conversations.index');
81+
});
6782
}
6883
}
6984
});

app/routes/project/conversations/index.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@ import Route from '@ember/routing/route';
33
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
44

55
export default Route.extend(AuthenticatedRouteMixin, {
6-
redirect() {
6+
redirect(model, transition) {
77
let { conversations } = this.modelFor('project.conversations');
8-
if (get(conversations, 'length') > 0) {
9-
this.transitionTo('project.conversations.conversation', get(conversations, 'firstObject'));
8+
9+
// If status changed on one conversation, the model did not update
10+
// We filter here to ensure the statuses are filtered
11+
let status = transition.queryParams.status || 'open';
12+
let filteredConversations = conversations.filterBy('status', status);
13+
14+
if (get(filteredConversations, 'length') > 0) {
15+
let sortedConversations = filteredConversations.sortBy('updatedAt');
16+
this.transitionTo('project.conversations.conversation', get(sortedConversations, 'lastObject'));
1017
}
1118
}
1219
});

app/styles/_buttons.scss

+10-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@
116116
color: $text--dark;
117117
font-weight: 400;
118118

119+
.fa {
120+
color: $text--lighter;
121+
}
122+
119123
&:disabled, &.disabled {
120124
background: $background-gray;
121125
}
@@ -156,7 +160,12 @@
156160
}
157161

158162
.fa {
159-
padding-right: 5px;
163+
&:first-child {
164+
padding-right: 5px;
165+
}
166+
&:last-child {
167+
padding-left: 5px;
168+
}
160169
}
161170

162171
span {

app/styles/app.scss

+1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
@import "components/conversations/conversation-list-item";
114114
@import "components/conversations/conversation-part";
115115
@import "components/conversations/new-conversation-modal";
116+
@import "components/conversations/status-select";
116117

117118
//
118119
// COMPONENTS - DONATIONS
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.conversations__status-select {
2+
position: relative;
3+
4+
.dropdown-menu {
5+
margin-top: 0.5em;
6+
}
7+
8+
&__selector {
9+
border: 1px solid transparent;
10+
border-radius: 4px;
11+
padding: 0.2em 0.5em;
12+
13+
&.active, &:hover {
14+
border: 1px solid $gray--lightest;
15+
background: $clear-hover;
16+
background-image: linear-gradient(white, $clear-hover);
17+
color: $text--dark;
18+
}
19+
}
20+
21+
a {
22+
color: $text--lightest;
23+
24+
i {
25+
&:first-child {
26+
padding-right: 2px;
27+
}
28+
29+
&:last-child:not(:first-child) {
30+
padding-left: 5px;
31+
}
32+
}
33+
}
34+
}

app/styles/components/dropdown-menu.scss

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
// having problems with "navigation__options a"
9494
// overwriting the properties below
9595
border: 0;
96+
display: block;
9697
font-weight: normal;
9798
padding: 8px 11px;
9899

app/styles/shared/conversation.scss

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
.conversation__loading {
2+
background: $clear-focus;
3+
position: absolute;
4+
top: 0; right: 0; bottom: 0; left: 0;
5+
}
6+
17
.conversation-thread {
28
background: $clear-focus;
39
border-right: 1px solid $gray--lighter;

app/styles/shared/conversations.scss

+5
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ p.conversations__empty__icon {
3737
font-size: $header-font-size-large;
3838
margin: 1em 0 0 0;
3939
}
40+
41+
.conversations__list-actions {
42+
border-bottom: 1px solid $gray--lighter;
43+
padding: 1em;
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{{#click-outside action=(action (mut showDropdown) false)}}
2+
{{#if (eq status 'open')}}
3+
<a data-test-open-selector class="conversations__status-select__selector {{if showDropdown "active"}}" {{action (toggle "showDropdown" this)}}>{{fa-icon "inbox"}} Open {{fa-icon "angle-down"}}</a>
4+
{{else if (eq status 'closed')}}
5+
<a data-test-closed-selector class="conversations__status-select__selector {{if showDropdown "active"}}" {{action (toggle "showDropdown" this)}}>{{fa-icon "check"}} Closed {{fa-icon "angle-down"}}</a>
6+
{{/if}}
7+
{{/click-outside}}
8+
9+
{{#if showDropdown}}
10+
<div class="dropdown-menu">
11+
<div class="dropdown__body">
12+
<ul class="dropdown__options">
13+
<li>
14+
<a data-test-open-link class="{{if (eq status "open") "active"}}" {{action (action (mut status) "open")}}>
15+
{{fa-icon "inbox"}} Open
16+
</a>
17+
</li>
18+
<li>
19+
<a data-test-closed-link class="{{if (eq status "closed") "active"}}" {{action (action (mut status) "closed")}}>
20+
{{fa-icon "check"}} Closed
21+
</a>
22+
</li>
23+
</ul>
24+
</div>
25+
</div>
26+
{{/if}}

app/templates/project/conversations.hbs

+35-17
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,46 @@
88

99
<div class="conversations">
1010
<aside>
11-
{{#each (sort-by "updatedAt:desc" conversations) as |conversation|}}
12-
{{conversations/conversation-list-item-with-user
13-
conversation=conversation
14-
close=(action 'close')
15-
reopen=(action 'reopen')
11+
<div class="conversations__list-actions">
12+
{{conversations/status-select
13+
status=status
1614
}}
15+
</div>
16+
{{#if currentlyLoading}}
17+
{{loading-spinner}}
1718
{{else}}
18-
<div class="conversations__empty">
19-
<p class="conversations__empty__icon">
20-
{{fa-icon "comment"}}
21-
</p>
22-
<p><strong>You haven't had any conversations yet.</strong></p>
23-
<p>Go start one with someone in your project!</p>
24-
<p>
25-
{{link-to 'See your users' 'project.people' class="button default"}}
26-
</p>
27-
</div>
28-
{{/each}}
19+
{{#each (sort-by "updatedAt:desc" (filter-by "status" status conversations)) as |conversation|}}
20+
{{conversations/conversation-list-item-with-user
21+
conversation=conversation
22+
close=(action 'close')
23+
reopen=(action 'reopen')
24+
}}
25+
{{else}}
26+
<div class="conversations__empty">
27+
<p class="conversations__empty__icon">
28+
{{fa-icon "comment"}}
29+
</p>
30+
{{#if (eq status "open")}}
31+
<p><strong>You don't have any open conversations.</strong></p>
32+
<p>Go start one with someone in your project!</p>
33+
<p>
34+
{{link-to 'See your users' 'project.people' class="button default"}}
35+
</p>
36+
{{else if (eq status "closed")}}
37+
<p><strong>You don't have any closed conversations.</strong></p>
38+
{{/if}}
39+
</div>
40+
{{/each}}
41+
{{/if}}
2942
</aside>
3043
<section>
3144
<div class="conversation">
32-
{{outlet}}
45+
{{#if currentlyLoading}}
46+
<div class="conversation__loading">
47+
</div>
48+
{{else}}
49+
{{outlet}}
50+
{{/if}}
3351
</div>
3452
</section>
3553
</div>

0 commit comments

Comments
 (0)