Skip to content

Instantly share code, notes, and snippets.

@supertinou
Last active June 12, 2018 11:53
Show Gist options
  • Save supertinou/602645c7bfb7ee99c84b to your computer and use it in GitHub Desktop.
Save supertinou/602645c7bfb7ee99c84b to your computer and use it in GitHub Desktop.
React component which displays participants statuses and refresh the statuses in Realtime.

Component

Usage

You can display / refresh / add participants by passing to the participants property an array of participants. See the examples below:

Displaying some participants:

participants = [
  {uuid: '45689', status: 'online', name: 'Martin', email: '[email protected]'},
  {uuid: '89656', status: 'online', name: 'John', email: '[email protected]'}
]
React.render(<ParticipantsList participants=participants />, mountNode) 

Refreshing the status of a participant:

participants = [{ uuid: '45689', status: 'offline' }]
React.render(<ParticipantsList participants=participants />, mountNode) 

Dependencies

  • Twitter Bootsrap 3.3
  • Underscore 1.8
  • Font awesome 4.4
  • A custom md5 function for displaying the gravatar
.c-list {
padding: 0px;
min-height: 44px;
}
.c-title {
display: inline-block;
font-size: 1.0em;
font-weight: bold;
padding: 10px 15px;
}
.c-name {
font-size: 1.0em;
font-weight: 700;
}
.c-info {
padding: 5px 10px;
font-size: 1.25em;
}
@ParticipantStatus = React.createClass(
render: ->
status_classes = classNames('c-info', 'fa', 'fa-circle', this.props.participant.status)
gravatar_email = this.props.participant.email || "#{Math.random().toString(36)}@provider.com"
<li className="list-group-item">
<div className="col-xs-12 col-sm-4">
<img src={gravatarUrl(gravatar_email, 200)} alt="{this.props.participant.name}" className="img-responsive img-circle" />
</div>
<div className="col-xs-12 col-sm-7">
<span className="c-name">{this.props.participant.name}</span><br/>
<span className={ status_classes } data-toggle="tooltip" title={this.props.participant.status}></span>
<span className="visible-xs"> <br/></span>
<span className="fa fa-envelope-o c-info" data-toggle="tooltip" title={this.props.participant.email}></span>
<span className="visible-xs"><br/></span>
</div>
<div className="clearfix"></div>
</li>
)
@ParticipantsList = React.createClass(
componentWillReceiveProps: (nextProps) ->
current_participants = this.state.participants
updated_participants = current_participants
addOrUpdateParticipant =(new_participant) ->
existing_participant_index = _.findIndex(current_participants, (current_participant) ->
current_participant.uuid is new_participant.uuid
)
if existing_participant_index?
new_name = if new_participant.name? then new_participant.name else current_participants[existing_participant_index].name
new_email = if new_participant.email? then new_participant.email else current_participants[existing_participant_index].email
new_participant = {uuid: new_participant.uuid, name: new_name, status: new_participant.status, email: new_email }
current_participants[existing_participant_index] = new_participant
else
updated_participants.push(new_participant)
_.each nextProps.participants, (participant) ->
addOrUpdateParticipant(participant)
this.setState
participants: updated_participants
getInitialState: ->
participants: this.props.participants
render: ->
<div className="panel panel-default">
<div className="panel-heading c-list">
<span className="c-title">Participants ({countOnlineParticipants(this.state.participants)} online)</span>
</div>
<ul className="list-group" >
{
this.state.participants.map( (participant)->
<ParticipantStatus key={participant.uuid} participant={participant} />
)
}
</ul>
</div>
)
// find the array index of an object with a specific key value
_.findIndex = _.detect = function(obj, predicate, context) {
var result;
_.any(obj, function(value, index, list) {
if (predicate.call(context, value, index, list)) {
result = index;
return true;
}
});
return result;
};
@countOnlineParticipants = (participants) ->
_.where(participants, {status: "online"}).length
@gravatarUrl = (email, size) ->
size ||= 200
'http://www.gravatar.com/avatar/' + md5(email) + "?d=retro&s=#{size}"
@supertinou
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment