breeze_cms 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
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")