Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Component from '@ember/component';

export default Component.extend({
});
2 changes: 1 addition & 1 deletion app/components/conversations/new-conversation-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { and, not, notEmpty } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import RSVP from 'rsvp';

const SAVE_SUCCESS = 'Your message is queued to send.';
const SAVE_SUCCESS = 'Your message is sending now.';

export default Component.extend({
classNames: ['new-conversation-modal-container'],
Expand Down
5 changes: 5 additions & 0 deletions app/components/conversations/project-details.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Component from '@ember/component';

export default Component.extend({
classNames: ['conversation-details']
});
20 changes: 20 additions & 0 deletions app/controllers/conversations/conversation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Controller from '@ember/controller';
import { get } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';

export default Controller.extend({
currentUser: service(),

conversation: alias('model'),
user: alias('currentUser.user'),

send(body) {
let conversation = get(this, 'conversation');
let store = get(this, 'store');
let user = get(this, 'user');

let params = { author: user, body, conversation };
return store.createRecord('conversation-part', params).save();
}
});
7 changes: 7 additions & 0 deletions app/controllers/project/conversations.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import Controller from '@ember/controller';
import { set } from '@ember/object';

export default Controller.extend({
actions: {
close(conversation) {
set(conversation, 'status', 'closed');
return conversation.save();
}
}
});
4 changes: 4 additions & 0 deletions app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ Router.map(function() {
this.route('projects', function() {});
});

this.route('conversations', function() {
this.route('conversation', { path: '/:id' });
});

// GitHub OAuth redirection route
this.route('github', {
path: '/oauth/github'
Expand Down
45 changes: 45 additions & 0 deletions app/routes/conversations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { get } from '@ember/object';
import { alias } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Route.extend(AuthenticatedRouteMixin, {
conversations: service(),
currentUser: service(),
store: service(),

user: alias('currentUser.user'),

async model() {
let user = get(this, 'user');
let store = get(this, 'store');
// peekAll returns a live array, so it will also render any newly created
// messages
await store.query('conversation', { user_id: user.id });
let conversations = store.peekAll('conversation');
return { conversations };
},

renderTemplate() {
this.render('conversations', { into: 'application' });
},

setupController(controller, { conversations }) {
controller.setProperties({ conversations });
},

deactivate() {
this._super(...arguments);
get(this, 'conversations').deactivate();
return true;
},

actions: {
didTransition() {
this._super(...arguments);
get(this, 'conversations').activate();
return true;
}
}
});
30 changes: 30 additions & 0 deletions app/routes/conversations/conversation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { get } from '@ember/object';
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import { CanMixin } from 'ember-can';

export default Route.extend(AuthenticatedRouteMixin, CanMixin, {
conversationChannel: service(),
store: service(),

async model(params) {
let conversation = await get(this, 'store').findRecord('conversation', params.id);
await get(conversation, 'conversationParts');
return conversation;
},

afterModel(model) {
let conversation = model;
let conversationChannel = get(this, 'conversationChannel');
conversationChannel.join(conversation);
},

actions: {
willTransition() {
let conversation = get(this, 'controller.conversation');
let conversationChannel = get(this, 'conversationChannel');
conversationChannel.leave(conversation);
}
}
});
12 changes: 12 additions & 0 deletions app/routes/conversations/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { get } from '@ember/object';
import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Route.extend(AuthenticatedRouteMixin, {
redirect() {
let { conversations } = this.modelFor('conversations');
if (get(conversations, 'length') > 0) {
this.transitionTo('conversations.conversation', get(conversations, 'firstObject'));
}
}
});
2 changes: 1 addition & 1 deletion app/routes/project/conversations/conversation.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default Route.extend(AuthenticatedRouteMixin, CanMixin, {

actions: {
willTransition() {
let conversation = this.controller.get('conversation');
let conversation = get(this, 'controller.conversation');
let conversationChannel = get(this, 'conversationChannel');
conversationChannel.leave(conversation);
}
Expand Down
3 changes: 2 additions & 1 deletion app/styles/layout/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
order: 3;
}
}

.header-navigation__options {
display: flex;
justify-content: flex-end;
Expand All @@ -80,7 +81,7 @@
color: $gray;
font-size: 24px;
margin: 0 5px;
padding: 5px 10px;
padding: 4px 10px;
}

&.active, &:hover {
Expand Down
21 changes: 20 additions & 1 deletion app/styles/shared/conversation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}

.conversation-details {
overflow-y: auto;
position: absolute;
top: 0; bottom: 0; right: 0;
width: 33%;
Expand All @@ -41,13 +42,31 @@
}
}

&__user {
&__project, &__user {
text-align: center;

p {
margin: 0.5em 0;
}
}

&__project {
&__title {
font-size: $header-font-size-small;
}

&__description {
color: $text--lighter;
font-size: $body-font-size-small;
}

&__categories {
display: flex;
justify-content: center;
}
}

&__user {
&__username {
color: $text--lighter;
font-size: $body-font-size-small;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{#link-to "conversations.conversation" conversation.id class="conversation-list-item conversation-list-item--with-project"}}
<div class="conversation-list-item__avatar">
<img data-test-project-icon class="icon" src={{conversation.message.project.iconThumbUrl}} />
</div>
<div class="conversation-list-item__info">
<p data-test-project-title class="conversation-list-item__name">
<strong>
{{conversation.message.project.title}}
</strong>
</p>
<p data-test-updated-at class="conversation-list-item__timestamp">
{{moment-from-now conversation.updatedAt}}
</p>
</div>
{{/link-to}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{#link-to "project.conversations.conversation" conversation.id class="conversation-list-item"}}
{{#link-to "project.conversations.conversation" conversation.id class="conversation-list-item conversation-list-item--with-user"}}
<div class="conversation-list-item__avatar">
<img data-test-target-photo class="icon" src={{conversation.user.photoThumbUrl}} />
</div>
Expand All @@ -18,8 +18,11 @@
<p data-test-updated-at class="conversation-list-item__timestamp">
{{moment-from-now conversation.updatedAt}}
</p>
<span data-test-close-link class="conversation-list-item__close-link">
{{fa-icon "check"}} <span>Close</span>
</span>
{{#if (eq conversation.status 'open')}}
{{!-- bubbles=false to prevent bubbling to wrapping link-to element --}}
<span data-test-close-link class="conversation-list-item__close-link" {{action close conversation bubbles=false}}>
{{fa-icon "check"}}<span>Close</span>
</span>
{{/if}}
</div>
{{/link-to}}
15 changes: 15 additions & 0 deletions app/templates/components/conversations/project-details.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="conversation-details__section conversation-details__project">
<p><img class="icon" src={{project.iconThumbUrl}} /></p>
<p class="conversation-details__project__title" data-test-title>
<strong>
{{project.title}}
</strong>
</p>
<p class="conversation-details__project__categories">
{{project-categories-list categories=project.categories}}
</p>
<p class="conversation-details__project__description" data-test-description>
{{project.description}}
</p>
{{related-skills class="project-card__skills" overflowHidden=true skills=project.skills}}
</div>
3 changes: 3 additions & 0 deletions app/templates/components/navigation-menu.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
{{#if navigationMenu.isDefault}}
{{#if session.isAuthenticated}}
<nav class="header-navigation--right">
<ul class="header-navigation__options">
<li>{{#link-to "conversations" data-test-conversations-link class="header-navigation__icon-link"}}{{fa-icon "comments"}}{{/link-to}}</li>
</ul>
{{user-menu user=currentUser.user class="header-navigation__options" }}
</nav>
{{else}}
Expand Down
23 changes: 23 additions & 0 deletions app/templates/conversations.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{title "Conversations"}}

<div class="conversations">
<aside>
{{#each conversations as |conversation|}}
{{conversations/conversation-list-item-with-project
conversation=conversation
}}
{{else}}
<div class="conversations__empty">
<p class="conversations__empty__icon">
{{fa-icon "comment"}}
</p>
<p><strong>You haven't had any conversations yet.</strong></p>
</div>
{{/each}}
</aside>
<section>
<div class="conversation">
{{outlet}}
</div>
</section>
</div>
7 changes: 7 additions & 0 deletions app/templates/conversations/conversation.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{{conversations/conversation-thread
conversation=conversation
send=(action send)
}}
{{conversations/project-details
project=conversation.message.project
}}
Empty file.
5 changes: 4 additions & 1 deletion app/templates/project/conversations.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
<div class="conversations">
<aside>
{{#each conversations as |conversation|}}
{{conversations/conversation-list-item conversation=conversation}}
{{conversations/conversation-list-item-with-user
conversation=conversation
close=(action 'close')
}}
{{else}}
<div class="conversations__empty">
<p class="conversations__empty__icon">
Expand Down
23 changes: 16 additions & 7 deletions mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ function generatePreviewMentions(schema, preview) {

// The set of routes we have defined; needs updated when adding new routes
const routes = [
'categories', 'comment-user-mentions', 'comments', 'donation-goals',
'github-events', 'messages', 'organizations', 'organization-invites',
'task-lists', 'task-skills', 'task-user-mentions', 'tasks', 'previews',
'projects', 'project-categories', 'slugged-routes', 'stripe-connect-accounts',
'stripe-connect-subscriptions', 'stripe-connect-plans',
'stripe-platform-cards', 'stripe-platform-customers', 'user-categories',
'users'
'categories', 'comment-user-mentions', 'comments', 'conversations',
'conversation-parts', 'donation-goals', 'github-events', 'messages',
'organizations', 'organization-invites', 'task-lists', 'task-skills',
'task-user-mentions', 'tasks', 'previews', 'projects', 'project-categories',
'slugged-routes', 'stripe-connect-accounts', 'stripe-connect-subscriptions',
'stripe-connect-plans', 'stripe-platform-cards', 'stripe-platform-customers',
'user-categories', 'users'
];

export default function() {
Expand Down Expand Up @@ -142,6 +142,15 @@ export default function() {

this.get('/conversations', { coalesce: true });
this.get('/conversations/:id');
this.patch('/conversations/:id');

/**
* Conversation parts
*/

this.get('/conversation-parts', { coalesce: true });
this.get('/conversation-parts/:id');
this.post('/conversation-parts');

/**
* Donation goals
Expand Down
15 changes: 15 additions & 0 deletions mirage/factories/conversation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,22 @@ import { Factory } from 'ember-cli-mirage';
import moment from 'moment';

export default Factory.extend({
status: 'open',

updatedAt(i) {
return moment().subtract(i, 'days');
},

// ensures creation of associated records if they were not otherwise specified
afterCreate(conversation, server) {
if (!conversation.user) {
conversation.user = server.create('user');
conversation.save();
}

if (!conversation.message) {
conversation.message = server.create('message');
conversation.save();
}
}
});
5 changes: 3 additions & 2 deletions mirage/models/conversation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Model, belongsTo } from 'ember-cli-mirage';
import { Model, belongsTo, hasMany } from 'ember-cli-mirage';

export default Model.extend({
message: belongsTo(),
user: belongsTo()
user: belongsTo(),
conversationParts: hasMany()
});
Loading