Parley is a single-page live-chat application inspired by Slack built with Ruby-on-Rails on the backend and JavaScript/React.js with Redux on the front end.
Try out Parley's functionality by signing in as a guest or creating an account!
- Sign in or create an account
- Join or leave a channel
- View complete message history of a channel
- Start a direct conversation with your friends
- Receive messages in real time via Web Sockets
- Chat with the Parley Bot
- Use Emojis to express yourself
Parley is a single-page application built using Rails, React, and Redux. All content is delivered on one static page. Information is served via API calls to the Rails server, stored on the client using Redux, and rendered using React.
Parley employs front-end authentication for secure login and signup. It utilizes BCrypt for storing password digests in the database. Additionally to preview Parley, automated demo login is also set up.
Messages are stored in one table in the database with the following attributes:
id
body
user_id
channel_id
The user_id
attribute associates a message to the author. This allows only the author to delete their messages. The channel_id
attribute associates messages to the channel they belong to. Messages are rendered by a MessageIndex
component.
The MessageIndex
component renders each message via the MessageList
component and also provides an input field via the MessageForm
component.
- The
MessageList
component includes a React Emoji component that renders emoji-like text into actual emojis. - The
MessageForm
component includes a React Emoji Picker component which allows a user to select emojis.
Channels are stored in a table with the following attributes:
id
name
user_id
private
The private
attribute is a boolean value that identifies if a channel is public or private (Direct Message). All channel names are modified to lowercase and joined into one word separated by a -
(i.e. lunch plans
is changed to lunch-plans
before committing into the database). Users are subscribed
to a channel by the Subscription
join table.
Public
Channel names are verified to ensure they are unique. If a user attempts to create a public channel that already exists, the Rails Controller and Model will subscribe
the user to the existing channel.
Subscriptions are stored in the Subscription
join table. The join table belongs to a user
and a channel
. Records in this table are created by using the following Rails Association Helper Methods:
user.subscribed_channel_ids
channel.subscriber_ids
When a user opens the Channel form, search results are displayed for existing channels which a user can subscribe to. If a user selects a suggested result, the POST
request to the server subscribes the user to the channel. If the user inputs a new channel name, the POST
request will create a new channel.
For private channels / direct messages (DM), channel names are not validated for uniqueness. A username input box provides existing user suggestions when a user starts typing. Creating a new conversation with a user adds the conversation into the user's DM list in real time.
For Real Time Message functionality, Pusher API is used to create an Encrypted Web Socket connection between the client and the server. Once the connection is established, whenever a message is posted to the channel a user is on, a 'Pusher' event is triggered that the client listens for. This event triggers a callback to fetch new messages on the client. Similar events are used for:
- Real time message deletion
- Adding any new DM conversations if the user is added to a new DM conversation
A bot
user is setup which connects to an external API. For every new user that joins Parley, the Rails Users Controller automatically creates a DM between the user and the bot
.
def create
@user = User.new(user_params)
if @user.save
Pusher.trigger('users', 'new_user', {})
@user.subscribed_channel_ids = 1
ch = Channel.create!(name:"bot", user_id: 2, private: true)
ch.subscriber_ids = @user.id
login!(@user)
render "api/users/show"
else
render json: @user.errors.full_messages, status: 422
end
end
When a user posts a message to the bot
conversation, if the message saves to the database, a call is made with the message content to the chatbot API. The response from the API call is saved under the bot
username in the same channel. The bot is pre-configured by the API to reply to simple conversations.
React-Emoji and React-Emoji-Picker components are used to render emojis present in the body of the message and emoji picker.
In addition to the features already implemented, I plan on working on the following features.
Currently, a user must open a channel to check for new messages. To combat this, I plan on implementing additional actions which would listen for new messages from other channels allowing users to be notified when new messages appear.
I plan on using CarrierWave or Cloudinary to support file upload and utilize GitHub's Gists API to convert content into snippets. This will also help me to enable user profile images.