Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User settings #79

Merged
merged 11 commits into from
Sep 11, 2014
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
@import "users/sign_up";
@import "users/password_reset";
@import "users/profile";
@import "users/settings";

@import "pages/frontpage";

Expand Down
55 changes: 55 additions & 0 deletions app/assets/stylesheets/users/_settings.css.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.user-settings {

margin-top: 20px;

h1 {
font-size: 16px;
padding-top: 5px;
border-top: solid 1px $soft-grey;
margin-bottom: 20px;
}

p {

padding-bottom: 10px;
margin-bottom: 5px;

label {
display: inline-block;
font-weight: bold;
width: 150px;
}

input, select, .inline {
display: inline-block;
}
select { width: 153px }

.inline {
padding: 5px 10px;
font-weight: bold;
background-color: $ultra-soft-grey;
border-radius: 4px;
}
.password-field, .mail_notifications_choice {
display: inline-block;
width: 153px;
}

.mail_notifications_choice {
label, input {
display: inline-block;
font-weight: normal;
vertical-align: top;
}
label { width: 125px; }
}

.password-reset {
@include button;
padding: 4px 10px;
}

input[type=submit] { margin-top: 20px; }
}
}
21 changes: 21 additions & 0 deletions app/controllers/settings_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class SettingsController < ApplicationController
before_action :require_login
before_action :set_user

def show
end

def update
@settings.assign_attributes(params[:settings])
flash[:notice] = @settings.save ? t('flash.saved') : t('settings.error')
render json: {redirect: user_path(@user)}
end

private

def set_user
redirect_to root_path, notice: t('access_denied') unless current_user.id == params[:id].to_i
@user = current_user
@settings = @user.settings
end
end
4 changes: 4 additions & 0 deletions app/helpers/concerns/i18n_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@ def current_translations
@translations ||= I18n.backend.send(:translations)
(@translations[I18n.locale] || {}).with_indifferent_access
end

def language_options
I18n.available_locales.map { |lang| [i18n_language_names[lang], lang.to_s] }
end
end
end
32 changes: 32 additions & 0 deletions app/models/settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class Settings
extend ActiveModel::Model
extend ActiveModel::Naming
include ActiveModel::Conversion

attr_accessor :user, :language, :auth_token, :mail_notifications

def initialize(user)
self.user = user
self.language = user.language
self.auth_token = user.auth_token
self.mail_notifications = user.mail_notifications
end

def assign_attributes(attrs)
attrs.each { |name, value| send "#{name}=", value }
end

def save
user.assign_attributes language: language, mail_notifications: mail_notifications
user.save
end

def persisted?
false
end

def id
nil
end

end
4 changes: 4 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ def unread_notifications_count
Notification.where(user: self, status: "unread").count
end

def settings
@settings ||= Settings.new(self)
end

private

def set_auth_token
Expand Down
4 changes: 3 additions & 1 deletion app/presenters/toolbar_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ def _history_tool
end

def _settings_tool
{ icon: :'cog', title: t('toolbar.settings'), url: "" }
settings_url = ctx.settings_path
{ icon: :'cog', title: t('toolbar.settings'), url: settings_url,
active?: ctx.request.path == settings_url }
end

def _flag_tool
Expand Down
44 changes: 44 additions & 0 deletions app/views/settings/_edit_settings.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<section class="user-settings wrapper">

<header><h1><%= t 'settings.title' %></h1></header>

<%= remote_form_for @settings, url: settings_path, method: 'patch' do |f| %>

<p>
<%= f.label :password, t('settings.password.label') %>
<%= link_to_modal t('settings.password.button'), forgot_password_users_path,
:remote => true, html: {class: 'password-reset'} %>
</p>

<p>
<%= f.label :language, t('settings.language') %>
<%= f.select :language, language_options %>
</p>

<p>
<%= f.label :mail_notifications, t('settings.mail_notifications.label') %>
<span class="mail_notifications_choice">
<%= f.radio_button:mail_notifications, "daily" %>
<%= f.label :mail_notifications_daily, t('settings.mail_notifications.daily') %>
</span>
<span class="mail_notifications_choice">
<%= f.radio_button :mail_notifications, "weekly" %>
<%= f.label :mail_notifications_weekly, t('settings.mail_notifications.weekly') %>
</span>
<span class="mail_notifications_choice">
<%= f.radio_button :mail_notifications, "never" %>
<%= f.label :mail_notifications_never, t('settings.mail_notifications.never') %>
</span>
</p>

<p>
<%= f.label :auth_token, t('settings.api_token') %>
<span class="auth_token inline"><%= @settings.auth_token%></span>
</p>

<p>
<%= f.submit t('settings.submit') %>
</p>
<% end %>

</section>
4 changes: 4 additions & 0 deletions app/views/settings/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<%= render 'shared/object',
presenter: ObjectPresenter.new(object: @user, ctx: self,
show_location: false, content: 'settings/edit_settings')
%>
2 changes: 1 addition & 1 deletion app/views/shared/header/_settings_tooltip.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ul class="settings-tooltip">

<% if current_user %>
<li><%= link_to icon('cog', t('header.settings_menu.settings')), '#', class: 'settings-item' %></li>
<li><%= link_to icon('cog', t('header.settings_menu.settings')), settings_path(current_user), class: 'settings-item' %></li>
<% end %>

<li><%= link_to_modal icon('flag-o', t('header.settings_menu.language')), "#language-selector", :html => {:class => 'settings-item'} %></li>
Expand Down
21 changes: 21 additions & 0 deletions config/locales/en/settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
en:
settings:

title: 'Update Settings'

password:
label: 'Change Password'
button: 'Send a reset link'

language: 'Language'

mail_notifications:
label: 'E-mail notifications'
daily: 'Daily'
weekly: 'Weekly'
never: 'Never'

api_token: 'API Token'
submit: 'save changes'

error: 'Error saving settings'
21 changes: 21 additions & 0 deletions config/locales/pt-BR/settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pt-BR:
settings:

title: 'Atualizar Configurações'

password:
label: 'Mudar Senha'
button: 'Enviar link para resetar'

language: 'Linguagem'

mail_notifications:
label: 'Notificações por e-mail'
daily: 'Diariamente'
weekly: 'Semanalmente'
never: 'Nunca'

api_token: 'API Token'
submit: 'salvar mudanças'

error: 'Erro ao salvar configurações'
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
member do
get :activate
get "activity" => "activities#user_activity"
resource :settings, only: [:show, :update]
end

collection do
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20140909233348_add_mail_notifications_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddMailNotificationsToUsers < ActiveRecord::Migration
def change
add_column :users, :mail_notifications, :string, default: 'daily'
end
end
9 changes: 5 additions & 4 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20140908010847) do
ActiveRecord::Schema.define(version: 20140909233348) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -153,8 +153,8 @@
end

create_table "users", force: true do |t|
t.string "name", null: false
t.string "email", null: false
t.string "name", null: false
t.string "email", null: false
t.string "crypted_password"
t.datetime "created_at"
t.datetime "updated_at"
Expand All @@ -171,8 +171,9 @@
t.spatial "location", limit: {:srid=>4326, :type=>"geometry"}
t.string "remember_me_token"
t.datetime "remember_me_token_expires_at"
t.text "interests", default: [], array: true
t.text "interests", default: [], array: true
t.string "auth_token"
t.string "mail_notifications", default: "daily"
end

add_index "users", ["activation_token"], :name => "index_users_on_activation_token"
Expand Down
45 changes: 45 additions & 0 deletions spec/controllers/settings_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'spec_helper'

describe SettingsController do
let(:user) { FactoryGirl.create :user, language: 'en', mail_notifications: 'daily' }

before { login_user user }

describe "GET show" do
it 'renders setings page' do
get :show, id: user.id
expect(assigns :user).to eq user
expect(assigns :settings).to eq user.settings
expect(response).to render_template :show
end

it "redirects if not user itself" do
other = FactoryGirl.create :user
get :show, id: other.id
expect(response).to redirect_to controller.root_path
end
end

describe "GET show" do
it 'renders setings page' do
expect(user.language).to eq 'en'
expect(user.mail_notifications).to eq 'daily'

patch :update, id: user.id, settings: {mail_notifications: 'weekly', language: 'pt-BR' }

expect(response.status).to eq 200
expect(response.body).to include({redirect: controller.user_path(user)}.to_json)

user.reload
expect(user.language).to eq 'pt-BR'
expect(user.mail_notifications).to eq 'weekly'
end

it "redirects if not user itself" do
other = FactoryGirl.create :user
patch :update, id: other.id
expect(response).to redirect_to controller.root_path
end
end

end
9 changes: 9 additions & 0 deletions spec/helpers/application_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@
expect(translations).to eq I18n.backend.send(:translations)[:en].with_indifferent_access
end
end

describe "#language_options" do
it "generates list of options" do
opts = helper.language_options
expect(opts).to be_a_kind_of Array
expect(opts).to include ['English', 'en']
expect(opts).to include ['Português', 'pt-BR']
end
end
end

describe "Concerns::ContactsHelper" do
Expand Down
34 changes: 34 additions & 0 deletions spec/models/settings_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'spec_helper'

describe Settings do
let(:user) { FactoryGirl.create :user, language: 'en', mail_notifications: 'daily'}
let(:settings) { Settings.new user }

describe 'initialize' do
it { expect(settings.language).to eq user.language }
it { expect(settings.auth_token).to eq user.auth_token }
it { expect(settings.mail_notifications).to eq user.mail_notifications }
it { expect(settings.user).to eq user }
end

describe 'assign_attributes' do
before { settings.assign_attributes language: 'pt-BR', mail_notifications: 'weekly' }
it { expect(settings.language).to eq 'pt-BR' }
it { expect(settings.mail_notifications).to eq 'weekly' }
end

describe 'save' do
it "saves settings on user model" do
expect(user.language).to eq 'en'
expect(user.mail_notifications).to eq 'daily'

settings.assign_attributes language: 'pt-BR', mail_notifications: 'weekly'
expect(settings.save).to eq true

user.reload
expect(user.language).to eq 'pt-BR'
expect(user.mail_notifications).to eq 'weekly'
end
end

end
Loading