From ce9d1f327f1c237681992978754ea524deec2ced Mon Sep 17 00:00:00 2001 From: Saurabh Bhatia Date: Fri, 30 May 2014 18:36:29 +0800 Subject: [PATCH] Member Profile Custom Fields, Member Status Complete, Member Position Reordering --- app/assets/javascripts/lib/member/sort.js.erb | 4 +- app/controllers/admin/members_controller.rb | 87 +++- app/helpers/attribute_fields_helper.rb | 37 +- app/models/member_profile.rb | 24 + app/models/member_profile_field.rb | 2 +- app/models/member_profile_field_value.rb | 4 +- .../admin/members/_edit_order_card.html.erb | 23 + .../admin/members/_edit_order_list.html.erb | 44 ++ .../admin/members/_index_paginator.html.erb | 2 +- app/views/admin/members/_info.html.erb | 9 + app/views/admin/members/_infos.html.erb | 1 + .../members/_member_for_listing.html.erb | 2 + .../members/_member_for_summary.html.erb | 2 +- app/views/admin/members/_show_roles.html.erb | 2 +- .../admin/members/_update_order_list.js.erb | 1 + .../admin/members/_user_profile.html.erb | 7 +- .../members/_user_setting_account.html.erb | 45 ++ app/views/admin/members/destroy.js.erb | 1 + app/views/admin/members/edit.html.erb | 1 + app/views/admin/members/edit_order.html.erb | 30 ++ app/views/admin/members/index.html.erb | 3 +- app/views/admin/members/new.html.erb | 1 + .../admin/members/setting_account.html.erb | 38 ++ app/views/admin/members/show.html.erb | 6 +- .../admin/members/update_order_list.js.erb | 1 + config/routes.rb | 8 + lib/mongoid/tree.rb | 442 ++++++++++++++++++ lib/mongoid/tree/ordering.rb | 236 ++++++++++ 28 files changed, 1027 insertions(+), 36 deletions(-) create mode 100644 app/views/admin/members/_edit_order_card.html.erb create mode 100644 app/views/admin/members/_edit_order_list.html.erb create mode 100644 app/views/admin/members/_info.html.erb create mode 100644 app/views/admin/members/_infos.html.erb create mode 100644 app/views/admin/members/_update_order_list.js.erb create mode 100644 app/views/admin/members/_user_setting_account.html.erb create mode 100644 app/views/admin/members/destroy.js.erb create mode 100644 app/views/admin/members/edit_order.html.erb create mode 100644 app/views/admin/members/setting_account.html.erb create mode 100644 app/views/admin/members/update_order_list.js.erb create mode 100644 lib/mongoid/tree.rb create mode 100644 lib/mongoid/tree/ordering.rb diff --git a/app/assets/javascripts/lib/member/sort.js.erb b/app/assets/javascripts/lib/member/sort.js.erb index be5b2f8..3f66c09 100644 --- a/app/assets/javascripts/lib/member/sort.js.erb +++ b/app/assets/javascripts/lib/member/sort.js.erb @@ -6,7 +6,7 @@ function dragMode() { _userPosition.position = $(ui.item).index(); _userPosition.id = $(ui.item).data('user-id'); $.ajax({ - url: "<%#= Rails.application.routes.url_helpers.update_order_card_admin_users_new_interface_index_path %>", + url: "<%= Rails.application.routes.url_helpers.update_order_card_admin_members_path %>", type: 'POST', dataType: 'script', data: {users: _userPosition} @@ -46,7 +46,7 @@ function typeMode() { _userPosition.push([$(this).val(), $(this).siblings('a').data('user-id')]); }); $.ajax({ - url: "<%#= Rails.application.routes.url_helpers.update_order_list_admin_users_new_interface_index_path %>", + url: "<%= Rails.application.routes.url_helpers.update_order_list_admin_members_path %>", type: 'POST', dataType: 'script', data: {users: _userPosition} diff --git a/app/controllers/admin/members_controller.rb b/app/controllers/admin/members_controller.rb index 597f02b..d449a66 100644 --- a/app/controllers/admin/members_controller.rb +++ b/app/controllers/admin/members_controller.rb @@ -2,7 +2,7 @@ class Admin::MembersController < OrbitMemberController before_action :set_member_profile, only: [:show, :edit, :update] def index - @roles = Role.where(disabled: false).asc("_id") + @roles = Role.excludes(disabled: true) page_num = params[:page] || 1 @filter = params[:filter] @@ -70,6 +70,7 @@ class Admin::MembersController < OrbitMemberController end def show + @custom_fields = @member.member_profile_field_values rescue nil end def new @@ -91,10 +92,17 @@ class Admin::MembersController < OrbitMemberController def create @member = MemberProfile.new(member_profile_params) - @user = User.new(user_params) - + @user = User.new(user_params) rescue nil if @member.save @user.member_profile_id = @member.id + + if !params[:member_profile_field_value].nil? + params[:member_profile_field_value].each_with_index do |m,i| + @custom_field_value = @member.member_profile_field_values.new(value: m.second["value"], member_profile_field_id: m.second["member_profile_field_id"]) + @custom_field_value.save + end + end + @user.save redirect_to admin_members_path else @@ -130,8 +138,10 @@ class Admin::MembersController < OrbitMemberController @member_profile.user.delete if @member_profile.user.present? @member_profile.delete end - - render action: "index" + + respond_to do |format| + format.js + end end def unapproved_members @@ -173,6 +183,70 @@ class Admin::MembersController < OrbitMemberController end end + def edit_order_card + @members = MemberProfile.order('created_at DESC') + @type = 'card' + render 'edit_order' + end + + def edit_order_list + @members = MemberProfile.order('created_at DESC') + @type = 'list' + render 'edit_order' + end + + def update_order_card + @error = false + if params[:users].present? + to_go = params[:users][:position].to_i + member_at_position = MemberProfile.find_by(position: to_go + 1) + member = MemberProfile.find(params[:users][:id]) + if member_at_position + if member.position > member_at_position.position + member.move_above(member_at_position) + else + member.move_below(member_at_position) + end + end + end + render nothing: true, status: 200 + end + + def update_order_list + @error = [] + if params[:users].present? + params[:users].values.sort.each do |pair| + to_go = pair[0].to_i + + if to_go > 0 + member_at_position = MemberProfile.where(position: to_go).first + member = MemberProfile.find(pair[1]) + if member_at_position && !(member_at_position == member) + if member.position > member_at_position.position + member.move_above(member_at_position) + else + member.move_below(member_at_position) + end + elsif to_go > MemberProfile.count + member.move_to_bottom + end + end + end + end + @members = MemberProfile.asc(:position) + end + + def setting_account + if params[:member_id].blank? + redirect_to action: :index + else + @user = MemberProfile.find(params[:member_id]) + if current_user.id != @user.id + redirect_to action: :index + end + end + end + private # Use callbacks to share common setup or constraints between actions. @@ -193,7 +267,8 @@ class Admin::MembersController < OrbitMemberController protected def get_info_and_roles - @roles = Role.excludes('disabled' => true) + @roles = Role.excludes(disabled: true) + @infos = MemberProfileField.excludes(disabled: true) end def set_attribute diff --git a/app/helpers/attribute_fields_helper.rb b/app/helpers/attribute_fields_helper.rb index 2771823..c5fcf0b 100644 --- a/app/helpers/attribute_fields_helper.rb +++ b/app/helpers/attribute_fields_helper.rb @@ -10,15 +10,15 @@ module AttributeFieldsHelper include OrbitFormHelper - def block_helper(user,index,disable = false) + def block_helper(member,index,disable = false) unless self.disabled @index = index @markup_options = markup_options.merge(:disabled=>disable,:func=>"input_unit") - @user = user - @attribute_value = @user.get_value_from_field_id(id) + @member = member + @attribute_value = @member.get_value_from_field_id(id) @new_attribute = @attribute_value.nil? - @attribute_value = @attribute_value || @user.attribute_values.build( attribute_field_id: id ) - @prefiled_value = @attribute_value.value + @attribute_value = @attribute_value || @member.member_profile_field_values.build(member_profile_field: id) + @prefiled_value = @attribute_value.value rescue nil @panel_setting = self.get_data return instance_eval("render_#{markup}") #rescue "" @@ -179,12 +179,17 @@ module AttributeFieldsHelper protected + def valid_locales + site = Site.first + site.valid_locales + end + def lang_panel_tabbable_wrapper(add_more_params,&block) add_more_counter = '' if self.markup=='text_area' #or self.markup=='address' - tmp1 = VALID_LOCALES.collect do |key| + tmp1 = valid_locales.collect do |key| value = @prefiled_value[key] rescue nil # div_class_ary = ["tab-pane" ,"fade","#{get_pairing_tab_class({})}_#{key}"] div_class_ary = ["tab-pane" ,"fade"] @@ -205,7 +210,7 @@ protected tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do - buff2 = VALID_LOCALES.each.collect do |key| + buff2 = valid_locales.each.collect do |key| # link_entry = self.add_more ? "#{add_more_tab(:tab_btn,loop_counter,key)}" : "#tab"+id.to_s+"_#{key}" link_entry_ary = ["##{get_pairing_tab_class({})}","_#{key}"] link_entry_ary << ".add_more_item_#{add_more_counter}" if can_add_more @@ -229,7 +234,7 @@ protected tmp1 = content_tag :div,:class=> "tab-content" do - buff = VALID_LOCALES.collect do |key| + buff = valid_locales.collect do |key| value = @prefiled_value[key] rescue nil # div_class_ary = ["tab-pane" ,"fade","#{get_pairing_tab_class({})}_#{key}"] div_class_ary = ["tab-pane" ,"fade"] @@ -254,7 +259,7 @@ protected end tmp2 = content_tag(:div,:class => 'btn-group', :data=>{:toggle=>"buttons-radio"}) do - buff2 = VALID_LOCALES.each.collect do |key| + buff2 = valid_locales.each.collect do |key| # link_entry = self.add_more ? "#{add_more_tab(:tab_btn,loop_counter,key)}" : "#tab"+id.to_s+"_#{key}" link_entry_ary = ["##{get_pairing_tab_class({})}","_#{key}"] link_entry_ary << ".add_more_item_#{add_more_counter}" if can_add_more @@ -342,14 +347,14 @@ protected end - temp = label + content_tag(:div, multipleInputs + add_more_unt, :class=>'controls add-input') + temp = form_label + content_tag(:div, multipleInputs + add_more_unt, :class=>'controls add-input') result = content_tag(:div,temp,:class=>div_class) # result = label + multipleInputs + add_more_unt # result = label + 一堆的輸入框(要用 multipleInput editMore 包起來) + add_more btn + hidden_fields else - temp = label + content_tag(:div, controls_wrapper(&block), :class=>'controls') + temp = form_label + content_tag(:div, controls_wrapper(&block), :class=>'controls') result = content_tag(:div,temp,:class=>div_class) end @@ -358,13 +363,13 @@ protected # address = content_tag :div,:class=>"multipleInput editMore" do address = content_tag :div,:class=>"control-group" do - label + content_tag(:div, controls_wrapper(&block), :class=>'controls add-input') + form_label + content_tag(:div, controls_wrapper(&block), :class=>'controls add-input') end # of div multipleInput editMore result = address else - temp = label + content_tag(:div, controls_wrapper(&block), :class=>'controls') + temp = form_label + content_tag(:div, controls_wrapper(&block), :class=>'controls') result = content_tag(:div,temp,:class=>div_class) end @@ -395,7 +400,7 @@ protected def end_block if @new_attribute - hidden_field_tag(get_basic_field_name_base+"[attribute_field_id]",id,:for=>"field_#{@index}") + hidden_field_tag(get_basic_field_name_base+"[member_profile_field_id]",id,:for=>"field_#{@index}") else hidden_field_tag(get_basic_field_name_base+"[id]",@attribute_value.id,:for=>"field_#{@index}") end @@ -420,9 +425,9 @@ protected def get_basic_field_name_base if @new_attribute - "user[new_attribute_values][#{@index}]" + "member_profile_field_value[#{@index}]" else - "user[attribute_values][#{@index}]" + "member_profile_field_values[#{@index}]" end end diff --git a/app/models/member_profile.rb b/app/models/member_profile.rb index 66f7924..878f605 100644 --- a/app/models/member_profile.rb +++ b/app/models/member_profile.rb @@ -1,6 +1,8 @@ class MemberProfile include Mongoid::Document include Mongoid::Timestamps + include Mongoid::Tree + include Mongoid::Tree::Ordering field :first_name, type: String, localize: true field :last_name, type: String, localize: true @@ -12,14 +14,21 @@ class MemberProfile field :personal_website field :autobiography, type: String, localize: true field :email, type: String + field :position, type: Integer VALID_EMAIL_FORMAT = /\A[^@\s]+@([^@.\s]+\.)+[^@.\s]+\z/ validates :email, uniqueness: true, format: { with: VALID_EMAIL_FORMAT } + validates :position, uniqueness: true has_one :user has_and_belongs_to_many :roles has_and_belongs_to_many :role_statuses + has_many :member_profile_field_values + accepts_nested_attributes_for :member_profile_field_values + + before_save :assign_default_position, :if => :assign_default_position? + mount_uploader :avatar, AvatarUploader paginates_per 10 @@ -38,4 +47,19 @@ class MemberProfile end end end + + def get_attribute_values + @attribute_values ||= self.member_profile_field_values rescue nil + end + + def get_value_from_field_id(field_id) + values = get_attribute_values + value = values.detect {|value| value.attribute_field_id == field_id} rescue nil + value ? value : nil + end + + def assign_default_position? + self.position.nil? || self.parent_id_changed? + end + end diff --git a/app/models/member_profile_field.rb b/app/models/member_profile_field.rb index faf6996..bbbb236 100644 --- a/app/models/member_profile_field.rb +++ b/app/models/member_profile_field.rb @@ -21,7 +21,7 @@ class MemberProfileField field :typeD, type: Hash, default: {cross_lang: false} field :typeE, type: Hash, default: {} - embeds_many :member_profile_field_values + has_many :member_profile_field_values def markup_value get_data["option_list"] diff --git a/app/models/member_profile_field_value.rb b/app/models/member_profile_field_value.rb index ecae25c..6db36d3 100644 --- a/app/models/member_profile_field_value.rb +++ b/app/models/member_profile_field_value.rb @@ -5,6 +5,8 @@ class MemberProfileFieldValue field :key field :address_key + field :value - embedded_in :member_profile_field + belongs_to :member_profile_field + belongs_to :member_profile end diff --git a/app/views/admin/members/_edit_order_card.html.erb b/app/views/admin/members/_edit_order_card.html.erb new file mode 100644 index 0000000..dbc0fd4 --- /dev/null +++ b/app/views/admin/members/_edit_order_card.html.erb @@ -0,0 +1,23 @@ +
+
+
    + <% @members.each do |member| %> +
  • + +
  • + <% end %> +
+
+
+ + \ No newline at end of file diff --git a/app/views/admin/members/_edit_order_list.html.erb b/app/views/admin/members/_edit_order_list.html.erb new file mode 100644 index 0000000..f001952 --- /dev/null +++ b/app/views/admin/members/_edit_order_list.html.erb @@ -0,0 +1,44 @@ +
+ + + + + + + + + + + <% @members.each do |member| %> + <% + case member.sex + when 'male' + member_sex = 'gender-man' + when 'female' + member_sex = 'gender-woman' + else + member_sex = 'gender-none' + end + %> + + + + + + + <% end %> + +
<%= t(:position) %><%= t(:name) %><%= t(:email) %>
<%= link_to member.position, '#', class: 'edit_position', 'data-user-id' => member.id %><%= link_to member.name, admin_member_path(member) %><%= member.email %>
+
+ +
+
+ <%= link_to t(:update_), '#', class: "btn btn-primary pull-right" %> +
+
+ + \ No newline at end of file diff --git a/app/views/admin/members/_index_paginator.html.erb b/app/views/admin/members/_index_paginator.html.erb index 67464b4..76d1ab9 100644 --- a/app/views/admin/members/_index_paginator.html.erb +++ b/app/views/admin/members/_index_paginator.html.erb @@ -2,7 +2,7 @@
<% if params[:action] != "unapproved_members" %> <% if current_user.is_admin? %> - <%= link_to t(:edit_order),new_admin_member_path ,:class => "btn btn-primary" %> + <%= link_to t(:edit_order), edit_order_list_admin_members_path,:class => "btn btn-primary" %> <%= link_to(new_admin_member_path,:class=> "btn btn-primary") do %> <%= t(:add) %> <% end -%> diff --git a/app/views/admin/members/_info.html.erb b/app/views/admin/members/_info.html.erb new file mode 100644 index 0000000..16a314c --- /dev/null +++ b/app/views/admin/members/_info.html.erb @@ -0,0 +1,9 @@ +
+
+

<%= info.title %>

+
+
+ <%= info.block_helper(@member, @form_index)%> + <% @form_index = @form_index +1 %> +
+
\ No newline at end of file diff --git a/app/views/admin/members/_infos.html.erb b/app/views/admin/members/_infos.html.erb new file mode 100644 index 0000000..d9d47fc --- /dev/null +++ b/app/views/admin/members/_infos.html.erb @@ -0,0 +1 @@ +<%=render partial: "info", collection: @infos%> \ No newline at end of file diff --git a/app/views/admin/members/_member_for_listing.html.erb b/app/views/admin/members/_member_for_listing.html.erb index a83c548..5a37e1d 100644 --- a/app/views/admin/members/_member_for_listing.html.erb +++ b/app/views/admin/members/_member_for_listing.html.erb @@ -22,7 +22,9 @@
diff --git a/app/views/admin/members/_member_for_summary.html.erb b/app/views/admin/members/_member_for_summary.html.erb index de97d41..6b779ed 100644 --- a/app/views/admin/members/_member_for_summary.html.erb +++ b/app/views/admin/members/_member_for_summary.html.erb @@ -12,7 +12,7 @@

<%= link_to(content_tag(:i, nil, :class => 'icon-edit'),edit_admin_member_path(member_for_summary),:class=>"edit" ) if current_user.is_admin?%> - <%= link_to(content_tag(:i, nil, :class => 'icon-key'),:class=>"key" ) if current_user.is_admin? and current_user.id != member_for_summary.id %> + <%= link_to(content_tag(:i, nil, :class => 'icon-key'),admin_member_edit_privilege_path(member_for_summary),:class=>"key" ) if current_user.is_admin? and current_user.id != member_for_summary.id %> <%= link_to(content_tag(:i, nil, :class => 'icon-trash'), admin_members_path(member_for_summary, :at=>params[:at]), :confirm => t(:sure?), :method => :delete, :class=>"trash", :remote => true) if current_user.is_admin? %>
<%= image_tag(member_for_summary.avatar) %> diff --git a/app/views/admin/members/_show_roles.html.erb b/app/views/admin/members/_show_roles.html.erb index 4d52b5e..b2bb986 100644 --- a/app/views/admin/members/_show_roles.html.erb +++ b/app/views/admin/members/_show_roles.html.erb @@ -3,6 +3,6 @@

<%= show_roles.title %><%= t(:role_info)%>

<%= t('status') %>
-
<%= show_attribute_value(@user.role_statuses.where(:role_id=>show_roles.id).map{|t|t.title.to_s}.join(',')) rescue '' %>
+
<%= @member.role_statuses.where(role_id: show_roles.id).map{|t|t.title.to_s}.join(',') rescue '' %>
diff --git a/app/views/admin/members/_update_order_list.js.erb b/app/views/admin/members/_update_order_list.js.erb new file mode 100644 index 0000000..f07ed70 --- /dev/null +++ b/app/views/admin/members/_update_order_list.js.erb @@ -0,0 +1 @@ +$('#order_content').html("<%= j render 'edit_order_list' %>") \ No newline at end of file diff --git a/app/views/admin/members/_user_profile.html.erb b/app/views/admin/members/_user_profile.html.erb index 7ce3bd0..9a13d32 100644 --- a/app/views/admin/members/_user_profile.html.erb +++ b/app/views/admin/members/_user_profile.html.erb @@ -14,7 +14,10 @@
<%= @member.office_tel %>
<% end %>
<%= t('users.sex')%>
-
<%= t("users.#{(@member.sex.nil? ? 'unknown' : @member.sex)}") %>
- +
<%= t("users.#{(@member.sex.nil? ? 'unknown' : @member.sex)}") %>
+ <% items.each do |item| %> +
<%= item.member_profile_field.title %>
+
<%= item.value %>
+ <% end -%> \ No newline at end of file diff --git a/app/views/admin/members/_user_setting_account.html.erb b/app/views/admin/members/_user_setting_account.html.erb new file mode 100644 index 0000000..a1cd0d5 --- /dev/null +++ b/app/views/admin/members/_user_setting_account.html.erb @@ -0,0 +1,45 @@ +<%= form_for @user, :html => { :class=>"form-horizontal main-forms", :id=>"user-forms"} do |f| %> + +
+
+

<%=t(:sys_basic_id_form)%>

+
+
+ + +
+ +
+ <%= f.text_field :user_name, :class=>"input-medium", :id=>"account", :placeholder=>"#{t('users.user_id')}" %> + <%= t("users.user_id_note")%> +
+
+ + +
+ +
+ <%= f.password_field :password, :class=>"input-medium", :id=>"password" %> + <%= t("users.new_password_note")%> +
+
+ + +
+ +
+ <%= f.password_field :password_confirmation, :class=>"input-medium", :id=>"confirm_password" %> +
+
+ + <%= f.hidden_field :approved, value: true if current_user.is_admin? %> + +
+
+<% end %> \ No newline at end of file diff --git a/app/views/admin/members/destroy.js.erb b/app/views/admin/members/destroy.js.erb new file mode 100644 index 0000000..0f9a84c --- /dev/null +++ b/app/views/admin/members/destroy.js.erb @@ -0,0 +1 @@ +$("#<%= dom_id @member_profile %>").remove(); \ No newline at end of file diff --git a/app/views/admin/members/edit.html.erb b/app/views/admin/members/edit.html.erb index afa2305..a49ee6d 100644 --- a/app/views/admin/members/edit.html.erb +++ b/app/views/admin/members/edit.html.erb @@ -28,6 +28,7 @@ <%= render partial: 'user_basic_passwd'%> <%= render partial: 'member_basic', locals: {f: f}%> + <%= render partial: "infos"%> <%= render partial: 'roles', locals: {f: f} %> diff --git a/app/views/admin/members/edit_order.html.erb b/app/views/admin/members/edit_order.html.erb new file mode 100644 index 0000000..beb595f --- /dev/null +++ b/app/views/admin/members/edit_order.html.erb @@ -0,0 +1,30 @@ +<% content_for :side_bar do %> + <%= render :partial => 'admin/members/side_bar' %> +<% end %> +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "lib/member" %> + <%= stylesheet_link_tag "lib/checkbox-card" %> +<% end %> + +<% content_for :right_nav do %> +
+ <%= link_to content_tag(:i, nil, class: 'icon-list'), edit_order_list_admin_members_path, class: "btn btn-small#{' active' if @type.eql?('list')}" %> + <%= link_to content_tag(:i, nil, class: 'icon-th'), edit_order_card_admin_members_path, class: "btn btn-small#{' active' if @type.eql?('card')}" %> +
+<% end %> + +
+ <% case @type %> + <% when 'card' %> + <%= render 'edit_order_card' %> + <% when 'list' %> + <%= render 'edit_order_list' %> + <% end %> +
+ +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "jquery.ui.sortable" %> + <%= javascript_include_tag "lib/jquery.ui.touch-punch.min" %> + <%= javascript_include_tag "lib/jquery.lite.image.resize" %> + <%= javascript_include_tag "lib/member/sort" %> +<% end %> \ No newline at end of file diff --git a/app/views/admin/members/index.html.erb b/app/views/admin/members/index.html.erb index a9651e6..fa1ad0e 100644 --- a/app/views/admin/members/index.html.erb +++ b/app/views/admin/members/index.html.erb @@ -27,8 +27,7 @@
- - <%= render :partial => "filter"%> + <%= render :partial => "filter", locals: {:role => @roles}%>
diff --git a/app/views/admin/members/new.html.erb b/app/views/admin/members/new.html.erb index 00a186f..0a33dd3 100644 --- a/app/views/admin/members/new.html.erb +++ b/app/views/admin/members/new.html.erb @@ -26,6 +26,7 @@
<%= render partial: 'user_basic_passwd'%> <%= render partial: 'member_basic', locals: {f: f}%> + <%= render partial: "infos"%> <%= render partial: 'roles', locals: { f: f } %>
diff --git a/app/views/admin/members/setting_account.html.erb b/app/views/admin/members/setting_account.html.erb new file mode 100644 index 0000000..d985690 --- /dev/null +++ b/app/views/admin/members/setting_account.html.erb @@ -0,0 +1,38 @@ +<% content_for :side_bar do %> + <%= render :partial => 'admin/members/side_bar' %> +<% end %> + +<% content_for :page_specific_css do -%> + <%= stylesheet_link_tag "lib/wrap-nav.css" %> + <%= stylesheet_link_tag "lib/pageslide.css" %> + <%= stylesheet_link_tag "lib/main-forms.css" %> + <%= stylesheet_link_tag "lib/fileupload.css" %> + <%= stylesheet_link_tag "lib/togglebox.css" %> +<% end -%> +<% content_for :page_specific_javascript do -%> + <%= javascript_include_tag "lib/jquery.tmpl.min.js" %> + <%= javascript_include_tag "lib/bootstrap-fileupload.js" %> + <%= javascript_include_tag "lib/member/role-forms.js" %> + <%= javascript_include_tag "lib/member/textarea-lang-btn.js" %> +<% end -%> + + +<%= form_for @member, :url => admin_member_path(@member), :html => { :multipart => true , :class=>"form-horizontal main-forms", :id=>"user-forms"} do |f| %> + +
+
+ + <%= render :partial => 'user_setting_account', :locals => {:f => f}%> + +
+ + +
+ <%= link_back('btn') %> + <%= hidden_field_tag 'edit_type', 'setting_account' %> + <%= link_to t(:update_), "#", :class=>"btn btn-primary returnDecide", :onclick=>"$('#edit_user_#{@user.id}').submit()" %> +
+ +
+ +<% end -%> \ No newline at end of file diff --git a/app/views/admin/members/show.html.erb b/app/views/admin/members/show.html.erb index e79b7ce..bbe4e3c 100644 --- a/app/views/admin/members/show.html.erb +++ b/app/views/admin/members/show.html.erb @@ -20,14 +20,14 @@ <%= @member.email %>
<%= link_to(" #{t(:edit)}".html_safe,edit_admin_member_path(@member.id),:class=>"btn btn-mini" ) if current_user.is_admin?%> - <%= link_to(" #{t("users.change_passwd")}".html_safe,admin_member_edit_passwd_path(@member),:class=>"btn btn-mini" ) if current_user.is_admin? and current_user.id != @member.user.id %> - <%= link_to(" #{t("users.setting_privilege")}".html_safe,admin_member_edit_privilege_path(@member),:class=>"btn btn-mini" ) if current_user.is_admin? and current_user.id != @member.user.id %> + <%= link_to(" #{t("users.change_passwd")}".html_safe,admin_member_edit_passwd_path(@member),:class=>"btn btn-mini" ) if current_user.is_admin? and current_user.id != @member.user.id rescue nil %> + <%= link_to(" #{t("users.setting_privilege")}".html_safe,admin_member_edit_privilege_path(@member),:class=>"btn btn-mini" ) if current_user.is_admin? and current_user.id != @member.user.id rescue nil%>
- <%= render :partial=> "user_profile",:locals=>{:role_class=>"basic",:i18n=>"profile"} %> + <%= render :partial=> "user_profile",:locals=>{:role_class=>"basic",:i18n=>"profile", :items=>@custom_fields} %> <%= render :partial=> "show_roles",collection: @member.roles %>
diff --git a/app/views/admin/members/update_order_list.js.erb b/app/views/admin/members/update_order_list.js.erb new file mode 100644 index 0000000..f07ed70 --- /dev/null +++ b/app/views/admin/members/update_order_list.js.erb @@ -0,0 +1 @@ +$('#order_content').html("<%= j render 'edit_order_list' %>") \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 867cf1c..fe25239 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -81,9 +81,17 @@ Orbit::Application.routes.draw do get 'get_month_traffic' end end + get "members/unapproved_members" => "members#unapproved_members" resources :members do + collection do + get 'edit_order_card' + get 'edit_order_list' + post 'update_order_card' + post 'update_order_list' + end + match "setting_account" => "members#setting_account" ,:as => :setting_account, via: [:get, :post] match "edit_passwd" => "members#edit_passwd" ,:as => :edit_passwd, via: [:get, :post] match "accept_member" => "members#accept_member" ,:as => :accept_member, via: [:get, :post] match "edit_privilege" => "members#edit_privilege" ,:as => :edit_privilege, via: [:get, :post] diff --git a/lib/mongoid/tree.rb b/lib/mongoid/tree.rb new file mode 100644 index 0000000..7dd2abd --- /dev/null +++ b/lib/mongoid/tree.rb @@ -0,0 +1,442 @@ +module Mongoid + ## + # = Mongoid::Tree + # + # This module extends any Mongoid document with tree functionality. + # + # == Usage + # + # Simply include the module in any Mongoid document: + # + # class Node + # include Mongoid::Document + # include Mongoid::Tree + # end + # + # === Using the tree structure + # + # Each document references many children. You can access them using the #children method. + # + # node = Node.create + # node.children.create + # node.children.count # => 1 + # + # Every document references one parent (unless it's a root document). + # + # node = Node.create + # node.parent # => nil + # node.children.create + # node.children.first.parent # => node + # + # === Destroying + # + # Mongoid::Tree does not handle destroying of nodes by default. However it provides + # several strategies that help you to deal with children of deleted documents. You can + # simply add them as before_destroy callbacks. + # + # Available strategies are: + # + # * :nullify_children -- Sets the children's parent_id to null + # * :move_children_to_parent -- Moves the children to the current document's parent + # * :destroy_children -- Destroys all children by calling their #destroy method (invokes callbacks) + # * :delete_descendants -- Deletes all descendants using a database query (doesn't invoke callbacks) + # + # Example: + # + # class Node + # include Mongoid::Document + # include Mongoid::Tree + # + # before_destroy :nullify_children + # end + # + # === Callbacks + # + # Mongoid::Tree offers callbacks for its rearranging process. This enables you to + # rebuild certain fields when the document was moved in the tree. Rearranging happens + # before the document is validated. This gives you a chance to validate your additional + # changes done in your callbacks. See ActiveModel::Callbacks and ActiveSupport::Callbacks + # for further details on callbacks. + # + # Example: + # + # class Page + # include Mongoid::Document + # include Mongoid::Tree + # + # after_rearrange :rebuild_path + # + # field :slug + # field :path + # + # private + # + # def rebuild_path + # self.path = self.ancestors_and_self.collect(&:slug).join('/') + # end + # end + # + module Tree + extend ActiveSupport::Concern + + autoload :Ordering, 'mongoid/tree/ordering' + autoload :Traversal, 'mongoid/tree/traversal' + + included do + has_many :children, :class_name => self.name, :foreign_key => :parent_id, :inverse_of => :parent, :validate => false + + belongs_to :parent, :class_name => self.name, :inverse_of => :children, :index => true, :validate => false + + field :parent_ids, :type => Array, :default => [] + index :parent_ids => 1 + + field :depth, :type => Integer + index :depth => 1 + + set_callback :save, :after, :rearrange_children, :if => :rearrange_children? + set_callback :validation, :before do + run_callbacks(:rearrange) { rearrange } + end + + validate :position_in_tree + + define_model_callbacks :rearrange, :only => [:before, :after] + + class_eval "def base_class; ::#{self.name}; end" + end + + ## + # This module implements class methods that will be available + # on the document that includes Mongoid::Tree + module ClassMethods + + ## + # Returns the first root document + # + # @example + # Node.root + # + # @return [Mongoid::Document] The first root document + def root + roots.first + end + + ## + # Returns all root documents + # + # @example + # Node.roots + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve all root documents + def roots + where(:parent_id => nil) + end + + ## + # Returns all leaves (be careful, currently involves two queries) + # + # @example + # Node.leaves + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve all leave nodes + def leaves + where(:_id.nin => only(:parent_id).collect(&:parent_id)) + end + + end + + ## + # @!method before_rearrange + # @!scope class + # + # Sets a callback that is called before the document is rearranged + # + # @example + # class Node + # include Mongoid::Document + # include Mongoid::Tree + # + # before_rearrage :do_something + # + # private + # + # def do_something + # # ... + # end + # end + # + # @note Generated by ActiveSupport + # + # @return [undefined] + + ## + # @!method after_rearrange + # @!scope class + # + # Sets a callback that is called after the document is rearranged + # + # @example + # class Node + # include Mongoid::Document + # include Mongoid::Tree + # + # after_rearrange :do_something + # + # private + # + # def do_something + # # ... + # end + # end + # + # @note Generated by ActiveSupport + # + # @return [undefined] + + ## + # @!method children + # Returns a list of the document's children. It's a references_many association. + # + # @note Generated by Mongoid + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's children + + ## + # @!method parent + # Returns the document's parent (unless it's a root document). It's a referenced_in association. + # + # @note Generated by Mongoid + # + # @return [Mongoid::Document] The document's parent document + + ## + # @!method parent=(document) + # Sets this documents parent document. + # + # @note Generated by Mongoid + # + # @param [Mongoid::Tree] document + + ## + # @!method parent_ids + # Returns a list of the document's parent_ids, starting with the root node. + # + # @note Generated by Mongoid + # + # @return [Array] The ids of the document's ancestors + + ## + # Returns the depth of this document (number of ancestors) + # + # @example + # Node.root.depth # => 0 + # Node.root.children.first.depth # => 1 + # + # @return [Fixnum] Depth of this document + def depth + super || parent_ids.count + end + + ## + # Is this document a root node (has no parent)? + # + # @return [Boolean] Whether the document is a root node + def root? + parent_id.nil? + end + + ## + # Is this document a leaf node (has no children)? + # + # @return [Boolean] Whether the document is a leaf node + def leaf? + children.empty? + end + + ## + # Returns this document's root node. Returns `self` if the + # current document is a root node + # + # @example + # node = Node.find(...) + # node.root + # + # @return [Mongoid::Document] The documents root node + def root + if parent_ids.present? + base_class.find(parent_ids.first) + else + self.root? ? self : self.parent.root + end + end + + ## + # Returns a chainable criteria for this document's ancestors + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the documents ancestors + def ancestors + base_class.where(:_id.in => parent_ids).order(:depth => :asc) + end + + ## + # Returns an array of this document's ancestors and itself + # + # @return [Array] Array of the document's ancestors and itself + def ancestors_and_self + ancestors + [self] + end + + ## + # Is this document an ancestor of the other document? + # + # @param [Mongoid::Tree] other document to check against + # + # @return [Boolean] The document is an ancestor of the other document + def ancestor_of?(other) + other.parent_ids.include?(self.id) + end + + ## + # Returns a chainable criteria for this document's descendants + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's descendants + def descendants + base_class.where(:parent_ids => self.id) + end + + ## + # Returns and array of this document and it's descendants + # + # @return [Array] Array of the document itself and it's descendants + def descendants_and_self + [self] + descendants + end + + ## + # Is this document a descendant of the other document? + # + # @param [Mongoid::Tree] other document to check against + # + # @return [Boolean] The document is a descendant of the other document + def descendant_of?(other) + self.parent_ids.include?(other.id) + end + + ## + # Returns this document's siblings + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's siblings + def siblings + siblings_and_self.excludes(:id => self.id) + end + + ## + # Returns this document's siblings and itself + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's siblings and itself + def siblings_and_self + base_class.where(:parent_id => self.parent_id) + end + + ## + # Is this document a sibling of the other document? + # + # @param [Mongoid::Tree] other document to check against + # + # @return [Boolean] The document is a sibling of the other document + def sibling_of?(other) + self.parent_id == other.parent_id + end + + ## + # Returns all leaves of this document (be careful, currently involves two queries) + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's leaves + def leaves + base_class.where(:_id.nin => base_class.only(:parent_id).collect(&:parent_id)).and(:parent_ids => self.id) + end + + ## + # Forces rearranging of all children after next save + # + # @return [undefined] + def rearrange_children! + @rearrange_children = true + end + + ## + # Will the children be rearranged after next save? + # + # @return [Boolean] Whether the children will be rearranged + def rearrange_children? + !!@rearrange_children + end + + ## + # Nullifies all children's parent_id + # + # @return [undefined] + def nullify_children + children.each do |c| + c.parent = c.parent_id = nil + c.save + end + end + + ## + # Moves all children to this document's parent + # + # @return [undefined] + def move_children_to_parent + children.each do |c| + c.parent = self.parent + c.save + end + end + + ## + # Deletes all descendants using the database (doesn't invoke callbacks) + # + # @return [undefined] + def delete_descendants + base_class.delete_all(:conditions => { :parent_ids => self.id }) + end + + ## + # Destroys all children by calling their #destroy method (does invoke callbacks) + # + # @return [undefined] + def destroy_children + children.destroy_all + end + + private + + ## + # Updates the parent_ids and marks the children for + # rearrangement when the parent_ids changed + # + # @private + # @return [undefined] + def rearrange + if self.parent_id + self.parent_ids = parent.parent_ids + [self.parent_id] + else + self.parent_ids = [] + end + + self.depth = parent_ids.size + + rearrange_children! if self.parent_ids_changed? + end + + def rearrange_children + @rearrange_children = false + self.children.each { |c| c.save } + end + + def position_in_tree + errors.add(:parent_id, :invalid) if self.parent_ids.include?(self.id) + end + end +end \ No newline at end of file diff --git a/lib/mongoid/tree/ordering.rb b/lib/mongoid/tree/ordering.rb new file mode 100644 index 0000000..98bca04 --- /dev/null +++ b/lib/mongoid/tree/ordering.rb @@ -0,0 +1,236 @@ +module Mongoid + module Tree + ## + # = Mongoid::Tree::Ordering + # + # Mongoid::Tree doesn't order the tree by default. To enable ordering of children + # include both Mongoid::Tree and Mongoid::Tree::Ordering into your document. + # + # == Utility methods + # + # This module adds methods to get related siblings depending on their position: + # + # node.lower_siblings + # node.higher_siblings + # node.first_sibling_in_list + # node.last_sibling_in_list + # + # There are several methods to move nodes around in the list: + # + # node.move_up + # node.move_down + # node.move_to_top + # node.move_to_bottom + # node.move_above(other) + # node.move_below(other) + # + # Additionally there are some methods to check aspects of the document + # in the list of children: + # + # node.at_top? + # node.at_bottom? + module Ordering + extend ActiveSupport::Concern + + included do + field :position, :type => Integer + + default_scope ->{ asc(:position) } + + before_save :assign_default_position, :if => :assign_default_position? + before_save :reposition_former_siblings, :if => :sibling_reposition_required? + after_destroy :move_lower_siblings_up + end + + ## + # Returns a chainable criteria for this document's ancestors + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's ancestors + def ancestors + base_class.unscoped { super } + end + + ## + # Returns siblings below the current document. + # Siblings with a position greater than this document's position. + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's lower siblings + def lower_siblings + self.siblings.where(:position.gt => self.position) + end + + ## + # Returns siblings above the current document. + # Siblings with a position lower than this document's position. + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the document's higher siblings + def higher_siblings + self.siblings.where(:position.lt => self.position) + end + + ## + # Returns siblings between the current document and the other document + # Siblings with a position between this document's position and the other document's position. + # + # @return [Mongoid::Criteria] Mongoid criteria to retrieve the documents between this and the other document + def siblings_between(other) + range = [self.position, other.position].sort + self.siblings.where(:position.gt => range.first, :position.lt => range.last) + end + + ## + # Returns the lowest sibling (could be self) + # + # @return [Mongoid::Document] The lowest sibling + def last_sibling_in_list + siblings_and_self.last + end + + ## + # Returns the highest sibling (could be self) + # + # @return [Mongoid::Document] The highest sibling + def first_sibling_in_list + siblings_and_self.first + end + + ## + # Is this the highest sibling? + # + # @return [Boolean] Whether the document is the highest sibling + def at_top? + higher_siblings.empty? + end + + ## + # Is this the lowest sibling? + # + # @return [Boolean] Whether the document is the lowest sibling + def at_bottom? + lower_siblings.empty? + end + + ## + # Move this node above all its siblings + # + # @return [undefined] + def move_to_top + return true if at_top? + move_above(first_sibling_in_list) + end + + ## + # Move this node below all its siblings + # + # @return [undefined] + def move_to_bottom + return true if at_bottom? + move_below(last_sibling_in_list) + end + + ## + # Move this node one position up + # + # @return [undefined] + def move_up + switch_with_sibling_at_offset(-1) unless at_top? + end + + ## + # Move this node one position down + # + # @return [undefined] + def move_down + switch_with_sibling_at_offset(1) unless at_bottom? + end + + ## + # Move this node above the specified node + # + # This method changes the node's parent if nescessary. + # + # @param [Mongoid::Tree] other document to move this document above + # + # @return [undefined] + def move_above(other) + ensure_to_be_sibling_of(other) + + if position > other.position + new_position = other.position + self.siblings_between(other).inc(:position => 1) + other.inc(:position => 1) + else + new_position = other.position - 1 + self.siblings_between(other).inc(:position => -1) + end + + self.position = new_position + save! + end + + ## + # Move this node below the specified node + # + # This method changes the node's parent if nescessary. + # + # @param [Mongoid::Tree] other document to move this document below + # + # @return [undefined] + def move_below(other) + ensure_to_be_sibling_of(other) + + if position > other.position + new_position = other.position + 1 + self.siblings_between(other).inc(:position => 1) + else + new_position = other.position + self.siblings_between(other).inc(:position => -1) + other.inc(:position => -1) + end + + self.position = new_position + save! + end + + private + + def switch_with_sibling_at_offset(offset) + siblings.where(:position => self.position + offset).first.inc(:position => -offset) + inc(:position => offset) + end + + def ensure_to_be_sibling_of(other) + return if sibling_of?(other) + self.parent_id = other.parent_id + save! + end + + def move_lower_siblings_up + lower_siblings.inc(:position => -1) + end + + def reposition_former_siblings + former_siblings = base_class.where(:parent_id => attribute_was('parent_id')). + and(:position.gt => (attribute_was('position') || 0)). + excludes(:id => self.id) + former_siblings.inc(:position => -1) + end + + def sibling_reposition_required? + parent_id_changed? && persisted? + end + + def assign_default_position + self.position = if self.siblings.where(:position.ne => nil).any? + self.last_sibling_in_list.position + 1 + else + 0 + end + end + + def assign_default_position? + self.position.nil? || self.parent_id_changed? + end + end + end +end \ No newline at end of file