Skip to content

Commit

Permalink
[43] Mark as read from react side
Browse files Browse the repository at this point in the history
  • Loading branch information
notmarkmiranda committed Feb 21, 2019
1 parent f1eca63 commit 1994b92
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 16 deletions.
1 change: 1 addition & 0 deletions app/controllers/api/v1/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def mark_as_read
if params[:id]
notification = current_user.notifications.find(params[:id])
notification.mark_as_read!
render json: notification, status: 200
else
current_user.notifications.update_all(read_at: Time.now)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def navbar_props
},
userAttributes: {
currentUserEmail: current_user&.email,
notificationCount: current_user&.unread_notifications_count
unreadNotificationCount: current_user&.unread_notifications_count
},
isLoggedIn: current_user.present?
}
Expand Down
4 changes: 4 additions & 0 deletions app/decorators/notification_decorator.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class NotificationDecorator < ApplicationDecorator
delegate_all

def decorated_created_at
"#{h.time_ago_in_words(object.created_at)} ago"
end

def mark_as_read_link
unless object.read_at
"| #{h.link_to 'mark as read', '#'}"
Expand Down
35 changes: 34 additions & 1 deletion app/javascript/components/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,43 @@ class NavBar extends Component {
}

componentDidMount() {
console.log(this.state);
if (this.state.isLoggedIn) {
axios.get(this.state.routes.lastFiveNotificationsPath)
.then((response) => {
this.setState({ notifications: response.data })
console.log(this.state);
})
} else {
}
}

markSingleNotificationAsRead = (notificationId) => {
if (notificationId) {
const csrfToken = document.querySelector('[name="csrf-token"]').content;
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken;

axios.patch(`/api/v1/notifications/${notificationId}/mark_as_read`)
.then((response) => {
const newUnreadCount = this.state.userAttributes.unreadNotificationCount - 1
const index = this.state.notifications.findIndex((notification) => notification.id === notificationId)
const updatedNotifications = this.state.notifications
updatedNotifications[index] = response.data
const newState = { ...this.state.userAttributes }

newState.unreadNotificationCount = newUnreadCount
this.setState({ notifications: updatedNotifications, userAttributes: newState })
console.log(this.state);

// this is correct, i need to replace the notification in the notification part of state to refresh the dropdown
})
.catch((error) => {
console.log(error);
})
}
// make api call
}

render () {
const { isLoggedIn, userAttributes, routes, notifications } = this.state
const { rootPath } = routes
Expand All @@ -35,7 +63,12 @@ class NavBar extends Component {
<span className="navbar-toggler-icon"></span>
</button>
{ isLoggedIn
? <UserNav routes={ routes } userAttributes={ userAttributes } notifications={ notifications } />
? <UserNav
routes={ routes }
userAttributes={ userAttributes }
notifications={ notifications }
markSingleNotificationAsRead={ this.markSingleNotificationAsRead }
/>
: <VisitorNav routes={ routes } />
}
</div>
Expand Down
9 changes: 8 additions & 1 deletion app/javascript/components/Notification.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import React from 'react'

const Notification = ({ notificationText }) => {
const Notification = ({ notificationText, notificationReadAt, notificationCreatedAt, notificationId, markSingleNotificationAsRead }) => {
return (
<div className="dropdown-item">
{ notificationText }
<div className="caption-text">
{ notificationCreatedAt }
{
!notificationReadAt &&
<span> | <a onClick={ () => markSingleNotificationAsRead(notificationId) } className="muted-text caption-text">mark as read</a></span>
}
</div>
</div>
)
}
Expand Down
27 changes: 18 additions & 9 deletions app/javascript/components/UserNav.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import React, { Component } from 'react'
import React, { Component } from 'react'

import Notification from './Notification'

class UserNav extends Component {
renderNotifications = (notes) => {
return notes.map((note) => {
return <Notification notificationText={ note.note_text } key={ note.id } />
return <Notification
notificationText={ note.note_text }
notificationReadAt={ note.read_at }
notificationCreatedAt={ note.decorated_created_at }
notificationId={ note.id }
markSingleNotificationAsRead={ this.props.markSingleNotificationAsRead }
key={ note.id }
/>
})
}

render() {
const { routes, userAttributes, notifications } = this.props
const { routes, userAttributes, notifications, markSingleNotificationAsRead } = this.props
const { leaguesPath, dashboardPath, newLeaguePath, destroyUserSessionPath, notificationsPath } = routes
const { currentUserEmail, notificationCount } = userAttributes
const { currentUserEmail, unreadNotificationCount } = userAttributes

return (
<div className="collapse navbar-collapse" id="navbarSupportedContent">
Expand Down Expand Up @@ -41,23 +48,25 @@ class UserNav extends Component {
</a>
</div>
</li> { /* user dropdown */ }
<li className="nav-item-dropdown">
<li className="nav-item dropdown">
<a className="nav-link" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<h6>
<span className="badge badge-info dropdown-toggle">
{ notificationCount }
{ unreadNotificationCount }
</span>
</h6>
</a>
<div className="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
{
notifications
notifications && notifications.length > 0
? this.renderNotifications(notifications)
: <div>nope</div>
: <div className="dropdown-item">There are currently no notifications!</div>
}
<div className="dropdown-divider"></div>
<a href={ notificationsPath } className="dropdown-item">view all notifications</a>
<a href='#' className="dropdown-item">mark all as read</a>
{
unreadNotificationCount > 0 && <a href='#' className="dropdown-item">mark all as read</a>
}
</div>
</li> { /* notifications dropdown */ }
</ul>
Expand Down
2 changes: 1 addition & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def full_name
end

def last_five_notifications
notifications.last(5)
notifications.order(created_at: :desc).first(5)
end

def number_of_leagues_played_in
Expand Down
11 changes: 10 additions & 1 deletion app/serializers/notification_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
require 'action_view'
require 'action_view/helpers'

class NotificationSerializer < ActiveModel::Serializer
attributes :id, :note_text
include ActionView::Helpers::DateHelper

attributes :id, :note_text, :read_at, :decorated_created_at

def note_text
object.notification_text
end

def decorated_created_at
object.decorate.decorated_created_at
end
end
1 change: 1 addition & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ default: &default
# For details on connection pooling, see Rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: localhost

development:
<<: *default
Expand Down
6 changes: 4 additions & 2 deletions spec/requests/api/v1/notifications_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

describe 'as a user' do
let(:expected_return) do
notifications.map do |note|
notifications.sort_by(&:created_at).reverse.map do |note|
{
"id" => note.id,
"note_text" => note.notification_text
"note_text" => note.notification_text,
"read_at" => note.read_at,
"decorated_created_at" => note.decorate.decorated_created_at
}
end
end
Expand Down

0 comments on commit 1994b92

Please sign in to comment.