decidim-homepage_proposals 1.0.0 → 1.0.1

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
  SHA256:
3
- metadata.gz: 072cc3b7f3c4dd841b2f6268339ee1977fbe471389c52684969528fadae7ac99
4
- data.tar.gz: c89b39bd4bdfb084d90ffc20082de012f745c1782776c73f7bcb1c1961aafa59
3
+ metadata.gz: b2f59c3f281a8e0a637928618dcfcd6a4afc4fb613e8ddcb48d331852b38b81a
4
+ data.tar.gz: 9e536edf44c0e0c6175c911066f25e16f08cb4914f88ec7f4ebf75bc8fd3b542
5
5
  SHA512:
6
- metadata.gz: dac25549785613af9ef39c2a32f6436b9956a6a1f44f63f7bc23524a541361bd0e4ee4d8a0d99033a5fa52382fb6b5725fec82136f829dc1f3f7b8e6b5dfd2ab
7
- data.tar.gz: f06f4f3b8ffba9c0c2ed83648b043a8a060b84b8a14d103768527648fe2e70bc800d88a863357046ab2b4a4e1af6deb73c257aa7147eeb7ec956c15876042fd9
6
+ metadata.gz: cc4b98d0f56d8f4c06a898d443ab4550dc4011ff394de0e0579535c85b0bdce4afe27a83cc083e7d1494777c8f7f9a1e19b90af3faadd41a993cd014468b62c5
7
+ data.tar.gz: 6082c4cbf2fb06cc437a7d28e824cbd841d404d13d98ce09aa2bf09f0f1aae400f652c2260e3944fdd7dde4376ae172d24d818c85b4451fe86f801bdfb7d75ae
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # Decidim::HomepageProposals
2
2
 
3
- Homepage slider for proposals.
3
+ Proposals homepage content block presented as carousel.
4
4
 
5
- ## Usage
5
+ ![Demo image](./docs/images/glanced_proposals.png)
6
6
 
7
- HomepageProposals will be available as a Component for a Participatory
8
- Space.
7
+ With this module you can have an overview of current proposals on the platform. Carousel support live reload based on selected filters and refreshing using Ajax requests.
8
+
9
+ ## Requirements
10
+
11
+ * [GlideJS](https://github.com/glidejs/glide)
9
12
 
10
13
  ## Installation
11
14
 
@@ -23,6 +26,13 @@ bundle exec rake decidim_module_homepage_proposals:webpacker:install
23
26
  bundle exec rake assets:precompile
24
27
  ```
25
28
 
29
+ ## Usage in Decidim
30
+
31
+ * Go to the backoffice
32
+ * Navigate to homepage content blocks
33
+ * Configure the homepage proposals content block
34
+ * Enable content block
35
+
26
36
  ## Contributing
27
37
 
28
38
  See [Decidim](https://github.com/decidim/decidim).
@@ -12,8 +12,13 @@ module Decidim
12
12
  include ActionView::Helpers::FormOptionsHelper
13
13
  include Decidim::FiltersHelper
14
14
  include Decidim::FilterResource
15
+ include Decidim::ComponentPathHelper
15
16
 
16
- private
17
+ def default_linked_component_path
18
+ main_component_path(Decidim::Component.find(selected_component_id))
19
+ rescue ActiveRecord::RecordNotFound
20
+ root_path
21
+ end
17
22
 
18
23
  def content_block_settings
19
24
  @content_block_settings ||= Decidim::ContentBlock.find_by(
@@ -23,8 +28,7 @@ module Decidim
23
28
  end
24
29
 
25
30
  def options_for_default_component
26
- components = Decidim::Component.where(id: content_block_settings.linked_components_id.compact)
27
- options = components.map do |component|
31
+ options = linked_components.map do |component|
28
32
  ["#{translated_attribute(component.name)} (#{translated_attribute(component.participatory_space.title)})", component.id]
29
33
  end
30
34
 
@@ -1,16 +1,52 @@
1
1
  import Glide from "@glidejs/glide";
2
2
 
3
+ // Create a GlideJS carousel
4
+ // See documentation: https://glidejs.com/docs/
3
5
  export default class GlideBuilder {
4
- constructor(selector = '.glide', type = 'carousel') {
6
+ static defaultPervView() {
7
+ return 4;
8
+ }
9
+
10
+ static defaultBreakpoints() {
11
+ return { 1024: { perView: 3 }, 768: { perView: 2 }, 480: { perView: 1 } };
12
+ }
13
+
14
+ constructor(selector = '.glide', type = 'carousel', pervView = GlideBuilder.defaultPervView()) {
5
15
  this.type = type
16
+ this.pervView = this.setPervView(pervView);
17
+ this.breakpoints = this.setBreakpoints();
6
18
  this.setOpts()
7
19
  this.glide = new Glide(selector, this.options)
8
20
 
9
21
  this.bindings()
10
22
  }
11
23
 
12
- static pervView() {
13
- return 4;
24
+ // Set pervView, must be between 0 and 4 excluded
25
+ // Returns default pervView when :
26
+ // * pervView < 1 : Placeholder is added at ./glideItems/Manager.js:122
27
+ // * pervView > 4 : Max pervView must be 4
28
+ setPervView(pervView) {
29
+ if (pervView > 0 && pervView < 4) {
30
+ return pervView;
31
+ } else {
32
+ return GlideBuilder.defaultPervView();
33
+ }
34
+ }
35
+
36
+ // Glide breakpoints must be accorded to the pervView to prevent scrolling on placeholders
37
+ setBreakpoints() {
38
+ let breakpoints;
39
+ switch (this.pervView) {
40
+ case 2:
41
+ breakpoints = { 1024: {perView: 2}, 768: {perView: 2}, 480: {perView: 1} };
42
+ break;
43
+ case 1:
44
+ breakpoints = { 1024: {perView: 1}, 768: {perView: 1}, 480: {perView: 1} };
45
+ break;
46
+ default:
47
+ breakpoints = GlideBuilder.defaultBreakpoints();
48
+ }
49
+ return breakpoints;
14
50
  }
15
51
 
16
52
  destroy() {
@@ -28,8 +64,10 @@ export default class GlideBuilder {
28
64
  bindings() {
29
65
  this.glide.on("run", () => {
30
66
  let bulletNumber = this.glide.index;
31
- $($(".glide__bullets").children()).css("color", "lightgrey");
32
- $($(".glide__bullets").children().get(bulletNumber + 1)).css("color", "grey");
67
+ let $glideBullets = $(".glide__bullets");
68
+
69
+ $($glideBullets.children()).css("color", "lightgrey");
70
+ $($glideBullets.children().get(bulletNumber + 1)).css("color", "grey");
33
71
  });
34
72
  }
35
73
 
@@ -38,11 +76,9 @@ export default class GlideBuilder {
38
76
  type: this.type,
39
77
  startAt: 0,
40
78
  autoplay: 0,
41
- perView: GlideBuilder.pervView(),
79
+ perView: this.pervView,
80
+ breakpoints: this.breakpoints,
42
81
  hoverpause: true,
43
- breakpoints: {
44
- 1024: { perView: 3 }, 768: { perView: 2 }, 480: { perView: 1 }
45
- },
46
82
  perTouch: 1
47
83
  }
48
84
  }
@@ -73,9 +73,9 @@ export default class Manager {
73
73
  this.generateGlides([])
74
74
  })
75
75
  .always((res) => {
76
- this.glide = new GlideBuilder('.glide', 'carousel');
76
+ this.glide = new GlideBuilder('.glide', 'carousel', res.length);
77
77
 
78
- if (res.length <= 1 || res.status === 500) {
78
+ if (res.length === undefined || res.length <= 1 || res.status === 500) {
79
79
  this.glide.disable()
80
80
  }
81
81
  this.endLoading();
@@ -104,7 +104,7 @@ export default class Manager {
104
104
  this.$proposalsGlideItems.append(notFoundGlide.render())
105
105
  $(".glide__bullets > .glide__bullet:last").before(notFoundGlide.bullet(0));
106
106
 
107
- for (let i = 0; i < GlideBuilder.pervView() - 1; i++) {
107
+ for (let i = 0; i < GlideBuilder.defaultPervView() - 1; i++) {
108
108
  this.$proposalsGlideItems.append(notFoundGlide.placeholder());
109
109
  }
110
110
  }
@@ -118,13 +118,5 @@ export default class Manager {
118
118
  this.$proposalsGlideItems.append(proposalGlide.render());
119
119
  $(".glide__bullets > .glide__bullet:last").before(proposalGlide.bullet(i));
120
120
  }
121
-
122
- if (proposals.length < GlideBuilder.pervView()) {
123
- let missingCount = GlideBuilder.pervView() - proposals.length
124
-
125
- for (let i = 0; i < missingCount; i++) {
126
- this.$proposalsGlideItems.append(new GlideItem(null).placeholder());
127
- }
128
- }
129
121
  }
130
122
  }
@@ -1,5 +1,10 @@
1
1
  import Manager from "./glidejs/Manager"
2
2
 
3
+ // Build GlideJS carousel in the content block
4
+ // Tree
5
+ // ./glideBuilder.js - Build a new instance of GlideJS carousel with options based on current number of proposals found
6
+ // ./glidejs/Manager.js - Start, Refresh, Stop GlideJS carousel, creates proposals cards items in carousel
7
+ // ./glidejs/glideitems/* - GlideJS items to render
3
8
  $(() => {
4
9
  const $proposalsSlider = $("#proposals_slider");
5
10
  const $proposalsGlideItems = $("#proposals_glide_items");
@@ -9,10 +14,12 @@ $(() => {
9
14
  const smallSlider = new Manager($proposalsSlider, $proposalsGlideItems, $(".glide__bullet.glide__bullet_idx"), $smallFilterForm);
10
15
  slider.start()
11
16
 
17
+ // Refresh slider when Desktop filter form changes
12
18
  $filterForm.on("change", () => {
13
19
  slider.start()
14
20
  });
15
21
 
22
+ // Refresh slider when Mobile filter form changes
16
23
  $smallFilterForm.on("change", () => {
17
24
  smallSlider.start()
18
25
  });
@@ -43,3 +43,14 @@
43
43
  .proposal-glance.card__title {
44
44
  max-height: 30px;
45
45
  }
46
+
47
+ .flex-v-center {
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: space-between;
51
+ }
52
+
53
+ .flex-justify-end {
54
+ display: flex;
55
+ justify-content: end
56
+ }
@@ -1,47 +1,47 @@
1
- <%= filter_form_for filter, decidim_participatory_processes_path , id: 'filters-form' do |form| %>
2
- <div class="columns mediumlarge-4 large-3">
3
- <%= cell(
4
- "decidim/scopes_picker",
5
- form,
6
- attribute: :scope_id,
7
- multiple: true,
8
- legend_title: t("decidim.homepage_proposals.proposal_at_a_glance.filters.scope"),
9
- label: false,
10
- checkboxes_on_top: false
11
- ) %>
12
- </div>
13
- <div class="columns mediumlarge-4 large-3">
14
- <%= form.categories_select :category_id,
15
- categories_filter,
16
- legend_title: t("decidim.homepage_proposals.proposal_at_a_glance.filters.categories"),
17
- disable_parents: false,
18
- label: "",
19
- selected: filter.category_id,
20
- include_blank: t("decidim.homepage_proposals.proposal_at_a_glance.filters.default_categories") %>
21
- </div>
22
- <div class="columns mediumlarge-4 large-3">
23
- <div class="filters__section">
24
- <fieldset class="">
25
- <legend class="mini-title"><%= t("decidim.homepage_proposals.proposal_at_a_glance.filters.components") %></legend>
26
- <label for="">
27
-
28
- <%= form.select :component_id,
29
- options_for_default_component,
30
- label: false,
31
- selected: filter.component_id,
32
- data: { placeholder: t("decidim.homepage_proposals.proposal_at_a_glance.filters.components") }
33
- %>
34
- </label>
35
-
36
- </fieldset>
37
-
1
+ <%= filter_form_for filter, decidim_participatory_processes_path, id: 'filters-form' do |form| %>
2
+ <div class="row">
3
+ <div class="columns flex-v-center">
4
+ <p><%= I18n.t("decidim.homepage_proposals.proposal_at_a_glance.filters.intro") %></p>
5
+ <div>
6
+ <%= cell(
7
+ "decidim/scopes_picker",
8
+ form,
9
+ attribute: :scope_id,
10
+ multiple: true,
11
+ label: false,
12
+ checkboxes_on_top: false
13
+ ) %>
14
+ </div>
15
+ <p><%= I18n.t("decidim.homepage_proposals.proposal_at_a_glance.filters.about") %></p>
16
+ <div>
17
+ <%= form.categories_select :category_id,
18
+ categories_filter,
19
+ disable_parents: false,
20
+ label: false,
21
+ selected: filter.category_id,
22
+ include_blank: t("decidim.homepage_proposals.proposal_at_a_glance.filters.default_categories") %>
23
+ </div>
24
+ <p><%= I18n.t("decidim.homepage_proposals.proposal_at_a_glance.filters.in") %></p>
25
+ <div>
26
+ <%= form.select :component_id,
27
+ options_for_default_component,
28
+ label: false,
29
+ selected: filter.component_id,
30
+ data: { placeholder: t("decidim.homepage_proposals.proposal_at_a_glance.filters.components") }
31
+ %>
32
+ </div>
38
33
  </div>
39
-
40
34
  </div>
41
- <%# Small button to clear filters %>
42
- <div class="columns mediumlarge-12 large-3">
43
- <div class="clear-filters">
44
- <%= link_to t("decidim.homepage_proposals.proposal_at_a_glance.filters.clear_filters"), decidim_participatory_processes_path, class: "button--clear-filters" %>
35
+ <div class="row">
36
+ <div class="columns medium-3">
37
+ <div class="clear-filters">
38
+ <%= link_to t("decidim.homepage_proposals.proposal_at_a_glance.filters.clear_filters"), decidim_participatory_processes_path(anchor: "proposals_slider"), class: "button button--secondary small button--sc" %>
39
+ </div>
40
+ </div>
41
+ <div class="columns medium-3">
42
+ <div class="all-proposals flex-justify-end">
43
+ <%= link_to t("decidim.homepage_proposals.proposal_at_a_glance.filters.all_proposals"), default_linked_component_path, class: "button button--secondary small button--sc" %>
44
+ </div>
45
45
  </div>
46
46
  </div>
47
47
  <% end %>
@@ -2,9 +2,37 @@
2
2
 
3
3
  base_locale: en
4
4
  locales: [en]
5
-
5
+ search:
6
+ relative_roots:
7
+ - app/cells
8
+ - app/controllers
9
+ - app/helpers
10
+ - app/mailers
11
+ - app/presenters
12
+ - app/views
6
13
  ignore_unused:
7
14
  - "decidim.components.homepage_proposals.name"
15
+ - decidim.homepage_proposals.content_blocks.proposals_slider.filters_small_view.{close_modal,filter,filter_by,unfold}
16
+ - decidim.homepage_proposals.content_blocks.proposals_slider.{learn_more,loading,name,search}
17
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.activate_filters
18
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.default_linked_component
19
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.linked_components_id
20
+ - decidim.homepage_proposals.proposal_at_a_glance.filters.categories
21
+ - decidim.homepage_proposals.proposal_at_a_glance.filters.default_components
22
+ - decidim.homepage_proposals.proposal_at_a_glance.filters.default_scope
23
+ - decidim.homepage_proposals.proposal_at_a_glance.filters.scope
24
+ - decidim.homepage_proposals.proposal_at_a_glance.learn_more
25
+ - decidim.homepage_proposals.proposal_at_a_glance.no_proposals.description
26
+ - decidim.homepage_proposals.proposal_at_a_glance.no_proposals.title
8
27
 
9
28
  ignore_missing:
10
29
  - decidim.participatory_processes.scopes.global
30
+ - decidim.homepage_proposals.content_blocks.proposals_slider.show.loading
31
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.show.activate_filters
32
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.show.linked_components_id
33
+ - decidim.homepage_proposals.content_blocks.proposals_slider_settings_form.show.default_linked_component
34
+ - decidim.shared.homepage_proposals.filters_small_view.filters_small_view.filter
35
+ - decidim.shared.homepage_proposals.filters_small_view.filters_small_view.unfold
36
+ - decidim.shared.homepage_proposals.filters_small_view.filters_small_view.filter_by
37
+ - decidim.shared.homepage_proposals.filters_small_view.filters_small_view.close_modal
38
+
@@ -10,24 +10,28 @@ en:
10
10
  filter_by: Filter by
11
11
  unfold: Unfold
12
12
  learn_more: Learn more
13
- name: Proposals slider
14
13
  loading: Loading...
14
+ name: Proposals slider
15
15
  search: Search
16
16
  proposals_slider_settings_form:
17
17
  activate_filters: Activate filters
18
18
  default_linked_component: Component displayed by default
19
19
  linked_components_id: Components available in filters
20
20
  proposal_at_a_glance:
21
- title: Explore proposals
22
21
  filters:
22
+ about: about
23
+ all_proposals: All proposals
23
24
  categories: Categories
24
25
  clear_filters: Clear filters
25
26
  components: Components
26
27
  default_categories: All categories
27
28
  default_components: All components
28
29
  default_scope: All scopes
30
+ in: in
31
+ intro: I'd like to see projects from
29
32
  scope: Scope
30
33
  learn_more: Learn more
31
34
  no_proposals:
32
- title: No proposals
33
35
  description: There are no proposals that match the selected filters.
36
+ title: No proposals
37
+ title: Explore proposals
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module HomepageProposals
5
5
  def self.version
6
- "1.0.0"
6
+ "1.0.1"
7
7
  end
8
8
 
9
9
  def self.decidim_version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-homepage_proposals
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elie Gaboriau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-16 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-core