diff --git a/Changelog.md b/Changelog.md index 53ea9795d..cac9e22d9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -32,6 +32,7 @@ * Show pod version in footer and updated the link to the changelog [#3822](https://github.com/diaspora/diaspora/pull/3822) * User interface enhancements [#3832](https://github.com/diaspora/diaspora/pull/3832), [#3839](https://github.com/diaspora/diaspora/pull/3839), [#3834](https://github.com/diaspora/diaspora/pull/3834), [#3840](https://github.com/diaspora/diaspora/issues/3840), [#3846](https://github.com/diaspora/diaspora/issues/3846), [#3851](https://github.com/diaspora/diaspora/issues/3851), [#3828](https://github.com/diaspora/diaspora/issues/3828), [#3874](https://github.com/diaspora/diaspora/issues/3874), [#3806](https://github.com/diaspora/diaspora/issues/3806), [#3906](https://github.com/diaspora/diaspora/issues/3906). * Show links in sidebar [#3827](https://github.com/diaspora/diaspora/pull/3827) +* Add settings web mobile. [#3701](https://github.com/diaspora/diaspora/pull/3701) ## Bug Fixes diff --git a/app/assets/javascripts/mobile.js b/app/assets/javascripts/mobile.js index 226da53e6..92ec62281 100644 --- a/app/assets/javascripts/mobile.js +++ b/app/assets/javascripts/mobile.js @@ -7,6 +7,7 @@ //= require mbp-respond.min //= require mbp-helper //= require jquery.autoSuggest.custom + $(document).ready(function(){ $('.shield a').click(function(){ diff --git a/app/assets/stylesheets/mobile.css.scss b/app/assets/stylesheets/mobile.css.scss index 02fa6d94e..0d354767b 100644 --- a/app/assets/stylesheets/mobile.css.scss +++ b/app/assets/stylesheets/mobile.css.scss @@ -836,3 +836,99 @@ form#new_user.new_user input.btn { max-width: 400px; } } + + +form p.checkbox_select { + position: relative; + label { + left: 25px; + top: 4px; + position: absolute; + font-size: 1em; + } + img { + position: relative; + top: 6px; + } +} + +#profile_photo_upload { + margin-top: 5px; + min-height: 100px; + position: relative; + + img { + @include border-radius(5px); + @include box-shadow(0,1px,2px,#666); + + position: absolute; + left: 0; + height: 100px; + width: 100px; + + &.avatar { + @include transition(opacity, 0.5s); + &.loading { + @include opacity(0.3); + } + } + } + padding-left: 120px; +} + +#file-upload.button { + @include border-radius(3px); + @include button-gradient($light-grey); + @include box-shadow(0,1px,1px,#cfcfcf); + @include transition(border); + + display: inline-block; + + font { + style: normal; + size: 12px; + } + color: #505050; + + padding: 4px 9px; + + min-height: 10px; + + border: 1px solid; + + cursor: pointer; + white-space: normal; + + &:hover { + @include button-gradient-hover-no-saturation($light-grey); + color: #505050; + text-decoration: none; + border: 1px solid; + } +} + +#settings_nav { + font-size: 1em; + + ul { + margin: 0 0 0 15px; + } + + li { + display: inline; + } +} + +form#update_profile_form { + select { + padding: 3px; + } +} + +select#user_language, #user_auto_follow_back_aspect_id { + padding: 3px; +} + +#file-upload-spinner { + top: 0px; +} diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 342158afa..ef1ec28e4 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -53,7 +53,7 @@ class ProfilesController < ApplicationController respond_to do |format| format.js { render :nothing => true, :status => 200 } - format.html { + format.any { flash[:notice] = I18n.t 'profiles.update.updated' if current_user.getting_started? redirect_to getting_started_path diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index fe25b7717..f980f2424 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -60,8 +60,10 @@ class UsersController < ApplicationController elsif u[:email] @user.unconfirmed_email = u[:email] if @user.save - @user.mail_confirm_email - flash[:notice] = I18n.t 'users.update.unconfirmed_email_changed' + @user.mail_confirm_email == @user.email + if @user.unconfirmed_email + flash[:notice] = I18n.t 'users.update.unconfirmed_email_changed' + end else flash[:error] = I18n.t 'users.update.unconfirmed_email_not_changed' end diff --git a/app/views/photos/_new_profile_photo.mobile.haml b/app/views/photos/_new_profile_photo.mobile.haml new file mode 100644 index 000000000..4cd9510a6 --- /dev/null +++ b/app/views/photos/_new_profile_photo.mobile.haml @@ -0,0 +1,60 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :head do + :javascript + function createUploader(){ + var uploader = new qq.FileUploaderBasic({ + element: document.getElementById('file-upload'), + params: {'photo' : {'pending' : true, 'aspect_ids' : "all", 'set_profile_photo': true}}, + allowedExtensions: ['jpg', 'jpeg', 'png'], + action: "#{photos_path}", + button: document.getElementById('file-upload'), + sizeLimit: 4194304, + + onProgress: function(id, fileName, loaded, total){ + var progress = Math.round(loaded / total * 100 ); + $('#fileInfo').text(fileName + ' ' + progress + '%'); + }, + + messages: { + typeError: "#{t('photos.new_photo.invalid_ext')}", + sizeError: "#{t('photos.new_photo.size_error')}", + emptyError: "#{t('photos.new_photo.empty')}" + }, + + onSubmit: function(id, fileName){ + $('#file-upload').addClass("loading"); + $("#profile_photo_upload").find(".avatar").addClass('loading'); + $("#file-upload-spinner").removeClass("hidden"); + }, + + onComplete: function(id, fileName, result){ + $("#file-upload-spinner").addClass("hidden"); + $('#fileInfo').text(fileName + ' completed').fadeOut(2000); + $('#file-upload').removeClass("loading"); + location.reload(); + } + }); + } + window.onload = createUploader; + +#profile_photo_upload + = owner_image_tag(:thumb_medium) + + -if !aspect.nil? && aspect == :getting_started + %br + %br + + #file-upload.button + =t('.upload') + + = image_tag('mobile-spinner.gif', :class => 'hidden', :style => "z-index:-1", :id => 'file-upload-spinner') + + %br + %br + %p + #fileInfo + + #publisher_photo_upload diff --git a/app/views/profiles/_edit.mobile.haml b/app/views/profiles/_edit.mobile.haml new file mode 100644 index 000000000..8442536e9 --- /dev/null +++ b/app/views/profiles/_edit.mobile.haml @@ -0,0 +1,54 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :page_title do + = t('.edit_profile') + += form_tag profile_path, :method => :put, :multipart => true, :id => 'update_profile_form' do + = render 'profiles/edit_public', :profile => profile, :aspect => aspect, :person => person + + %hr + %h4 + = t('profiles.edit.your_private_profile') + + + %h4 + = t('profiles.edit.your_bio') + = text_area_tag 'profile[bio]', profile.bio, :rows => 5, :placeholder => t('fill_me_out') + + %h4 + = t('profiles.edit.your_location') + = text_field_tag 'profile[location]', profile.location, :placeholder => t('fill_me_out') + + + %br + + %h4 + = t('profiles.edit.your_gender') + = text_field_tag 'profile[gender]', profile.gender, :placeholder => t("fill_me_out") + + %br + + %h4 + = t('profiles.edit.your_birthday') + = select_date profile.birthday, :prompt => true, + :default => true, :order => t('date.order'), :start_year => 2000, :end_year => 1930, :prefix => 'profile[date]' + + %h4 + = t('search') + + %p{:class=>"checkbox_select"} + = label_tag 'profile[searchable]', t('profiles.edit.allow_search') + = check_box_tag 'profile[searchable]', true, profile.searchable + %br + + %h4= t('nsfw') + %p.nsfw_explanation=profile.nsfw? ? t('.you_are_nsfw') : t('.you_are_safe_for_work') + %p{:class=>"checkbox_select"} + = check_box_tag 'profile[nsfw]', true, profile.nsfw? + = label_tag 'profile[nsfw]', "nsfw?" + %br + + .submit_block + =yield(:submit_block) diff --git a/app/views/profiles/_edit_public.mobile.haml b/app/views/profiles/_edit_public.mobile.haml new file mode 100644 index 000000000..635c905f0 --- /dev/null +++ b/app/views/profiles/_edit_public.mobile.haml @@ -0,0 +1,72 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :head do + = javascript_include_tag :jquery + = javascript_include_tag :home + + :javascript + $(document).ready(function () { + var data = $.parseJSON( '#{@tags_array.to_json.gsub("'", "\\\\'")}' ), + autocompleteInput = $("#profile_tag_string"); + + autocompleteInput.autoSuggest("#{tags_path}", { + selectedItemProp: "name", + selectedValuesProp: "name", + searchObjProps: "name", + asHtmlID: "tags", + neverSubmit: true, + retrieveLimit: 10, + minChars: 2, + keyDelay: 200, + startText: "", + emptyText: "#{t('no_results')}", + preFill: data + }); + + autocompleteInput.bind('keydown', function(evt){ + if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ + evt.preventDefault(); + if( $('li.as-result-item.active').length == 0 ){ + $('li.as-result-item').first().click(); + } + } + }); + }); + +.stream + - flash.each do |name, msg| + %div{:id => "flash_#{name}", :class => "expose"} + .message= msg + .stream + %p{:class => "conversation_#{name}"}= msg + +%h4 + = t('profiles.edit.your_public_profile') + += error_messages_for profile + +%h4 + = t('profiles.edit.your_name') += label_tag 'profile[first_name]', t('profiles.edit.first_name') += text_field_tag 'profile[first_name]', profile.first_name, :placeholder => "Raphael" + += label_tag 'profile[first_name]', t('profiles.edit.last_name') += text_field_tag 'profile[last_name]', profile.last_name, :placeholder => "Sofaer" + +%br + +%h4 + = t('profiles.edit.your_tags') + += text_field_tag 'profile[tag_string]', "", :placeholder => t('profiles.edit.your_tags_placeholder') + +%br + +%h4 + = t('profiles.edit.your_photo') + += render 'photos/new_profile_photo', :aspect => aspect, :person => person + +%br diff --git a/app/views/profiles/edit.mobile.haml b/app/views/profiles/edit.mobile.haml new file mode 100644 index 000000000..b07788b3a --- /dev/null +++ b/app/views/profiles/edit.mobile.haml @@ -0,0 +1,16 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + + +#section_header + %h3 + = t('settings') + = render 'shared/settings_nav' + +.span-12.prepend-5.last + - content_for :submit_block do + = link_to t('cancel'), local_or_remote_person_path(current_user.person), :class => "button" + = submit_tag t('.update_profile'), :class => "btn" + = render :partial => 'edit', :locals => {:person => @person, + :profile => @profile, :aspect => @aspect, :step => @step} diff --git a/app/views/shared/_footer.mobile.haml b/app/views/shared/_footer.mobile.haml index bc7fd2a8e..a35b88cdf 100644 --- a/app/views/shared/_footer.mobile.haml +++ b/app/views/shared/_footer.mobile.haml @@ -1,5 +1,6 @@ %footer %strong = link_to current_user.name, current_user.person + = link_to t('layouts.header.settings'), users_edit_path = link_to t('layouts.application.toggle'), toggle_mobile_path = link_to t('layouts.header.logout'), destroy_user_session_path diff --git a/app/views/shared/_settings_nav.mobile.haml b/app/views/shared/_settings_nav.mobile.haml new file mode 100644 index 000000000..9c673d74c --- /dev/null +++ b/app/views/shared/_settings_nav.mobile.haml @@ -0,0 +1,7 @@ +#span-24 + %h3 + #settings_nav + %ul + %li= link_to_unless_current t('profile'), edit_profile_path + | + %li= link_to_unless_current t('account'), edit_user_path diff --git a/app/views/users/edit.mobile.haml b/app/views/users/edit.mobile.haml new file mode 100644 index 000000000..927444a6e --- /dev/null +++ b/app/views/users/edit.mobile.haml @@ -0,0 +1,207 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +- content_for :page_title do + = t('.edit_account') + +.stream + - flash.each do |name, msg| + %div{:id => "flash_#{name}", :class => "expose"} + .message= msg + .stream + %p{:class => "conversation_#{name}"}= msg + +#section_header + %h3 + = t('settings') + = render 'shared/settings_nav' + +.span-12.prepend-5.last + %hr + + %h4 + = t('.your_handle') + %p + %b= current_user.diaspora_handle + + %h4 + = t('.your_email') + = form_for 'user', :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + %p + = f.text_field :email, :value => @user.unconfirmed_email || @user.email + = f.submit t('.change_email'), :class => "btn" + - if @user.unconfirmed_email.present? + %p= t('.email_awaiting_confirmation', :email => @user.email, :unconfirmed_email => @user.unconfirmed_email) + + %hr + + %h4 + = t('.change_password') + = form_for 'user', :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + %p + = f.label :current_password, t('.current_password') + = f.password_field :current_password, :placeholder => t('.current_password_expl') + %p + = f.label :password, t('.new_password') + = f.password_field :password, :placeholder => t('.character_minimum_expl') + %p + = f.label :password_confirmation, t('password_confirmation') + = f.password_field :password_confirmation, :placeholder => t('.character_minimum_expl') + + .submit_block + = f.submit t('.change_password'), :class => "btn" + + %hr + + %h4 + = t('.change_language') + = form_for 'user', :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p + = f.select :language, available_language_options + = f.submit t('.change_language'), :class => "btn" + + %hr + + %h4#stream-preferences + = t('.stream_preferences') + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p.checkbox_select + = f.label :show_community_spotlight_in_stream, t('.show_community_spotlight') + = f.check_box :show_community_spotlight_in_stream + + %br + = f.submit t('.change'), :class => 'btn' + + %hr + + %h4#auto-follow-back-preferences + = t('.following') + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p.checkbox_select + = f.label :auto_follow_back, t('.auto_follow_back') + = f.check_box :auto_follow_back + %br + %p.checkbox_select + %span{:style => "color: #999"} + = t('.auto_follow_aspect') + = f.select :auto_follow_back_aspect_id, aspect_options_for_select(current_user.aspects) + %br + = f.submit t('.change'), :class => 'btn' + + %hr + + %h4#getting-started-preferences + = t('.show_getting_started') + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p.checkbox_select + = f.label :getting_started, t('.show_getting_started') + = f.check_box :getting_started + %br + = f.submit t('.change'), :class => 'btn' + + %hr + + %h4 + = t('.receive_email_notifications') + = form_for 'user', :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + = f.fields_for :email_preferences do |type| + #email_prefs + %p.checkbox_select + = type.label :also_commented, t('.also_commented') + = type.check_box :also_commented, {:checked => @email_prefs['also_commented']}, false, true + %br + %p.checkbox_select + = type.label :mentioned, t('.mentioned') + = type.check_box :mentioned, {:checked => @email_prefs['mentioned']}, false, true + + + %br + %p.checkbox_select + = type.label :comment_on_post, t('.comment_on_post') + = type.check_box :comment_on_post, {:checked => @email_prefs['comment_on_post']}, false, true + + %br + %p.checkbox_select + = type.label :private_message, t('.private_message') + = type.check_box :private_message, {:checked => @email_prefs['private_message']}, false, true + + %br + %p.checkbox_select + = type.label :started_sharing, t('.started_sharing') + = type.check_box :started_sharing, {:checked => @email_prefs['started_sharing']}, false, true + + %br + %p.checkbox_select + = type.label :liked, t('.liked') + = type.check_box :liked, {:checked => @email_prefs['liked']}, false, true + + %br + %p.checkbox_select + = type.label :reshared, t('.reshared') + = type.check_box :reshared, {:checked => @email_prefs['reshared']}, false, true + %br + = f.submit t('.change'), :class => "btn" + + %hr + + #account_data.span-5.append-2 + %h4 + = t('.export_data') + = link_to t('.download_xml'), export_user_path, :class => "btn" + %br + %br + = link_to t('.download_photos'), "#", :class => "btn", :id => "photo-export-button", :title => t('.photo_export_unavailable') + + .span-5.last + %h4 + = t('.close_account_text') + =link_to t('.close_account_text'), '#close_account_pane', :rel => 'facebox', :class => "btn" + + .hidden#close_account_pane{:rel => 'facebox'} + #inner_account_delete + %h1 + = t('.close_account.dont_go') + %p + = t('.close_account.make_diaspora_better') + .span-10 + = image_tag 'http://itstrulyrandom.com/wp-content/uploads/2008/03/sadcat.jpg' + %br + %small + %b + = t('.close_account.mr_wiggles') + .span-10.last + %ul + %li + = t('.close_account.what_we_delete') + %li + = t('.close_account.locked_out') + %li + = t('.close_account.lock_username') + %li + = t('.close_account.no_turning_back') + %p + %b + = t('.close_account.no_turning_back') + + + = form_for 'user', :url => user_path, :html => { :method => :delete } do |f| + = f.error_messages + + %p + = f.label :close_account_password, t('.current_password'), :for => :close_account_password + = f.password_field :current_password, :id => :close_account_password + %p + = f.submit t('.close_account_text'), :data => { :confirm => t('are_you_sure_delete_account') } diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index a0000c622..537e7390f 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -119,6 +119,13 @@ describe UsersController do Resque.stub!(:enqueue) end + it 'disallow the user to change his new (unconfirmed) mail when it is the same as the old' do + @user.email = "my@newemail.com" + put(:update, :id => @user.id, :user => { :email => "my@newemail.com"}) + @user.reload + @user.unconfirmed_email.should eql(nil) + end + it 'allow the user to change his (unconfirmed) email' do put(:update, :id => @user.id, :user => { :email => "my@newemail.com"}) @user.reload