Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

An assembly member can be an existing user #3302

Merged
merged 1 commit into from May 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -26,6 +26,7 @@ end
**Added**:

- **decidim-assemblies**: Add members to assemblies. [\#3008](https://github.com/decidim/decidim/pull/3008)
- **decidim-assemblies**: An assembly member can be related to an existing user. [\#3302](https://github.com/decidim/decidim/pull/3302)
- **decidim-meetings**: Add organizer to meeting and meeting types [\#3136](https://github.com/decidim/decidim/pull/3136)
- **decidim-meetings**: Add Minutes entity to manage Minutes. [\#3213](https://github.com/decidim/decidim/pull/3213)
- **decidim-admin**: Links to participatory space index & show pages from the admin dashboard. [\#3325](https://github.com/decidim/decidim/pull/3325)
Expand Down
2 changes: 1 addition & 1 deletion decidim-admin/lib/decidim/admin/form_builder.rb
Expand Up @@ -19,7 +19,7 @@ class FormBuilder < Decidim::FormBuilder
# @param [Hash] prompt_options
# Prompt configuration. A hash with options:
# - :url (String) The url where the ajax endpoint to fill the select
# - :text (String) Text to use as placeholder
# - :placeholder (String) Text to use as placeholder
# - :no_results (String) (optional) Text to use when there are no matching results (default: No results found)
# - :search_prompt (String) (optional) Text to prompt for search input (default: Type at least three characters to search)
#
Expand Down
@@ -1,6 +1,28 @@
((exports) => {
const { createFieldDependentInputs } = exports.DecidimAdmin;

const $assemblyMemberType = $("#assembly_member_existing_user");

createFieldDependentInputs({
controllerField: $assemblyMemberType,
wrapperSelector: ".user-fields",
dependentFieldsSelector: ".user-fields--full-name",
dependentInputSelector: "input",
enablingCondition: ($field) => {
return $field.val() === "false"
}
});

createFieldDependentInputs({
controllerField: $assemblyMemberType,
wrapperSelector: ".user-fields",
dependentFieldsSelector: ".user-fields--user-picker",
dependentInputSelector: "input",
enablingCondition: ($field) => {
return $field.val() === "true"
}
});

const $assemblyMemberPosition = $("#assembly_member_position");

createFieldDependentInputs({
Expand Down
Expand Up @@ -61,7 +61,8 @@ def create_assembly_member!
:position_other,
:weight
).merge(
assembly: assembly
assembly: assembly,
user: form.user
),
log_info
)
Expand Down
Expand Up @@ -57,6 +57,8 @@ def update_assembly_member!
:position,
:position_other,
:weight
).merge(
user: form.user
),
log_info
)
Expand Down
Expand Up @@ -18,11 +18,24 @@ class AssemblyMemberForm < Form
attribute :designation_mode, String
attribute :position, String
attribute :position_other, String
attribute :user_id, Integer
attribute :existing_user, Boolean, default: false

validates :full_name, :designation_date, presence: true
validates :designation_date, presence: true
validates :full_name, presence: true, unless: proc { |object| object.existing_user }
validates :position, inclusion: { in: Decidim::AssemblyMember::POSITIONS }
validates :position_other, presence: true, if: ->(form) { form.position == "other" }
validates :ceased_date, date: { after: :designation_date, allow_blank: true }
validates :user, presence: true, if: proc { |object| object.existing_user }

def map_model(model)
self.user_id = model.decidim_user_id
self.existing_user = user_id.present?
end

def user
@user ||= current_organization.users.find_by(id: user_id)
end

def positions_for_select
Decidim::AssemblyMember::POSITIONS.map do |position|
Expand Down
1 change: 1 addition & 0 deletions decidim-assemblies/app/models/decidim/assembly_member.rb
Expand Up @@ -9,6 +9,7 @@ class AssemblyMember < ApplicationRecord

POSITIONS = %w(president vice_president secretary other).freeze

belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User", optional: true
belongs_to :assembly, foreign_key: "decidim_assembly_id", class_name: "Decidim::Assembly"
alias participatory_space assembly

Expand Down
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Decidim
module Admin
#
# Decorator for assembly members
#
class AssemblyMemberPresenter < SimpleDelegator
def name
if user
"#{user.name} (#{Decidim::UserPresenter.new(user).nickname})"
else
full_name
end
end

def position
return position_other if __getobj__.position == "other"

I18n.t(__getobj__.position, scope: "decidim.admin.models.assembly_member.positions", default: "")
end
end
end
end
Expand Up @@ -11,6 +11,14 @@ def age

delegate :profile_url, :avatar_url, to: :user, allow_nil: true

def name
user ? user.name : full_name
end

def nickname
user.nickname if user
end

def personal_information
[
gender.presence,
Expand All @@ -24,5 +32,15 @@ def position

I18n.t(__getobj__.position, scope: "decidim.admin.models.assembly_member.positions", default: "")
end

private

def user
@user ||= begin
if (user = __getobj__.user.presence)
Decidim::UserPresenter.new(user)
end
end
end
end
end
Expand Up @@ -6,8 +6,21 @@
</div>

<div class="card-section">
<div class="row column">
<%= form.text_field :full_name, autofocus: true %>
<div class="user-fields">
<div class="row column">
<%= form.select :existing_user, [[t(".non_user"), false], [t(".existing_user"), true]], label: t(".user_type") %>
</div>

<div class="row column user-fields--full-name">
<%= form.text_field :full_name, autofocus: true %>
</div>

<div class="row column user-fields--user-picker">
<% prompt_options = { url: decidim_admin.users_organization_url, placeholder: t(".select_user") } %>
<%= form.autocomplete_select(:user_id, form.object.user.presence, { multiple: false }, prompt_options) do |user|
{ value: user.id, label: "#{user.name} (@#{user.nickname})" }
end %>
</div>
</div>

<div class="position-fields">
Expand Down
Expand Up @@ -59,12 +59,13 @@
</thead>
<tbody>
<% @assembly_members.each do |member| %>
<% member_presenter = Decidim::Admin::AssemblyMemberPresenter.new(member) %>
<tr>
<td>
<%= member.full_name %>
<%= member_presenter.name %>
</td>
<td>
<%= Decidim::AssemblyMemberPresenter.new(member).position %>
<%= member_presenter.position %>
</td>
<td>
<%= l member.designation_date, format: :datepicker %>
Expand Down
Expand Up @@ -7,21 +7,41 @@
<div class="author-data author-data--big">
<div class="author-data__main">
<div class="author author--flex">
<span class="author__avatar">
<%= image_tag asset_path("decidim/default-avatar.svg") %>
</span>
<div>
<div class="author__name--container">
<%= member_presenter.full_name %>
<% if (profile_url = member_presenter.profile_url) %>
<a href="<%= profile_url %>" class="author__avatar">
<%= image_tag member_presenter.avatar_url(:big) %>
</a>
<div>
<div class="author__name--container">
<a href="<%= profile_url %>" class="author__name">
<%= member_presenter.name %>
</a>
</div>
<% if (nickname = member_presenter.nickname) %>
<a href="<%= profile_url %>" class="author__nickname">
<%= nickname %>
</a>
<% end %>
</div>
</div>
<% else %>
<span class="author__avatar"><%= image_tag asset_path("decidim/default-avatar.svg") %></span>
<div>
<div class="author__name--container"><%= member_presenter.name %></div>
<% if (nickname = member_presenter.nickname) %>
<span class="author__nickname"><%= nickname %></span>
<% end %>
</div>
<% end %>
</div>
</div>
</div>
</div>
<div class="card__text card--picture-offset">
<div><small><strong><%= member_presenter.position %></strong></small></div>
<div class="text-small"><%= t(".desiganted_on") %> <strong> <%= l assembly_member.designation_date, format: :datepicker %></strong></div>
<div>
<small><strong><%= member_presenter.position %></strong></small>
</div>
<div class="text-small"><%= t(".desiganted_on") %>
<strong> <%= l assembly_member.designation_date, format: :datepicker %></strong></div>
<div class="text-small mt-s"><%= member_presenter.personal_information %></div>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions decidim-assemblies/config/locales/en.yml
Expand Up @@ -208,7 +208,11 @@ en:
slug_help: 'URL slugs are used to generate the URLs that point to this assembly. Only accepts letters, numbers and dashes, and must start with a letter. Example: %{url}'
assembly_members:
form:
existing_user: Existing user
non_user: Non user
select_a_position: Select a position
select_user: Select an user
user_type: User type
index:
filter:
all: All
Expand Down
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AssemblyMemberBelongsToUser < ActiveRecord::Migration[5.1]
def change
add_reference :decidim_assembly_members, :decidim_user, index: { name: "index_decidim_assembly_members_on_decidim_user_id" }
end
end
4 changes: 4 additions & 0 deletions decidim-assemblies/lib/decidim/assemblies/test/factories.rb
Expand Up @@ -128,5 +128,9 @@
trait :ceased do
ceased_date { Faker::Date.between(1.day.ago, 5.days.ago) }
end

trait :with_user do
user { create(:user, organization: assembly.organization) }
end
end
end
11 changes: 11 additions & 0 deletions decidim-assemblies/spec/commands/create_assembly_member_spec.rb
Expand Up @@ -7,12 +7,14 @@ module Decidim::Assemblies
subject { described_class.new(form, current_user, assembly) }

let(:assembly) { create(:assembly) }
let(:user) { nil }
let!(:current_user) { create :user, :confirmed, organization: assembly.organization }
let(:form) do
instance_double(
Admin::AssemblyMemberForm,
invalid?: invalid,
full_name: "Full name",
user: user,
attributes: {
weight: 0,
full_name: "Full name",
Expand Down Expand Up @@ -63,6 +65,15 @@ module Decidim::Assemblies
action_log = Decidim::ActionLog.last
expect(action_log.version).to be_present
end

context "with an existing user in the platform" do
let!(:user) { create(:user, organization: assembly.organization) }

it "sets the user" do
subject.call
expect(assembly_member.user).to eq user
end
end
end
end
end
14 changes: 13 additions & 1 deletion decidim-assemblies/spec/commands/update_assembly_member_spec.rb
Expand Up @@ -7,14 +7,16 @@ module Decidim::Assemblies
subject { described_class.new(form, assembly_member) }

let!(:assembly) { create(:assembly) }
let(:assembly_member) { create :assembly_member, assembly: assembly }
let(:assembly_member) { create :assembly_member, :with_user, assembly: assembly }
let!(:current_user) { create :user, :confirmed, organization: assembly.organization }
let(:user) { nil }
let(:form) do
instance_double(
Admin::AssemblyMemberForm,
invalid?: invalid,
current_user: current_user,
full_name: "New name",
user: user,
attributes: {
weight: 0,
full_name: "New name",
Expand Down Expand Up @@ -60,6 +62,16 @@ module Decidim::Assemblies
action_log = Decidim::ActionLog.last
expect(action_log.version).to be_present
end

context "when is an existing user in the platform" do
let!(:user) { create :user, organization: assembly.organization }

it "sets the user" do
expect do
subject.call
end.to change { assembly_member.reload && assembly_member.user }.from(assembly_member.user).to(user)
end
end
end
end
end