1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

allow user to set his organization on registration

This commit is contained in:
Sylvain 2016-08-02 12:27:45 +02:00
parent ccc1eaf3a0
commit 2afd6ade8a
14 changed files with 137 additions and 50 deletions

View File

@ -99,11 +99,18 @@ Application.Controllers.controller 'ApplicationController', ["$rootScope", "$sco
$scope.ok = ->
# try to create the account
$scope.alerts = []
# remove 'organization' attribute
orga = $scope.user.organization
delete $scope.user.organization
# register on server
Auth.register($scope.user).then (user) ->
# creation successful
$uibModalInstance.close(user)
, (error) ->
# creation failed...
# restore organization param
$scope.user.organization = orga
# display errors
angular.forEach error.data.errors, (v, k) ->
angular.forEach v, (err) ->
$scope.alerts.push

View File

@ -559,3 +559,13 @@ padding: 10px;
}
}
.checkbox-group {
display: flex;
justify-content: flex-start;
input[type=checkbox] {
font-size: 16px;
width: 2em;
}
}

View File

@ -29,7 +29,7 @@
<div class="form-group">
<div class="col-sm-6" ng-class="{'has-error': signupForm.first_name.$dirty && signupForm.first_name.$invalid}">
<input type="first_name"
<input type="text"
name="first_name"
ng-model="user.profile_attributes.first_name"
class="form-control"
@ -39,7 +39,7 @@
</div>
<div class="m-b visible-xs"></div>
<div class="col-sm-6" ng-class="{'has-error': signupForm.last_name.$dirty && signupForm.last_name.$invalid}">
<input type="last_name"
<input type="text"
name="last_name"
ng-model="user.profile_attributes.last_name"
class="form-control"
@ -53,7 +53,7 @@
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
<input type="username"
<input type="text"
name="username"
ng-model="user.username"
class="form-control"
@ -105,14 +105,55 @@
ng-model="user.password_confirmation"
class="form-control"
placeholder="{{ 'type_your_password_again' | translate }}"
required ng-minlength="8" m
atch="user.password">
required ng-minlength="8"
match="user.password">
</div>
<span class="help-block" ng-show="signupForm.password_confirmation.$dirty && signupForm.password_confirmation.$error.required" translate>{{ 'password_confirmation_is_required' }}</span>
<span class="help-block" ng-show="signupForm.password_confirmation.$error.match" translate>{{ 'password_does_not_match_with_confirmation' }}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-12 checkbox-group">
<input type="checkbox"
name="organization"
id="organization"
ng-model="user.organization"
value="false"/>
<label for="organization" translate>{{ 'i_am_an_organization' }}</label>
</div>
</div>
<div class="form-group" ng-show="user.organization" ng-class="{'has-error': signupForm.organization_name.$dirty && signupForm.organization_name.$invalid}">
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-building-o"></i></span>
<input type="text"
name="organization_name"
ng-model="user.profile_attributes.organization_attributes.name"
class="form-control"
placeholder="{{ 'name_of_your_organization' | translate }}"
ng-required="user.organization">
</div>
<span class="help-block" ng-show="signupForm.organization_name.$dirty && signupForm.organization_name.$error.required" translate>{{ 'organization_name_is_required' }}</span>
</div>
</div>
<div class="form-group" ng-show="user.organization" ng-class="{'has-error': signupForm.organization_address.$dirty && signupForm.organization_address.$invalid}">
<div class="col-sm-12">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-map-marker"></i></span>
<input type="text"
name="organization_address"
ng-model="user.profile_attributes.organization_attributes.address_attributes.address"
class="form-control"
placeholder="{{ 'address_of_your_organization' | translate }}"
ng-required="user.organization">
</div>
<span class="help-block" ng-show="signupForm.organization_address.$dirty && signupForm.organization_address.$error.required" translate>{{ 'organization_address_is_required' }}</span>
</div>
</div>
<div class="form-group" ng-class="{'has-error': signupForm.group_id.$dirty && signupForm.group_id.$invalid}">
<div class="col-sm-12">
<div>
@ -159,34 +200,36 @@
</div>
<div class="form-group" ng-class="{'has-error': signupForm.is_allow_contact.$dirty && signupForm.is_allow_contact.$invalid}">
<div class="col-sm-12">
<div class="col-sm-12 checkbox-group">
<input type="checkbox"
name="is_allow_contact"
id="is_allow_contact"
ng-model="user.is_allow_contact"
value="true"/>
<span translate>{{ 'i_authorize_Fablab_users_registered_on_the_site_to_contact_me' }}</span>
<label for="is_allow_contact" translate>{{ 'i_authorize_Fablab_users_registered_on_the_site_to_contact_me' }}</label>
</div>
</div>
<div class="form-group" ng-class="{'has-error': signupForm.is_allow_newsletter.$dirty && signupForm.is_allow_newsletter.$invalid}">
<div class="col-sm-12">
<div class="col-sm-12 checkbox-group">
<input type="checkbox"
name="is_allow_newsletter"
id="is_allow_newsletter"
ng-model="user.is_allow_newsletter"
value="true"/>
<span translate>{{ 'i_accept_to_receive_informations_from_the_fablab' }}</span>
<label for="is_allow_newsletter" translate>{{ 'i_accept_to_receive_informations_from_the_fablab' }}</label>
</div>
</div>
<div class="form-group" ng-class="{'has-error': signupForm.cgu.$dirty && signupForm.cgu.$invalid}" ng-show="cgu">
<div class="col-sm-12">
<div class="col-sm-12 checkbox-group">
<input type="checkbox"
name="cgu"
id="cgu"
ng-model="user.cgu"
value="true"
ng-required="cgu != null"/>
<span translate>{{ 'i_ve_read_and_i_accept_' }}</span>
<a href="{{cgu.custom_asset_file_attributes.attachment_url}}" target="_blank" translate>{{ '_the_fablab_policy' }}</a>
<label for="cgu"><span translate>{{ 'i_ve_read_and_i_accept_' }}</span> <a href="{{cgu.custom_asset_file_attributes.attachment_url}}" target="_blank" translate>{{ '_the_fablab_policy' }}</a></label>
</div>
</div>
<div ng-if="!cgu">

View File

@ -258,14 +258,16 @@ class API::MembersController < API::ApiController
params.require(:user).permit(:username, :email, :password, :password_confirmation, :group_id, :is_allow_contact, :is_allow_newsletter,
profile_attributes: [:id, :first_name, :last_name, :gender, :birthday, :phone, :interest, :software_mastered, :website, :job,
:facebook, :twitter, :google_plus, :viadeo, :linkedin, :instagram, :youtube, :vimeo, :dailymotion, :github, :echosciences, :pinterest, :lastfm, :flickr,
:user_avatar_attributes => [:id, :attachment, :_destroy], :address_attributes => [:id, :address]])
user_avatar_attributes: [:id, :attachment, :_destroy], address_attributes: [:id, :address],
organization_attributes: [:name, address_attributes: [:id, :address]]])
elsif current_user.is_admin?
params.require(:user).permit(:username, :email, :password, :password_confirmation, :invoicing_disabled, :is_allow_contact, :is_allow_newsletter,
:group_id, training_ids: [], tag_ids: [],
profile_attributes: [:id, :first_name, :last_name, :gender, :birthday, :phone, :interest, :software_mastered, :website, :job,
:facebook, :twitter, :google_plus, :viadeo, :linkedin, :instagram, :youtube, :vimeo, :dailymotion, :github, :echosciences, :pinterest, :lastfm, :flickr,
user_avatar_attributes: [:id, :attachment, :_destroy], address_attributes: [:id, :address]])
user_avatar_attributes: [:id, :attachment, :_destroy], address_attributes: [:id, :address],
organization_attributes: [:name, address_attributes: [:id, :address]]])
end
end

View File

@ -29,7 +29,8 @@ class ApplicationController < ActionController::Base
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) <<
{profile_attributes: [:phone, :last_name, :first_name,
:gender, :birthday, :interest, :software_mastered]}
:gender, :birthday, :interest, :software_mastered,
organization_attributes: [:name, address_attributes: [:address]]]}
devise_parameter_sanitizer.for(:sign_up).concat [:username, :is_allow_contact, :is_allow_newsletter, :cgu, :group_id]
end

View File

@ -1,4 +1,5 @@
class Organization < ActiveRecord::Base
belongs_to :profile
has_one :address, as: :placeable, dependent: :destroy
accepts_nested_attributes_for :address, allow_destroy: true
end

View File

@ -7,6 +7,9 @@ class Profile < ActiveRecord::Base
has_one :address, as: :placeable, dependent: :destroy
accepts_nested_attributes_for :address, allow_destroy: true
has_one :organization, dependent: :destroy
accepts_nested_attributes_for :organization, allow_destroy: false
validates :first_name, presence: true, length: { maximum: 30 }
validates :last_name, presence: true, length: { maximum: 30 }
validates :gender, :inclusion => {:in => [true, false]}

View File

@ -68,6 +68,11 @@ en:
type_your_password_again: "Type your password again"
password_confirmation_is_required: "Password confirmation is required."
password_does_not_match_with_confirmation: "Password does not match with confirmation."
i_am_an_organization: "I am an organization"
name_of_your_organization: "Name of your organization"
organization_name_is_required: "Organization name is required."
address_of_your_organization: "Address of your organization"
organization_address_is_required: "Organization address is required."
your_user_s_profile: "Your user's profile"
user_s_profile_is_required: "User's profile is required."
birth_date: "Birth date"

View File

@ -68,6 +68,11 @@ fr:
type_your_password_again: "Ressaisissez votre mot de passe"
password_confirmation_is_required: "La confirmation du mot de passe est requise."
password_does_not_match_with_confirmation: "Le mot de passe ne concorde pas avec la confirmation."
i_am_an_organization: "Je suis une structure"
name_of_your_organization: "Nom de votre structure"
organization_name_is_required: "Le nom de la structure est requis."
address_of_your_organization: "Adresse de votre structure"
organization_address_is_required: "L'adresse de la structure est requise."
your_user_s_profile: "Votre profil utilisateur"
user_s_profile_is_required: "Le profil utilisateur est requis."
birth_date: "Date de naissance"

View File

@ -1,5 +0,0 @@
class AddOrganizationToProfile < ActiveRecord::Migration
def change
add_reference :profiles, :organization, index: true, foreign_key: true
end
end

View File

@ -0,0 +1,5 @@
class AddProfileToOrganization < ActiveRecord::Migration
def change
add_reference :organizations, :profile, index: true, foreign_key: true
end
end

View File

@ -328,8 +328,11 @@ ActiveRecord::Schema.define(version: 20160801153454) do
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "profile_id"
end
add_index "organizations", ["profile_id"], name: "index_organizations_on_profile_id", using: :btree
create_table "plans", force: :cascade do |t|
t.string "name", limit: 255
t.integer "amount"
@ -390,10 +393,8 @@ ActiveRecord::Schema.define(version: 20160801153454) do
t.string "lastfm"
t.string "flickr"
t.string "job"
t.integer "organization_id"
end
add_index "profiles", ["organization_id"], name: "index_profiles_on_organization_id", using: :btree
add_index "profiles", ["user_id"], name: "index_profiles_on_user_id", using: :btree
create_table "project_steps", force: :cascade do |t|
@ -757,9 +758,9 @@ ActiveRecord::Schema.define(version: 20160801153454) do
add_foreign_key "invoices", "wallet_transactions"
add_foreign_key "o_auth2_mappings", "o_auth2_providers"
add_foreign_key "open_api_calls_count_tracings", "open_api_clients"
add_foreign_key "organizations", "profiles"
add_foreign_key "prices", "groups"
add_foreign_key "prices", "plans"
add_foreign_key "profiles", "organizations"
add_foreign_key "user_tags", "tags"
add_foreign_key "user_tags", "users"
add_foreign_key "wallet_transactions", "users"

View File

@ -2,11 +2,11 @@
address_1:
id: 1
address: 14 rue Brecourt, Annecy
street_number:
route:
locality:
country:
postal_code:
street_number:
route:
locality:
country:
postal_code:
placeable_id: 2
placeable_type: Profile
created_at: 2016-04-04 15:06:22.166469000 Z
@ -15,11 +15,11 @@ address_1:
address_2:
id: 2
address: 23 cours Berriat, Grenoble
street_number:
route:
locality:
country:
postal_code:
street_number:
route:
locality:
country:
postal_code:
placeable_id: 4
placeable_type: Profile
created_at: 2016-04-04 15:10:42.353039000 Z
@ -28,11 +28,11 @@ address_2:
address_3:
id: 3
address: 36 chemin des puits, Mousson-sur-Luire
street_number:
route:
locality:
country:
postal_code:
street_number:
route:
locality:
country:
postal_code:
placeable_id: 5
placeable_type: Profile
created_at: 2016-04-04 15:14:08.579603000 Z
@ -41,12 +41,24 @@ address_3:
address_4:
id: 4
address: ''
street_number:
route:
locality:
country:
postal_code:
street_number:
route:
locality:
country:
postal_code:
placeable_id: 3
placeable_type: Profile
created_at: 2016-04-05 08:35:18.597812000 Z
updated_at: 2016-04-05 08:35:18.597812000 Z
address_5:
id: 5
address: 2 Place St Laurent 38000 GRENOBLE
street_number:
route:
locality:
postal_code:
placeable_id: 1
placeable_type: Organization
created_at: 2016-08-02 11:16:24.412236000 Z
updated_at: 2016-08-02 11:16:24.412236000 Z

View File

@ -1,7 +1,4 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
one:
name: MyString
two:
name: MyString
casemate:
id: 1
name: La Casemate
profile_id: 7