decidim-meetings 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d1998702c63adcee35cf6ba712d2f8ea986f05bd
4
- data.tar.gz: bd7b21aa2f323b62e7b195c42eae8238d3e28e15
3
+ metadata.gz: 8e19fd2bced64fedffeeb7e466c5afcbcad2b814
4
+ data.tar.gz: 8fadc5f684e7324c085da6f956923b66eb7c1818
5
5
  SHA512:
6
- metadata.gz: 48441620d5786ab9855fecc90165b6cd87a0b8fbf1ddf7d0b90391f4fa8de14bbbad538bc015990e6c56c05d2149748887b23012cd55cdf2ca864d5552738626
7
- data.tar.gz: 289779e9f898af0c999b83ff61ae254b481d721cd3682c3f243f3734fb64beada153d64480bd4b116ce8d696de04ca7879f4602aceea72801a5780cc5d8c5b0c
6
+ metadata.gz: 7784edad8cef64c16f94fd8c94c175a23b61361beb7dafa50cf4b1ec8fc0aec0c86005578923baf7dce7c4bc2c13a55357375c21263926701a5c226fbe44fc1f
7
+ data.tar.gz: 17e3efaa9f8d2e42642811a6b0336ae04409344f7e6b0ec19a12a18f3171b5e386432f884017674c8a30625bebce40e4b543c3b331728e6321cf4fc37ddca5dd
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
1
  # frozen_string_literal: true
2
- require "decidim/common_rake"
2
+ require "decidim/dev/common_rake"
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36.02 36.02"><path d="M693.07,543.84a18,18,0,1,1,18-18A18,18,0,0,1,693.07,543.84Zm0-34a16,16,0,1,0,16,16A16,16,0,0,0,693.07,509.83Z" transform="translate(-675.07 -507.83)"/><path d="M693.07,526.93a4.1,4.1,0,1,1,4.1-4.1A4.1,4.1,0,0,1,693.07,526.93Zm0-6.19a2.1,2.1,0,1,0,2.1,2.1A2.1,2.1,0,0,0,693.07,520.74Z" transform="translate(-675.07 -507.83)"/><path d="M693.07,536.65a1,1,0,0,1-.67-0.26c-0.29-.26-7.11-6.5-7.11-14a7.78,7.78,0,0,1,15.57,0c0,7.46-6.82,13.71-7.11,14A1,1,0,0,1,693.07,536.65Zm0-20a5.79,5.79,0,0,0-5.78,5.78c0,5.29,4.13,10.11,5.78,11.82,1.65-1.72,5.78-6.54,5.78-11.82A5.79,5.79,0,0,0,693.07,516.64Z" transform="translate(-675.07 -507.83)"/></svg>
@@ -23,6 +23,8 @@ module Decidim
23
23
 
24
24
  def create_meeting
25
25
  Meeting.create!(
26
+ scope: @form.scope,
27
+ category: @form.category,
26
28
  title: @form.title,
27
29
  short_description: @form.short_description,
28
30
  description: @form.description,
@@ -28,6 +28,8 @@ module Decidim
28
28
 
29
29
  def update_meeting
30
30
  @meeting.update_attributes!(
31
+ scope: @form.scope,
32
+ category: @form.category,
31
33
  title: @form.title,
32
34
  short_description: @form.short_description,
33
35
  description: @form.description,
@@ -2,23 +2,47 @@
2
2
 
3
3
  module Decidim
4
4
  module Meetings
5
- # This controller is the abstract class from which all other controllers of
6
- # this engine inherit.
7
- #
8
- # Note that it inherits from `Decidim::Features::BaseController`, which
9
- # override its layout and provide all kinds of useful methods.
5
+ # Exposes the meeting resource so users can view them
10
6
  class MeetingsController < Decidim::Meetings::ApplicationController
7
+ include FilterResource
8
+
11
9
  helper_method :meetings, :meeting
12
10
 
11
+ def index; end
12
+
13
13
  private
14
14
 
15
15
  def meetings
16
- @meetings ||= Meeting.where(decidim_feature_id: current_feature.id).order(start_time: :asc)
16
+ @meetings ||= search.results
17
17
  end
18
18
 
19
19
  def meeting
20
20
  @meeting ||= meetings.find(params[:id])
21
21
  end
22
+
23
+ def search_klass
24
+ MeetingSearch
25
+ end
26
+
27
+ def default_search_params
28
+ {
29
+ page: params[:page],
30
+ per_page: 12
31
+ }
32
+ end
33
+
34
+ def default_filter_params
35
+ {
36
+ order_start_time: "asc",
37
+ search_text: "",
38
+ scope_id: "",
39
+ category_id: ""
40
+ }
41
+ end
42
+
43
+ def context_params
44
+ { feature: current_feature, organization: current_organization }
45
+ end
22
46
  end
23
47
  end
24
48
  end
@@ -14,6 +14,8 @@ module Decidim
14
14
  attribute :address, String
15
15
  attribute :start_time, DateTime
16
16
  attribute :end_time, DateTime
17
+ attribute :decidim_scope_id, Integer
18
+ attribute :decidim_category_id, Integer
17
19
 
18
20
  validates :title, translatable_presence: true
19
21
  validates :short_description, translatable_presence: true
@@ -24,6 +26,18 @@ module Decidim
24
26
  validates :end_time, presence: true, date: { after: :start_time }
25
27
 
26
28
  validates :current_feature, presence: true
29
+ validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? }
30
+ validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
31
+
32
+ def scope
33
+ return unless current_feature
34
+ @scope ||= current_feature.scopes.where(id: decidim_scope_id).first
35
+ end
36
+
37
+ def category
38
+ return unless current_feature
39
+ @category ||= current_feature.categories.where(id: decidim_category_id).first
40
+ end
27
41
  end
28
42
  end
29
43
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Meetings
4
+ # Custom helpers, scoped to the meetings engine.
5
+ #
6
+ module ApplicationHelper
7
+ include PaginateHelper
8
+ end
9
+ end
10
+ end
@@ -5,8 +5,25 @@ module Decidim
5
5
  # title, description and any other useful information to render a custom meeting.
6
6
  class Meeting < Meetings::ApplicationRecord
7
7
  belongs_to :feature, foreign_key: "decidim_feature_id", class_name: Decidim::Feature
8
-
8
+ belongs_to :scope, foreign_key: "decidim_scope_id", class_name: Decidim::Scope
9
+ belongs_to :category, foreign_key: "decidim_category_id", class_name: Decidim::Category
10
+ has_one :organization, through: :feature
9
11
  validates :title, presence: true
12
+
13
+ validate :scope_belongs_to_organization
14
+ validate :category_belongs_to_organization
15
+
16
+ private
17
+
18
+ def scope_belongs_to_organization
19
+ return unless scope
20
+ errors.add(:scope, :invalid) unless feature.scopes.where(id: scope.id).exists?
21
+ end
22
+
23
+ def category_belongs_to_organization
24
+ return unless category
25
+ errors.add(:category, :invalid) unless feature.categories.where(id: category.id).exists?
26
+ end
10
27
  end
11
28
  end
12
29
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ module Decidim
3
+ module Meetings
4
+ # This class handles search and filtering of meetings. Needs a
5
+ # `current_feature` param with a `Decidim::Feature` in order to
6
+ # find the meetings.
7
+ class MeetingSearch < ResourceSearch
8
+ # Public: Initializes the service.
9
+ # feature - A Decidim::Feature to get the meetings from.
10
+ # page - The page number to paginate the results.
11
+ # per_page - The number of proposals to return per page.
12
+ def initialize(options = {})
13
+ super(Meeting.all, options)
14
+ end
15
+
16
+ # Handle the search_text filter
17
+ def search_search_text
18
+ query
19
+ .where(localized_search_text_in(:title), text: "%#{search_text}%")
20
+ .or(query.where(localized_search_text_in(:description), text: "%#{search_text}%"))
21
+ .or(query.where(localized_search_text_in(:short_description), text: "%#{search_text}%"))
22
+ end
23
+
24
+ # Handle the order_start_time filter
25
+ def search_order_start_time
26
+ query.order(start_time: order_start_time)
27
+ end
28
+
29
+ # Handle the scope_id filter
30
+ def search_scope_id
31
+ query.where(decidim_scope_id: scope_id)
32
+ end
33
+
34
+ private
35
+
36
+ # Internal: builds the needed query to search for a text in the organization's
37
+ # available locales. Note that it is intended to be used as follows:
38
+ #
39
+ # Example:
40
+ # Resource.where(localized_search_text_for(:title, text: "my_query"))
41
+ #
42
+ # The Hash with the `:text` key is required or it won't work.
43
+ def localized_search_text_in(field)
44
+ options[:organization].available_locales.map { |l| "#{field} ->> '#{l}' ILIKE :text" }.join(" OR ")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -11,11 +11,11 @@
11
11
  </div>
12
12
 
13
13
  <div class="field" >
14
- <%= form.translated :editor, :location %>
14
+ <%= form.translated :text_area, :location %>
15
15
  </div>
16
16
 
17
17
  <div class="field" >
18
- <%= form.translated :editor, :location_hints %>
18
+ <%= form.translated :text_area, :location_hints %>
19
19
  </div>
20
20
 
21
21
  <div class="field" >
@@ -30,3 +30,10 @@
30
30
  <%= form.datetime_field :end_time %>
31
31
  </div>
32
32
 
33
+ <div class="field" >
34
+ <%= form.collection_select :decidim_scope_id, current_organization.scopes, :id, :name, include_blank: true %>
35
+ </div>
36
+
37
+ <div class="field" >
38
+ <%= form.categories_select :decidim_category_id, current_participatory_process.categories, prompt: "", disable_parents: false %>
39
+ </div>
@@ -0,0 +1,24 @@
1
+ <%= filter_form_for filter do |form| %>
2
+ <div class="filters__section">
3
+ <div class="filters__search">
4
+ <div class="input-group">
5
+ <%= form.search_field :search_text, label: false, class: "input-group-field", placeholder: t('.search') %>
6
+ <div class="input-group-button">
7
+ <button type="submit" class="button button--muted">
8
+ <%= icon "magnifying-glass", aria_label: t('.search') %>
9
+ </button>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ </div>
14
+
15
+ <%= form.collection_radio_buttons :order_start_time, [["asc", t('.ascendent')], ["desc", t('.descendent')]], :first, :last, legend_title: t('.date') %>
16
+
17
+ <% if current_organization.scopes.any? %>
18
+ <%= form.collection_check_boxes :scope_id, current_organization.scopes, lambda {|scope| scope.id.to_s}, :name, legend_title: t('.scopes') %>
19
+ <% end %>
20
+
21
+ <% if current_feature.categories.any? %>
22
+ <%= form.categories_select :category_id, current_feature.categories, legend_title: t('.category'), disable_parents: false, label: false, include_blank: true %>
23
+ <% end %>
24
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <div class="row small-up-1 medium-up-2 card-grid">
2
+ <% meetings.each do |meeting| %>
3
+ <div class="column">
4
+ <article class="card card--meeting">
5
+ <div class="card__content">
6
+ <%= link_to meeting, class: "card__link" do %>
7
+ <h5 class="card__title"><%= translated_attribute meeting.title %></h5>
8
+ <% end %>
9
+ <div class="card__datetime">
10
+ <div class="card__datetime__date">
11
+ <%= l meeting.start_time, format: "%d" %> <span class="card__datetime__month"><%= l meeting.start_time, format: "%B" %></span>
12
+ </div>
13
+ <div class="card__datetime__time">
14
+ <%= meeting.start_time.strftime("%H:%M") %> - <%= meeting.end_time.strftime("%H:%M") %>
15
+ </div>
16
+ </div>
17
+ <%== translated_attribute meeting.short_description %>
18
+ <%= render partial: "tags", locals: { meeting: meeting } %>
19
+ <div class="address card__extra">
20
+ <div class="address__icon">
21
+ <%= icon "meetings", remove_icon_class: true, width: 40, height: 70 %>
22
+ </div>
23
+ <%= render partial: 'address_details', locals: { meeting: meeting } %>
24
+ </div>
25
+ </div>
26
+ </article>
27
+ </div>
28
+ <% end %>
29
+ </div>
30
+ <%= decidim_paginate meetings, order_start_time: params[:order_start_time], scope_id: params[:scope_id] %>
@@ -0,0 +1,10 @@
1
+ <% if meeting.category.present? || meeting.scope.present? %>
2
+ <ul class="tags tags--meeting" >
3
+ <% if meeting.category.present? %>
4
+ <li><%= link_to translated_attribute(meeting.category.name), decidim_meetings.meetings_path(filter: { category_id: meeting.category.id }) %></li>
5
+ <% end %>
6
+ <% if meeting.scope.present? %>
7
+ <li><%= link_to meeting.scope.name, decidim_meetings.meetings_path(filter: { scope_id: [meeting.scope.id] }) %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
@@ -1,30 +1,12 @@
1
1
  <% content_for(:title, t(".title")) %>
2
2
 
3
- <div class="row small-up-1 medium-up-2 large-up-3 card-grid">
4
- <% meetings.each do |meeting| %>
5
- <div class="column">
6
- <article class="card card--meeting">
7
- <div class="card__content">
8
- <%= link_to meeting, class: "card__link" do %>
9
- <h5 class="card__title"><%= translated_attribute meeting.title %></h5>
10
- <% end %>
11
- <div class="card__datetime">
12
- <div class="card__datetime__date">
13
- <%= l meeting.start_time, format: "%d" %> <span class="card__datetime__month"><%= l meeting.start_time, format: "%B" %></span>
14
- </div>
15
- <div class="card__datetime__time">
16
- <%= meeting.start_time.strftime("%H:%M") %> - <%= meeting.end_time.strftime("%H:%M") %>
17
- </div>
18
- </div>
19
- <%== translated_attribute meeting.description %>
20
- <div class="address card__extra">
21
- <div class="address__icon">
22
- <%= icon "meetings", removeIconClass: true, width: 40, height: 70 %>
23
- </div>
24
- <%= render partial: 'address_details', locals: { meeting: meeting } %>
25
- </div>
26
- </div>
27
- </article>
3
+ <div class="row">
4
+ <div class="columns mediumlarge-4 large-3">
5
+ <div class="card card--secondary show-for-mediumlarge" >
6
+ <%= render partial: "filters" %>
28
7
  </div>
29
- <% end %>
8
+ </div>
9
+ <div id="meetings" class="columns mediumlarge-8 large-9">
10
+ <%= render partial: "meetings" %>
11
+ </div>
30
12
  </div>
@@ -0,0 +1,2 @@
1
+ var $meetings = $('#meetings');
2
+ $meetings.html('<%= j(render partial: "meetings") %>');
@@ -30,6 +30,7 @@
30
30
  </div>
31
31
  </div>
32
32
  </div>
33
+ <%= render partial: "tags", locals: { meeting: meeting } %>
33
34
  </div>
34
35
  <div class="section">
35
36
  <h3 class="section-heading"><%= t(".meeting_description") %></h3>
@@ -32,6 +32,13 @@ ca:
32
32
  meeting:
33
33
  name: Trobada
34
34
  meetings:
35
+ filters:
36
+ ascendent: Ascendent
37
+ category: Categoria
38
+ date: Data
39
+ descendent: Descendent
40
+ scopes: Àmbits
41
+ search: Cerca
35
42
  index:
36
43
  title: Llistat de trobades
37
44
  show:
@@ -33,6 +33,13 @@ en:
33
33
  meeting:
34
34
  name: Meeting
35
35
  meetings:
36
+ filters:
37
+ ascendent: Ascendent
38
+ category: Category
39
+ date: Date
40
+ descendent: Descendent
41
+ scopes: Scopes
42
+ search: Search
36
43
  index:
37
44
  title: Meetings
38
45
  show:
@@ -32,6 +32,13 @@ es:
32
32
  meeting:
33
33
  name: Encuentro
34
34
  meetings:
35
+ filters:
36
+ ascendent: Ascendente
37
+ category: Categoría
38
+ date: Fecha
39
+ descendent: Descendiente
40
+ scopes: Ámbitos
41
+ search: Buscar
35
42
  index:
36
43
  title: Lista de encuentros
37
44
  show:
@@ -11,6 +11,8 @@ class CreateMeetings < ActiveRecord::Migration[5.0]
11
11
  t.jsonb :location_hints
12
12
  t.references :decidim_feature, index: true
13
13
  t.references :decidim_author, index: true
14
+ t.references :decidim_scope, index: true
15
+ t.references :decidim_category, index: true
14
16
 
15
17
  t.timestamps
16
18
  end
@@ -5,8 +5,9 @@ require_dependency "decidim/features/namer"
5
5
  Decidim.register_feature(:meetings) do |feature|
6
6
  feature.engine = Decidim::Meetings::ListEngine
7
7
  feature.admin_engine = Decidim::Meetings::AdminEngine
8
+ feature.icon = "decidim/meetings/icon.svg"
8
9
 
9
- feature.on(:destroy) do |instance|
10
+ feature.on(:before_destroy) do |instance|
10
11
  raise StandardError, "Can't remove this feature" if Decidim::Meetings::Meeting.where(feature: instance).any?
11
12
  end
12
13
 
@@ -21,8 +22,10 @@ Decidim.register_feature(:meetings) do |feature|
21
22
  )
22
23
 
23
24
  3.times do
24
- Decidim::Meetings::Meeting.create!(
25
+ meeting = Decidim::Meetings::Meeting.create!(
25
26
  feature: feature,
27
+ scope: process.organization.scopes.sample,
28
+ category: process.categories.sample,
26
29
  title: Decidim::Faker::Localized.sentence(2),
27
30
  description: Decidim::Faker::Localized.wrapped("<p>", "</p>") do
28
31
  Decidim::Faker::Localized.paragraph(3)
@@ -36,6 +39,8 @@ Decidim.register_feature(:meetings) do |feature|
36
39
  end_time: 3.weeks.from_now + 4.hours,
37
40
  address: "#{Faker::Address.street_address} #{Faker::Address.zip} #{Faker::Address.city}"
38
41
  )
42
+
43
+ Decidim::Comments::Seed.comments_for(meeting)
39
44
  end
40
45
  end
41
46
  end
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
+ require "searchlight"
3
+ require "kaminari"
4
+
2
5
  module Decidim
3
6
  module Meetings
4
7
  # This is the engine that runs on the public interface of `decidim-meetings`.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-meetings
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josep Jaume Rey Peroy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-12-21 00:00:00.000000000 Z
13
+ date: 2017-01-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: decidim-core
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.0.1
21
+ version: 0.0.2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 0.0.1
28
+ version: 0.0.2
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: rectify
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -54,20 +54,48 @@ dependencies:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0.9'
57
+ - !ruby/object:Gem::Dependency
58
+ name: searchlight
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: 4.1.0
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: 4.1.0
71
+ - !ruby/object:Gem::Dependency
72
+ name: kaminari
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.1
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: 1.0.1
57
85
  - !ruby/object:Gem::Dependency
58
86
  name: decidim-dev
59
87
  requirement: !ruby/object:Gem::Requirement
60
88
  requirements:
61
89
  - - '='
62
90
  - !ruby/object:Gem::Version
63
- version: 0.0.1
91
+ version: 0.0.2
64
92
  type: :development
65
93
  prerelease: false
66
94
  version_requirements: !ruby/object:Gem::Requirement
67
95
  requirements:
68
96
  - - '='
69
97
  - !ruby/object:Gem::Version
70
- version: 0.0.1
98
+ version: 0.0.2
71
99
  description: ''
72
100
  email:
73
101
  - josepjaume@gmail.com
@@ -79,6 +107,7 @@ extra_rdoc_files: []
79
107
  files:
80
108
  - README.md
81
109
  - Rakefile
110
+ - app/assets/images/decidim/meetings/icon.svg
82
111
  - app/commands/decidim/meetings/admin/create_meeting.rb
83
112
  - app/commands/decidim/meetings/admin/update_meeting.rb
84
113
  - app/controllers/decidim/meetings/admin/application_controller.rb
@@ -86,14 +115,20 @@ files:
86
115
  - app/controllers/decidim/meetings/application_controller.rb
87
116
  - app/controllers/decidim/meetings/meetings_controller.rb
88
117
  - app/forms/decidim/meetings/admin/meeting_form.rb
118
+ - app/helpers/decidim/meetings/application_helper.rb
89
119
  - app/models/decidim/meetings/application_record.rb
90
120
  - app/models/decidim/meetings/meeting.rb
121
+ - app/services/decidim/meetings/meeting_search.rb
91
122
  - app/views/decidim/meetings/admin/meetings/_form.html.erb
92
123
  - app/views/decidim/meetings/admin/meetings/edit.html.erb
93
124
  - app/views/decidim/meetings/admin/meetings/index.html.erb
94
125
  - app/views/decidim/meetings/admin/meetings/new.html.erb
95
126
  - app/views/decidim/meetings/meetings/_address_details.html.erb
127
+ - app/views/decidim/meetings/meetings/_filters.html.erb
128
+ - app/views/decidim/meetings/meetings/_meetings.html.erb
129
+ - app/views/decidim/meetings/meetings/_tags.html.erb
96
130
  - app/views/decidim/meetings/meetings/index.html.erb
131
+ - app/views/decidim/meetings/meetings/index.js.erb
97
132
  - app/views/decidim/meetings/meetings/show.html.erb
98
133
  - config/i18n-tasks.yml
99
134
  - config/locales/ca.yml
@@ -125,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
160
  version: '0'
126
161
  requirements: []
127
162
  rubyforge_project:
128
- rubygems_version: 2.5.2
163
+ rubygems_version: 2.6.8
129
164
  signing_key:
130
165
  specification_version: 4
131
166
  summary: A meetings component for decidim's participatory processes.