diff --git a/Gemfile b/Gemfile index d09fcca..9e8c2c8 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,9 @@ gem 'simple_form' # Phone validation gem 'phony_rails' +# Picture uploads +gem 'carrierwave' + group :development do gem 'spring' gem 'spring-commands-rspec' diff --git a/Gemfile.lock b/Gemfile.lock index 2c5503c..06dfa18 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,11 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) + carrierwave (0.10.0) + activemodel (>= 3.2.0) + activesupport (>= 3.2.0) + json (>= 1.7) + mime-types (>= 1.16) celluloid (0.15.2) timers (~> 1.1.0) choice (0.1.6) @@ -221,6 +226,7 @@ PLATFORMS DEPENDENCIES capybara + carrierwave coffee-rails devise devise-i18n diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a443db3..ab1028f 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -13,3 +13,12 @@ *= require_tree . *= require_self */ + +#main { + font-size: 16px; +} + +h1 { + margin: 0 0 1em 0; + font-size: 2em; +} diff --git a/app/assets/stylesheets/flash_messages.css.scss b/app/assets/stylesheets/flash_messages.css.scss new file mode 100644 index 0000000..b47a0b8 --- /dev/null +++ b/app/assets/stylesheets/flash_messages.css.scss @@ -0,0 +1,18 @@ +#flash_messages { + border: 1px solid #CCC; + background-color: #F1F1F1; + padding: 10px; + margin: 0px 100px 10px 100px; + + div { + text-align: center; + } + + .notice { + color: green; + } + + .alert { + color: orange; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/forms.css.scss b/app/assets/stylesheets/forms.css.scss index 0a51e9d..ebc16a8 100644 --- a/app/assets/stylesheets/forms.css.scss +++ b/app/assets/stylesheets/forms.css.scss @@ -1,30 +1,31 @@ -#main { - font-size: 16px; -} -h1 { - margin: 0 0 1em 0; - font-size: 2em; +.alert-error { + color: red; } + .input { position: relative; margin: 0 0 1em 0; border-top: 0.1em dotted #999; padding: 1em 0; } + .input label { font-size: 1em; display: block; width: 12em; float: left; } + .input input, .input textarea, .input select { font-size: 1em; width: 20em; float: left; } + .input textarea { height: 8em; } + .input .hint, .input .error { display: block; clear: both; @@ -34,11 +35,13 @@ h1 { margin: 0 0 0 16em; padding: 1em 0 0 0; } + .input .error { font-style: normal; padding: 1em 0 0 0; color: #F00; } + .input .error::before { content: "⇧"; display: inline-block; @@ -46,6 +49,7 @@ h1 { margin: 0 0.2em 0 0; transform: translate(0, 0.1em); } + .btn { display: block; margin: 2em 0 0 13em; @@ -63,9 +67,11 @@ h1 { transition: background 200ms, border 200ms, transform 200ms; -webkit-transition: background 200ms, border 200ms, transform 200ms; } + .btn:hover { background: #152551; } + .btn:active { background: #597AD2; border-bottom: 0.2em solid #000; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..948c310 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,13 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + before_filter :configure_permitted_parameters, if: :devise_controller? + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.for(:account_update) do |u| + u.permit(:email, :password, :password_confirmation, :current_password, speaker_profile_attributes: [:first_name, :last_name, :public_email, :organisation, :github, :twitter, :mobile_phone, :biography, :picture, :id]) + end + end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb new file mode 100644 index 0000000..a781c0c --- /dev/null +++ b/app/controllers/registrations_controller.rb @@ -0,0 +1,35 @@ +class RegistrationsController < Devise::RegistrationsController + def edit + resource.build_speaker_profile unless resource.speaker_profile.present? + end + + def update + @user = User.find(current_user.id) + + successfully_updated = if needs_password?(@user, params) + @user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update)) + else + # remove the virtual current_password attribute + # update_without_password doesn't know how to ignore it + params[:user].delete(:current_password) + @user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update)) + end + + if successfully_updated + set_flash_message :notice, :updated + # Sign in the user bypassing validation in case their password changed + sign_in @user, :bypass => true + redirect_to after_update_path_for(@user) + else + render "edit" + end + end + + private + + def needs_password?(user, params) + user.email != params[:user][:email] || + params[:user][:password].present? || + params[:user][:password_confirmation].present? + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..c9f6a1a --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,9 @@ +class SessionsController < Devise::SessionsController + def after_sign_in_path_for(user) + if user.speaker_profile.present? + stored_location_for(user) || signed_in_root_path(user) + else + edit_user_registration_path + end + end +end diff --git a/app/controllers/speaker_profiles_controller.rb b/app/controllers/speaker_profiles_controller.rb new file mode 100644 index 0000000..a51e033 --- /dev/null +++ b/app/controllers/speaker_profiles_controller.rb @@ -0,0 +1,16 @@ +class SpeakerProfilesController < ApplicationController + before_filter :authenticate_user! + before_action :assign_speaker_profile + + def edit + end + + def update + end + + private + + def assign_speaker_profile + @speaker_profile = SpeakerProfile.find_or_initialize_by(user: current_user) + end +end diff --git a/app/models/speaker_profile.rb b/app/models/speaker_profile.rb index 4af25d1..9e0ce34 100644 --- a/app/models/speaker_profile.rb +++ b/app/models/speaker_profile.rb @@ -3,7 +3,7 @@ class SpeakerProfile < ActiveRecord::Base validates :first_name, presence: true validates :last_name, presence: true - validates :photo_url, presence: true + validates :picture, presence: true validates :mobile_phone, phony_plausible: true, presence: true validates :biography, presence: true validates :public_email, format: {with: /\A[^@]+@[^@]+\z/}, allow_blank: true @@ -12,6 +12,8 @@ class SpeakerProfile < ActiveRecord::Base phony_normalize :mobile_phone, default_country_code: 'BG' + mount_uploader :picture, PictureUploader + def twitter=(handle) write_attribute :twitter, handle.gsub(/\A@/,'') if handle end diff --git a/app/models/user.rb b/app/models/user.rb index f7fa261..8ae638a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,4 +7,6 @@ class User < ActiveRecord::Base has_one :speaker_profile has_many :lectures has_many :workshops + + accepts_nested_attributes_for :speaker_profile, update_only: true end diff --git a/app/uploaders/picture_uploader.rb b/app/uploaders/picture_uploader.rb new file mode 100644 index 0000000..217f662 --- /dev/null +++ b/app/uploaders/picture_uploader.rb @@ -0,0 +1,51 @@ +# encoding: utf-8 + +class PictureUploader < CarrierWave::Uploader::Base + + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + # include CarrierWave::MiniMagick + + # Choose what kind of storage to use for this uploader: + storage :file + # storage :fog + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + # Provide a default URL as a default if there hasn't been a file uploaded: + # def default_url + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) + # + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') + # end + + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end + + # Create different versions of your uploaded files: + # version :thumb do + # process :resize_to_fit => [50, 50] + # end + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + # def extension_white_list + # %w(jpg jpeg gif png) + # end + + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + +end diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb deleted file mode 100644 index 949b172..0000000 --- a/app/views/devise/confirmations/new.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -

Resend confirmation instructions

- -<%= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - <%= f.full_error :confirmation_token %> - -
- <%= f.input :email, required: true, autofocus: true %> -
- -
- <%= f.button :submit, "Resend confirmation instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/confirmations/new.html.slim b/app/views/devise/confirmations/new.html.slim new file mode 100644 index 0000000..4437d9d --- /dev/null +++ b/app/views/devise/confirmations/new.html.slim @@ -0,0 +1,13 @@ +h2.entry-title Повторно изпращане на инструкции за потвърждаване на акаунт + += simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| + = f.error_notification + = f.full_error :confirmation_token + + .form-inputs + = f.input :email, required: true, autofocus: true, hint: false + + .form-actions + = f.button :submit, 'Изпрати отново инструкциите' + +== render 'devise/shared/links' diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb index dc55f64..879307d 100644 --- a/app/views/devise/mailer/confirmation_instructions.html.erb +++ b/app/views/devise/mailer/confirmation_instructions.html.erb @@ -1,5 +1,5 @@ -

Welcome <%= @email %>!

+

Добре дошли, <%= @email %>!

-

You can confirm your account email through the link below:

+

Можете да потвърдите акаунта си като кликнете на линка отдолу:

-

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

+

<%= link_to 'Потвърди акаунта ми', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb index f667dc1..387dcaa 100644 --- a/app/views/devise/mailer/reset_password_instructions.html.erb +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -1,8 +1,8 @@ -

Hello <%= @resource.email %>!

+

Здравейте, <%= @resource.email %>!

-

Someone has requested a link to change your password. You can do this through the link below.

+

Някой поиска линк за промяна на парола на аканута Ви. Паролата може да бъде променена от линкът отдолу.

-

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

+

<%= link_to 'Промяна на парола', edit_password_url(@resource, reset_password_token: @token) %>

-

If you didn't request this, please ignore this email.

-

Your password won't change until you access the link above and create a new one.

+

Ако не желаете да смените паролата си, моля изтрийте това писмо.

+

Паролата Ви няма да бъде променена докато не кликнете горния линк и не въведете нова парола.

diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb index 41e148b..145011d 100644 --- a/app/views/devise/mailer/unlock_instructions.html.erb +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -1,7 +1,7 @@ -

Hello <%= @resource.email %>!

+

Здравейте, <%= @resource.email %>!

-

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

+

Акаунтът Ви беше заключен поради голям брой неуспешни опити за влизане в него.

-

Click the link below to unlock your account:

+

Кликнете линкът отдолу, за да го отключите:

-

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

+

<%= link_to 'Отключване на акаунт', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb deleted file mode 100644 index 8f995ed..0000000 --- a/app/views/devise/passwords/edit.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -

Change your password

- -<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> - <%= f.error_notification %> - - <%= f.input :reset_password_token, as: :hidden %> - <%= f.full_error :reset_password_token %> - -
- <%= f.input :password, label: "New password", required: true, autofocus: true %> - <%= f.input :password_confirmation, label: "Confirm your new password", required: true %> -
- -
- <%= f.button :submit, "Change my password" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/passwords/edit.html.slim b/app/views/devise/passwords/edit.html.slim new file mode 100644 index 0000000..2a698ca --- /dev/null +++ b/app/views/devise/passwords/edit.html.slim @@ -0,0 +1,16 @@ +h2.entry-title Промяна на парола + += simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| + = f.error_notification + + = f.input :reset_password_token, as: :hidden + = f.full_error :reset_password_token + + .form-inputs + = f.input :password, required: true, autofocus: true + = f.input :password_confirmation, required: true + + .form-actions + = f.button :submit, 'Промяна на паролата' + += render 'devise/shared/links' diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb deleted file mode 100644 index d1503e7..0000000 --- a/app/views/devise/passwords/new.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -

Forgot your password?

- -<%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - -
- <%= f.input :email, required: true, autofocus: true %> -
- -
- <%= f.button :submit, "Send me reset password instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/passwords/new.html.slim b/app/views/devise/passwords/new.html.slim new file mode 100644 index 0000000..81f8378 --- /dev/null +++ b/app/views/devise/passwords/new.html.slim @@ -0,0 +1,12 @@ +h2.entry-title Забравена парола? + += simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| + = f.error_notification + + .form-inputs + = f.input :email, required: true, autofocus: true, hint: false + + .form-actions + = f.button :submit, 'Изпрати ми инструкции за промяна на парола' + +== render 'devise/shared/links' diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb deleted file mode 100644 index 5db350b..0000000 --- a/app/views/devise/registrations/edit.html.erb +++ /dev/null @@ -1,27 +0,0 @@ -

Edit <%= resource_name.to_s.humanize %>

- -<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= f.error_notification %> - -
- <%= f.input :email, required: true, autofocus: true %> - - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -

Currently waiting confirmation for: <%= resource.unconfirmed_email %>

- <% end %> - - <%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %> - <%= f.input :password_confirmation, required: false %> - <%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %> -
- -
- <%= f.button :submit, "Update" %> -
-<% end %> - -

Cancel my account

- -

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

- -<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/edit.html.slim b/app/views/devise/registrations/edit.html.slim new file mode 100644 index 0000000..53d5b36 --- /dev/null +++ b/app/views/devise/registrations/edit.html.slim @@ -0,0 +1,29 @@ += simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| + .form_inputs + h2.entry-title Лекторски профил + = f.error_notification + = f.simple_fields_for :speaker_profile do |ff| + = ff.input :picture, as: :file + = ff.input :first_name + = ff.input :last_name + = ff.input :public_email + = ff.input :organisation + = ff.input :github + = ff.input :twitter + = ff.input :mobile_phone, input_html: {value: resource.speaker_profile.mobile_phone.try(:phony_formatted, format: :international)} + = ff.input :biography + + .form-inputs + h3.entry-title Данни за вход в системата + = f.input :email, required: true, autofocus: true + + - if devise_mapping.confirmable? && resource.pending_reconfirmation? + p + Очаква се потвърждение на: #{resource.unconfirmed_email} + + = f.input :password, autocomplete: "off", hint: "Не попълвайте, ако не желаете да промените паролата си", required: false + = f.input :password_confirmation, required: false + = f.input :current_password, hint: "Попълнете, ако искате да промените паролата или имейл адреса си.", required: true + + .form-actions + = f.button :submit, 'Обнови' diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb deleted file mode 100644 index 090fb29..0000000 --- a/app/views/devise/registrations/new.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -

Sign up

- -<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> - <%= f.error_notification %> - -
- <%= f.input :email, required: true, autofocus: true %> - <%= f.input :password, required: true %> - <%= f.input :password_confirmation, required: true %> -
- -
- <%= f.button :submit, "Sign up" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/registrations/new.html.slim b/app/views/devise/registrations/new.html.slim new file mode 100644 index 0000000..f024368 --- /dev/null +++ b/app/views/devise/registrations/new.html.slim @@ -0,0 +1,14 @@ +h2.entry-title Регистрация + += simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| + = f.error_notification + + .form-inputs + = f.input :email, required: true, autofocus: true + = f.input :password, required: true + = f.input :password_confirmation, required: true + + .form-actions + = f.button :submit + +== render 'devise/shared/links' diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb deleted file mode 100644 index c790b49..0000000 --- a/app/views/devise/sessions/new.html.erb +++ /dev/null @@ -1,15 +0,0 @@ -

Sign in

- -<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> -
- <%= f.input :email, required: false, autofocus: true %> - <%= f.input :password, required: false %> - <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> -
- -
- <%= f.button :submit, "Sign in" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/sessions/new.html.slim b/app/views/devise/sessions/new.html.slim new file mode 100644 index 0000000..996b085 --- /dev/null +++ b/app/views/devise/sessions/new.html.slim @@ -0,0 +1,12 @@ +h2.entry-title Вход + += simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| + .form-inputs + = f.input :email, required: false, autofocus: true, hint: false + = f.input :password, required: false, hint: false + = f.input :remember_me, as: :boolean if devise_mapping.rememberable? + + .form-actions + = f.button :submit, 'Влез' + +== render 'devise/shared/links' diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb deleted file mode 100644 index d84bdde..0000000 --- a/app/views/devise/shared/_links.erb +++ /dev/null @@ -1,25 +0,0 @@ -<%- if controller_name != 'sessions' %> - <%= link_to "Sign in", new_session_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.registerable? && controller_name != 'registrations' %> - <%= link_to "Sign up", new_registration_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> - <%= link_to "Forgot your password?", new_password_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> - <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> - <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
-<% end -%> - -<%- if devise_mapping.omniauthable? %> - <%- resource_class.omniauth_providers.each do |provider| %> - <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
- <% end -%> -<% end -%> diff --git a/app/views/devise/shared/_links.html.slim b/app/views/devise/shared/_links.html.slim new file mode 100644 index 0000000..366b7c3 --- /dev/null +++ b/app/views/devise/shared/_links.html.slim @@ -0,0 +1,23 @@ +- if controller_name != 'sessions' + = link_to 'Вход', new_session_path(resource_name) + br + +- if devise_mapping.registerable? && controller_name != 'registrations' + = link_to 'Регистрация', new_registration_path(resource_name) + br + +- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' + = link_to 'Забравена парола?', new_password_path(resource_name) + br + +- if devise_mapping.confirmable? && controller_name != 'confirmations' + = link_to 'Не Сте получили инструкции за потвърждение?', new_confirmation_path(resource_name) + br + +- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' + = link_to 'Не Сте получили инструкции за отключване?', new_unlock_path(resource_name) + br + +- if devise_mapping.omniauthable? + - resource_class.omniauth_providers.each do |provider| + = link_to 'Влез с #{provider.to_s.titleize}', omniauth_authorize_path(resource_name, provider) diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb deleted file mode 100644 index 788f62e..0000000 --- a/app/views/devise/unlocks/new.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -

Resend unlock instructions

- -<%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> - <%= f.error_notification %> - <%= f.full_error :unlock_token %> - -
- <%= f.input :email, required: true, autofocus: true %> -
- -
- <%= f.button :submit, "Resend unlock instructions" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/devise/unlocks/new.html.slim b/app/views/devise/unlocks/new.html.slim new file mode 100644 index 0000000..9b5abf7 --- /dev/null +++ b/app/views/devise/unlocks/new.html.slim @@ -0,0 +1,13 @@ +h2 Изпрати отново инструкции за отключване + += simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| + = f.error_notification + = f.full_error :unlock_token + + .form-inputs + = f.input :email, required: true, autofocus: true, hint: false + + .form-actions + = f.button :submit, 'Изпрати отново инструкциите' + +== render 'devise/shared/links' diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index cb9643b..55074fb 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -26,6 +26,7 @@
+ <%= render('/shared/flash_messages') unless flash.empty? %> <%= yield %>
diff --git a/app/views/shared/_flash_messages b/app/views/shared/_flash_messages new file mode 100644 index 0000000..c94abd1 --- /dev/null +++ b/app/views/shared/_flash_messages @@ -0,0 +1,3 @@ +div#flash_messages + - flash.each do |key, value| + = content_tag :div, value, class: "flash #{key}" diff --git a/app/views/shared/_flash_messages.html.slim b/app/views/shared/_flash_messages.html.slim new file mode 100644 index 0000000..c94abd1 --- /dev/null +++ b/app/views/shared/_flash_messages.html.slim @@ -0,0 +1,3 @@ +div#flash_messages + - flash.each do |key, value| + = content_tag :div, value, class: "flash #{key}" diff --git a/app/views/speaker_profiles/_form.html.slim b/app/views/speaker_profiles/_form.html.slim new file mode 100644 index 0000000..6c3702b --- /dev/null +++ b/app/views/speaker_profiles/_form.html.slim @@ -0,0 +1,14 @@ +== simple_form_for @speaker_profile do |form| + p + = form.error_notification + + .form-inputs + = form.input :first_name, autofocus: true + = form.input :last_name + = form.input :public_email + = form.input :organisation + = form.input :github + = form.input :twitter + = form.input :mobile_phone + = form.input :biography + = form.button :submit diff --git a/app/views/speaker_profiles/edit.html.slim b/app/views/speaker_profiles/edit.html.slim new file mode 100644 index 0000000..bcfe4cf --- /dev/null +++ b/app/views/speaker_profiles/edit.html.slim @@ -0,0 +1,3 @@ +h1.entry-title Редакция на лекторски профил + +== render 'form' diff --git a/config/locales/bg.yml b/config/locales/bg.yml index f26b51b..91c3d13 100644 --- a/config/locales/bg.yml +++ b/config/locales/bg.yml @@ -22,6 +22,9 @@ bg: activerecord: models: + user: + one: Потребител + other: Потребители lecture: one: Лекция other: Лекции @@ -30,6 +33,22 @@ bg: other: Уъркшопи track: Поток от лекции attributes: + user: + email: E-mail + current_password: Текуща парола + password: Парола + password_confirmation: Отново паролата + remember_me: Запомни ме + speaker_profile: + picture: Снимка + first_name: Име + last_name: Фамилия + organisation: Организация + public_email: Публичен email + mobile_phone: Мобилен телефон + biography: Биография + github: Github акаунт + twitter: Twitter акаунт lecture: title: Заглавие subtitle: Подзаглавие @@ -48,6 +67,14 @@ bg: description: Описание notes: Забележки track: Поток от лекции + errors: + models: + user: + attributes: + email: + invalid: не е валиден имейл адрес + password_confirmation: + confirmation: не съответства на паролата errors: messages: improbable_phone: 'не е валиден телефонен номер' \ No newline at end of file diff --git a/config/locales/simple_form.bg.yml b/config/locales/simple_form.bg.yml index 4641608..c9a6497 100644 --- a/config/locales/simple_form.bg.yml +++ b/config/locales/simple_form.bg.yml @@ -1,13 +1,27 @@ bg: simple_form: - "yes": 'Да' - "no": 'Не' + "yes": Да + "no": Не required: - text: 'Задължително поле' + text: Задължително поле mark: '*' error_notification: - default_message: "Моля разгледайте проблемите по-долу:" + default_message: 'Моля разгледайте посочените грешки във формуляра:' hints: + user: + email: Имейл адресът Ви. Ще бъде видим само от организаторите. + password: Парола с дължина между 8 и 128 символа + password_confirmation: Отново въведената отгоре парола + speaker_profile: + picture: Ваша снимка + first_name: Малкото Ви име + last_name: Фамилното Ви име + organisation: Организацията, която представлявате + public_email: E-mail адрес, който ще бъде видим за посетителите + mobile_phone: Мобилен телефон, който ще бъде видим само за организаторите + biography: Опишете се с няколко изречения в трето лице :). + github: Github акаунтът Ви + twitter: Twitter акаунтът Ви lecture: title: Заглавието на лекцията Ви subtitle: Подзаглавието на лекцията Ви (ако има такова) @@ -25,4 +39,7 @@ bg: language: Език, на който ще бъде воден уъркшопа abstract: Резюме на уъркшопа, което да може да бъде прочетено от посетителите description: Подробно описание на уъркшопа, което да бъде използвано от организаторския екип - notes: Забележки, които искате да споделите с организаторския екип \ No newline at end of file + notes: Забележки, които искате да споделите с организаторския екип + labels: + user: + a: b \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 65c7913..13994b4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,7 +2,11 @@ Rails.application.routes.draw do resources :lectures, only: [:index, :new, :create, :edit, :update, :show] resources :workshops, only: [:index, :new, :create, :edit, :update, :show] - devise_for :users + devise_for :users, controllers: {registrations: 'registrations', sessions: 'sessions'} + + resource :user, only: [] do + resource :speaker_profile, only: [:edit, :update] + end root 'home#index' # The priority is based upon order of creation: first created -> highest priority. diff --git a/db/migrate/20140807103632_create_speaker_profiles.rb b/db/migrate/20140807103632_create_speaker_profiles.rb index 286e036..9abfa88 100644 --- a/db/migrate/20140807103632_create_speaker_profiles.rb +++ b/db/migrate/20140807103632_create_speaker_profiles.rb @@ -1,15 +1,15 @@ class CreateSpeakerProfiles < ActiveRecord::Migration def change create_table :speaker_profiles do |t| - t.string :first_name, null: false - t.string :last_name, null: false + t.string :first_name + t.string :last_name t.string :organisation t.string :public_email - t.string :photo_url, null: false - t.string :mobile_phone, null: false - t.text :biography, null: false - t.string :github, null: false - t.string :twitter, null: false + t.string :photo_url + t.string :mobile_phone + t.text :biography + t.string :github + t.string :twitter t.timestamps end diff --git a/db/migrate/20140831121527_rename_picture_url_to_picture_in_speaker_profiles.rb b/db/migrate/20140831121527_rename_picture_url_to_picture_in_speaker_profiles.rb new file mode 100644 index 0000000..fc253c3 --- /dev/null +++ b/db/migrate/20140831121527_rename_picture_url_to_picture_in_speaker_profiles.rb @@ -0,0 +1,5 @@ +class RenamePictureUrlToPictureInSpeakerProfiles < ActiveRecord::Migration + def change + rename_column :speaker_profiles, :photo_url, :picture + end +end diff --git a/public/uploads/.keep b/public/uploads/.keep new file mode 100644 index 0000000..e69de29 diff --git a/public/uploads/tmp/.keep b/public/uploads/tmp/.keep new file mode 100644 index 0000000..e69de29 diff --git a/spec/factories/speaker_profiles.rb b/spec/factories/speaker_profiles.rb index 2e64802..dbabf5a 100644 --- a/spec/factories/speaker_profiles.rb +++ b/spec/factories/speaker_profiles.rb @@ -6,7 +6,7 @@ FactoryGirl.define do last_name "Doe" organisation "Example Org" public_email "a@b.com" - photo_url "http://placehold.it/50x50" + picture { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec', 'support', 'picture.jpg')) } mobile_phone "0883444555" biography "Lorem ipsum" github "octocat" diff --git a/spec/models/speaker_profile_spec.rb b/spec/models/speaker_profile_spec.rb index 008941d..76453df 100644 --- a/spec/models/speaker_profile_spec.rb +++ b/spec/models/speaker_profile_spec.rb @@ -9,8 +9,8 @@ RSpec.describe SpeakerProfile, :type => :model do expect(build(:speaker_profile, last_name: nil)).to have_error_on :last_name end - it 'is invalid without a photo' do - expect(build(:speaker_profile, photo_url: nil)).to have_error_on :photo_url + it 'is invalid without a picture' do + expect(build(:speaker_profile, picture: nil)).to have_error_on :picture end describe 'mobile_phone' do diff --git a/spec/support/picture.jpg b/spec/support/picture.jpg new file mode 100644 index 0000000..e69de29