breeze_cms 1.0.2 → 1.0.3

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/breeze/card_preview/faq_item.jpg +0 -0
  3. data/app/assets/images/breeze/section_preview/section_faq.jpg +0 -0
  4. data/app/assets/images/breeze/section_preview/section_half_slider.jpg +0 -0
  5. data/app/controllers/breeze/images_controller.rb +15 -2
  6. data/app/controllers/breeze/pages_controller.rb +1 -1
  7. data/app/controllers/breeze/sections_controller.rb +1 -1
  8. data/app/helpers/breeze/images_helper.rb +11 -5
  9. data/app/helpers/breeze/options_helper.rb +1 -1
  10. data/app/helpers/breeze/view_helper.rb +25 -0
  11. data/app/models/breeze/section.rb +5 -0
  12. data/app/models/breeze/shared_base.rb +1 -1
  13. data/app/models/breeze/view_base.rb +11 -2
  14. data/app/views/breeze/images/_editor.haml +22 -22
  15. data/app/views/breeze/images/index.haml +6 -4
  16. data/app/views/breeze/images/show.haml +6 -3
  17. data/app/views/breeze/pages/show.haml +52 -62
  18. data/app/views/breeze/view/_form_section.haml +1 -1
  19. data/app/views/breeze/view/_section_faq.haml +29 -0
  20. data/app/views/breeze/view/_section_full_image.haml +1 -1
  21. data/app/views/breeze/view/_section_full_up.haml +1 -1
  22. data/app/views/breeze/view/_section_half_image.haml +1 -1
  23. data/app/views/breeze/view/_section_half_slider.haml +67 -0
  24. data/app/views/breeze/view/_section_large_image.haml +1 -1
  25. data/app/views/breeze/view/_section_slider.haml +33 -14
  26. data/app/views/breeze/view/_section_small_image.haml +1 -1
  27. data/app/views/breeze/view/cards/_faq_item.haml +9 -0
  28. data/config/breeze/card_styles.yml +41 -31
  29. data/config/breeze/option_definitions.yml +7 -0
  30. data/config/breeze/page_styles.yml +1 -0
  31. data/config/breeze/section_styles.yml +50 -0
  32. data/lib/breeze/engine.rb +2 -2
  33. data/lib/breeze/version.rb +1 -1
  34. metadata +12 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9e5223e9803e23cbf7eaa43ceade1e390ca57c00be935d615963dd014edad1a
4
- data.tar.gz: 5cdad7b32634b3b2593be5c96e92b19a084a26803a0926a4e645b6ffce224a62
3
+ metadata.gz: 0ba08a0e333284d5d591c49c10a088411353a4469a51b63c6d471343459983af
4
+ data.tar.gz: e96dad08ce51904be0fc2bb0bf57e5520a3cbfe42c61286e7ae40720e18590cc
5
5
  SHA512:
6
- metadata.gz: 8b2dab3efcd663abe6b3d486a67c8220042773b07900a155f7e13a8a5849d0953eb82c551cf1e63edffd223ee9a2bf4014e64f5695f217ae2c3edc970a3a6893
7
- data.tar.gz: 7a98375009528f06d7857c9cc3778bf4b7c9b52c47e0c232b38a19327db2f3bda22eb9a22cd319db8904ec775af39eb4f3db109ad4aa07e1f3f77e1fd3864294
6
+ metadata.gz: d1261b892056365a77c59fa412f64e088a74ddc84296d6c2ba3ee7442a56914973ae49c87b26d531b5b6154447836c56db4b7524a11ec58d5c0d32066db2e6ab
7
+ data.tar.gz: 4fdc3af31bb3d690e4fc7d1cfcfa13d3a7d34a9458350424a001fc9dd9b233b8954566b9892cb598d6134c99c6f2c1d19f0ca710c628d314ed6cfb56ab078107
@@ -48,6 +48,8 @@ module Breeze
48
48
  @cards = Card.find_all(:image_id, params[:id].to_i)
49
49
  @used = ((@cards.length > 0) || (@sections.length > 0))
50
50
  @image_data = @image.data
51
+ @global_scale = get_scale(@image)
52
+ puts @global_scale
51
53
  end
52
54
 
53
55
  def copy
@@ -75,17 +77,28 @@ module Breeze
75
77
 
76
78
  private
77
79
 
80
+ def get_scale(image)
81
+ x_scale = (image.width / 1700.0).ceil
82
+ y_scale = (image.height / 1000.0).ceil
83
+ [x_scale , y_scale].max
84
+ end
85
+
78
86
  def get_images
79
87
  images = Image.all
80
- return images unless params[:unused]
88
+ return images if params[:unused].nil?
81
89
  hash = images.collect{|i| [i.id , i ] }.to_h
82
90
  Section.all.each{ |s| hash.delete(s.image&.id)}
83
91
  Card.all.each{ |s| hash.delete(s.image&.id)}
84
- hash.values
92
+ return hash.values if params[:unused] == "true"
93
+ all = images.collect{|i| [i.id , i ] }.to_h
94
+ hash.each_key{|i| all.delete(i)}
95
+ all.values
85
96
  end
97
+
86
98
  def set_image
87
99
  @image = Image.find(params[:id] || params[:image_id])
88
100
  end
101
+
89
102
  def determine_redirect(image)
90
103
  if(params[:section_id])
91
104
  view_context.section_set_image_url(params[:section_id],image_id: image.id )
@@ -20,7 +20,7 @@ module Breeze
20
20
  if( !params[:name].blank? && (params[:name] != @page.name))
21
21
  @page.set_name params[:name]
22
22
  end
23
- @page.update_options( params[:options])
23
+ @page.update_present_options( params[:options])
24
24
  @page.edit_save(current_member_email)
25
25
  message = "Saved"
26
26
  redirect_to page_url(@page) , notice: message
@@ -62,7 +62,7 @@ module Breeze
62
62
  def set_card_template
63
63
  card_template = params[:card_template]
64
64
  raise "no card template given" if card_template.blank?
65
- @section.card_template = card_template
65
+ @section.set_card_template( card_template )
66
66
  @section.edit_save(current_member_email)
67
67
  redirect_to section_url(@section.id)
68
68
  end
@@ -5,13 +5,19 @@ module Breeze
5
5
  def text_for_index
6
6
  if(section_id)
7
7
  section = Section.find(section_id)
8
- "Select image for Section #{section.index} : #{section.header}"
9
- elsif(card_id)
8
+ return "Select image for Section #{section.index} : #{section.header}"
9
+ end
10
+ if(card_id)
10
11
  card = Card.find(card_id)
11
- "Select image for Card #{card.index} : #{card.header}"
12
- else
13
- "All Images"
12
+ return "Select image for Card #{card.index} : #{card.header}"
13
+ end
14
+ if(params[:unused].nil?)
15
+ return "All Images"
16
+ end
17
+ if(params[:unused] == "true")
18
+ return "Unused Images"
14
19
  end
20
+ return "Used Images"
15
21
  end
16
22
 
17
23
  def text_for_new
@@ -38,7 +38,7 @@ module Breeze
38
38
 
39
39
  def order_option(section , clazz = "")
40
40
  if section.has_option?("order")
41
- clazz += " order-last" if section.option('order') == "right"
41
+ clazz += " md:order-last" if section.option('order') == "right"
42
42
  end
43
43
  {class: clazz}
44
44
  end
@@ -2,6 +2,31 @@ module Breeze
2
2
  module ViewHelper
3
3
  include BreezeHelper
4
4
 
5
+ def title
6
+ @page.options ? @page.options["title"] : ""
7
+ end
8
+
9
+ def description
10
+ @page.options ? @page.options["description"] : ""
11
+ end
12
+
13
+ def breeze_meta_tags
14
+ metas = "<title> #{title}</title>\n" +
15
+ "<meta name='description' content='#{description}' />" +
16
+ breeze_fb_tags
17
+ metas.html_safe
18
+ end
19
+
20
+ # private, just breaking it up. Returns not safe string
21
+ def breeze_fb_tags
22
+ return "" unless @page.options
23
+ image = Image.find( @page.options["main_image"] )
24
+ return "" unless image
25
+ image_path = asset_path("breeze/" + image.id.to_s + "." + image.type)
26
+ "\n<meta property='og:image' content='http://nomads.feenix.community#{image_path}' />" +
27
+ "\n<meta property='og:image:secure_url' content='https://nomads.feenix.community#{image_path}' />"
28
+ end
29
+
5
30
  def current_lang
6
31
  params[:lang]
7
32
  end
@@ -51,6 +51,7 @@ module Breeze
51
51
  def set_template(new_template)
52
52
  self.template = new_template
53
53
  new_style = template_style
54
+ add_default_options
54
55
  if(new_style.has_cards?)
55
56
  if card_template.blank?
56
57
  self.card_template = CardStyle.first.template
@@ -58,6 +59,10 @@ module Breeze
58
59
  end
59
60
  end
60
61
 
62
+ def set_card_template(new_template)
63
+ self.card_template = new_template
64
+ end
65
+
61
66
  def allowed_fields
62
67
  super + [:page_id]
63
68
  end
@@ -14,7 +14,7 @@ module Breeze
14
14
  breeze_path = Breeze::Engine.root.join("config")
15
15
  breeze_res = YAML.load(File.read(File.join(breeze_path , fullname )))
16
16
 
17
- res + breeze_res
17
+ breeze_res + res
18
18
  end
19
19
  end
20
20
  end
@@ -26,7 +26,7 @@ module Breeze
26
26
  last = Time.now
27
27
  last_section = nil
28
28
  elements.each do |section|
29
- if( section.updated_at < last )
29
+ if( section.updated_at > last )
30
30
  last = section.updated_at
31
31
  last_section = section
32
32
  end
@@ -58,13 +58,14 @@ module Breeze
58
58
  year = value[:year] || Time.new.year
59
59
  value = Time.new( year.to_i , value[:month] , value[:day]).to_date
60
60
  end
61
- safe_options[option] = value
61
+ safe_options[option] = value.to_s
62
62
  end
63
63
 
64
64
  def add_default_options( definitions = nil )
65
65
  definitions = option_definitions if definitions.nil?
66
66
  definitions.each do |option|
67
67
  next unless option.default
68
+ next unless option(option.name).blank?
68
69
  set_option( option.name , option.default)
69
70
  end
70
71
  end
@@ -90,6 +91,14 @@ module Breeze
90
91
  set_option(option.name, options[option.name])
91
92
  end
92
93
  end
94
+ def update_present_options( options )
95
+ return unless options
96
+ option_definitions.each do |option|
97
+ next unless options.has_key?(option.name)
98
+ set_option(option.name, options[option.name])
99
+ end
100
+ end
101
+
93
102
  #other may be nil
94
103
  def swap_index_with(other)
95
104
  return unless other
@@ -1,27 +1,26 @@
1
- %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"}
2
2
 
3
3
  %section.image
4
4
  .flex.justify-between.mx-20
5
5
  .flex.justify-between
6
6
  %div.justify-self-start.ml-20.mr-10
7
- %b Presets
8
- 600
9
- %input{ name: :pre, type: "radio", value: "600", "v-on:input": "handle_preset($event)" }/
10
- 800
11
- %input{ name: :pre, type: "radio", value: "800", "v-on:input": "handle_preset($event)" }/
12
- 1800
13
- %input{ name: :pre, type: "radio", value: "1800", "v-on:input": "handle_preset($event)" }/
14
- %br
15
7
  %b Scale {{scaled_x}} x {{scaled_y}}
8
+ %select.ml-4.mb-2.form-control{ "v-on:input": "handle_preset($event)" }
9
+ %option{ } Select a preset
10
+ %option{ value: "600", "v-on:input": "handle_preset($event)" } Card 600
11
+ %option{ value: "800", "v-on:input": "handle_preset($event)" } Half 800
12
+ %option{ value: "1200", "v-on:input": "handle_preset($event)" } 2/3 1200
13
+ %option{ value: "1800", "v-on:input": "handle_preset($event)" } Full 1800
14
+
16
15
  %br/
17
16
  %input{":min": 20 , ":max": 100 , ":step": 0.1 , :type => "range",
18
17
  "v-bind:value": "scale" , "v-on:input" => "handle_scale($event)"}/
19
18
 
20
19
  = form_tag( breeze.image_scale_path(image_id: image.id) ) do
21
20
  %input{ hidden: true , id: :scale_id , name: :scale , "v-bind:value": "scale" }
22
- %button.my-3.button.change Scale {{scale}} %
21
+ %button.button.change Scale {{scale}} %
23
22
 
24
- %div.mt-2
23
+ %div
25
24
  %b.pr-2 Ratio
26
25
  %br/
27
26
  %em {{ratio}} : 1
@@ -31,9 +30,9 @@
31
30
  %input{ hidden: true , id: :height_id , name: :size_y , "v-bind:value": "size_y" }
32
31
  %input{ hidden: true , id: :off_x_id , name: :off_x , "v-bind:value": "off_x" }
33
32
  %input{ hidden: true , id: :off_y_id , name: :off_y , "v-bind:value": "off_y" }
34
- %button.my-3.button.change Crop
33
+ %button.button.change Crop
35
34
 
36
- %div.mt-2.ml-32
35
+ %div.ml-32
37
36
  %b.pr-2 Fix ratio to
38
37
  %select{ "@change": "set_ratio"}
39
38
  %option{value: "0" } Any Ratio
@@ -44,11 +43,6 @@
44
43
 
45
44
  .flex.justify-between.mb-5
46
45
  %div.ml-20
47
- %b Y Offset {{off_y}}
48
- %br/
49
- %input.horizontal{":min": 0 , ":max": "#{image.height}", ":step": 1 , :type => "range",
50
- "v-bind:value": "off_y" , "v-on:input" => "handle_off_y($event)"}
51
- %div
52
46
  %b X Offset {{off_x}}
53
47
  %br/
54
48
  %input{":min": 0 , ":max": "#{image.width}", ":step": 1 , :type => "range",
@@ -58,16 +52,21 @@
58
52
  %br/
59
53
  %input{":min": 0 , ":max": "#{image.width}", ":step": 1 , :type => "range",
60
54
  "v-bind:value": "size_x" , "v-on:input" => "handle_size_x($event)"}
61
- %div.mr-20
55
+ %div
62
56
  %b Y Size {{size_y.toFixed(0)}}
63
57
  %br
64
58
  %input.horizontal{":min": 0 , ":max": "#{image.height}", ":step": 1 , :type => "range",
65
59
  "v-bind:value": "size_y" , "v-on:input" => "handle_size_y($event)"}
60
+ %div.mr-20
61
+ %b Y Offset {{off_y}}
62
+ %br/
63
+ %input.horizontal{":min": 0 , ":max": "#{image.height}", ":step": 1 , :type => "range",
64
+ "v-bind:value": "off_y" , "v-on:input" => "handle_off_y($event)"}
66
65
 
67
66
  .flex.justify-center
68
- .image-container.overflow-hidden.relative{ "v-bind:style": "{height: scaled_y + 'px' , width: scaled_x + 'px'} " }
69
- = image_tag(image.asset_name , class: "")
70
- .absolute.bg-transparent.border-4.border-black{ "v-bind:style": "{height: size_y + 'px' , width: size_x + 'px' , top: off_y + 'px', left: off_x + 'px' }" }
67
+ .image-container.overflow-hidden.relative{ "v-bind:style": "{height: (scaled_y/global_scale) + 'px' , width: (scaled_x/global_scale) + 'px'} " }
68
+ = image_tag(image.asset_name , class: "" , width: (@image.width / @global_scale).to_i , height: (@image.height/@global_scale).to_i)
69
+ .absolute.bg-transparent.border-4.border-black{ "v-bind:style": "{height: (size_y/global_scale).toFixed() + 'px' , width: (size_x/global_scale).toFixed() + 'px' , top: (off_y/global_scale).toFixed() + 'px', left: (off_x/global_scale).toFixed() + 'px' }" }
71
70
 
72
71
  :ruby2js
73
72
  class Images < Vue
@@ -76,6 +75,7 @@
76
75
  @image_data = #{@image_data.to_json.html_safe}
77
76
  @off_x = 0
78
77
  @off_y = 0
78
+ @global_scale = "#{@global_scale}"
79
79
  @scale = 100
80
80
  @size_x = @image_data[:width]
81
81
  @size_y = @image_data[:height]
@@ -1,4 +1,4 @@
1
- %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"}
2
2
 
3
3
  .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16.justify-between
4
4
  .flex.gap-20
@@ -7,8 +7,10 @@
7
7
 
8
8
  = link_to(breeze.new_image_path(new_link_params) ) do
9
9
  .button.action New Image
10
- = link_to(breeze.images_path(unused: true) ) do
11
- .button.action Show unused Images
10
+ = link_to(breeze.images_path(unused: false) ) do
11
+ .button.bg-cyan-100 Show used
12
+ = link_to(breeze.images_path(unused: true) ) do
13
+ .button.bg-orange-100 Show unused
12
14
 
13
15
  .images
14
16
  .flex.justify-center.gap-4
@@ -45,7 +47,7 @@
45
47
  %strong.inline-block.rounded.bg-orange-50.px-3.py-1.text-md.font-medium
46
48
  {{image.updated_at}}
47
49
  %strong.rounded.h-10.bg-orange-50.px-5.py-2.font-medium
48
- {{image.tags}}
50
+ {{image.type}}
49
51
 
50
52
  .hidden.list
51
53
  -@images.each do |image|
@@ -1,9 +1,9 @@
1
- %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"}
2
2
 
3
3
  .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
4
4
  .text-xl.font-bold.text-gray-900
5
5
  Image: #{@image.name}
6
-
6
+ = @global_scale
7
7
  = form_tag( breeze.image_copy_path(@image.id) , method: :post) do
8
8
  %button.mx-40.button.change Copy
9
9
 
@@ -25,7 +25,10 @@
25
25
  %p.align-center Not used
26
26
  = form_tag( breeze.image_path(@image.id) , {method: :delete } ) do
27
27
  %button.button.remove{type: :submit} Delete
28
-
28
+ .m-2.bg-cyan-200
29
+ - if(@global_scale > 1)
30
+ Downscaled by
31
+ = @global_scale
29
32
 
30
33
  .flex.m-20
31
34
  .left.flex.gap-2.mt-3
@@ -1,83 +1,73 @@
1
1
  - @page.sections.each do |section|
2
2
  = render_section( section )
3
3
 
4
- .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
4
+ .grid.grid-cols-4.mx-20.md:mx-12.gap-8.mt-8
5
5
  .text-xl.font-bold.text-gray-900
6
6
  = @page.type.capitalize
7
7
  = ":"
8
- .text-xl.font-bold.text-gray-900
9
8
  =@page.name
10
- %strong.rounded.bg-green-100.px-4.py-2.text-lg.font-medium.text-green-700{:class => "py-1.5"}
11
- = link_to 'Section details', breeze.page_sections_path(@page.id)
9
+ -unless @page.redirects.blank?
10
+ .mt-4
11
+ Page redirects from
12
+ = @page.redirects
13
+ %div
14
+ %button.button.change
15
+ = link_to 'Section details', breeze.page_sections_path(@page.id)
12
16
 
13
17
  = form_tag( breeze.section_new_path(@page.id), method: :post ) do
14
- %button.button.change.mr-3{type: :submit} New Section
18
+ %button.button.action{type: :submit} New Section
15
19
 
16
20
  .text-xl
17
21
  Edited
18
22
  = distance_of_time_in_words_to_now(@page.updated_at)
19
23
  ago
20
- .flex.gap-4.justify-center.m-20
21
- .grid.grid-cols-5
22
- .text.font-bold Section
23
- .text.font-bold Cards
24
- .text.font-bold Translations
25
- .text.font-bold Updated
26
- .text.font-bold Actions
27
- - @page.sections.each do |section |
28
- .span
29
- =link_to( breeze.section_path(section.id)) do
30
- #{section.index} : #{section.header}
31
- .text
32
- =link_to breeze.section_cards_path(section.id) do
33
- #{section.cards.length} Cards
34
- .text
35
- = link_to breeze.translation_path(@page.id) do
36
- %button.button.action
37
- =section.missing_translations
38
- missing
39
- .text
40
- = updated_by(section)
41
- .flex
42
- = form_tag( breeze.section_new_path(@page.id), method: :post ) do
43
- %button.button.change.mr-3{type: :submit} New
44
- = link_to breeze.section_path(section.id) do
45
- %button.button.action Edit
46
- .p-2
47
- =link_to(breeze.section_move_path(section.id , dir: :down)) do
48
- %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
49
- %path{:d => "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
50
- .p-2
51
- =link_to(breeze.section_move_path(section.id , dir: :up)) do
52
- %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
53
- %path{:d => "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
54
24
 
55
- .flex.flex-col
56
- .basis-80
57
- = form_tag( breeze.page_path(@page.id) , {method: :patch , class: "mx-auto mt-8 mb-0 max-w space-y-4" } ) do
58
- %label.block
59
- %h4.text-lg.font-bold Name
60
- = text_field_tag( :name , @page.name, class: "w-full rounded-lg border-gray-200 p-4 pr-12 text-sm shadow-sm")
61
- %button.button.change.mt-4{type: :submit} Update name
25
+ = form_tag( breeze.page_path(@page.id) , {method: :patch , class: "mx-auto mt-8 mb-0 max-w space-y-4" } ) do
26
+ %h4.text-lg.font-bold Name
27
+ = text_field_tag( :name , @page.name, class: "w-full rounded-lg border-gray-200 p-4 text-sm shadow-sm")
28
+ %button.button.change.mt-4{type: :submit} Update name
62
29
 
63
- -unless @page.redirects.blank?
64
- .mt-4
65
- Page redirects from
66
- = @page.redirects
30
+ - @page.option_definitions.each do |option|
31
+ = form_tag( breeze.page_path(@page.id) , {method: :patch , class: "mx-auto mt-8 mb-0 max-w space-y-4" } ) do
32
+ =render "/breeze/sections/option_form_#{option.type}" , section: @page , option: option
33
+ %button.button.change.mt-4{type: :submit} Update #{option.name.camelcase}
67
34
 
68
- .relative.block.delete_page.mt-8
69
- = form_tag( breeze.page_path(@page.id) , {method: :delete } ) do
70
- %button.button.remove{type: :submit} Delete Page
35
+ = form_tag( breeze.page_path(@page.id) , {method: :delete } ) do
36
+ %button.button.mt-40.ml-10.remove{type: :submit} Delete Page
71
37
 
72
- .basis-80.grow.options
73
- %h3.mt-4.text-lg.font-bold Options
74
- = form_tag( breeze.page_path(@page.id) , {method: :patch , class: "mx-auto mt-8 mb-0 max-w space-y-4" } ) do
75
- - @page.option_definitions.each do |option|
76
- =render "/breeze/sections/option_form_#{option.type}" , section: @page , option: option
77
- -if @page.option_definitions.empty?
78
- %p No options
79
- -else
80
- %button.button.change.mt-4{type: :submit} Update Options
38
+ .grid.grid-cols-5.gap-8.m-20
39
+ .text.font-bold Section
40
+ .text.font-bold Actions
41
+ .text.font-bold Translations
42
+ .text.font-bold Cards
43
+ .text.font-bold Updated
44
+ - @page.sections.each do |section |
45
+ .span
46
+ =link_to( breeze.section_path(section.id)) do
47
+ #{section.index} : #{section.header}
48
+ .flex
49
+ = form_tag( breeze.section_new_path(@page.id), method: :post ) do
50
+ %button.button.change.mr-3{type: :submit} New
51
+ = link_to breeze.section_path(section.id) do
52
+ %button.button.action Edit
53
+ .p-2
54
+ =link_to(breeze.section_move_path(section.id , dir: :down)) do
55
+ %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
56
+ %path{:d => "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
57
+ .p-2
58
+ =link_to(breeze.section_move_path(section.id , dir: :up)) do
59
+ %svg.w-6.h-6{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
60
+ %path{:d => "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
61
+ .text
62
+ = link_to breeze.translation_path(@page.id) do
63
+ %button.button.action
64
+ =section.missing_translations
65
+ missing
66
+ .text
67
+ =link_to breeze.section_cards_path(section.id) do
68
+ #{section.cards.length} Cards
69
+ .text
70
+ = updated_by(section)
81
71
 
82
72
  :javascript
83
73
  var sections = #{ render( partial: "sections" , formats: :json).html_safe }
@@ -5,7 +5,7 @@
5
5
  .mt-4.text-lg.pt-10{ prose_classes }
6
6
  = markdown(section,current_lang)
7
7
  .flex.items-center.justify-start.m-10.md:m-20
8
- .mx-auto.w-full.max-w-4xl{class: "max-w-[50%]"}
8
+ .mx-auto.w-full.max-w-4xl{class: "max-w-[90%]"}
9
9
  = form_tag( main_app.post_form_path , {class: "mt-10" }) do
10
10
  - challenge = rand(8)
11
11
  = hidden_field_tag :section_id , section.id
@@ -0,0 +1,29 @@
1
+ %section.m-6.md:m-12.lg:m-20{ options(section , :background , :text_color), id: section.type_id}
2
+ .flex.justify-center
3
+ .px-4.py-4.md:py-10.lg:py-16{ options(section , :text_align)}
4
+ %h1.section_header.text-2xl.font-bold.tracking-tight.sm:text-4xl
5
+ = section.header_text(current_lang)
6
+ - unless section.text.blank?
7
+ .section_text.text-lg.pt-10{ prose_classes }
8
+ = markdown(section , current_lang)
9
+ - template = "breeze/view/cards/" + section.card_template
10
+ .max-w-3xl.mx-auto.mt-8.space-y-4.md:mt-16
11
+ - section.cards.each_with_index do |card, index|
12
+ = render( template , card: card , index: index + 1)
13
+
14
+ :javascript
15
+ // JavaScript to toggle the answers and rotate the arrows
16
+ document.querySelectorAll('[id^="question"]').forEach(function(button, index) {
17
+ button.addEventListener('click', function() {
18
+ var answer = document.getElementById('answer' + (index + 1));
19
+ var arrow = document.getElementById('arrow' + (index + 1));
20
+
21
+ if (answer.style.display === 'none' || answer.style.display === '') {
22
+ answer.style.display = 'block';
23
+ arrow.style.transform = 'rotate(0deg)';
24
+ } else {
25
+ answer.style.display = 'none';
26
+ arrow.style.transform = 'rotate(-180deg)';
27
+ }
28
+ });
29
+ });
@@ -7,4 +7,4 @@
7
7
  = section.header_text(current_lang)
8
8
  .section_text.sm:mt-4.text-2xl{ prose_classes }
9
9
  = markdown(section,current_lang)
10
- =view_button(section , "my-2")
10
+ =view_button(section , "my-4")
@@ -5,4 +5,4 @@
5
5
  = section.header_text(current_lang)
6
6
  .section_text.mt-4.text-lg.pt-10{ prose_classes }
7
7
  = markdown(section,current_lang)
8
- =view_button(section , "my-2")
8
+ =view_button(section , "my-4")
@@ -7,4 +7,4 @@
7
7
  = section.header_text(current_lang)
8
8
  .section_text.mt-8{ prose_classes }
9
9
  = markdown(section,current_lang)
10
- =view_button(section , "my-2")
10
+ =view_button(section , "my-4")
@@ -0,0 +1,67 @@
1
+ %section.overflow-hidden.grid.grid-cols-1.m-5.md:m-12.lg:m-20.md:grid-cols-2{id: section.type_id}
2
+ %div{ order_option(section)}
3
+ .swiper{ class: "swiper-#{section.id}"}
4
+ .swiper-wrapper
5
+ - template = "breeze/view/cards/" + section.card_template
6
+ - section.cards.each do |card|
7
+ .swiper-slide{ column_option(section)}
8
+ = render( template , card: card)
9
+
10
+ .swiper-pagination
11
+ .swiper-button-prev
12
+ .swiper-button-next
13
+
14
+ .p-8.md:p-12.lg:px-16.lg:py-24{ background_option(section)}
15
+ .mx-auto.max-w-xl{options(section , :text_align , :text_color)}
16
+ %h2.section_header.text-2xl.font-bold.md:text-4xl
17
+ = section.header_text(current_lang)
18
+ .section_text.mt-8{ prose_classes }
19
+ = markdown(section,current_lang)
20
+ =view_button(section , "my-4")
21
+
22
+ %script{:src => "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"}
23
+
24
+ :javascript
25
+ var breaks = #{slider_columns_option(section).to_json};
26
+ document.addEventListener("DOMContentLoaded", function(event) {
27
+
28
+ function initSwiper(){
29
+ const swiper = new Swiper(".swiper-#{section.id}", {
30
+ loop: true,
31
+ speed: 1500,
32
+ breakpoints: breaks ,
33
+ autoplay: true,
34
+ pagination: {
35
+ el: '.swiper-pagination',
36
+ },
37
+ navigation: {
38
+ nextEl: '.swiper-button-next',
39
+ prevEl: '.swiper-button-prev',
40
+ },
41
+ });
42
+ }
43
+
44
+ // Intersection Observer to detect when the element is in view
45
+ const observer = new IntersectionObserver((entries) => {
46
+ entries.forEach(entry => {
47
+ if (entry.isIntersecting) {
48
+ initSwiper(); // Initialize Swiper when the element is in view
49
+ observer.unobserve(entry.target); // Stop observing after initialization
50
+ }
51
+ });
52
+ });
53
+
54
+ // Start observing the Swiper container
55
+ const swiperContainer = document.querySelector(".swiper-#{section.id}");
56
+ observer.observe(swiperContainer);
57
+
58
+ });
59
+
60
+ var head = document.getElementsByTagName("head")[0];
61
+ cssLink = document.createElement("link");
62
+ cssLink.href = "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css";
63
+ cssLink.rel="stylesheet";
64
+ cssLink.id="dynamic-css";
65
+ cssLink.media="screen";
66
+ cssLink.type="text/css";
67
+ head.appendChild(cssLink);
@@ -7,4 +7,4 @@
7
7
  %h2.section_header.text-4xl.font-bold.text-center.mb-4.lg:mb-8= section.header_text(current_lang)
8
8
  .section_text.mt-3{ prose_classes }
9
9
  = markdown(section,current_lang)
10
- =view_button(section , "my-2")
10
+ =view_button(section , "my-4")
@@ -6,8 +6,8 @@
6
6
  = section.header_text(current_lang)
7
7
  .section_text.mt-4.text-lg.pt-10{ prose_classes }
8
8
  = markdown(section,current_lang)
9
- =view_button(section , "my-2")
10
- .swiper
9
+ =view_button(section , "my-4")
10
+ .swiper{ class: "swiper-#{section.id}"}
11
11
  .swiper-wrapper
12
12
  - template = "breeze/view/cards/" + section.card_template
13
13
  - section.cards.each do |card|
@@ -23,19 +23,38 @@
23
23
  :javascript
24
24
  var breaks = #{slider_columns_option(section).to_json};
25
25
  document.addEventListener("DOMContentLoaded", function(event) {
26
- const swiper = new Swiper('.swiper', {
27
- loop: true,
28
- speed: 1500,
29
- breakpoints: breaks ,
30
- autoplay: true,
31
- pagination: {
32
- el: '.swiper-pagination',
33
- },
34
- navigation: {
35
- nextEl: '.swiper-button-next',
36
- prevEl: '.swiper-button-prev',
37
- },
26
+
27
+ function initSwiper(){
28
+ const swiper = new Swiper(".swiper-#{section.id}", {
29
+ loop: true,
30
+ speed: 1500,
31
+ breakpoints: breaks ,
32
+ autoplay: true,
33
+ pagination: {
34
+ el: '.swiper-pagination',
35
+ },
36
+ navigation: {
37
+ nextEl: '.swiper-button-next',
38
+ prevEl: '.swiper-button-prev',
39
+ },
40
+ });
41
+ }
42
+
43
+
44
+ // Intersection Observer to detect when the element is in view
45
+ const observer = new IntersectionObserver((entries) => {
46
+ entries.forEach(entry => {
47
+ if (entry.isIntersecting) {
48
+ initSwiper(); // Initialize Swiper when the element is in view
49
+ observer.unobserve(entry.target); // Stop observing after initialization
50
+ }
51
+ });
38
52
  });
53
+
54
+ // Start observing the Swiper container
55
+ const swiperContainer = document.querySelector(".swiper-#{section.id}");
56
+ observer.observe(swiperContainer);
57
+
39
58
  });
40
59
 
41
60
  var head = document.getElementsByTagName("head")[0];
@@ -5,4 +5,4 @@
5
5
  %h2.section_header.text-4xl.font-bold.text-left.mb-4.lg:mb-8{text_align_option(section)}= section.header_text(current_lang)
6
6
  .section_text.mt-3{ prose_classes }
7
7
  = markdown(section,current_lang)
8
- =view_button(section , "my-2")
8
+ =view_button(section , "my-4")
@@ -0,0 +1,9 @@
1
+ .transition-all.duration-200.bg-white.border.border-gray-200.shadow-lg.cursor-pointer.hover:bg-gray-50{options(card, :text_color)}
2
+ %button.flex.items-center.justify-between.w-full.px-4.py-5.sm:p-6{"data-state" => "closed",
3
+ :type => "button" , id: "question#{index}" }
4
+ %span.flex.text-lg.font-semibold.text-black= card.header_text(current_lang)
5
+ %svg.w-6.h-6.text-gray-400{fill: :none, stroke: :currentColor, id: "arrow#{index}",
6
+ :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
7
+ %path{:d => "M19 9l-7 7-7-7", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
8
+ .px-4.pb-5.sm:px-6.sm:pb-6{style: "display:none" , id: "answer#{index}"}
9
+ %p= markdown(card,current_lang)
@@ -1,4 +1,35 @@
1
1
  ---
2
+ - :template: card_normal_round
3
+ :header: Standard card with rounded look
4
+ :text: Otherwise quite similar to standard. But there is gap under the image.
5
+ Images can be wide or square, for 2 column 800 wide,
6
+ 3 column 600 , 4 column 400
7
+
8
+ :fields:
9
+ - header
10
+ - text
11
+ :options:
12
+ - background
13
+ - text_color
14
+ - text_align
15
+ - button_link
16
+ - button_text
17
+ - :template: card_normal_square
18
+ :header: Standard card with square image
19
+ :text: Image, header, text, normal stuff. No margin between image and text.
20
+ Text alignment option. Also option to turn upside down with order.
21
+ Images can be wide or square, for 2 column 800 wide,
22
+ 3 column 600 , 4 column 400
23
+ :fields:
24
+ - header
25
+ - text
26
+ :options:
27
+ - background
28
+ - text_color
29
+ - text_align
30
+ - order
31
+ - button_link
32
+ - button_text
2
33
  - :template: card_full_image
3
34
  :header: Full background
4
35
  :text: Text in box on top of the imag. Adjustable background
@@ -36,22 +67,6 @@
36
67
  - text_color
37
68
  - order
38
69
  - text_align
39
- - :template: card_normal_square
40
- :header: Standard card with square image
41
- :text: Image, header, text, normal stuff. No margin between image and text.
42
- Text alignment option. Also option to turn upside down with order.
43
- Images can be wide or square, for 2 column 800 wide,
44
- 3 column 600 , 4 column 400
45
- :fields:
46
- - header
47
- - text
48
- :options:
49
- - background
50
- - text_color
51
- - text_align
52
- - order
53
- - button_link
54
- - button_text
55
70
  - :template: card_wide_square
56
71
  :header: Sideway card with square image
57
72
  :text: Much like standard square card, just turned sideways.
@@ -98,21 +113,6 @@
98
113
  - text_align
99
114
  - button_link
100
115
  - button_text
101
- - :template: card_normal_round
102
- :header: Standard card with rounded look
103
- :text: Otherwise quite similar to standard. But there is gap under the image.
104
- Images can be wide or square, for 2 column 800 wide,
105
- 3 column 600 , 4 column 400
106
-
107
- :fields:
108
- - header
109
- - text
110
- :options:
111
- - background
112
- - text_color
113
- - text_align
114
- - button_link
115
- - button_text
116
116
  - :template: form_field
117
117
  :header: A single field in a form
118
118
  :text: The header is the Name of the field, the description
@@ -123,3 +123,13 @@
123
123
  :options:
124
124
  - compulsory
125
125
  - form_type
126
+ - :template: faq_item
127
+ :header: A question answer in an faq section
128
+ :text: The header is the qustion, the description
129
+ is the answer. (No image)
130
+ :fields:
131
+ - header
132
+ - text
133
+ :options:
134
+ - background
135
+ - text_color
@@ -132,3 +132,10 @@
132
132
  :values:
133
133
  :default:
134
134
  :id: 25
135
+ - :name: main_image
136
+ :description: Image that should be shown in posts (fb)
137
+ Should be the number of a breeze picture,
138
+ ie what is in the url eg 381 for /breeze/images/381
139
+ :values:
140
+ :default:
141
+ :id: 26
@@ -6,6 +6,7 @@
6
6
  :options:
7
7
  - title
8
8
  - description
9
+ - main_image
9
10
  - :type: blog
10
11
  :description: An news or similar article.
11
12
  :section_template: blog_header
@@ -30,6 +30,26 @@
30
30
  - item_align
31
31
  - button_link
32
32
  - button_text
33
+ - :template: section_half_slider
34
+ :header: Half text, half slider with optional header with text
35
+ :text: Header. text button on the right (constant) slider left.
36
+ Slider slides any (number) of cards.
37
+ Columns means how many slides are visible on desktop.
38
+ Optional header text on top of the slider (like the section with header/text)
39
+ :cards: true
40
+ :fields:
41
+ - header
42
+ - text
43
+ :options:
44
+ - slider_columns
45
+ - order
46
+ - background
47
+ - text_color
48
+ - margin
49
+ - text_align
50
+ - item_align
51
+ - button_link
52
+ - button_text
33
53
  - :template: section_feature
34
54
  :header: Feature section with 2 column,
35
55
  :text: A split header with two column layout on the right.
@@ -193,3 +213,33 @@
193
213
  - text_columns
194
214
  - background
195
215
  - text_color
216
+ - :template: section_faq
217
+ :header: Faq section with Cards as questions
218
+ :text: A header with text and collapsable faq layout.
219
+ Only works proper with faq_item card style
220
+ :cards: true
221
+ :fields:
222
+ - header
223
+ - text
224
+ :options:
225
+ - background
226
+ - text_color
227
+ - text_align
228
+ - :template: section_slider
229
+ :header: Slider with optional header with text
230
+ :text: Slider slides any (number) of cards. Columns means how many
231
+ slides are visible on desktop.
232
+ Optional header text on top of the slider (like the section with header/text)
233
+ :cards: true
234
+ :fields:
235
+ - header
236
+ - text
237
+ :options:
238
+ - slider_columns
239
+ - background
240
+ - text_color
241
+ - margin
242
+ - text_align
243
+ - item_align
244
+ - button_link
245
+ - button_text
data/lib/breeze/engine.rb CHANGED
@@ -66,7 +66,7 @@ module ActionDispatch::Routing
66
66
  Rails.application.routes.draw do
67
67
  begin
68
68
  if options[:root]
69
- root "breeze/view#page" , id: 'index'
69
+ root "breeze/view#page" , id: 'index'
70
70
  end
71
71
  Breeze.language_strings.each do |lang|
72
72
  get "/#{lang}/:id" , to: "breeze/view#page" , lang: lang , id: :id
@@ -83,7 +83,7 @@ module ActionDispatch::Routing
83
83
 
84
84
  post "/form" , to: "breeze/form#post" , as: :post_form
85
85
  get "/news/:id" , to: "breeze/view#page" , id: :id , as: :view_blog
86
- get ":id" , to: "breeze/view#page" , id: :id , as: :view_page
86
+ get ":id" , to: "breeze/view#page" , id: :id , as: :view_page, constraints: { format: 'html' }
87
87
 
88
88
  engine_path = options[:path] || "/breeze"
89
89
  if ! Rails.env.production? or options[:production].present?
@@ -1,3 +1,3 @@
1
1
  module Breeze
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breeze_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Torsten
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-02-18 00:00:00.000000000 Z
10
+ date: 2025-06-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '7.0'
18
+ version: '7.1'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '7.0'
25
+ version: '7.1'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: rake
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -206,15 +205,18 @@ files:
206
205
  - app/assets/images/breeze/card_preview/card_normal_round.png
207
206
  - app/assets/images/breeze/card_preview/card_normal_square.png
208
207
  - app/assets/images/breeze/card_preview/card_wide_square.png
208
+ - app/assets/images/breeze/card_preview/faq_item.jpg
209
209
  - app/assets/images/breeze/card_preview/form_field.png
210
210
  - app/assets/images/breeze/home.jpg
211
211
  - app/assets/images/breeze/section_preview/blog_header.png
212
212
  - app/assets/images/breeze/section_preview/form_section.png
213
213
  - app/assets/images/breeze/section_preview/section_cards.png
214
+ - app/assets/images/breeze/section_preview/section_faq.jpg
214
215
  - app/assets/images/breeze/section_preview/section_feature.png
215
216
  - app/assets/images/breeze/section_preview/section_full_image.png
216
217
  - app/assets/images/breeze/section_preview/section_full_up.png
217
218
  - app/assets/images/breeze/section_preview/section_half_image.png
219
+ - app/assets/images/breeze/section_preview/section_half_slider.jpg
218
220
  - app/assets/images/breeze/section_preview/section_large_image.png
219
221
  - app/assets/images/breeze/section_preview/section_news.png
220
222
  - app/assets/images/breeze/section_preview/section_slider.png
@@ -296,10 +298,12 @@ files:
296
298
  - app/views/breeze/view/_blog_header.haml
297
299
  - app/views/breeze/view/_form_section.haml
298
300
  - app/views/breeze/view/_section_cards.haml
301
+ - app/views/breeze/view/_section_faq.haml
299
302
  - app/views/breeze/view/_section_feature.haml
300
303
  - app/views/breeze/view/_section_full_image.haml
301
304
  - app/views/breeze/view/_section_full_up.haml
302
305
  - app/views/breeze/view/_section_half_image.haml
306
+ - app/views/breeze/view/_section_half_slider.haml
303
307
  - app/views/breeze/view/_section_large_image.haml
304
308
  - app/views/breeze/view/_section_news.haml
305
309
  - app/views/breeze/view/_section_slider.haml
@@ -314,6 +318,7 @@ files:
314
318
  - app/views/breeze/view/cards/_card_normal_round.haml
315
319
  - app/views/breeze/view/cards/_card_normal_square.haml
316
320
  - app/views/breeze/view/cards/_card_wide_square.haml
321
+ - app/views/breeze/view/cards/_faq_item.haml
317
322
  - app/views/breeze/view/cards/_form_field.haml
318
323
  - app/views/breeze/view/elements/_button.haml
319
324
  - app/views/breeze/view/page.haml
@@ -352,7 +357,6 @@ metadata:
352
357
  homepage_uri: https://breeze.codeberg.page
353
358
  source_code_uri: https://codeberg.org/breeze/breeze
354
359
  changelog_uri: https://codeberg.org/breeze/breeze/src/branch/main/CHANGELOG.md
355
- post_install_message:
356
360
  rdoc_options: []
357
361
  require_paths:
358
362
  - lib
@@ -360,15 +364,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
360
364
  requirements:
361
365
  - - ">="
362
366
  - !ruby/object:Gem::Version
363
- version: 2.7.0
367
+ version: 3.2.0
364
368
  required_rubygems_version: !ruby/object:Gem::Requirement
365
369
  requirements:
366
370
  - - ">="
367
371
  - !ruby/object:Gem::Version
368
372
  version: '0'
369
373
  requirements: []
370
- rubygems_version: 3.5.23
371
- signing_key:
374
+ rubygems_version: 3.6.2
372
375
  specification_version: 4
373
376
  summary: The tailwind based, developers CMS
374
377
  test_files: []