decidim-assemblies 0.8.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +1 -1
  3. data/app/assets/javascripts/decidim/assemblies/admin/assemblies.js.es6 +11 -9
  4. data/app/commands/decidim/assemblies/admin/create_assembly_admin.rb +93 -0
  5. data/app/commands/decidim/assemblies/admin/update_assembly_admin.rb +42 -0
  6. data/app/controllers/decidim/assemblies/admin/assemblies_controller.rb +2 -4
  7. data/app/controllers/decidim/assemblies/admin/assembly_user_roles_controller.rb +99 -0
  8. data/app/forms/decidim/assemblies/admin/assembly_user_role_form.rb +30 -0
  9. data/app/models/decidim/assemblies/abilities/admin/admin_ability.rb +1 -0
  10. data/app/models/decidim/assemblies/abilities/admin/assembly_admin_ability.rb +54 -0
  11. data/app/models/decidim/assemblies/abilities/admin/assembly_collaborator_ability.rb +25 -0
  12. data/app/models/decidim/assemblies/abilities/admin/assembly_moderator_ability.rb +33 -0
  13. data/app/models/decidim/assemblies/abilities/admin/assembly_role_ability.rb +65 -0
  14. data/app/models/decidim/assemblies/abilities/assembly_admin_ability.rb +15 -0
  15. data/app/models/decidim/assemblies/abilities/assembly_collaborator_ability.rb +15 -0
  16. data/app/models/decidim/assemblies/abilities/assembly_moderator_ability.rb +15 -0
  17. data/app/models/decidim/assemblies/abilities/assembly_role_ability.rb +51 -0
  18. data/app/models/decidim/assembly.rb +1 -0
  19. data/app/models/decidim/assembly_user_role.rb +22 -0
  20. data/app/queries/decidim/assemblies/assemblies_with_user_role.rb +48 -0
  21. data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +1 -1
  22. data/app/views/decidim/assemblies/admin/assembly_user_roles/_form.html.erb +22 -0
  23. data/app/views/decidim/assemblies/admin/assembly_user_roles/edit.html.erb +7 -0
  24. data/app/views/decidim/assemblies/admin/assembly_user_roles/index.html.erb +65 -0
  25. data/app/views/decidim/assemblies/admin/assembly_user_roles/new.html.erb +7 -0
  26. data/app/views/decidim/assemblies/assemblies/show.html.erb +5 -0
  27. data/app/views/layouts/decidim/admin/assembly.html.erb +19 -14
  28. data/config/locales/ca.yml +28 -1
  29. data/config/locales/en.yml +28 -0
  30. data/config/locales/es.yml +32 -5
  31. data/config/locales/eu.yml +28 -0
  32. data/config/locales/fi.yml +66 -38
  33. data/config/locales/fr.yml +28 -0
  34. data/config/locales/gl.yml +165 -0
  35. data/config/locales/it.yml +30 -2
  36. data/config/locales/nl.yml +28 -0
  37. data/config/locales/pl.yml +28 -0
  38. data/config/locales/pt-BR.yml +165 -0
  39. data/config/locales/pt.yml +48 -20
  40. data/config/locales/sv.yml +165 -0
  41. data/db/migrate/20180109105917_add_assembly_user_roles.rb +17 -0
  42. data/lib/decidim/assemblies/admin_engine.rb +11 -2
  43. data/lib/decidim/assemblies/engine.rb +9 -0
  44. data/lib/decidim/assemblies/participatory_space.rb +7 -2
  45. data/lib/decidim/assemblies/test/factories.rb +36 -0
  46. data/lib/decidim/assemblies/version.rb +1 -1
  47. metadata +34 -12
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Abilities
6
+ module Admin
7
+ # Defines the abilities for an assembly admin user, whatever they role. Intended to be used
8
+ # with `cancancan`.
9
+ class AssemblyRoleAbility
10
+ include CanCan::Ability
11
+
12
+ def initialize(user, context)
13
+ @user = user
14
+ @context = context
15
+
16
+ # Define abilities if the user is not an admin and has at least one assembly to manage.
17
+ if not_admin? && has_manageable_assemblies?
18
+ define_abilities
19
+
20
+ define_assembly_abilities if current_assembly && can_manage_assembly?(current_assembly)
21
+ end
22
+ end
23
+
24
+ # Grant access to admin panel by default.
25
+ def define_abilities
26
+ can :read, :admin_dashboard
27
+ end
28
+
29
+ def define_assembly_abilities; end
30
+
31
+ # Abstract: A subclass must define this method returning a valid role.
32
+ # See ParticipatoryProcessUserRoles::ROLES for more information.
33
+ def role
34
+ raise "Needs implementation"
35
+ end
36
+
37
+ # Whether the user is an admin or not.
38
+ def not_admin?
39
+ @user && !@user.admin?
40
+ end
41
+
42
+ # Returns a collection of assemblies where the given user has the
43
+ # specific role privilege.
44
+ def assemblies_with_role_privileges
45
+ @assemblies ||= Decidim::Assemblies::AssembliesWithUserRole.for(@user, role)
46
+ end
47
+
48
+ # Whether the user has at least one assembly to manage or not.
49
+ def has_manageable_assemblies?
50
+ assemblies_with_role_privileges.any?
51
+ end
52
+
53
+ # Whether the user can manage the given assembly or not.
54
+ def can_manage_assembly?(assembly)
55
+ assemblies_with_role_privileges.include? assembly
56
+ end
57
+
58
+ def current_assembly
59
+ @current_assembly ||= @context[:current_participatory_space]
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Abilities
6
+ # Defines the abilities for an assembly admin user.
7
+ # Intended to be used with `cancancan`.
8
+ class AssemblyAdminAbility < Decidim::Assemblies::Abilities::AssemblyRoleAbility
9
+ def role
10
+ :admin
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Abilities
6
+ # Defines the abilities for an assembly collaborator user
7
+ # Intended to be used with `cancancan`.
8
+ class AssemblyCollaboratorAbility < Decidim::Assemblies::Abilities::AssemblyRoleAbility
9
+ def role
10
+ :collaborator
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Abilities
6
+ # Defines the abilities for an assembly moderator user
7
+ # Intended to be used with `cancancan`.
8
+ class AssemblyModeratorAbility < Decidim::Assemblies::Abilities::AssemblyRoleAbility
9
+ def role
10
+ :moderator
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ module Abilities
6
+ # Defines the abilities for any user that can manage assemblies (whatever their role).
7
+ # Intended to be used with `cancancan`.
8
+ class AssemblyRoleAbility
9
+ include CanCan::Ability
10
+
11
+ attr_reader :user
12
+
13
+ def initialize(user, context)
14
+ @user = user
15
+ @context = context
16
+
17
+ define_abilities if not_admin? && has_manageable_assemblies?
18
+ end
19
+
20
+ def define_abilities
21
+ can :read, :admin_dashboard
22
+ can :read, Assembly
23
+ end
24
+
25
+ private
26
+
27
+ # Whether the user is an admin or not.
28
+ def not_admin?
29
+ @user && !@user.admin?
30
+ end
31
+
32
+ # Abstract: A subclass must define this method returning a valid role.
33
+ # See ParticipatoryProcessUserRoles::ROLES for more information.
34
+ def role
35
+ raise "Needs implementation"
36
+ end
37
+
38
+ # Returns a collection of Participatory assemblies where the given user has the
39
+ # specific role privilege.
40
+ def assemblies_with_role_privileges
41
+ @assemblies ||= Decidim::Assemblies::AssembliesWithUserRole.for(@user, role)
42
+ end
43
+
44
+ # Whether the user has at least one assembly to manage or not.
45
+ def has_manageable_assemblies?
46
+ assemblies_with_role_privileges.any?
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -9,6 +9,7 @@ module Decidim
9
9
  include Decidim::Participable
10
10
  include Decidim::Publicable
11
11
  include Decidim::Scopable
12
+ include Decidim::Followable
12
13
 
13
14
  belongs_to :organization,
14
15
  foreign_key: "decidim_organization_id",
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # Defines a relation between a user and an assembly, and what kind of relation
5
+ # does the user have.
6
+ class AssemblyUserRole < ApplicationRecord
7
+ belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User", optional: true
8
+ belongs_to :assembly, foreign_key: "decidim_assembly_id", class_name: "Decidim::Assembly", optional: true
9
+
10
+ ROLES = %w(admin collaborator moderator).freeze
11
+ validates :role, inclusion: { in: ROLES }, uniqueness: { scope: [:user, :assembly] }
12
+ validate :user_and_assembly_same_organization
13
+
14
+ private
15
+
16
+ # Private: check if the process and the user have the same organization
17
+ def user_and_assembly_same_organization
18
+ return if !assembly || !user
19
+ errors.add(:assembly, :invalid) unless user.organization == assembly.organization
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Assemblies
5
+ # A class used to find the Assemblies that the given user has
6
+ # the specific role privilege.
7
+ class AssembliesWithUserRole < Rectify::Query
8
+ # Syntactic sugar to initialize the class and return the queried objects.
9
+ #
10
+ # user - a User that needs to find which assemblies can manage
11
+ # role - (optional) a Symbol to specify the role privilege
12
+ def self.for(user, role = :any)
13
+ new(user, role).query
14
+ end
15
+
16
+ # Initializes the class.
17
+ #
18
+ # user - a User that needs to find which assemblies can manage
19
+ # role - (optional) a Symbol to specify the role privilege
20
+ def initialize(user, role = :any)
21
+ @user = user
22
+ @role = role
23
+ end
24
+
25
+ # Finds the Assemblies that the given user has role privileges.
26
+ # If the special role ':any' is provided it returns all assemblies where
27
+ # the user has some kind of role privilege.
28
+ #
29
+ # Returns an ActiveRecord::Relation.
30
+ def query
31
+ # Admin users have all role privileges for all organization assemblies
32
+ return Assemblies::OrganizationAssemblies.new(user.organization).query if user.admin?
33
+
34
+ Assembly.where(id: assembly_ids)
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :user, :role
40
+
41
+ def assembly_ids
42
+ user_roles = AssemblyUserRole.where(user: user) if role == :any
43
+ user_roles = AssemblyUserRole.where(user: user, role: role) if role != :any
44
+ user_roles.pluck(:decidim_assembly_id)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -72,7 +72,7 @@
72
72
  </div>
73
73
 
74
74
  <div class="row column">
75
- <%= form.scopes_select :scope_id, prompt: t("decidim.scopes.global"), remote_path: decidim.scopes_search_path %>
75
+ <%= scopes_picker_field form, :scope_id, root: nil %>
76
76
  </div>
77
77
 
78
78
  <div class="row column">
@@ -0,0 +1,22 @@
1
+ <div class="card">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= title %>
5
+ </h2>
6
+ </div>
7
+
8
+ <div class="card-section">
9
+ <div class="row">
10
+ <div class="columns xlarge-4">
11
+ <%= form.text_field :name, readonly: @form.persisted? %>
12
+ </div>
13
+ <div class="columns xlarge-4">
14
+ <%= form.email_field :email, readonly: @form.persisted? %>
15
+ </div>
16
+ <div class="columns xlarge-4">
17
+ <%= form.label :role %>
18
+ <%= select :assembly_user_role, :role, @form.roles, include_blank: false %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= decidim_form_for(@form, url: assembly_user_role_path(@user_role.assembly, @user_role), html: { class: "form edit_assembly_user_roles" }) do |f| %>
2
+ <%= render partial: 'form', object: f, locals: { title: t('assembly_user_roles.edit.title', scope: "decidim.admin") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t("assembly_user_roles.edit.update", scope: "decidim.admin") %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,65 @@
1
+ <div class='card' id="assembly_admins">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= t("assembly_user_roles.index.assembly_admins_title", scope: "decidim.admin") %>
5
+ <% if can? :create, Decidim::AssemblyUserRole %>
6
+ <%= link_to t("actions.new", scope: "decidim.admin", name: t("models.assembly_user_role.name", scope: "decidim.admin")), new_assembly_user_role_path(current_assembly), class: 'button tiny button--title new' %>
7
+ <% end %>
8
+ </h2>
9
+ </div>
10
+
11
+ <div class="card-section">
12
+ <div class="table-scroll">
13
+ <table class="stack">
14
+ <thead>
15
+ <tr>
16
+ <th><%= t("models.assembly_user_role.fields.name", scope: "decidim.admin") %></th>
17
+ <th><%= t("models.assembly_user_role.fields.email", scope: "decidim.admin") %></th>
18
+ <th><%= t("models.user.fields.invitation_sent_at", scope: "decidim.admin") %></th>
19
+ <th><%= t("models.user.fields.invitation_accepted_at", scope: "decidim.admin") %></th>
20
+ <th><%= t("models.assembly_user_role.fields.role", scope: "decidim.admin") %></th>
21
+ <th class="actions"></th>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ <% @assembly_user_roles.each do |role| %>
26
+ <tr>
27
+ <td>
28
+ <%= role.user.name %><br />
29
+ </td>
30
+ <td>
31
+ <%= role.user.email %><br />
32
+ </td>
33
+ <td>
34
+ <% if role.user.invitation_sent_at %>
35
+ <%= l role.user.invitation_sent_at, format: :short %>
36
+ <% end %>
37
+ </td>
38
+ <td>
39
+ <% if role.user.invitation_accepted_at %>
40
+ <%= l role.user.invitation_accepted_at, format: :short %>
41
+ <% end %>
42
+ </td>
43
+ <td>
44
+ <%= t("#{role.role}", scope: "decidim.admin.models.assembly_user_role.roles") %><br />
45
+ </td>
46
+ <td class="table-list__actions">
47
+ <% if can?(:invite, role) && role.user.invited_to_sign_up? %>
48
+ <%= icon_link_to "reload", resend_invitation_assembly_user_role_path(current_assembly, role), t("actions.resend_invitation", scope: "decidim.admin"), class: "resend-invitation", method: :post %>
49
+ <% end %>
50
+
51
+ <% if can? :update, role %>
52
+ <%= icon_link_to "pencil", edit_assembly_user_role_path(current_assembly, role), t("actions.edit", scope: "decidim.admin"), class: "action-icon--edit" %>
53
+ <% end %>
54
+
55
+ <% if can? :destroy, role %>
56
+ <%= icon_link_to "circle-x", assembly_user_role_path(current_assembly, role), t("actions.destroy", scope: "decidim.admin"), class: "action-icon--remove", method: :delete, data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
57
+ <% end %>
58
+ </td>
59
+ </tr>
60
+ <% end %>
61
+ </tbody>
62
+ </table>
63
+ </div>
64
+ </div>
65
+ </div>
@@ -0,0 +1,7 @@
1
+ <%= decidim_form_for(@form, html: { class: "form new_assembly_user_role" }) do |f| %>
2
+ <%= render partial: 'form', object: f, locals: { title: t('assembly_user_roles.new.title', scope: "decidim.admin") } %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t("assembly_user_roles.new.create", scope: "decidim.admin") %>
6
+ </div>
7
+ <% end %>
@@ -18,6 +18,11 @@
18
18
  <%= attachments_for current_participatory_space %>
19
19
  </div>
20
20
  <div class="section columns medium-5 mediumlarge-4 large-3">
21
+ <div class="card extra">
22
+ <div class="card__content">
23
+ <%= render partial: "decidim/shared/follow_button", locals: { followable: current_participatory_space } %>
24
+ </div>
25
+ </div>
21
26
  <div class="card extra definition-data">
22
27
  <% if translated_attribute(current_participatory_space.meta_scope).present? %>
23
28
  <div class="definition-data__item scope">
@@ -1,18 +1,18 @@
1
1
  <% content_for :secondary_nav do %>
2
2
  <div class="secondary-nav secondary-nav--subnav">
3
3
  <ul>
4
- <% if can? :update, current_assembly %>
5
- <li <% if is_active_link?(decidim_admin_assemblies.edit_assembly_path(current_assembly)) %> class="is-active" <% end %>>
6
- <%= aria_selected_link_to t("info", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.edit_assembly_path(current_assembly) %>
4
+ <% if can? :update, current_participatory_space %>
5
+ <li <% if is_active_link?(decidim_admin_assemblies.edit_assembly_path(current_participatory_space)) %> class="is-active" <% end %>>
6
+ <%= aria_selected_link_to t("info", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.edit_assembly_path(current_participatory_space) %>
7
7
  </li>
8
8
  <% end %>
9
9
  <% if can? :read, Decidim::Feature %>
10
- <li <% if is_active_link?(decidim_admin_assemblies.features_path(current_assembly)) %> class="is-active" <% end %>>
11
- <%= aria_selected_link_to t("features", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.features_path(current_assembly) %>
10
+ <li <% if is_active_link?(decidim_admin_assemblies.features_path(current_participatory_space)) %> class="is-active" <% end %>>
11
+ <%= aria_selected_link_to t("features", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.features_path(current_participatory_space) %>
12
12
  <ul>
13
- <% current_assembly.features.each do |feature| %>
13
+ <% current_participatory_space.features.each do |feature| %>
14
14
  <% if feature.manifest.admin_engine %>
15
- <li <% if is_active_link?(manage_feature_path(feature)) || is_active_link?(decidim_admin_assemblies.edit_feature_path(current_assembly, feature)) || is_active_link?(decidim_admin_assemblies.edit_feature_permissions_path(current_assembly, feature)) %> class="is-active" <% end %>>
15
+ <li <% if is_active_link?(manage_feature_path(feature)) || is_active_link?(decidim_admin_assemblies.edit_feature_path(current_participatory_space, feature)) || is_active_link?(decidim_admin_assemblies.edit_feature_permissions_path(current_participatory_space, feature)) %> class="is-active" <% end %>>
16
16
  <%= link_to manage_feature_path(feature) do %>
17
17
  <%= translated_attribute feature.name %>
18
18
  <% if feature.primary_stat.present? %>
@@ -26,18 +26,23 @@
26
26
  </li>
27
27
  <% end %>
28
28
  <% if can? :read, Decidim::Category %>
29
- <li <% if is_active_link?(decidim_admin_assemblies.categories_path(current_assembly)) %> class="is-active" <% end %>>
30
- <%= aria_selected_link_to t("categories", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.categories_path(current_assembly) %>
29
+ <li <% if is_active_link?(decidim_admin_assemblies.categories_path(current_participatory_space)) %> class="is-active" <% end %>>
30
+ <%= aria_selected_link_to t("categories", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.categories_path(current_participatory_space) %>
31
31
  </li>
32
32
  <% end %>
33
33
  <% if can? :read, Decidim::Attachment %>
34
- <li <% if is_active_link?(decidim_admin_assemblies.assembly_attachments_path(current_assembly)) %> class="is-active" <% end %>>
35
- <%= aria_selected_link_to t("attachments", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.assembly_attachments_path(current_assembly) %>
34
+ <li <% if is_active_link?(decidim_admin_assemblies.assembly_attachments_path(current_participatory_space)) %> class="is-active" <% end %>>
35
+ <%= aria_selected_link_to t("attachments", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.assembly_attachments_path(current_participatory_space) %>
36
+ </li>
37
+ <% end %>
38
+ <% if can? :read, Decidim::AssemblyUserRole %>
39
+ <li <% if is_active_link?(decidim_admin_assemblies.assembly_user_roles_path(current_participatory_space)) %> class="is-active" <% end %>>
40
+ <%= aria_selected_link_to t("assembly_admins", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.assembly_user_roles_path(current_participatory_space) %>
36
41
  </li>
37
42
  <% end %>
38
43
  <% if can? :read, Decidim::Moderation %>
39
- <li <% if is_active_link?(decidim_admin_assemblies.moderations_path(current_assembly)) %> class="is-active" <% end %>>
40
- <%= aria_selected_link_to t("moderations", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.moderations_path(current_assembly) %>
44
+ <li <% if is_active_link?(decidim_admin_assemblies.moderations_path(current_participatory_space)) %> class="is-active" <% end %>>
45
+ <%= aria_selected_link_to t("moderations", scope: "decidim.admin.menu.assemblies_submenu"), decidim_admin_assemblies.moderations_path(current_participatory_space) %>
41
46
  </li>
42
47
  <% end %>
43
48
  </ul>
@@ -47,7 +52,7 @@
47
52
  <%= render "layouts/decidim/admin/application" do %>
48
53
  <div class="process-title">
49
54
  <div class="process-title-content">
50
- <%= translated_attribute(current_assembly.title) %>
55
+ <%= translated_attribute(current_participatory_space.title) %>
51
56
  </div>
52
57
  </div>
53
58
  <%= yield %>
@@ -1,4 +1,3 @@
1
- ---
2
1
  ca:
3
2
  activemodel:
4
3
  attributes:
@@ -60,9 +59,27 @@ ca:
60
59
  destroy:
61
60
  error: S'ha produït un error en despublicar aquesta assemblea.
62
61
  success: Assemblea despublicada amb èxit.
62
+ assembly_user_roles:
63
+ create:
64
+ error: S'ha produït un error en afegir un usuari per a aquesta assamblea.
65
+ success: L'usuari s'ha creat correctament per a aquesta assemblea.
66
+ destroy:
67
+ success: S'ha destruït l'usuari amb èxit per a aquesta assemblea.
68
+ edit:
69
+ title: Actualitza l'usuari de l'assemblea.
70
+ update: Actualitza
71
+ index:
72
+ assembly_admins_title: Usuaris de l'assemblea
73
+ new:
74
+ create: Crea
75
+ title: Nou usuari de l'assemblea.
76
+ update:
77
+ error: S'ha produït un error en l'actualització d'un usuari per a aquesta assemblea.
78
+ success: L'usuari s'ha actualitzat correctament per a aquesta assemblea.
63
79
  menu:
64
80
  assemblies: Assemblees
65
81
  assemblies_submenu:
82
+ assembly_admins: Usuaris de l'assemblea
66
83
  attachments: Adjunts
67
84
  categories: Categories
68
85
  features: Funcionalitats
@@ -76,6 +93,16 @@ ca:
76
93
  published: Publicat
77
94
  title: Grup de processos participatius
78
95
  name: Assemblea
96
+ assembly_user_role:
97
+ fields:
98
+ email: Correu electrònic
99
+ name: Nom
100
+ role: Rol
101
+ name: Usuari de l'assemblea
102
+ roles:
103
+ admin: Administrador
104
+ collaborator: Col·laborador
105
+ moderator: Moderador
79
106
  titles:
80
107
  assemblies: Assemblees
81
108
  assemblies: