Skip to content
This repository was archived by the owner on Jul 24, 2020. It is now read-only.

[1572] Convert User Profile to React #1579

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 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
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ diff.py
Vagrantfile
*.sublime*
coverage/
.env
.env# React on Rails
npm-debug.log
node_modules

# Generated js bundles
/app/assets/webpack/*
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ AllCops:
# 2015/01/04 - skipping Capistrano deploy.rb file for now, remove the
# following line once #1074 is resolved
- 'config/deploy.rb'
- 'config/initializers/react_on_rails.rb'
- 'lib/**/*.erb'
- 'script/**/*'
- 'vendor/**/*'
- 'node_modules/**/*'
# disable the documentation check at the start of classes / modules
Documentation:
Enabled: false
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ before_script:
- cp config/secrets.yml.example config/secrets.yml
- bundle exec rake db:create
- bundle exec rake db:schema:load
- npm run build:test

script:
# JS linters, uncomment once code passes
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ gem 'select2-rails', '~> 4.0.2'
gem 'kaminari', '~> 0.16.3'
gem 'draper', '~> 2.1.0'
gem 'inline_svg', '~> 0.8.0'
gem 'react_on_rails', '~> 6.0.1'
gem 'active_model_serializers', '~> 0.10.0'

# forms / formatting
gem 'simple_form', '~> 3.2.1'
Expand Down
16 changes: 16 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ GEM
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
active_model_serializers (0.10.0)
actionpack (>= 4.0)
activemodel (>= 4.0)
railties (>= 4.0)
activejob (4.2.6)
activesupport (= 4.2.6)
globalid (>= 0.3.0)
Expand Down Expand Up @@ -104,6 +108,7 @@ GEM
execjs
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
connection_pool (2.2.0)
daemons (1.2.3)
database_cleaner (1.5.3)
debug_inspector (0.0.2)
Expand Down Expand Up @@ -144,6 +149,8 @@ GEM
ffi (1.9.10)
font-awesome-rails (4.6.3.0)
railties (>= 3.2, < 5.1)
foreman (0.82.0)
thor (~> 0.19.1)
formatador (0.2.5)
fullcalendar-rails (2.6.1.0)
jquery-rails (>= 4.0.5, < 5.0.0)
Expand Down Expand Up @@ -339,6 +346,13 @@ GEM
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
react_on_rails (6.0.1)
addressable
connection_pool
execjs (~> 2.5)
foreman
rails (>= 3.2)
rainbow (~> 2.1)
redcarpet (3.3.4)
ref (2.0.0)
remotipart (1.2.1)
Expand Down Expand Up @@ -445,6 +459,7 @@ PLATFORMS
ruby

DEPENDENCIES
active_model_serializers (~> 0.10.0)
awesome_print (~> 1.6.1)
aws-sdk (< 2.0)
bootstrap-sass (~> 3.3.6)
Expand Down Expand Up @@ -501,6 +516,7 @@ DEPENDENCIES
rails_12factor (~> 0.0.3)
rails_admin (~> 0.8.1)
rake (~> 11.1.2)
react_on_rails (~> 6.0.1)
redcarpet (~> 3.3.4)
rspec-rails (~> 3.4.2)
rubocop (~> 0.40.0)
Expand Down
2 changes: 2 additions & 0 deletions Procfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web: rails s
client: sh -c 'rm app/assets/webpack/* || true && cd client && npm run build:development'
2 changes: 2 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//= require webpack-bundle

//= require jquery
//= require jquery_ujs
//= require datatables.min.js
Expand Down
68 changes: 45 additions & 23 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# rubocop:disable ClassLength
class UsersController < ApplicationController
include ReactOnRails::Controller

load_and_authorize_resource
layout 'application_with_sidebar', only: [:show, :edit]

Expand All @@ -12,6 +14,7 @@ class UsersController < ApplicationController
only: [:show, :edit, :update, :destroy, :ban, :unban]
before_action :check_cas_auth, only: [:show, :new, :create, :quick_create,
:edit, :update]
before_action :props, only: [:show]

include Autocomplete
include Calendarable
Expand Down Expand Up @@ -168,29 +171,10 @@ def edit
@can_edit_username = can? :edit_username, User
end

def update # rubocop:disable CyclomaticComplexity, PerceivedComplexity
@edit_title_text = (current_user == @user) ? 'Profile' : 'User'
par = user_params
# use :update_with_password when we're not using CAS and you're editing
# your own profile
if @cas_auth || ((can? :manage, User) && (@user.id != current_user.id))
method = :update_attributes
# delete the current_password key from the params hash just in case it's
# present (and :update_attributes will throw an error)
par.delete('current_password')
else
method = :update_with_password
# make sure we update the username as well
par[:username] = par[:email]
end
if @user.send(method, par)
# sign in the user if you've edited yourself since you have a new
# password, otherwise don't
sign_in @user, bypass: true if @user.id == current_user.id
flash[:notice] = 'Successfully updated user.'
redirect_to user_path(@user)
else
render :edit
def update
respond_to do |format|
format.html { html_update }
format.json { js_update }
end
end

Expand Down Expand Up @@ -243,6 +227,37 @@ def find # rubocop:disable CyclomaticComplexity, PerceivedComplexity

private

def html_update # rubocop:disable CyclomaticComplexity, PerceivedComplexity
@edit_title_text = (current_user == @user) ? 'Profile' : 'User'
par = user_params
# use :update_with_password when we're not using CAS and you're editing
# your own profile
if @cas_auth || ((can? :manage, User) && (@user.id != current_user.id))
method = :update_attributes
# delete the current_password key from the params hash just in case it's
# present (and :update_attributes will throw an error)
par.delete('current_password')
else
method = :update_with_password
# make sure we update the username as well
par[:username] = par[:email]
end
if @user.send(method, par)
# sign in the user if you've edited yourself since you have a new
# password, otherwise don't
sign_in @user, bypass: true if @user.id == current_user.id
flash[:notice] = 'Successfully updated user.'
redirect_to user_path(@user)
else
render :edit
end
end

def js_update
flash[:error] unless @user.update(user_params)
render nothing: true
end

def user_params
permitted_attributes = [:first_name, :last_name, :nickname, :phone,
:email, :affiliation, :terms_of_service_accepted,
Expand Down Expand Up @@ -273,4 +288,11 @@ def generate_calendar_resource
def calendar_name_method
:equipment_model
end

# React on Rails / Redux methods

def props
@props = ActiveModelSerializers::SerializableResource
.new(@user, scope: current_user, scope_name: :current_user)
end
end
16 changes: 16 additions & 0 deletions app/serializers/user_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class UserSerializer < ActiveModel::Serializer
attributes :id, :email, :first_name, :last_name, :nickname, :phone,
:affiliation, :terms_of_service_accepted, :role,
:reservation_counts

def reservation_counts
res = object.reservations
counts = { checked_out: res.checked_out.count,
overdue: res.overdue.count,
future: res.reserved.count,
past: res.returned.count,
past_overdue: res.returned_overdue.count }
counts[:missed] = res.missed.count unless AppConfig.check(:res_exp_time)
counts
end
end
45 changes: 1 addition & 44 deletions app/views/users/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,50 +25,7 @@
</div>


<div class="row">

<dl id="user_info" class="dl-horizontal col-md-6">
<div class="well">
<% if @cas_auth %>
<dt>Username</dt>
<dd><%= @user.username %></dd>
<% end %>

<dt>First Name</dt>
<dd><%= @user.first_name %></dd>

<dt>Last Name</dt>
<dd><%= @user.last_name %></dd>

<dt>Nickname</dt>
<dd><%= [email protected]? ? @user.nickname : "(none)" %></dd>

<dt>Phone</dt>
<dd><%= [email protected]? ? @user.phone : "(none)" %></dd>

<dt>Email</dt>
<dd><%= mail_to @user.email, @user.email %></dd>

<dt>Affiliation</dt>
<dd><%= @user.affiliation %></dd>
</div>
</dl>

<div id="user_stats" class="col-md-6">

<%# @show_equipment has reservation status (:overdue, ...) as key, full
reservations in question as value %>
<% @show_equipment.each do |status, reservations| %>
<%= content_tag :div, :id => "#{status}_count", :class => 'col-md-6' do %>
<%= content_tag :h4, status.to_s.titleize %>
<%= content_tag :div, :class => "#{status}_num" do %>
<%= content_tag :i, nil, :class => stats_icons(status) %>
<%= reservations.size %>
<% end %>
<% end %>
<% end %>
</div>
</div>
<%= react_component('UserProfile', props: @props) %>

<%# TODO: Make this prettier %>
<% unless @user.requirements.empty? %>
Expand Down
3 changes: 3 additions & 0 deletions client/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015", "stage-0", "react"]
}
9 changes: 9 additions & 0 deletions client/REACT_ON_RAILS_CLIENT_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Client folder generated by the React on Rails gem.

See documentation [at github.com/shakacode/react_on_rails](https://github.com/shakacode/react_on_rails) for details on how it is organized.

If you need additional help, please consider:

* [Our ShakaCode Forum for React on Rails](https://forum.shakacode.com/c/rails/reactonrails).
* Joining our Slack discussion room by [email us a bit about you and your project](mailto:[email protected]).
* [Hiring us](https://forum.shakacode.com/c/rails/reactonrails) for coaching and custom web application development for your project.
12 changes: 12 additions & 0 deletions client/app/reducers.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is our manifest of all reducers for the app.
import userReducer from './user/userReducer';
import { $$initialState as $$userState } from './user/userReducer';

export default {
$$userStore: userReducer,
};

export const initialStates = {
$$userState,
};

7 changes: 7 additions & 0 deletions client/app/registration.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import ReactOnRails from 'react-on-rails';

import UserProfile from './user/UserProfile';

ReactOnRails.register({
UserProfile,
});
24 changes: 24 additions & 0 deletions client/app/user/UserProfile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import User from './userContainer';
import userReducer from './userReducer';


export default (props, _railsContext) => {
const store = createStore(userReducer);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to createStore(userReducer, user: props.user); and get rid of the if statement on lines 10-15

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also should probably think about moving the store creation to a separate file

if (store.getState().user === null) {
store.dispatch({
type: 'SET_USER',
user: props
});
}

const reactComponent = (
<Provider store={store}>
<User />
</Provider>
);
return reactComponent;
};

Loading