breeze_cms 0.9.5

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 (151) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +24 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/config/breeze_manifest.js +2 -0
  6. data/app/assets/images/breeze/breeze_logo.png +0 -0
  7. data/app/assets/images/breeze/card_preview/card_feature_box.png +0 -0
  8. data/app/assets/images/breeze/card_preview/card_feature_normal.png +0 -0
  9. data/app/assets/images/breeze/card_preview/card_full_image.png +0 -0
  10. data/app/assets/images/breeze/card_preview/card_gap_square.png +0 -0
  11. data/app/assets/images/breeze/card_preview/card_large_image.png +0 -0
  12. data/app/assets/images/breeze/card_preview/card_normal_round.png +0 -0
  13. data/app/assets/images/breeze/card_preview/card_normal_square.png +0 -0
  14. data/app/assets/images/breeze/card_preview/card_wide_square.png +0 -0
  15. data/app/assets/images/breeze/card_preview/form_field.png +0 -0
  16. data/app/assets/images/breeze/home.jpg +0 -0
  17. data/app/assets/images/breeze/section_preview/blog_header.png +0 -0
  18. data/app/assets/images/breeze/section_preview/form_section.png +0 -0
  19. data/app/assets/images/breeze/section_preview/section_cards.png +0 -0
  20. data/app/assets/images/breeze/section_preview/section_feature.png +0 -0
  21. data/app/assets/images/breeze/section_preview/section_full_image.png +0 -0
  22. data/app/assets/images/breeze/section_preview/section_full_up.png +0 -0
  23. data/app/assets/images/breeze/section_preview/section_half_image.png +0 -0
  24. data/app/assets/images/breeze/section_preview/section_large_image.png +0 -0
  25. data/app/assets/images/breeze/section_preview/section_news.png +0 -0
  26. data/app/assets/images/breeze/section_preview/section_slider.png +0 -0
  27. data/app/assets/images/breeze/section_preview/section_small_image.png +0 -0
  28. data/app/assets/images/breeze/section_preview/section_spacer.png +0 -0
  29. data/app/assets/images/breeze/section_preview/section_text.png +0 -0
  30. data/app/assets/javascript/breeze_application.js.rb +101 -0
  31. data/app/assets/javascript/marked.js +6 -0
  32. data/app/assets/stylesheets/breeze/breeze.css +3633 -0
  33. data/app/assets/stylesheets/breeze/breeze.email.css +1344 -0
  34. data/app/assets/stylesheets/breeze.tailwind.css +2 -0
  35. data/app/assets/stylesheets/breeze_tailwind_styles.css +21 -0
  36. data/app/assets/stylesheets/tailwind_base.css +3 -0
  37. data/app/controllers/breeze/application_controller.rb +4 -0
  38. data/app/controllers/breeze/breeze_controller.rb +16 -0
  39. data/app/controllers/breeze/cards_controller.rb +58 -0
  40. data/app/controllers/breeze/changes_controller.rb +45 -0
  41. data/app/controllers/breeze/form_controller.rb +67 -0
  42. data/app/controllers/breeze/images_controller.rb +100 -0
  43. data/app/controllers/breeze/pages_controller.rb +66 -0
  44. data/app/controllers/breeze/sections_controller.rb +96 -0
  45. data/app/controllers/breeze/styles_controller.rb +11 -0
  46. data/app/controllers/breeze/translations_controller.rb +56 -0
  47. data/app/controllers/breeze/view_controller.rb +10 -0
  48. data/app/helpers/breeze/breeze_helper.rb +54 -0
  49. data/app/helpers/breeze/cards_helper.rb +11 -0
  50. data/app/helpers/breeze/changes_helper.rb +29 -0
  51. data/app/helpers/breeze/form_helper.rb +5 -0
  52. data/app/helpers/breeze/images_helper.rb +57 -0
  53. data/app/helpers/breeze/options_helper.rb +120 -0
  54. data/app/helpers/breeze/pages_helper.rb +5 -0
  55. data/app/helpers/breeze/sections_helper.rb +14 -0
  56. data/app/helpers/breeze/styles_helper.rb +4 -0
  57. data/app/helpers/breeze/translations_helper.rb +14 -0
  58. data/app/helpers/breeze/view_helper.rb +74 -0
  59. data/app/jobs/breeze/application_job.rb +4 -0
  60. data/app/mailers/breeze/application_mailer.rb +6 -0
  61. data/app/models/breeze/active_base.rb +34 -0
  62. data/app/models/breeze/active_yaml.rb +143 -0
  63. data/app/models/breeze/card.rb +90 -0
  64. data/app/models/breeze/card_style.rb +12 -0
  65. data/app/models/breeze/change_set.rb +58 -0
  66. data/app/models/breeze/image.rb +104 -0
  67. data/app/models/breeze/option_definition.rb +43 -0
  68. data/app/models/breeze/page.rb +97 -0
  69. data/app/models/breeze/page_style.rb +12 -0
  70. data/app/models/breeze/section.rb +137 -0
  71. data/app/models/breeze/section_style.rb +17 -0
  72. data/app/models/breeze/shared_base.rb +20 -0
  73. data/app/models/breeze/style.rb +17 -0
  74. data/app/models/breeze/translation.rb +83 -0
  75. data/app/models/breeze/view_base.rb +134 -0
  76. data/app/views/breeze/cards/index.haml +84 -0
  77. data/app/views/breeze/changes/index.haml +52 -0
  78. data/app/views/breeze/form/_editor.haml +33 -0
  79. data/app/views/breeze/form/form.haml +8 -0
  80. data/app/views/breeze/images/_editor.haml +144 -0
  81. data/app/views/breeze/images/index.haml +83 -0
  82. data/app/views/breeze/images/new.haml +12 -0
  83. data/app/views/breeze/images/show.haml +60 -0
  84. data/app/views/breeze/pages/_sections.rabl +4 -0
  85. data/app/views/breeze/pages/index.haml +49 -0
  86. data/app/views/breeze/pages/show.haml +85 -0
  87. data/app/views/breeze/sections/_option_form_date.haml +4 -0
  88. data/app/views/breeze/sections/_option_form_select.haml +4 -0
  89. data/app/views/breeze/sections/_option_form_text.haml +4 -0
  90. data/app/views/breeze/sections/_overlay.haml +33 -0
  91. data/app/views/breeze/sections/_section.rabl +5 -0
  92. data/app/views/breeze/sections/_sections_pagination.haml +29 -0
  93. data/app/views/breeze/sections/index.haml +88 -0
  94. data/app/views/breeze/sections/new.haml +12 -0
  95. data/app/views/breeze/sections/select_card_template.haml +13 -0
  96. data/app/views/breeze/sections/select_template.haml +15 -0
  97. data/app/views/breeze/sections/show.haml +91 -0
  98. data/app/views/breeze/styles/_options.haml +9 -0
  99. data/app/views/breeze/styles/index.haml +84 -0
  100. data/app/views/breeze/translations/_row.haml +29 -0
  101. data/app/views/breeze/translations/show.haml +79 -0
  102. data/app/views/breeze/view/_blog_header.haml +13 -0
  103. data/app/views/breeze/view/_form_section.haml +21 -0
  104. data/app/views/breeze/view/_section_cards.haml +17 -0
  105. data/app/views/breeze/view/_section_feature.haml +13 -0
  106. data/app/views/breeze/view/_section_full_image.haml +10 -0
  107. data/app/views/breeze/view/_section_full_up.haml +11 -0
  108. data/app/views/breeze/view/_section_half_image.haml +13 -0
  109. data/app/views/breeze/view/_section_large_image.haml +13 -0
  110. data/app/views/breeze/view/_section_news.haml +16 -0
  111. data/app/views/breeze/view/_section_slider.haml +51 -0
  112. data/app/views/breeze/view/_section_small_image.haml +11 -0
  113. data/app/views/breeze/view/_section_spacer.haml +1 -0
  114. data/app/views/breeze/view/_section_text.haml +17 -0
  115. data/app/views/breeze/view/cards/_card_feature_box.haml +13 -0
  116. data/app/views/breeze/view/cards/_card_feature_normal.haml +7 -0
  117. data/app/views/breeze/view/cards/_card_full_image.haml +10 -0
  118. data/app/views/breeze/view/cards/_card_gap_square.haml +11 -0
  119. data/app/views/breeze/view/cards/_card_large_image.haml +6 -0
  120. data/app/views/breeze/view/cards/_card_normal_round.haml +8 -0
  121. data/app/views/breeze/view/cards/_card_normal_square.haml +9 -0
  122. data/app/views/breeze/view/cards/_card_wide_square.haml +8 -0
  123. data/app/views/breeze/view/cards/_form_field.haml +8 -0
  124. data/app/views/breeze/view/elements/_button.haml +4 -0
  125. data/app/views/breeze/view/page.haml +2 -0
  126. data/app/views/layouts/breeze/_header.haml +37 -0
  127. data/app/views/layouts/breeze/_messages.haml +28 -0
  128. data/app/views/layouts/breeze/application.haml +20 -0
  129. data/app/views/layouts/mailer.html.haml +8 -0
  130. data/app/views/layouts/mailer.text.erb +1 -0
  131. data/config/breeze/card_styles.yml +129 -0
  132. data/config/breeze/option_definitions.yml +129 -0
  133. data/config/breeze/page_styles.yml +12 -0
  134. data/config/breeze/section_styles.yml +199 -0
  135. data/config/initializers/breeze.rb +13 -0
  136. data/config/initializers/rabl.rb +31 -0
  137. data/config/initializers/simple_form.rb +212 -0
  138. data/config/routes.rb +40 -0
  139. data/config/tailwind.config.js +17 -0
  140. data/config/tailwind.email.js +14 -0
  141. data/lib/breeze/engine.rb +97 -0
  142. data/lib/breeze/shared_helper.rb +44 -0
  143. data/lib/breeze/version.rb +3 -0
  144. data/lib/breeze.rb +104 -0
  145. data/lib/generators/breeze/install/install_generator.rb +19 -0
  146. data/lib/generators/breeze/install/templates/empty.yml +1 -0
  147. data/lib/generators/breeze/install/templates/initializer.rb +70 -0
  148. data/lib/generators/breeze/update/update_generator.rb +11 -0
  149. data/lib/tasks/condense.rake +60 -0
  150. data/lib/tasks/consistency.rake +84 -0
  151. metadata +371 -0
@@ -0,0 +1,84 @@
1
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
2
+ = render "breeze/sections/sections_pagination" , section: @section
3
+ .text-3xl.font-bold.text-gray-900
4
+ = @section.cards.length
5
+ Cards
6
+ = form_tag( breeze.card_new_path(@section.id) , method: :post ) do
7
+ %button.button.change.mr-3{type: :submit} New Card
8
+ .font-bold.text-xl Style
9
+ .text-xl #{@section.card_template}
10
+ = form_tag( breeze.section_select_card_template_path(@section.id), method: :post ) do
11
+ %button.button.action.mr-3{type: :submit} Change Card Style
12
+
13
+ .xl:mx-auto{class: "max-w-[1920px]"}
14
+ = render_section( @section )
15
+
16
+ - @section.cards.each_with_index do |card , index|
17
+ .flex.gap-10.px-20.pt-4.pb-2.mb-2.border.border-2.bg-neutral-50.border-slate-400{ id: "card_#{card.id}"}
18
+ .basis-60
19
+ %h3.mt-4.text-lg.font-bold Card #{index + 1}:#{card.header}
20
+ .flex.flex-wrap
21
+ .p-2
22
+ =link_to(breeze.card_move_path(card.id , dir: :down)) do
23
+ %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"}
24
+ %path{:d => "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
25
+ .p-2
26
+ =link_to(breeze.card_move_path(card.id , dir: :up)) do
27
+ %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"}
28
+ %path{:d => "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
29
+
30
+ .mt-6
31
+ .basis-full.mt-3
32
+ Updated at:
33
+ = distance_of_time_in_words_to_now(card.updated_at)
34
+ .basis-full.mb-3
35
+ Updated by:
36
+ = updated_by(card)
37
+ .basis-full.mb-3
38
+ = form_for( card , {method: :delete } ) do
39
+ %button.button.remove.mt-4{type: :submit} Delete Card
40
+ .flex.justify-between.mt-4
41
+ = simple_form_for( card , method: :patch ) do |f|
42
+ = f.input :section_id , label: "move to section (on this page)" ,
43
+ include_blank: false ,
44
+ collection: card_section_select(card)
45
+ %button.button.change{type: :submit} Move
46
+
47
+ .basis-80
48
+ -if card.image
49
+ = link_to(breeze.images_path(card_id: card.id)) do
50
+ %h3.mt-4.text-lg.font-bold Image #{card.image.name}
51
+ .flex.align-center.justify-between.mb-4
52
+ .text-lg.font-bold.mt-2.mx-2
53
+ = card.image.size.to_s + "k"
54
+ %strong.inline-block.rounded.bg-slate-200.px-3.py-1.text-md.font-medium
55
+ = card.image.aspect_ratio
56
+ = image_for( card , "mb-4")
57
+ .flex.gap-3
58
+ = link_to breeze.images_path(card_id: card.id) do
59
+ %button.button.action Change Image
60
+ = link_to breeze.image_path(card.image.id) do
61
+ %button.button.change Edit Image
62
+ = link_to breeze.card_set_image_path( card.id , image: "") do
63
+ %button.button.remove Remove image
64
+ -else
65
+ %h3.mt-4.text-lg.font-bold No image
66
+ = link_to(breeze.images_path(card_id: card.id)) do
67
+ %button.button.my-3.change Add Image
68
+ .basis-72.grow
69
+ %label.block
70
+ %h4.text-lg.font-bold Texts
71
+ = simple_form_for( card , method: :patch) do |f|
72
+ = f.input :header
73
+ = f.input :text , as: :text , input_html: {rows: rows(card)}
74
+ %button.button.change.mt-4{type: :submit} Update Texts
75
+
76
+ .basis-72.grow
77
+ = form_for( card , {method: :patch }) do
78
+ - card.option_definitions.each do |option|
79
+ .grid.grid-cols-3
80
+ =render "breeze/sections/option_form_#{option.type}" , section: card , option: option
81
+ -if card.option_definitions.empty?
82
+ %p No options
83
+ -else
84
+ %button.button.change.mt-3{type: :submit} Update Options
@@ -0,0 +1,52 @@
1
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
2
+ .text-xl.font-bold.text-gray-900
3
+ Changes
4
+ .text-xl.text-gray-900
5
+ Branch
6
+ = branch
7
+ -if flash.notice
8
+ .m-20.rounded-xl.border.border-gray-100.p-4.shadow-xl
9
+ .flex-1
10
+ %strong.block.font-medium.text-gray-900 Ok
11
+ %p.mt-1.text-sm.text-gray-700
12
+ = markdown flash.notice
13
+
14
+ .overflow-hidden.overflow-x-auto.rounded-lg.border.border-gray-200.m-20
15
+ %table.min-w-full.divide-y.divide-gray-200.text-sm
16
+ %thead.bg-gray-100
17
+ %tr
18
+ %th.whitespace-nowrap.px-4.py-2.text-left.font-medium.text-gray-900
19
+ .flex.items-center.gap-2
20
+ Change
21
+ -[:Page , :Section , :Card , :Image].each do |element|
22
+ %th.whitespace-nowrap.px-4.py-2.text-left.font-medium.text-gray-900
23
+ .flex.items-center.gap-2
24
+ =element
25
+ %tbody.divide-y.divide-gray-200
26
+ -[:add , :edit , :delete].each do |type|
27
+ %tr
28
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
29
+ = type.to_s.capitalize
30
+ -[:Page , :Section , :Card , :Image].each do |element|
31
+ %td.px-4.py-2.text-gray-700
32
+ - changeset(type , element).each do |name|
33
+ =name.last
34
+ %br
35
+
36
+ .grid.grid-cols-3.bg-white
37
+ .items-center.justify-center.col-span-2
38
+ .max-w-xl.px-4.py-8.mx-auto.text-center.commit_changes
39
+ = form_tag( breeze.changes_commit_path() , {method: :post } ) do
40
+ %h1.text-2xl.font-bold.tracking-tight.text-gray-900.sm:text-4xl
41
+ Commit changes
42
+ %p.mt-4.text-gray-500
43
+ %label.block
44
+ %h4.text-lg.font-bold Message (short summary of changes)
45
+ = text_field_tag( :message , "", class: "block w-full rounded-lg border-gray-200 p-4 pr-12 text-sm shadow-sm")
46
+ %button.button.change.mt-3{type: :submit} Commit Changes
47
+
48
+ .max-w-xl.px-4.py-8.mx-auto.text-center.reset_changes
49
+ = form_tag( breeze.changes_reset_path() , {method: :post } ) do
50
+ %h1.text-2xl.font-bold.tracking-tight.text-gray-900.sm:text-4xl
51
+ Reset changes
52
+ %button.button.remove.mt-2{type: :submit} Reset
@@ -0,0 +1,33 @@
1
+ .editor.mt-4
2
+ You can use
3
+ =link_to "markdown" , "https://www.markdown-cheatsheet.com/" , class: :underline, target: :blank
4
+ for styling, use Preview tab to view rendered output. Remember to save!
5
+ -if object.errors and object.errors[field] and ! object.errors[field].blank?
6
+ .text-red-700= "#{field.to_s.capitalize} #{object.errors[field].join( ' ')}"
7
+ %ul.flex.text-center.mt-4.font-bold
8
+ %li.p-2.flex-1.border-t.border-l.border-r.rounded-lg.border-gray-200{"v-bind:class" => "{'bg-gray-50 border-b font-normal': tab == 2}"}
9
+ %a.text-sm{"@click" => "tab = 1"}
10
+ Write text
11
+ %li.p-2.flex-1.border-t.border-l.border-r.rounded-lg.border-gray-200{"v-bind:class" => "{'bg-gray-50 border-b font-normal': tab == 1}"}
12
+ %a.p-4.text-sm{"@click" => "tab = 2"}
13
+ Preview
14
+
15
+ .my-3{"v-bind:class" => "{hidden: tab == 2}"}
16
+ %textarea.w-full{ rows: rows(object.send(field)) ,
17
+ name: "#{object.class.name.downcase}[#{field}]",
18
+ id: "#{object.class.name.downcase}_#{field}" ,
19
+ "v-model": "markdown" }
20
+
21
+ .my-3.prose{"v-html" => "compiledMarkdown" , "v-bind:class" => "{hidden: tab == 1}"}
22
+
23
+ :ruby2js
24
+ class MarkdownEditor < Vue
25
+ options el: '.editor'
26
+ def initialize
27
+ @tab = 1
28
+ @markdown = "#{CGI::escapeHTML(sanitize object.send(field).to_s)}"
29
+ end
30
+ def compiledMarkdown
31
+ marked.parse(@markdown)
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ .flex.flex-col.m-20
2
+ .flex.items-center.justify-center.flex-1
3
+ - @errors.each do |name , message|
4
+ .m-5.rounded.border-l-4.border-green-500.bg-red-50.p-4
5
+ %strong.font-medium.text-red-700= name.capitalize
6
+ .mt-2.text-sm.text-red-700= message
7
+
8
+ = render_section @section
@@ -0,0 +1,144 @@
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
2
+
3
+ %section.image
4
+ .flex.justify-between.mx-20
5
+ .flex.justify-between
6
+ %div.justify-self-start.ml-20.mr-10
7
+ %b Scale {{scaled_x}} x {{scaled_y}}
8
+ %br/
9
+ %input{":min": 20 , ":max": 100 , ":step": 0.1 , :type => "range",
10
+ "v-bind:value": "scale" , "v-on:input" => "handle_scale($event)"}/
11
+
12
+ = form_tag( breeze.image_scale_path(image_id: image.id) ) do
13
+ %input{ hidden: true , id: :scale_id , name: :scale , "v-bind:value": "scale" }
14
+ %button.my-3.button.change Scale {{scale}} %
15
+
16
+ %div.mt-2
17
+ %b.pr-2 Ratio
18
+ %br/
19
+ %em {{ratio}} : 1
20
+
21
+ = form_tag( breeze.image_crop_path(image_id: image.id) ) do
22
+ %input{ hidden: true , id: :width_id , name: :size_x , "v-bind:value": "size_x" }
23
+ %input{ hidden: true , id: :height_id , name: :size_y , "v-bind:value": "size_y" }
24
+ %input{ hidden: true , id: :off_x_id , name: :off_x , "v-bind:value": "off_x" }
25
+ %input{ hidden: true , id: :off_y_id , name: :off_y , "v-bind:value": "off_y" }
26
+ %button.my-3.button.change Crop
27
+
28
+ %div.mt-2.ml-32
29
+ %b.pr-2 Fix ratio to
30
+ %select{ "@change": "set_ratio"}
31
+ %option{value: "0" } Any Ratio
32
+ %option{value: "#{@image.ratio}" } Initial #{@image.ratio.round(2)} : 1
33
+ %option{"v-bind:value": "ratio" } Current {{ratio}} : 1
34
+ -[[4,1],[3,1],[21,9] ,[2,1] ,[16,9] ,[3,2] ,[4,3] ,[1,1] ,[3,4], [2,3],[1,2] ].each do |a|
35
+ %option{value: "#{a.first/a.last.to_f}" } #{a.first} : #{a.last}
36
+
37
+ .flex.justify-between.mb-5
38
+ %div.ml-20
39
+ %b Y Offset {{off_y}}
40
+ %br/
41
+ %input.horizontal{":min": 0 , ":max": "#{image.height}", ":step": 1 , :type => "range",
42
+ "v-bind:value": "off_y" , "v-on:input" => "handle_off_y($event)"}
43
+ %div
44
+ %b X Offset {{off_x}}
45
+ %br/
46
+ %input{":min": 0 , ":max": "#{image.width}", ":step": 1 , :type => "range",
47
+ "v-bind:value": "off_x" , "v-on:input" => "handle_off_x($event)"}
48
+ %div
49
+ %b X Size {{size_x.toFixed(0)}}
50
+ %br/
51
+ %input{":min": 0 , ":max": "#{image.width}", ":step": 1 , :type => "range",
52
+ "v-bind:value": "size_x" , "v-on:input" => "handle_size_x($event)"}
53
+ %div.mr-20
54
+ %b Y Size {{size_y.toFixed(0)}}
55
+ %br
56
+ %input.horizontal{":min": 0 , ":max": "#{image.height}", ":step": 1 , :type => "range",
57
+ "v-bind:value": "size_y" , "v-on:input" => "handle_size_y($event)"}
58
+
59
+ .flex.justify-center
60
+ .image-container.overflow-hidden.relative{ "v-bind:style": "{height: scaled_y + 'px' , width: scaled_x + 'px'} " }
61
+ = image_tag(image.asset_name , class: "")
62
+ .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' }" }
63
+
64
+ :ruby2js
65
+ class Images < Vue
66
+ options el: '.image'
67
+ def initialize
68
+ @image_data = #{@image_data.to_json.html_safe}
69
+ @off_x = 0
70
+ @off_y = 0
71
+ @scale = 100
72
+ @size_x = @image_data[:width]
73
+ @size_y = @image_data[:height]
74
+ @fixed_ratio = 0
75
+ end
76
+ def set_ratio(event)
77
+ @fixed_ratio = event.target.value.to_f
78
+ return if( @fixed_ratio < 0.1)
79
+ if( @fixed_ratio > ratio )
80
+ fix_y(@size_x)
81
+ else
82
+ fix_x(@size_y)
83
+ end
84
+ end
85
+ def fix_x(new_y)
86
+ new_x = (new_y * @fixed_ratio)
87
+ return false if( @off_x + new_x > @image_data[:width])
88
+ @size_x = new_x
89
+ return true
90
+ end
91
+ def fix_y(new_x)
92
+ new_y = (new_x / @fixed_ratio)
93
+ return false if( @off_y + new_y > @image_data[:height])
94
+ @size_y = new_y
95
+ return true
96
+ end
97
+
98
+ def set_size_x( new_x )
99
+ return if( @off_x + new_x > @image_data[:width])
100
+ if (@fixed_ratio >= 0.1 )
101
+ return unless fix_y(new_x)
102
+ end
103
+ @size_x = new_x
104
+ end
105
+
106
+ def set_size_y(new_y)
107
+ return if( @off_y + new_y > @image_data[:height])
108
+ if (@fixed_ratio >= 0.1 )
109
+ return unless fix_x(new_y)
110
+ end
111
+ @size_y = new_y
112
+ end
113
+
114
+ def handle_size_x(event)
115
+ set_size_x(event.target.value.to_f)
116
+ end
117
+ def handle_size_y(event)
118
+ set_size_y( event.target.value.to_f )
119
+ end
120
+ def handle_off_y(event)
121
+ new_off = event.target.value.to_f
122
+ if( new_off + @size_y <= @image_data[:height])
123
+ @off_y = new_off
124
+ end
125
+ end
126
+ def handle_off_x(event)
127
+ new_off = event.target.value.to_f
128
+ if( new_off + @size_x <= @image_data[:width])
129
+ @off_x = new_off
130
+ end
131
+ end
132
+ def handle_scale(event)
133
+ @scale = event.target.value.to_f
134
+ end
135
+ def ratio
136
+ ((@size_x / @size_y)*100).to_i / 100
137
+ end
138
+ def scaled_x
139
+ (@image_data[:width] * @scale / 100).to_i
140
+ end
141
+ def scaled_y
142
+ (@image_data[:height] * @scale / 100).to_i
143
+ end
144
+ end
@@ -0,0 +1,83 @@
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
2
+
3
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16.justify-between
4
+ .flex.gap-20
5
+ .text-xl.font-bold.text-gray-900
6
+ = text_for_index
7
+
8
+ = link_to(breeze.new_image_path(new_link_params) ) do
9
+ .button.action New Image
10
+ = link_to(breeze.images_path(unused: true) ) do
11
+ .button.action Show unused Images
12
+
13
+ .images
14
+ .flex.justify-center.gap-4
15
+
16
+ %label.block
17
+ .mt-1.text-lg.font-bold Search:
18
+ %input.border.rounded{:category => "query", placeholder:"by name", "v-model" => "search_name" }
19
+ %input.border.rounded{:category => "query", placeholder:"by tag", "v-model" => "search_tag" }
20
+
21
+ - ["name" , "created" , "size" , "ratio"].each do |ruby_sort_key|
22
+ .rounded{":class" => "{'border': sort_by == '#{ruby_sort_key}'}"}
23
+ .mx-4.text-lg.font-bold= ruby_sort_key.capitalize
24
+ %a{ "@click" => "sort_by = '#{ruby_sort_key}';sort_dir = 1" , href: "#" ,
25
+ ":class" => "{'bg-cyan-100': sort_dir == 1 && sort_by == '#{ruby_sort_key}'}"}
26
+ %svg.w-6.h-6.mt-1{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
27
+ %path{:d => "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
28
+ %a{ "@click" => "sort_by = '#{ruby_sort_key}';sort_dir = -1" , href: "#" ,
29
+ ":class" => "{'bg-cyan-100': sort_dir == -1 && sort_by == '#{ruby_sort_key}'}"}
30
+ %svg.w-6.h-6.mt-1{:fill => "none", :stroke => "currentColor", "stroke-width" => "1.5", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
31
+ %path{:d => "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3", "stroke-linecap" => "round", "stroke-linejoin" => "round"}
32
+
33
+ .grid.grid-cols-2.lg:grid-cols-4.xl:grid-cols-6.gap-4.m-8
34
+ .flex.flex-col.border.border-gray-100.rounded.image_box{"v-for": "image in filter_and_sort"}
35
+ .flex.align-center.justify-between.mb-4
36
+ .text-lg.font-bold.mt-2.mx-2
37
+ {{image.name}}
38
+ %strong.inline-block.rounded.bg-slate-200.px-3.py-1.text-md.font-medium
39
+ {{image.aspect_ratio}}
40
+ %a.w-full.object-contain.h-72{":href" => "image.link" }
41
+ %img{ ":src": "image.url" , ":alt": "image.name" }
42
+ .flex.justify-between.mb-8
43
+ %strong.inline-block.rounded.bg-orange-50.px-3.py-1.text-md.font-medium
44
+ {{image.size}}k
45
+ %strong.inline-block.rounded.bg-orange-50.px-3.py-1.text-md.font-medium
46
+ {{image.updated_at}}
47
+ %strong.rounded.h-10.bg-orange-50.px-5.py-2.font-medium
48
+ {{image.tags}}
49
+
50
+ .hidden.list
51
+ -@images.each do |image|
52
+ = image_tag(image.asset_name , alt: image.name )
53
+
54
+ :ruby2js
55
+ class Images < Vue
56
+ options el: '.images'
57
+ def initialize
58
+ @image_data = #{@image_data.to_json.html_safe}
59
+ @search_name = ""
60
+ @search_tag = ""
61
+ @sort_by = "created"
62
+ @sort_dir = -1 # 1 up
63
+ end
64
+ def filter_and_sort
65
+ dat = @image_data
66
+ if(@search_name.length > 0)
67
+ dat = dat.filter do |item|
68
+ return item["name"].toLowerCase().indexOf(@search_name) > -1
69
+ end
70
+ end
71
+ if(@search_tag.length > 0)
72
+ dat = dat.filter do |item|
73
+ return (item.tags.toLowerCase().indexOf(@search_tag) > -1)
74
+ end
75
+ end
76
+ dat = dat.slice().sort do |a, b| #a, b image data hashes
77
+ aa = a[@sort_by]
78
+ bb = b[@sort_by]
79
+ return (aa === bb ? 0 : (aa > bb ? 1 : -1) ) * @sort_dir
80
+ end
81
+ dat
82
+ end
83
+ end
@@ -0,0 +1,12 @@
1
+ .grid.grid-cols-3.gap-4.m-8{":class" => "{'hidden': !show_new }"}
2
+ %div
3
+ = form_tag(breeze.images_path, multipart: true) do
4
+ .flex.flex-col.border.border-gray-100.rounded.p-4
5
+ %h3.my-4.text-xl.font-bold= text_for_new
6
+ = text_field_tag 'filename' ,nil, placeholder: "Optional name", class: "rounded mt-4"
7
+ %p.my-4 Name will be taken from uploaded file if not given
8
+ = text_field_tag 'tags' ,nil, placeholder: "Optional tags", class: "rounded mt-4"
9
+ %p.my-4 Tags describe the size or format
10
+ = hidden_for_select_image
11
+ = file_field_tag 'image_file' , class: "mb-8 w-full px-2 text-xl bg-clip-padding border border-solid border-gray-300 rounded"
12
+ %button.button.change{type: :submit} Submit
@@ -0,0 +1,60 @@
1
+ %script{:src => "https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"}
2
+
3
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
4
+ .text-xl.font-bold.text-gray-900
5
+ Image: #{@image.name}
6
+
7
+ = form_tag( breeze.image_copy_path(@image.id) , method: :post) do
8
+ %button.mx-40.button.change Copy
9
+
10
+ .flex.m-20
11
+ .left.flex.gap-2.mt-3
12
+ %p
13
+ .mr-2.font-bold Type
14
+ = @image.type
15
+ %p
16
+ .font-bold Size
17
+ = "#{@image.size}k"
18
+ %p
19
+ .font-bold Ratio
20
+ = @image.ratio.round(2)
21
+ = @image.aspect_ratio
22
+ = form_tag( breeze.image_path , class: "ml-20 flex" , method: :patch) do
23
+ .font-bold.mt-3.mx-4 Name:
24
+ = text_field_tag( "name" , @image.name, class: "rounded border-gray-200 text-sm shadow-sm")
25
+ .font-bold.mt-3.mx-4 Tags:
26
+ = text_field_tag( "tags" , @image.tags, class: "rounded border-gray-200 text-sm shadow-sm")
27
+ %button.mx-4.button.change Update
28
+
29
+
30
+
31
+ =render "editor" , image: @image
32
+ .flex.gap-10.m-20
33
+ -if @used
34
+ .grid.grid-cols-2.gap-10
35
+ .grid.grid-cols-3.gap-10
36
+ %p.col-span-3.font-bold
37
+ Sections using the image
38
+ -@sections.each do |section|
39
+ %p
40
+ = link_to section.header , breeze.section_path(section)
41
+ %p
42
+ %em on Page
43
+ %p
44
+ = link_to section.page.name , breeze.page_sections_path(section.page)
45
+ .grid.grid-cols-3.gap-10
46
+ %p.col-span-3.font-bold
47
+ Cards using the image
48
+ -@cards.each do |card|
49
+ %p
50
+ = link_to card.header , breeze.section_cards_path(card.section)
51
+ %p
52
+ %em on Page
53
+ %p
54
+ = link_to card.section.page.name , breeze.page_sections_path(card.section.page)
55
+
56
+ -else
57
+ %p.align-center Not used, you may delete
58
+ %p
59
+ = form_tag( breeze.image_path(@image.id) , {method: :delete } ) do
60
+ %button.button.remove{type: :submit} Delete
@@ -0,0 +1,4 @@
1
+ collection @page.sections
2
+ node(false) do |section|
3
+ partial('breeze/sections/section', :object => section )
4
+ end
@@ -0,0 +1,49 @@
1
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
2
+ .text-xl.font-bold.text-gray-900
3
+ = link_to( "All" , breeze.pages_path(type: '') , class: "p-2 px-4 border border-gray-200 font-bold rounded-lg hover:bg-sky-100 #{params[:type].blank? ? 'bg-blue-200':''}")
4
+ - @page_styles.each do |style|
5
+ = link_to( "Only #{style.type.capitalize}s" , breeze.pages_path(type: style.type) , class: "p-2 px-4 border border-gray-200 font-bold rounded-lg hover:bg-sky-100 #{(params[:type] == style.type) ? 'bg-blue-200':''}")
6
+
7
+ .overflow-hidden.overflow-x-auto.rounded-lg.border.border-gray-200.mx-6.md:mx-12.mx-20.my-10
8
+ %table.min-w-full.divide-y.divide-gray-200.text-sm
9
+ %thead.bg-gray-100
10
+ %tr
11
+ -["Index", "Name","Sections" ,"Translations" ,"Edited by" ,
12
+ "Updated", "Sections by","Actions"].each do |header|
13
+ %th.whitespace-nowrap.px-4.py-2.text-left.font-medium.text-gray-900
14
+ .flex.items-center.gap-2
15
+ = header
16
+ %tbody.divide-y.divide-gray-200
17
+ - @pages.each do |page|
18
+ %tr{id: page.name}
19
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
20
+ = link_to page.id , breeze.page_path(page.id)
21
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
22
+ = link_to page.name , breeze.page_path(page.id)
23
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
24
+ = page.sections.length
25
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
26
+ = link_to page.missing_translations , breeze.translation_path(page.id)
27
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
28
+ =page.updated_by
29
+ - s = page.sections_update
30
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
31
+ =distance_of_time_in_words_to_now(s&.updated_at) if s
32
+ %td.whitespace-nowrap.px-4.py-2.text-gray-700
33
+ =s.updated_by if s
34
+ %td.whitespace-nowrap.px-4.py-2
35
+ %strong.rounded.bg-green-100.px-3.text-xs.font-medium.text-green-700{:class => "py-1.5"}
36
+ = link_to 'Sections', breeze.page_sections_path(page.id)
37
+ %strong.ml-2.rounded.bg-amber-100.px-3.text-xs.font-medium.text-amber-700{:class => "py-1.5"}
38
+ = link_to 'Edit', breeze.page_path(page.id)
39
+ %strong.ml-2.rounded.bg-blue-100.px-3.text-xs.font-medium.text-amber-700{:class => "py-1.5"}
40
+ =link_to "View live" , "/#{page.name}" , target: page.name
41
+
42
+ .flex.mx-6.md:mx-12.mx-20.new_page
43
+ = form_tag( breeze.pages_path , {method: :post } ) do
44
+ %label.block
45
+ %h4.text-lg.font-bold Name
46
+ = text_field_tag( :name , params[:name], class: "block w-full rounded-lg border-gray-200 p-4 pr-12 text-sm shadow-sm")
47
+ .flex.gap-3.mt-3.justify-between
48
+ - @page_styles.each do |page|
49
+ %button.button.change{name: :type , value: page.type}= "New #{page.type.capitalize}"
@@ -0,0 +1,85 @@
1
+ - @page.sections.each do |section|
2
+ = render_section( section )
3
+
4
+ .mx-6.md:mx-12.mx-20.flex.h-16.items-center.gap-16
5
+ .text-xl.font-bold.text-gray-900
6
+ = @page.type.capitalize
7
+ = ":"
8
+ .text-xl.font-bold.text-gray-900
9
+ =@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)
12
+
13
+ = form_tag( breeze.section_new_path(@page.id), method: :post ) do
14
+ %button.button.change.mr-3{type: :submit} New Section
15
+
16
+ .text-xl
17
+ Edited
18
+ = distance_of_time_in_words_to_now(@page.updated_at)
19
+ 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
+
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
62
+
63
+ -unless @page.redirects.blank?
64
+ .mt-4
65
+ Page redirects from
66
+ = @page.redirects
67
+
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
71
+
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
81
+
82
+ :javascript
83
+ var sections = #{ render( partial: "sections" , formats: :json).html_safe }
84
+
85
+ = render partial: 'breeze/sections/overlay'
@@ -0,0 +1,4 @@
1
+ %label.block
2
+ .mt-4.text-lg.font-bold
3
+ = option.name.camelcase
4
+ .col-span-2= select_date section.option(option.name) , :prefix => "options[#{option.name}]"
@@ -0,0 +1,4 @@
1
+ %label.block
2
+ .mt-4.text-lg.font-bold
3
+ = option.name.camelcase
4
+ .col-span-2= select_tag( "options[#{option.name}]" , options_for_select(option.values, section.option(option.name)), class: "w-full rounded-lg border-gray-200 p-4 pr-12 text-sm shadow-sm")
@@ -0,0 +1,4 @@
1
+ %label.block
2
+ .mt-4.text-lg.font-bold
3
+ = option.name.camelcase
4
+ .col-span-2= text_field_tag( "options[#{option.name}]" , section.option(option.name), class: "w-full rounded-lg border-gray-200 p-4 pr-12 text-sm shadow-sm")