decidim-homepage_proposals 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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