app/assets/javascripts/components/conversation_list.js.jsx
/** @jsx React.DOM */
var ConversationList = React.createClass({
getInitialState: function() {
return {
loaded: false,
conversations: [],
archived: this.props.archived,
};
},
componentDidMount: function() {
if(this.props.demo) {
this.setState({ loaded: true });
return;
}
if(this.props.conversationNumber) {
this.getConversation();
} else {
this.getConversations();
}
},
getConversation: function() {
$.getJSON(this.conversationPath(), function(response) {
this.setState({ archived: response.conversation.archived });
this.getConversations();
}.bind(this));
},
getConversations: function() {
$.getJSON(this.conversationsPath(), function(response) {
var conversations = response.conversations;
conversations = conversations.map(function(conversation) {
conversation.expanded = (this.props.conversationNumber == conversation.number)
return conversation;
}.bind(this));
this.setState({
loaded: true,
conversations: conversations
});
}.bind(this));
},
toggleHandler: function(toggled) {
return function(event) {
event.stopPropagation();
event.preventDefault();
if(getSelection().toString()) {
return;
}
var conversations = this.state.conversations.map(function(conversation) {
if(conversation === toggled) {
var expanded = !conversation.expanded;
conversation.expanded = expanded;
// TODO: Remove nested conditionals
if(expanded) {
conversation.unread = false;
this.read(conversation);
}
} else {
conversation.expanded = false;
}
return conversation;
}.bind(this));
this.setState({ conversations: conversations });
}.bind(this);
},
read: function(conversation) {
$.getJSON(conversation.path)
},
// FIXME: Add more nested functions for no reason
removeTagHandler: function(removeFrom) {
return function(tag) {
return function(event) {
event.stopPropagation();
event.preventDefault();
var removeTagEvent = function() {
var conversations = this.state.conversations.map(function(conversation) {
if(conversation === removeFrom) {
var filteredTagEvents = conversation.tag_events.filter(function(tagEvent) {
return tagEvent.id != tag.id;
});
conversation.tag_events = filteredTagEvents;
};
return conversation;
});
this.setState({ conversations: conversations });
}.bind(this);
var tagsPath = removeFrom.tags_path + '/' + tag.id;
$.ajax({
type: 'DELETE',
url: tagsPath,
success: function(response) {
removeTagEvent();
}.bind(this)
});
}.bind(this);
}.bind(this);
},
addStreamItemHandler: function(addedTo) {
return function(streamItem) {
var conversations = this.state.conversations.map(function(conversation) {
if(conversation === addedTo) {
switch(streamItem.type) {
case 'message':
conversation.messages.push(streamItem);
break;
case 'assignmentevent':
conversation.assignment_events.push(streamItem);
break;
case 'tagevent':
conversation.tag_events.push(streamItem);
break;
}
}
return conversation;
});
this.setState({ conversations: conversations });
}.bind(this);
},
archiveHandler: function(conversation) {
return function(event) {
if(event) {
event.stopPropagation();
event.preventDefault();
}
if(this.props.demo) {
this.moveToArchive(conversation);
return;
}
var data = {
conversation: {
archive: true
}
};
$.ajax({
type: 'PUT',
url: conversation.path,
data: JSON.stringify(data),
dataType: 'json',
contentType: 'application/json',
accepts: { json: 'application/json' },
success: function(response) {
this.moveToArchive(conversation);
}.bind(this)
});
}.bind(this);
},
moveToArchive: function(conversation) {
conversation.expanded = false;
var index = this.state.conversations.indexOf(conversation);
var conversations = this.state.conversations.slice(0, index).
concat(this.state.conversations.slice(index + 1));
this.setState({ conversations: conversations });
},
unarchiveHandler: function(conversation) {
return function(event) {
event.stopPropagation();
event.preventDefault();
var data = {
conversation: {
unarchive: true
}
};
$.ajax({
type: 'PUT',
url: conversation.path,
data: JSON.stringify(data),
dataType: 'json',
contentType: 'application/json',
accepts: { json: 'application/json' },
success: function(response) {
this.moveToArchive(conversation);
}.bind(this)
});
}.bind(this);
},
moveToInbox: function(conversation) {
conversation.expanded = false;
var index = this.state.conversations.indexOf(conversation);
var conversations = this.state.conversations.slice(0, index).
concat(this.state.conversations.slice(index + 1));
this.setState({ conversations: conversations });
},
renderConversation: function(conversation) {
if(conversation.messages.length > 0) {
return Conversation({
conversation: conversation,
toggleHandler: this.toggleHandler(conversation),
addStreamItemHandler: this.addStreamItemHandler(conversation),
archiveHandler: this.archiveHandler(conversation),
unarchiveHandler: this.unarchiveHandler(conversation),
removeTagHandler: this.removeTagHandler(conversation),
key: conversation.id,
demo: this.props.demo
});
}
},
render: function() {
if(this.state.conversations.length) {
var conversations = this.state.conversations.map(this.renderConversation);
return (
<div className="list list-conversations">{conversations}</div>
)
} else if(this.state.loaded) {
if (this.state.archived || this.props.query || this.props.tag || this.props.assignee) {
return <EmptyConversationList />
}
else {
return <InboxZero />
}
} else {
return <div></div>
}
},
inboxPath: function() {
return '/' + this.props.accountSlug + '/inbox';
},
archivePath: function() {
return '/' + this.props.accountSlug + '/archived';
},
conversationsPath: function() {
var path = [];
path.push('/accounts/');
path.push(this.props.accountSlug);
path.push('/conversations.json');
if(this.props.query || this.props.tag || this.props.assignee) {
if(this.props.query) {
path.push('?q=');
path.push(encodeURIComponent(this.props.query));
} else if(this.props.tag) {
path.push('?tag=');
path.push(encodeURIComponent(this.props.tag));
} else if(this.props.assignee) {
path.push('?assignee=');
path.push(encodeURIComponent(this.props.assignee));
}
} else {
path.push('?archived=');
path.push(this.state.archived);
}
return path.join('');
},
conversationPath: function() {
return '/accounts/' + this.props.accountSlug + '/conversations/' + this.props.conversationNumber + '.json';
}
});