fae-rails 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/app/assets/config/fae/manifest.js +2 -0
  4. data/app/assets/javascripts/fae/_contrast.js +50 -0
  5. data/app/assets/javascripts/fae/_deploy.js +198 -0
  6. data/app/assets/javascripts/fae/_modals.js +94 -0
  7. data/app/assets/javascripts/fae/application.js +7 -1
  8. data/app/assets/javascripts/fae/form/_ajax.js +17 -5
  9. data/app/assets/javascripts/fae/form/_filtering.js +34 -0
  10. data/app/assets/javascripts/fae/form/_form.js +5 -2
  11. data/app/assets/javascripts/fae/form/_form_manager.js +295 -0
  12. data/app/assets/javascripts/fae/form/_slugger.js.erb +2 -2
  13. data/app/assets/javascripts/fae/form/_validator.js +224 -55
  14. data/app/assets/javascripts/fae/form/drag_drop.js +109 -0
  15. data/app/assets/javascripts/fae/form/inputs/_select.js +10 -4
  16. data/app/assets/javascripts/fae/form/inputs/_text.js +23 -9
  17. data/app/assets/javascripts/fae/vendor/simplemde/codemirror-4.inline-attachment.js +95 -0
  18. data/app/assets/javascripts/fae/vendor/simplemde/inline-attachment.js +405 -0
  19. data/app/assets/stylesheets/fae/application.css +1 -0
  20. data/app/assets/stylesheets/fae/base.scss +7 -3
  21. data/app/assets/stylesheets/fae/globals/_tags.scss +1 -1
  22. data/app/assets/stylesheets/fae/globals/imports/_variables.scss +1 -0
  23. data/app/assets/stylesheets/fae/globals/layout/_base.scss +9 -4
  24. data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +14 -4
  25. data/app/assets/stylesheets/fae/globals/legacy/_pre-1.3.scss +1 -1
  26. data/app/assets/stylesheets/fae/globals/navigation/_footer.scss +1 -1
  27. data/app/assets/stylesheets/fae/globals/navigation/_header.scss +3 -3
  28. data/app/assets/stylesheets/fae/globals/navigation/_multi-col-subnav.scss +50 -0
  29. data/app/assets/stylesheets/fae/globals/navigation/_sidenav.scss +2 -2
  30. data/app/assets/stylesheets/fae/globals/navigation/_utility.scss +1 -1
  31. data/app/assets/stylesheets/fae/modules/_buttons.scss +11 -0
  32. data/app/assets/stylesheets/fae/modules/_deploy.scss +25 -0
  33. data/app/assets/stylesheets/fae/modules/_errors-bar.scss +19 -0
  34. data/app/assets/stylesheets/fae/modules/_modal.scss +25 -0
  35. data/app/assets/stylesheets/fae/modules/_toggles.scss +39 -23
  36. data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +1 -1
  37. data/app/assets/stylesheets/fae/modules/forms/_base.scss +14 -1
  38. data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +1 -1
  39. data/app/assets/stylesheets/fae/modules/forms/_date.scss +20 -4
  40. data/app/assets/stylesheets/fae/modules/forms/_form-manager.scss +82 -0
  41. data/app/assets/stylesheets/fae/modules/forms/_hints.scss +1 -1
  42. data/app/assets/stylesheets/fae/modules/forms/_label.scss +1 -1
  43. data/app/assets/stylesheets/fae/modules/forms/_radio.scss +1 -1
  44. data/app/assets/stylesheets/fae/modules/forms/_select.scss +9 -8
  45. data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +72 -1
  46. data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +1 -1
  47. data/app/assets/stylesheets/fae/modules/tables/_base.scss +1 -1
  48. data/app/assets/stylesheets/fae/modules/tables/_filters.scss +4 -0
  49. data/app/assets/stylesheets/fae/modules/tables/_pagination.scss +2 -2
  50. data/app/assets/stylesheets/fae/pages/_error.scss +1 -1
  51. data/app/assets/stylesheets/fae/pages/_login.scss +5 -1
  52. data/app/assets/stylesheets/fae/simplemde_override.scss +32 -0
  53. data/app/controllers/fae/application_controller.rb +9 -2
  54. data/app/controllers/fae/base_controller.rb +6 -2
  55. data/app/controllers/fae/deploy_controller.rb +24 -0
  56. data/app/controllers/fae/deploy_hooks_controller.rb +71 -0
  57. data/app/controllers/fae/form_managers_controller.rb +19 -0
  58. data/app/controllers/fae/options_controller.rb +1 -0
  59. data/app/controllers/fae/setup_controller.rb +2 -2
  60. data/app/controllers/fae/static_pages_controller.rb +6 -1
  61. data/app/controllers/fae/users_controller.rb +11 -1
  62. data/app/controllers/fae/utilities_controller.rb +18 -6
  63. data/app/helpers/fae/application_helper.rb +36 -2
  64. data/app/helpers/fae/form_helper.rb +26 -2
  65. data/app/helpers/fae/view_helper.rb +26 -9
  66. data/app/models/concerns/fae/base_model_concern.rb +17 -0
  67. data/app/models/concerns/fae/seo_set_concern.rb +1 -0
  68. data/app/models/fae/change.rb +20 -6
  69. data/app/models/fae/deploy_hook.rb +12 -0
  70. data/app/models/fae/form_manager.rb +24 -0
  71. data/app/models/fae/option.rb +1 -0
  72. data/app/models/fae/seo_set.rb +14 -0
  73. data/app/models/fae/user.rb +2 -2
  74. data/app/services/fae/netlify_api.rb +213 -0
  75. data/app/uploaders/fae/file_uploader.rb +1 -1
  76. data/app/uploaders/fae/image_uploader.rb +2 -2
  77. data/app/views/devise/unlocks/new.html.slim +5 -9
  78. data/app/views/fae/application/_content_form.html.slim +16 -11
  79. data/app/views/fae/application/_file_uploader.html.slim +7 -2
  80. data/app/views/fae/application/_global_search_results.html.slim +1 -1
  81. data/app/views/fae/application/_header.slim +4 -1
  82. data/app/views/fae/application/_mobilenav.slim +3 -0
  83. data/app/views/fae/application/_seo_set_form.html.slim +12 -0
  84. data/app/views/fae/deploy/index.html.slim +40 -0
  85. data/app/views/fae/deploy_hooks/_form.html.slim +18 -0
  86. data/app/views/fae/deploy_hooks/_table.html.slim +28 -0
  87. data/app/views/fae/deploy_hooks/edit.html.slim +3 -0
  88. data/app/views/fae/deploy_hooks/new.html.slim +3 -0
  89. data/app/views/fae/images/_image_uploader.html.slim +12 -3
  90. data/app/views/fae/options/_form.html.slim +6 -2
  91. data/app/views/fae/pages/activity_log.html.slim +7 -3
  92. data/app/views/fae/pages/home.html.slim +3 -4
  93. data/app/views/fae/shared/_errors.slim +0 -3
  94. data/app/views/fae/shared/_form_header.html.slim +20 -12
  95. data/app/views/fae/shared/_nested_table.html.slim +5 -2
  96. data/app/views/fae/shared/_recent_changes.html.slim +1 -1
  97. data/app/views/fae/shared/_shared_nested_table.html.slim +9 -3
  98. data/app/views/layouts/fae/application.html.slim +2 -1
  99. data/config/deploy.rb +3 -1
  100. data/config/initializers/carrierwave.rb +41 -2
  101. data/config/initializers/devise.rb +6 -6
  102. data/config/initializers/fae_judge.rb +4 -2
  103. data/config/locales/fae.en.yml +49 -4
  104. data/config/locales/fae.zh-CN.yml +2 -2
  105. data/config/puma.rb +82 -0
  106. data/config/routes.rb +9 -1
  107. data/db/migrate/20140809222030_add_user_table.rb +1 -1
  108. data/db/migrate/20190925153222_create_fae_form_managers.rb +11 -0
  109. data/db/migrate/20220118192729_create_fae_publish_hooks.rb +10 -0
  110. data/db/migrate/20220128133730_rename_publish_hooks.rb +5 -0
  111. data/db/migrate/20220202153607_add_position_to_deploy_hooks.rb +6 -0
  112. data/db/migrate/20221118161833_create_fae_seo_sets.rb +13 -0
  113. data/lib/fae/concerns/models/base.rb +2 -0
  114. data/lib/fae/engine.rb +3 -3
  115. data/lib/fae/options.rb +18 -18
  116. data/lib/fae/version.rb +1 -1
  117. data/lib/generators/fae/base_generator.rb +28 -5
  118. data/lib/generators/fae/controller_generator.rb +0 -1
  119. data/lib/generators/fae/install_generator.rb +1 -1
  120. data/lib/generators/fae/model_generator.rb +1 -2
  121. data/lib/generators/fae/nested_index_scaffold_generator.rb +1 -2
  122. data/lib/generators/fae/nested_scaffold_generator.rb +23 -2
  123. data/lib/generators/fae/page_generator.rb +1 -2
  124. data/lib/generators/fae/scaffold_generator.rb +1 -1
  125. data/lib/generators/fae/templates/assets/fae.js +1 -1
  126. data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +13 -1
  127. data/lib/generators/fae/templates/controllers/scaffold_controller.rb +7 -0
  128. data/lib/generators/fae/templates/initializers/fae.rb +16 -1
  129. data/lib/generators/fae/templates/views/_form.html.slim +12 -1
  130. data/lib/generators/fae/templates/views/_form_index_nested.html.slim +15 -1
  131. data/lib/generators/fae/templates/views/_form_nested.html.slim +22 -2
  132. data/lib/generators/fae/templates/views/static_page_form.html.slim +13 -1
  133. metadata +53 -24
  134. data/config/deploy/dev.rb +0 -19
  135. data/config/deploy/prod.rb +0 -19
  136. data/config/deploy/stage.rb +0 -19
  137. /data/app/assets/javascripts/fae/vendor/{simplemde.min.js → simplemde/simplemde.min.js} +0 -0
@@ -13,16 +13,20 @@ module Fae
13
13
  Rails.application.routes.url_helpers.fae_path[1..-1]
14
14
  end
15
15
 
16
- def fae_image_form(f, image_name, label: nil, alt_label: nil, caption_label: nil, show_alt: nil, show_caption: nil, required: nil, helper_text: nil, alt_helper_text: nil, caption_helper_text: nil, attached_as: nil)
17
- render 'fae/images/image_uploader', f: f, image_name: image_name, label: label, alt_label: alt_label, caption_label: caption_label, show_alt: show_alt, show_caption: show_caption, required: required, helper_text: helper_text, alt_helper_text: alt_helper_text, caption_helper_text: caption_helper_text, attached_as: attached_as
16
+ def fae_image_form(f, image_name, label: nil, alt_label: nil, caption_label: nil, show_alt: nil, show_caption: nil, required: nil, helper_text: nil, alt_helper_text: nil, caption_helper_text: nil, attached_as: nil, show_form_manager: true)
17
+ render 'fae/images/image_uploader', f: f, image_name: image_name, label: label, alt_label: alt_label, caption_label: caption_label, show_alt: show_alt, show_caption: show_caption, required: required, helper_text: helper_text, alt_helper_text: alt_helper_text, caption_helper_text: caption_helper_text, attached_as: attached_as, show_form_manager: show_form_manager
18
18
  end
19
19
 
20
- def fae_file_form(f, file_name, label: nil, helper_text: nil, required: nil)
21
- render 'fae/application/file_uploader', f: f, file_name: file_name, label: label, required: required, helper_text: helper_text
20
+ def fae_file_form(f, file_name, label: nil, helper_text: nil, required: nil, show_form_manager: true)
21
+ render 'fae/application/file_uploader', f: f, file_name: file_name, label: label, required: required, helper_text: helper_text, show_form_manager: show_form_manager
22
22
  end
23
23
 
24
- def fae_content_form(f, attribute, label: nil, hint: nil, helper_text: nil, markdown: nil, markdown_supported: nil, input_options: nil)
25
- render 'fae/application/content_form', f: f, attribute: attribute, label: label, hint: hint, helper_text: helper_text, markdown: markdown, markdown_supported: markdown_supported, input_options: input_options
24
+ def fae_content_form(f, attribute, label: nil, hint: nil, helper_text: nil, markdown: nil, markdown_supported: nil, input_options: nil, show_form_manager: true)
25
+ render 'fae/application/content_form', f: f, attribute: attribute, label: label, hint: hint, helper_text: helper_text, markdown: markdown, markdown_supported: markdown_supported, input_options: input_options, show_form_manager: show_form_manager
26
+ end
27
+
28
+ def fae_seo_set_form(f, seo_set_name)
29
+ render 'fae/application/seo_set_form', f: f, seo_set_name: seo_set_name
26
30
  end
27
31
 
28
32
  def fae_index_image(image, path = nil)
@@ -40,9 +44,9 @@ module Fae
40
44
 
41
45
  link_to url, class: "slider-wrapper #{link_class}", method: :post, remote: true do
42
46
  '<div class="slider-options">
43
- <div class="slider-option slider-option-yes">Yes</div>
47
+ <div class="slider-option slider-option-yes" aria-live="polite">Yes</div>
44
48
  <div class="slider-option-selector"></div>
45
- <div class="slider-option slider-option-no">No</div>
49
+ <div class="slider-option slider-option-no" aria-live="polite">No</div>
46
50
  </div>'.html_safe
47
51
  end
48
52
  end
@@ -56,7 +60,11 @@ module Fae
56
60
 
57
61
  def fae_delete_button(item, delete_path = nil, *custom_attrs)
58
62
  return if item.blank?
59
- delete_path ||= polymorphic_path([main_app, fae_scope, item.try(:fae_parent), item])
63
+
64
+ delete_path ||= polymorphic_path(
65
+ [main_app, fae_scope.to_sym, item.try(:fae_parent), item]
66
+ )
67
+
60
68
  attrs = { method: :delete, title: 'Delete', class: 'js-tooltip table-action', data: { confirm: t('fae.delete_confirmation') } }
61
69
  attrs.deep_merge!(custom_attrs[0]) if custom_attrs.present?
62
70
  link_to delete_path, attrs do
@@ -115,6 +123,15 @@ module Fae
115
123
  end
116
124
  end
117
125
 
126
+ def fae_filter_datepicker(attribute, options={})
127
+ options[:label] ||= attribute.to_s.titleize
128
+ options[:placeholder] = options[:label] if options[:placeholder].nil?
129
+ content_tag :div, class: 'table-filter-group text-input datepicker' do
130
+ concat label_tag "filter[#{attribute}]", options[:label]
131
+ concat text_field_tag "filter[#{attribute}]", nil, placeholder: options[:placeholder]
132
+ end
133
+ end
134
+
118
135
  def fae_avatar(user = current_user)
119
136
  hash = Digest::MD5.hexdigest(user.email.downcase)
120
137
  "https://secure.gravatar.com/avatar/#{hash}?s=80&d=mm"
@@ -27,6 +27,15 @@ module Fae
27
27
  "#{fae_nested_parent}_id"
28
28
  end
29
29
 
30
+ def fae_form_manager_model_name
31
+ return 'Fae::StaticPage' if self.class.name.constantize.superclass.name == 'Fae::StaticPage'
32
+ self.class.name
33
+ end
34
+
35
+ def fae_form_manager_model_id
36
+ self.id
37
+ end
38
+
30
39
  module ClassMethods
31
40
  def for_fae_index
32
41
  order(order_method)
@@ -91,6 +100,14 @@ module Fae
91
100
  accepts_nested_attributes_for file_name_symbol, allow_destroy: true
92
101
  end
93
102
 
103
+ def has_fae_seo_set(set_name_symbol)
104
+ has_one set_name_symbol,
105
+ as: :seo_setable,
106
+ class_name: '::Fae::SeoSet',
107
+ dependent: :destroy
108
+ accepts_nested_attributes_for set_name_symbol, allow_destroy: true
109
+ end
110
+
94
111
  end
95
112
 
96
113
  private
@@ -0,0 +1 @@
1
+ module Fae::SeoSetConcern; end
@@ -9,6 +9,7 @@ module Fae
9
9
  serialize :updated_attributes
10
10
 
11
11
  class << self
12
+
12
13
  # writing current_user to thread for thread safety
13
14
  def current_user=(user)
14
15
  Thread.current[:current_user] = user
@@ -28,12 +29,25 @@ module Fae
28
29
  conditions[:user_id] = params['user'] if params['user'].present?
29
30
  conditions[:changeable_type] = params['model'] if params['model'].present?
30
31
  conditions[:change_type] = params['type'] if params['type'].present?
32
+ params['date'] ||= ''
31
33
 
32
- date_scope = case params['date']
33
- when 'Last Hour' then ['fae_changes.updated_at >= ?', 60.minutes.ago]
34
- when 'Last Day' then ['fae_changes.updated_at >= ?', 1.day.ago]
35
- when 'Last Week' then ['fae_changes.updated_at >= ?', 1.week.ago]
36
- when 'Last Month' then ['fae_changes.updated_at >= ?', 1.month.ago]
34
+ date_scope = []
35
+ if params['start_date'].present? || params['end_date'].present?
36
+ start_date = params['start_date'].present? ? CGI.unescape(params['start_date']).to_date : nil
37
+ end_date = params['end_date'].present? ? CGI.unescape(params['end_date']).to_date : nil
38
+ date_scope = ['fae_changes.updated_at >= ?', start_date] if start_date.present?
39
+ date_scope = ['fae_changes.updated_at <= ?', end_date] if end_date.present?
40
+ date_scope = ['fae_changes.updated_at >= ? AND fae_changes.updated_at <= ?', start_date, end_date] if start_date.present? && end_date.present?
41
+ else
42
+ # normalize url param strings because "Last Hour" != "Last%20Hour"
43
+ date_scope = case params['date'].downcase.gsub('%20', '-')
44
+ when 'last-hour' then ['fae_changes.updated_at >= ?', 60.minutes.ago]
45
+ when 'last-day' then ['fae_changes.updated_at >= ?', 1.day.ago]
46
+ when 'last-week' then ['fae_changes.updated_at >= ?', 1.week.ago]
47
+ when 'last-month' then ['fae_changes.updated_at >= ?', 1.month.ago]
48
+ else
49
+ []
50
+ end
37
51
  end
38
52
 
39
53
  # use good 'ol MySQL to search if search param is present
@@ -45,7 +59,7 @@ module Fae
45
59
  # apply conditions and search from above to our scope
46
60
  order(id: :desc)
47
61
  .includes(:user).references(:user)
48
- .where(Arel.sql(date_scope)).where(conditions).where(Arel.sql(search))
62
+ .where(date_scope).where(conditions).where(search)
49
63
  end
50
64
 
51
65
  end
@@ -0,0 +1,12 @@
1
+ module Fae
2
+ class DeployHook < ApplicationRecord
3
+ include Fae::BaseModelConcern
4
+
5
+ acts_as_list add_new_at: :top
6
+ default_scope { order(:position) }
7
+
8
+ default_scope { order(:environment) }
9
+
10
+ validates :url, :environment, presence: true
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ module Fae
2
+ class FormManager < ActiveRecord::Base
3
+
4
+ include Fae::BaseModelConcern
5
+
6
+ def fae_display_field
7
+ model_name
8
+ end
9
+
10
+ class << self
11
+
12
+ def for_model(params, item)
13
+ if item.present? && item.class.superclass.name == 'Fae::StaticPage'
14
+ conditions = {form_manager_model_name: 'Fae::StaticPage', form_manager_model_id: item.fae_form_manager_model_id}
15
+ else
16
+ conditions = {form_manager_model_name: params[:controller].gsub('admin/','').classify}
17
+ end
18
+ where(conditions).first
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -6,6 +6,7 @@ module Fae
6
6
 
7
7
  validates_inclusion_of :singleton_guard, :in => [0]
8
8
  validates_presence_of :title, :time_zone, :live_url
9
+ validates :colorway, format: { with: /(^[0-9a-fA-F]{6}$)|(^$)/, message: "Invalid hex code or doesn't meet length requirement of exactly 6 characters" }
9
10
 
10
11
  has_one :logo, -> { where(attached_as: 'logo' ) },
11
12
  as: :imageable,
@@ -0,0 +1,14 @@
1
+ module Fae
2
+ class SeoSet < ActiveRecord::Base
3
+ include Fae::BaseModelConcern
4
+ include Fae::SeoSetConcern
5
+
6
+ has_fae_image :social_media_image
7
+ belongs_to :seo_setable, polymorphic: true, touch: true, optional: true
8
+
9
+ def fae_display_field
10
+ seo_title
11
+ end
12
+
13
+ end
14
+ end
@@ -5,9 +5,9 @@ module Fae
5
5
  include Fae::UserConcern
6
6
 
7
7
  # Include default devise modules. Others available are:
8
- # :registerable, :confirmable, :lockable, :timeoutable and :omniauthable
8
+ # :registerable, :confirmable, :timeoutable and :omniauthable
9
9
  devise :database_authenticatable,
10
- :recoverable, :rememberable, :trackable
10
+ :recoverable, :rememberable, :trackable, :lockable
11
11
 
12
12
  belongs_to :role
13
13
 
@@ -0,0 +1,213 @@
1
+ require 'net/http'
2
+
3
+ module Fae
4
+ class NetlifyApi
5
+
6
+ def initialize()
7
+ @netlify_api_user = Fae.netlify[:api_user]
8
+ @netlify_api_token = Fae.netlify[:api_token]
9
+ @site = Fae.netlify[:site]
10
+ @site_id = Fae.netlify[:site_id]
11
+ @endpoint_base = Fae.netlify[:api_base]
12
+ @logger = Logger.new(Rails.root.join('log', 'netlify_api.log'))
13
+ end
14
+
15
+ def get_deploys
16
+ path = "sites/#{@site_id}/deploys?per_page=15"
17
+ get_deploys_env_response(path)
18
+ end
19
+
20
+ def run_deploy(deploy_hook_type, current_user)
21
+ hook = Fae::DeployHook.find_by_environment(deploy_hook_type)
22
+ if hook.present?
23
+ post("#{hook.url}?trigger_title=#{current_user.full_name.gsub(' ', '+')}+triggered+a+#{deploy_hook_type.titleize}+deploy")
24
+ return true
25
+ end
26
+ false
27
+ end
28
+
29
+ private
30
+
31
+ def get(endpoint)
32
+ begin
33
+ uri = URI.parse(endpoint)
34
+ request = Net::HTTP::Get.new(uri)
35
+ set_headers(request)
36
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) {|http|
37
+ http.request(request)
38
+ }
39
+ if response.is_a?(Net::HTTPSuccess)
40
+ return JSON.parse(response.body) if response.body.present?
41
+ else
42
+ @logger.info "\n"
43
+ @logger.info "Get returned non-success code: #{response.code}"
44
+ @logger.info "Endpoint: #{endpoint}"
45
+ @logger.info "Body: #{response.body}" if response.body.present?
46
+ end
47
+ rescue Exception => e
48
+ @logger.info "\n"
49
+ @logger.info "Get failed"
50
+ @logger.info "Endpoint: #{endpoint}"
51
+ @logger.info "Reason: #{e}"
52
+ end
53
+ end
54
+
55
+ def post(endpoint, params = nil)
56
+ begin
57
+ uri = URI.parse(endpoint)
58
+ request = Net::HTTP::Post.new(uri)
59
+ set_headers(request)
60
+ request.body = params.to_json
61
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) {|http|
62
+ http.request(request)
63
+ }
64
+ if response.is_a?(Net::HTTPSuccess)
65
+ return JSON.parse(response.body) if response.body.present?
66
+ else
67
+ @logger.info "\n"
68
+ @logger.info "Post returned non-success code: #{response.code}"
69
+ @logger.info "Endpoint: #{endpoint}"
70
+ @logger.info "Params: #{params}"
71
+ @logger.info "Body: #{response.body}" if response.body.present?
72
+ end
73
+ rescue Exception => e
74
+ @logger.info "\n"
75
+ @logger.info "Post failed"
76
+ @logger.info "Endpoint: #{endpoint}"
77
+ @logger.info "Params: #{params}"
78
+ @logger.info "Reason: #{e}"
79
+ end
80
+ end
81
+
82
+ def set_headers(request)
83
+ request['User-Agent'] = "#{@site} (#{@netlify_api_user})"
84
+ request['Authorization'] = "Bearer #{@netlify_api_token}"
85
+ end
86
+
87
+ def get_deploys_env_response(path)
88
+ return get "#{@endpoint_base}#{path}" unless Rails.env.test?
89
+ [
90
+ {
91
+ "state"=>"building",
92
+ "name"=>"building-test",
93
+ "created_at"=>"2021-10-22T14:56:18.163Z",
94
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
95
+ "error_message"=>nil,
96
+ "commit_ref"=>nil,
97
+ "branch"=>"staging",
98
+ "title"=>"Staging building",
99
+ "review_url"=>nil,
100
+ "published_at"=>nil,
101
+ "context"=>"branch-deploy",
102
+ "deploy_time"=>93,
103
+ "committer"=>nil,
104
+ "skipped_log"=>nil,
105
+ "manual_deploy"=>false,
106
+ },
107
+ {
108
+ "state"=>"processing",
109
+ "name"=>"processing-test",
110
+ "created_at"=>"2021-10-22T14:56:18.163Z",
111
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
112
+ "error_message"=>nil,
113
+ "commit_ref"=>nil,
114
+ "branch"=>"staging",
115
+ "title"=>"Staging processing",
116
+ "review_url"=>nil,
117
+ "published_at"=>nil,
118
+ "context"=>"branch-deploy",
119
+ "deploy_time"=>93,
120
+ "committer"=>nil,
121
+ "skipped_log"=>nil,
122
+ "manual_deploy"=>false,
123
+ },
124
+ {
125
+ "state"=>"ready",
126
+ "name"=>"complete-test",
127
+ "created_at"=>"2021-10-22T14:56:18.163Z",
128
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
129
+ "error_message"=>nil,
130
+ "commit_ref"=>'string',
131
+ "branch"=>"staging",
132
+ "title"=>"Staging complete",
133
+ "review_url"=>nil,
134
+ "published_at"=>nil,
135
+ "context"=>"branch-deploy",
136
+ "deploy_time"=>93,
137
+ "committer"=>nil,
138
+ "skipped_log"=>nil,
139
+ "manual_deploy"=>false,
140
+ },
141
+ {
142
+ "state"=>"ready",
143
+ "name"=>"admin-test",
144
+ "created_at"=>"2021-10-22T14:56:18.163Z",
145
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
146
+ "error_message"=>nil,
147
+ "commit_ref"=>nil,
148
+ "branch"=>"staging",
149
+ "title"=>"Staging admin complete",
150
+ "review_url"=>nil,
151
+ "published_at"=>nil,
152
+ "context"=>"branch-deploy",
153
+ "deploy_time"=>93,
154
+ "committer"=>nil,
155
+ "skipped_log"=>nil,
156
+ "manual_deploy"=>false,
157
+ },
158
+ {
159
+ "state"=>"error",
160
+ "name"=>"error-test",
161
+ "created_at"=>"2021-10-22T14:56:18.163Z",
162
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
163
+ "error_message"=>'Error!',
164
+ "commit_ref"=>nil,
165
+ "branch"=>"staging",
166
+ "title"=>"FINE admin triggered a Staging build",
167
+ "review_url"=>nil,
168
+ "published_at"=>nil,
169
+ "context"=>"branch-deploy",
170
+ "deploy_time"=>93,
171
+ "committer"=>nil,
172
+ "skipped_log"=>nil,
173
+ "manual_deploy"=>false,
174
+ },
175
+ {
176
+ "state"=>"ready",
177
+ "name"=>"fae-dummy",
178
+ "created_at"=>"2021-10-22T14:56:18.163Z",
179
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
180
+ "error_message"=>nil,
181
+ "commit_ref"=>nil,
182
+ "branch"=>"master",
183
+ "title"=>"A production build",
184
+ "review_url"=>nil,
185
+ "published_at"=>nil,
186
+ "context"=>"production",
187
+ "deploy_time"=>93,
188
+ "committer"=>nil,
189
+ "skipped_log"=>nil,
190
+ "manual_deploy"=>false,
191
+ },
192
+ {
193
+ "state"=>"ready",
194
+ "name"=>"fae-dummy",
195
+ "created_at"=>"2021-10-22T14:56:18.163Z",
196
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
197
+ "error_message"=>nil,
198
+ "commit_ref"=>nil,
199
+ "branch"=>"master",
200
+ "title"=>"Another production build",
201
+ "review_url"=>nil,
202
+ "published_at"=>nil,
203
+ "context"=>"production",
204
+ "deploy_time"=>93,
205
+ "committer"=>nil,
206
+ "skipped_log"=>nil,
207
+ "manual_deploy"=>false,
208
+ },
209
+ ]
210
+ end
211
+
212
+ end
213
+ end
@@ -18,7 +18,7 @@ module Fae
18
18
 
19
19
  # Add a white list of extensions which are allowed to be uploaded.
20
20
  # For images you might use something like this:
21
- def extension_whitelist
21
+ def extension_allowlist
22
22
  %w(jpg jpeg gif png pdf)
23
23
  end
24
24
 
@@ -10,8 +10,8 @@ module Fae
10
10
  model.file_size = file.size
11
11
  end
12
12
 
13
- def extension_whitelist
14
- %w(jpg jpeg gif png ico)
13
+ def extension_allowlist
14
+ %w(jpg jpeg gif png ico svg)
15
15
  end
16
16
 
17
17
  # Override the directory where uploaded files will be stored.
@@ -1,13 +1,9 @@
1
- h2 Resend unlock instructions
1
+ .login-form
2
+ h2 Resend unlock instructions
2
3
 
3
- = simple_form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f|
4
- = f.error_notification
5
- = f.full_error :unlock_token
4
+ = simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, id: 'login_form' }) do |f|
6
5
 
7
- .form-inputs
8
6
  = f.input :email, :required => true, :autofocus => true
9
7
 
10
- .form-actions
11
- = f.button :submit, "Resend unlock instructions"
12
-
13
- == render "devise/shared/links"
8
+ .login-form-actions
9
+ = f.button :submit, "Resend unlock instructions", class: "login-form-actions-submit"
@@ -1,20 +1,21 @@
1
1
  ruby:
2
- require_locals ['attribute', 'f'], local_assigns
3
- has_label = ![false, ''].include?(local_assigns[:label])
4
- label ||= attribute.to_s.titleize
5
- required ||= f.object.send(attribute).is_required?(f.object.class)
6
- helper_text ||= attempt_common_helper_text(attribute)
7
- markdown ||= false
8
- markdown_supported ||= false
9
- hint ||= nil
10
- options ||= {}
11
- input_options ||= {}
2
+ require_locals ['attribute', 'f'], local_assigns
3
+ has_label = ![false, ''].include?(local_assigns[:label])
4
+ label ||= attribute.to_s.titleize
5
+ required ||= f.object.send(attribute).is_required?(f.object.class)
6
+ helper_text ||= attempt_common_helper_text(attribute)
7
+ markdown ||= false
8
+ markdown_supported ||= false
9
+ hint ||= nil
10
+ options ||= {}
11
+ input_options ||= {}
12
+ show_form_manager ||= true
12
13
 
13
14
  if has_label
14
15
  label_adjusted = required ? '<abbr title="required">*</abbr> ' : ''
15
16
  label_adjusted += label
16
17
  if markdown_supported.present? || helper_text.present?
17
- label_adjusted += content_tag :h6, class: 'helper_text' do
18
+ label_adjusted += content_tag :h6, class: 'helper_text helper_text_text' do
18
19
  concat(helper_text) if helper_text.present?
19
20
  concat(content_tag(:span, 'Markdown Supported', class: 'markdown-support')) if markdown_supported.present?
20
21
  end
@@ -28,6 +29,8 @@ ruby:
28
29
  options.merge! input_options if (input_options.keys).any?
29
30
  options.merge! wrapper_html: {} if input_options[:wrapper_html].blank?
30
31
 
32
+ options.merge! wrapper_html: { data: { form_manager_id: "#{f.object.class.name}_#{attribute}" } } if show_form_manager
33
+
31
34
  if options[:input_html].present? && options[:input_html][:class].present? && markdown.present?
32
35
  options[:input_html][:class] = options[:input_html][:class] + ' js-markdown-editor'
33
36
  elsif options[:input_html].blank?
@@ -45,6 +48,8 @@ ruby:
45
48
  - options.deep_merge! wrapper_html: { data: { language: lang } }
46
49
  - options[:label] = orig_label.gsub(label, "#{label} (#{lang.to_s})").html_safe
47
50
 
51
+ - options.deep_merge! wrapper_html: { data: { form_manager_id: "#{f.object.class.name}_#{attribute}_#{lang}" } } if show_form_manager
52
+
48
53
  = f.simple_fields_for "#{attribute}_#{lang}".to_sym, defaults: { wrapper_html: options[:wrapper_html] } do |i|
49
54
  - options[:input_html].merge! data: { validate: i.object.validation_json(f.object.class) }
50
55
  = i.input :content, options
@@ -8,21 +8,26 @@ ruby:
8
8
  required ||= false
9
9
  languages = f.object.class.try(:fae_fields).try(:[], file_name).try(:[], :languages)
10
10
  language ||= nil
11
+ show_form_manager ||= true
11
12
 
12
13
  - if languages.present?
13
14
  - languages.each do |lang|
14
15
  = render 'fae/application/file_uploader', f: f, item: item, file_name: "#{file_name}_#{lang}".to_sym, label: "#{label} (#{lang.to_s})", helper_text: helper_text, required: required, language: lang
15
16
 
16
17
  - else
18
+ ruby:
19
+ form_manager_id = show_form_manager ? "#{item.class.name}_#{file_name}" : nil
20
+ form_manager_id += "_#{language}" if language.present?
17
21
  - wrapper_html = language.present? ? { data: { language: language } } : {}
18
22
  = f.simple_fields_for file_name, defaults: { wrapper_html: wrapper_html } do |i|
19
- .input.field
23
+ .input.field class="#{file_name}" data-form-manager-id=form_manager_id
20
24
  = content_tag :label, class: ('required' if required) do
21
25
  - if required
22
26
  abbr title="required" *
23
27
  = label.html_safe
24
28
  - if helper_text.present?
25
- h6.helper_text = helper_text
29
+ h6.helper_text
30
+ span.helper_text_text = helper_text
26
31
 
27
32
  - if the_file.asset.present?
28
33
  .asset-actions.-files
@@ -25,7 +25,7 @@ ul.search-results.js-search-results
25
25
  - records.each do |item|
26
26
  - begin
27
27
  - parent = item.respond_to?(:fae_parent) ? item.fae_parent : nil
28
- - edit_path = edit_polymorphic_path([main_app, fae_scope, parent, item])
28
+ - edit_path = edit_polymorphic_path([main_app, fae_scope.to_sym, parent, item])
29
29
  li
30
30
  a href=edit_path
31
31
  span.search-record-label = item.class.name
@@ -9,12 +9,15 @@ header.main-header#js-main-header
9
9
  li class=nav_active_class(item[:class_name], 0, idx)
10
10
  a href=item[:nested_path] = item[:text]
11
11
  - if item[:subitems].present?
12
- ul
12
+ ul class=multi_column_nav_ul_class(item[:subitems])
13
13
  - item[:subitems].each_with_index do |subitem, sub_idx|
14
14
  li: a href=subitem[:nested_path] class=nav_active_class(subitem[:class_name], 1, sub_idx, idx) = subitem[:text]
15
15
 
16
16
  - if user_signed_in?
17
17
  ul.utility-nav#js-utility-nav
18
+ - if current_user.super_admin_or_admin? && netlify_enabled?
19
+ li class=deployments_active_class
20
+ a.deployments-nav-link href=fae.deploy_path = t('fae.navbar.deployments')
18
21
  li.utility-dropdown.js-utility-dropdown
19
22
  a.grabatar-link href="#"
20
23
  img.grabatar src=fae_avatar alt=current_user.full_name
@@ -31,6 +31,9 @@ nav.nav.mobilenav
31
31
  - thirditem[:path] ||= '#'
32
32
  li: a href=thirditem[:path] = thirditem[:text]
33
33
 
34
+ - if current_user.super_admin_or_admin? && netlify_enabled?
35
+ li: a href=fae.deploy_path = t('fae.navbar.deployments')
36
+
34
37
  - if current_user.super_admin_or_admin?
35
38
  li.mobilenav-accordion.js-accordion
36
39
  a href="#" Admin
@@ -0,0 +1,12 @@
1
+ ruby:
2
+ require_locals ['f'], local_assigns
3
+ item ||= f.object
4
+ seo_set_name ||= :seo_set
5
+ the_seo_set = item.send(seo_set_name)
6
+
7
+ = f.simple_fields_for seo_set_name do |i|
8
+ = fae_input i, :seo_title, label: 'SEO Title'
9
+ = fae_input i, :seo_description, label: 'SEO Description'
10
+ = fae_input i, :social_media_title
11
+ = fae_input i, :social_media_description
12
+ = fae_image_form i, :social_media_image, helper_text: '1200 x 630 px., JPG'
@@ -0,0 +1,40 @@
1
+ header.content-header.js-content-header
2
+ h1 = t('fae.deploy.page.heading')
3
+
4
+ == render 'flash_messages'
5
+
6
+ main.content
7
+ - if @deploy_hooks.present?
8
+ - @deploy_hooks.each do |deploy_hook|
9
+ button.button.deploy-button.js-run-deploy data-build-hook-type=deploy_hook.environment href="#" = "#{t('fae.deploy.ctas.deploy')} #{deploy_hook.environment.to_s.titleize}"
10
+
11
+ section.content
12
+ p = t('fae.deploy.table.deploying_helper').html_safe
13
+
14
+ section.content#js-deploying-section
15
+ h2.deploying-heading = t('fae.deploy.table.deploying_heading')
16
+ .js-deploys-list.running
17
+ table
18
+ thead
19
+ tr
20
+ th = t('fae.deploy.table.title')
21
+ th = t('fae.deploy.table.deployed')
22
+ th = t('fae.deploy.table.duration')
23
+ th = t('fae.deploy.table.context')
24
+ th = t('fae.deploy.table.error_msg')
25
+ tbody
26
+
27
+ section.content
28
+ h2 = t('fae.deploy.table.past_heading')
29
+ .js-deploys-list.past
30
+ table
31
+ thead
32
+ tr
33
+ th = t('fae.deploy.table.title')
34
+ th = t('fae.deploy.table.deployed')
35
+ th = t('fae.deploy.table.duration')
36
+ th = t('fae.deploy.table.context')
37
+ th = t('fae.deploy.table.error_msg')
38
+ tbody
39
+
40
+