fae-rails 1.7.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/Rakefile +0 -3
  4. data/app/assets/images/fae/tutorial_model_location.png +0 -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/_tables.js +11 -25
  8. data/app/assets/javascripts/fae/application.js +4 -2
  9. data/app/assets/javascripts/fae/fae_init.js +0 -4
  10. data/app/assets/javascripts/fae/form/_ajax.js +26 -7
  11. data/app/assets/javascripts/fae/form/_cancel.js +1 -0
  12. data/app/assets/javascripts/fae/form/_filtering.js +34 -0
  13. data/app/assets/javascripts/fae/form/_form.js +1 -0
  14. data/app/assets/javascripts/fae/form/_form_manager.js +295 -0
  15. data/app/assets/javascripts/fae/form/_slugger.js.erb +2 -2
  16. data/app/assets/javascripts/fae/form/_validator.js +24 -14
  17. data/app/assets/javascripts/fae/form/inputs/_color.js +2 -1
  18. data/app/assets/javascripts/fae/form/inputs/_select.js +5 -2
  19. data/app/assets/javascripts/fae/navigation/_language.js +1 -1
  20. data/app/assets/javascripts/fae/navigation/_navigation.js +9 -21
  21. data/app/assets/javascripts/fae/navigation/_subnav_highlighter.js +7 -41
  22. data/app/assets/javascripts/fae/vendor/jqColorPicker.min.js +0 -1
  23. data/app/assets/stylesheets/fae/base.scss +7 -8
  24. data/app/assets/stylesheets/fae/globals/imports/_variables.scss +1 -2
  25. data/app/assets/stylesheets/fae/globals/layout/_base.scss +7 -2
  26. data/app/assets/stylesheets/fae/globals/layout/_content-header.scss +17 -31
  27. data/app/assets/stylesheets/fae/globals/navigation/_header.scss +2 -2
  28. data/app/assets/stylesheets/fae/globals/navigation/_multi-col-subnav.scss +50 -0
  29. data/app/assets/stylesheets/fae/modules/_buttons.scss +11 -0
  30. data/app/assets/stylesheets/fae/modules/_deploy.scss +25 -0
  31. data/app/assets/stylesheets/fae/modules/_modal.scss +25 -0
  32. data/app/assets/stylesheets/fae/modules/_toggles.scss +39 -23
  33. data/app/assets/stylesheets/fae/modules/forms/_asset-actions.scss +1 -1
  34. data/app/assets/stylesheets/fae/modules/forms/_base.scss +1 -1
  35. data/app/assets/stylesheets/fae/modules/forms/_checkbox.scss +1 -1
  36. data/app/assets/stylesheets/fae/modules/forms/_date.scss +16 -0
  37. data/app/assets/stylesheets/fae/modules/forms/_form-manager.scss +82 -0
  38. data/app/assets/stylesheets/fae/modules/forms/_radio.scss +1 -1
  39. data/app/assets/stylesheets/fae/modules/forms/_select.scss +7 -6
  40. data/app/assets/stylesheets/fae/modules/forms/_simple-mde.scss +1 -1
  41. data/app/assets/stylesheets/fae/modules/forms/_textarea.scss +1 -1
  42. data/app/assets/stylesheets/fae/modules/tables/_filters.scss +4 -0
  43. data/app/assets/stylesheets/fae/pages/_home.scss +18 -0
  44. data/app/assets/stylesheets/fae/pages/_login.scss +4 -0
  45. data/app/controllers/fae/application_controller.rb +22 -1
  46. data/app/controllers/fae/base_controller.rb +6 -2
  47. data/app/controllers/fae/deploy_controller.rb +24 -0
  48. data/app/controllers/fae/deploy_hooks_controller.rb +71 -0
  49. data/app/controllers/fae/form_managers_controller.rb +19 -0
  50. data/app/controllers/fae/options_controller.rb +1 -0
  51. data/app/controllers/fae/pages_controller.rb +3 -2
  52. data/app/controllers/fae/static_pages_controller.rb +6 -1
  53. data/app/controllers/fae/users_controller.rb +19 -1
  54. data/app/controllers/fae/utilities_controller.rb +18 -6
  55. data/app/helpers/fae/application_helper.rb +27 -2
  56. data/app/helpers/fae/form_helper.rb +40 -8
  57. data/app/helpers/fae/nested_form_helper.rb +2 -2
  58. data/app/helpers/fae/view_helper.rb +99 -43
  59. data/app/models/concerns/fae/base_model_concern.rb +10 -7
  60. data/app/models/concerns/fae/user_concern.rb +10 -1
  61. data/app/models/fae/change.rb +18 -5
  62. data/app/models/fae/deploy_hook.rb +12 -0
  63. data/app/models/fae/file.rb +1 -1
  64. data/app/models/fae/form_manager.rb +24 -0
  65. data/app/models/fae/image.rb +1 -1
  66. data/app/models/fae/option.rb +1 -1
  67. data/app/models/fae/role.rb +1 -1
  68. data/app/models/fae/static_page.rb +11 -2
  69. data/app/models/fae/user.rb +4 -5
  70. data/app/services/fae/netlify_api.rb +197 -0
  71. data/app/uploaders/fae/file_uploader.rb +2 -5
  72. data/app/uploaders/fae/image_uploader.rb +3 -3
  73. data/app/views/devise/unlocks/new.html.slim +5 -9
  74. data/app/views/fae/application/_content_form.html.slim +16 -11
  75. data/app/views/fae/application/_file_uploader.html.slim +11 -3
  76. data/app/views/fae/application/_global_search_results.html.slim +2 -2
  77. data/app/views/fae/application/_header.slim +12 -9
  78. data/app/views/fae/application/_markdown_helper.slim +17 -17
  79. data/app/views/fae/application/_mobilenav.slim +9 -6
  80. data/app/views/fae/application/_user_log.html.slim +2 -2
  81. data/app/views/fae/deploy/index.html.slim +40 -0
  82. data/app/views/fae/deploy_hooks/_form.html.slim +18 -0
  83. data/app/views/fae/deploy_hooks/_table.html.slim +28 -0
  84. data/app/views/fae/deploy_hooks/edit.html.slim +3 -0
  85. data/app/views/fae/deploy_hooks/new.html.slim +3 -0
  86. data/app/views/fae/images/_image_uploader.html.slim +15 -6
  87. data/app/views/fae/options/_form.html.slim +11 -8
  88. data/app/views/fae/pages/activity_log.html.slim +16 -12
  89. data/app/views/fae/pages/disabled_environment.html.slim +2 -2
  90. data/app/views/fae/pages/error404.html.slim +5 -3
  91. data/app/views/fae/pages/home.html.slim +32 -21
  92. data/app/views/fae/setup/first_user.html.slim +3 -3
  93. data/app/views/fae/shared/_form_header.html.slim +37 -33
  94. data/app/views/fae/shared/_index_header.html.slim +3 -2
  95. data/app/views/fae/shared/_nested_table.html.slim +6 -6
  96. data/app/views/fae/shared/_recent_changes.html.slim +6 -6
  97. data/app/views/fae/shared/_shared_nested_table.html.slim +5 -2
  98. data/app/views/fae/static_pages/index.html.slim +2 -2
  99. data/app/views/fae/users/_form.html.slim +8 -12
  100. data/app/views/fae/users/index.html.slim +7 -7
  101. data/app/views/layouts/fae/application.html.slim +1 -0
  102. data/config/deploy.rb +3 -1
  103. data/config/initializers/devise.rb +6 -6
  104. data/config/locales/devise.cs.yml +59 -0
  105. data/config/locales/fae.cs.yml +125 -0
  106. data/config/locales/fae.en.yml +145 -0
  107. data/config/locales/fae.zh-CN.yml +109 -0
  108. data/config/routes.rb +9 -1
  109. data/db/migrate/20140809222030_add_user_table.rb +2 -2
  110. data/db/migrate/20140822224029_create_fae_roles.rb +1 -1
  111. data/db/migrate/20141008180718_create_fae_images_table.rb +1 -1
  112. data/db/migrate/20141017194616_create_fae_options.rb +1 -1
  113. data/db/migrate/20141021181327_create_fae_files.rb +1 -1
  114. data/db/migrate/20141021183047_create_fae_text_areas.rb +1 -1
  115. data/db/migrate/20141021184311_create_fae_pages.rb +1 -1
  116. data/db/migrate/20141105214814_create_fae_text_fields.rb +1 -1
  117. data/db/migrate/20150930224821_create_fae_changes.rb +1 -1
  118. data/db/migrate/20190925153222_create_fae_form_managers.rb +11 -0
  119. data/db/migrate/20220118192729_create_fae_publish_hooks.rb +10 -0
  120. data/db/migrate/20220128133730_rename_publish_hooks.rb +5 -0
  121. data/db/migrate/20220202153607_add_position_to_deploy_hooks.rb +6 -0
  122. data/lib/fae/options.rb +4 -2
  123. data/lib/fae/version.rb +1 -1
  124. data/lib/generators/fae/base_generator.rb +62 -8
  125. data/lib/generators/fae/nested_index_scaffold_generator.rb +1 -1
  126. data/lib/generators/fae/nested_scaffold_generator.rb +16 -2
  127. data/lib/generators/fae/page_generator.rb +8 -0
  128. data/lib/generators/fae/scaffold_generator.rb +1 -1
  129. data/lib/generators/fae/templates/assets/fae.js +1 -1
  130. data/lib/generators/fae/templates/controllers/nested_scaffold_controller.rb +14 -0
  131. data/lib/generators/fae/templates/graphql/graphql_page_type.rb +17 -0
  132. data/lib/generators/fae/templates/graphql/graphql_type.rb +13 -0
  133. data/lib/generators/fae/templates/initializers/fae.rb +16 -1
  134. data/lib/generators/fae/templates/views/_form.html.slim +11 -4
  135. data/lib/generators/fae/templates/views/_form_index_nested.html.slim +15 -1
  136. data/lib/generators/fae/templates/views/_form_nested.html.slim +19 -2
  137. data/lib/generators/fae/templates/views/index_nested.html.slim +1 -0
  138. data/lib/generators/fae/templates/views/static_page_form.html.slim +14 -3
  139. metadata +70 -47
  140. data/app/views/fae/shared/_form_buttons.html.slim +0 -11
  141. data/app/views/fae/shared/_nested_table_advanced.html.slim +0 -18
  142. data/lib/sub_test_task_patch.rb +0 -129
@@ -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)
@@ -45,12 +54,6 @@ module Fae
45
54
  end
46
55
  end
47
56
 
48
- # @depreciation - deprecate in v2.0
49
- def filter_all
50
- # override this method in your model
51
- for_fae_index
52
- end
53
-
54
57
  def filter(params)
55
58
  # override this method in your model
56
59
  for_fae_index
@@ -69,7 +72,7 @@ module Fae
69
72
  end
70
73
  end
71
74
 
72
- def translate(*attributes)
75
+ def fae_translate(*attributes)
73
76
  attributes.each do |attribute|
74
77
  define_method attribute.to_s do
75
78
  self.send "#{attribute}_#{I18n.locale}"
@@ -1 +1,10 @@
1
- module Fae::UserConcern; end
1
+ module Fae
2
+ module UserConcern
3
+ extend ActiveSupport::Concern
4
+ module ClassMethods
5
+ def available_languages
6
+ [:en]
7
+ end
8
+ end
9
+ end
10
+ end
@@ -28,12 +28,25 @@ module Fae
28
28
  conditions[:user_id] = params['user'] if params['user'].present?
29
29
  conditions[:changeable_type] = params['model'] if params['model'].present?
30
30
  conditions[:change_type] = params['type'] if params['type'].present?
31
+ params['date'] ||= ''
31
32
 
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]
33
+ date_scope = []
34
+ if params['start_date'].present? || params['end_date'].present?
35
+ start_date = params['start_date'].present? ? CGI.unescape(params['start_date']).to_date : nil
36
+ end_date = params['end_date'].present? ? CGI.unescape(params['end_date']).to_date : nil
37
+ date_scope = ['fae_changes.updated_at >= ?', start_date] if start_date.present?
38
+ date_scope = ['fae_changes.updated_at <= ?', end_date] if end_date.present?
39
+ date_scope = ['fae_changes.updated_at >= ? AND fae_changes.updated_at <= ?', start_date, end_date] if start_date.present? && end_date.present?
40
+ else
41
+ # normalize url param strings because "Last Hour" != "Last%20Hour"
42
+ date_scope = case params['date'].downcase.gsub('%20', '-')
43
+ when 'last-hour' then ['fae_changes.updated_at >= ?', 60.minutes.ago]
44
+ when 'last-day' then ['fae_changes.updated_at >= ?', 1.day.ago]
45
+ when 'last-week' then ['fae_changes.updated_at >= ?', 1.week.ago]
46
+ when 'last-month' then ['fae_changes.updated_at >= ?', 1.month.ago]
47
+ else
48
+ []
49
+ end
37
50
  end
38
51
 
39
52
  # use good 'ol MySQL to search if search param is present
@@ -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
@@ -14,7 +14,7 @@ module Fae
14
14
  maximum: Fae.max_file_upload_size.megabytes.to_i
15
15
  }
16
16
 
17
- belongs_to :fileable, polymorphic: true, touch: true
17
+ belongs_to :fileable, polymorphic: true, touch: true, optional: true
18
18
 
19
19
  def readonly?
20
20
  false
@@ -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
@@ -17,7 +17,7 @@ module Fae
17
17
  maximum: Fae.max_image_upload_size.megabytes.to_i
18
18
  }
19
19
 
20
- belongs_to :imageable, polymorphic: true, touch: true
20
+ belongs_to :imageable, polymorphic: true, touch: true, optional: true
21
21
 
22
22
  def readonly?
23
23
  false
@@ -27,7 +27,7 @@ module Fae
27
27
  instance = first
28
28
 
29
29
  if instance.blank?
30
- instance = Option.new({title: 'My FINE Admin', time_zone: 'Pacific Time (US & Canada)', live_url: 'http://www.wearefine.com'})
30
+ instance = Option.new({title: 'My Fae Admin', time_zone: 'Pacific Time (US & Canada)', live_url: 'http://www.wearefine.com'})
31
31
  instance.singleton_guard = 0
32
32
  instance.save!
33
33
  end
@@ -7,7 +7,7 @@ module Fae
7
7
  has_many :users
8
8
 
9
9
  acts_as_list add_new_at: :bottom
10
- default_scope { order('-position DESC') }
10
+ default_scope { order(Arel.sql('-position DESC')) }
11
11
 
12
12
  scope :public_roles, -> {where.not(name: 'super admin')}
13
13
 
@@ -42,7 +42,7 @@ module Fae
42
42
  languages.each do |lang|
43
43
  # Save with suffix for form fields
44
44
  define_association("#{name}_#{lang}", type)
45
- define_validations("#{name}_#{lang}", type, value[:validates]) if value.try(:[], :validates).present?
45
+ define_validations("#{name}_#{lang}", type, value[:validates]) if supports_validation(type, value)
46
46
  end
47
47
  # Save with lookup to have default language return in front-end use (don't need to worry about validations here)
48
48
  default_language = Rails.application.config.i18n.default_locale || languages.first
@@ -50,7 +50,7 @@ module Fae
50
50
  else
51
51
  # Normal content_blocks
52
52
  define_association(name, type)
53
- define_validations(name, type, value[:validates]) if value.try(:[], :validates).present?
53
+ define_validations(name, type, value[:validates]) if supports_validation(type, value)
54
54
  end
55
55
  end
56
56
 
@@ -75,6 +75,11 @@ module Fae
75
75
  end
76
76
  end
77
77
 
78
+ def self.supports_validation(type, value)
79
+ # validations are only supported on Fae::TextField and Fae::TextArea
80
+ poly_sym(type) == :contentable && value.try(:[], :validates).present?
81
+ end
82
+
78
83
  def self.poly_sym(assoc)
79
84
  case assoc.name
80
85
  when 'Fae::TextField', 'Fae::TextArea'
@@ -91,6 +96,10 @@ module Fae
91
96
  case assoc_obj.class.name
92
97
  when 'Fae::TextField', 'Fae::TextArea'
93
98
  return assoc_obj.content
99
+ when 'Fae::Image', 'Fae::File'
100
+ assoc_json = assoc_obj.as_json
101
+ assoc_json['asset'] = assoc_obj.asset.as_json
102
+ return assoc_json
94
103
  else
95
104
  return assoc_obj.as_json
96
105
  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
 
@@ -16,9 +16,8 @@ module Fae
16
16
  presence: true,
17
17
  uniqueness: { message: 'That email address is already in use. Give another one a go.' },
18
18
  format: {
19
- with: /^\s*(([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})[\s\/,;]*)+$/i,
20
- message: 'is invalid',
21
- multiline: true
19
+ with: Fae.validation_helpers.email_regex,
20
+ message: 'is invalid'
22
21
  }
23
22
  validates :password,
24
23
  presence: { on: :create },
@@ -0,0 +1,197 @@
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, params = nil)
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
+ return JSON.parse(response.body) if response.present? && response.body.present?
40
+ rescue Exception => e
41
+ @logger.info "\n"
42
+ @logger.info "Failed getting on #{DateTime.now} to #{endpoint}"
43
+ @logger.info "Params: #{params}"
44
+ @logger.info "Reason: #{e}"
45
+ end
46
+ end
47
+
48
+ def post(endpoint, params = nil)
49
+ begin
50
+ uri = URI.parse(endpoint)
51
+ request = Net::HTTP::Post.new(uri)
52
+ set_headers(request)
53
+ request.body = params.to_json
54
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) {|http|
55
+ http.request(request)
56
+ }
57
+ return JSON.parse(response.body) if response.present? && response.body.present?
58
+ rescue Exception => e
59
+ @logger.info "\n"
60
+ @logger.info "Failed posting on #{DateTime.now} to #{endpoint}"
61
+ @logger.info "Params: #{params}"
62
+ @logger.info "Reason: #{e}"
63
+ end
64
+ end
65
+
66
+ def set_headers(request)
67
+ request['User-Agent'] = "#{@site} (#{@netlify_api_user})"
68
+ request['Authorization'] = "Bearer #{@netlify_api_token}"
69
+ end
70
+
71
+ def get_deploys_env_response(path)
72
+ return get "#{@endpoint_base}#{path}" unless Rails.env.test?
73
+ [
74
+ {
75
+ "state"=>"building",
76
+ "name"=>"building-test",
77
+ "created_at"=>"2021-10-22T14:56:18.163Z",
78
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
79
+ "error_message"=>nil,
80
+ "commit_ref"=>nil,
81
+ "branch"=>"staging",
82
+ "title"=>"Staging building",
83
+ "review_url"=>nil,
84
+ "published_at"=>nil,
85
+ "context"=>"branch-deploy",
86
+ "deploy_time"=>93,
87
+ "committer"=>nil,
88
+ "skipped_log"=>nil,
89
+ "manual_deploy"=>false,
90
+ },
91
+ {
92
+ "state"=>"processing",
93
+ "name"=>"processing-test",
94
+ "created_at"=>"2021-10-22T14:56:18.163Z",
95
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
96
+ "error_message"=>nil,
97
+ "commit_ref"=>nil,
98
+ "branch"=>"staging",
99
+ "title"=>"Staging processing",
100
+ "review_url"=>nil,
101
+ "published_at"=>nil,
102
+ "context"=>"branch-deploy",
103
+ "deploy_time"=>93,
104
+ "committer"=>nil,
105
+ "skipped_log"=>nil,
106
+ "manual_deploy"=>false,
107
+ },
108
+ {
109
+ "state"=>"ready",
110
+ "name"=>"complete-test",
111
+ "created_at"=>"2021-10-22T14:56:18.163Z",
112
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
113
+ "error_message"=>nil,
114
+ "commit_ref"=>'string',
115
+ "branch"=>"staging",
116
+ "title"=>"Staging complete",
117
+ "review_url"=>nil,
118
+ "published_at"=>nil,
119
+ "context"=>"branch-deploy",
120
+ "deploy_time"=>93,
121
+ "committer"=>nil,
122
+ "skipped_log"=>nil,
123
+ "manual_deploy"=>false,
124
+ },
125
+ {
126
+ "state"=>"ready",
127
+ "name"=>"admin-test",
128
+ "created_at"=>"2021-10-22T14:56:18.163Z",
129
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
130
+ "error_message"=>nil,
131
+ "commit_ref"=>nil,
132
+ "branch"=>"staging",
133
+ "title"=>"Staging admin complete",
134
+ "review_url"=>nil,
135
+ "published_at"=>nil,
136
+ "context"=>"branch-deploy",
137
+ "deploy_time"=>93,
138
+ "committer"=>nil,
139
+ "skipped_log"=>nil,
140
+ "manual_deploy"=>false,
141
+ },
142
+ {
143
+ "state"=>"error",
144
+ "name"=>"error-test",
145
+ "created_at"=>"2021-10-22T14:56:18.163Z",
146
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
147
+ "error_message"=>'Error!',
148
+ "commit_ref"=>nil,
149
+ "branch"=>"staging",
150
+ "title"=>"FINE admin triggered a Staging build",
151
+ "review_url"=>nil,
152
+ "published_at"=>nil,
153
+ "context"=>"branch-deploy",
154
+ "deploy_time"=>93,
155
+ "committer"=>nil,
156
+ "skipped_log"=>nil,
157
+ "manual_deploy"=>false,
158
+ },
159
+ {
160
+ "state"=>"ready",
161
+ "name"=>"fae-dummy",
162
+ "created_at"=>"2021-10-22T14:56:18.163Z",
163
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
164
+ "error_message"=>nil,
165
+ "commit_ref"=>nil,
166
+ "branch"=>"master",
167
+ "title"=>"A production build",
168
+ "review_url"=>nil,
169
+ "published_at"=>nil,
170
+ "context"=>"production",
171
+ "deploy_time"=>93,
172
+ "committer"=>nil,
173
+ "skipped_log"=>nil,
174
+ "manual_deploy"=>false,
175
+ },
176
+ {
177
+ "state"=>"ready",
178
+ "name"=>"fae-dummy",
179
+ "created_at"=>"2021-10-22T14:56:18.163Z",
180
+ "updated_at"=>"2021-10-22T14:57:55.905Z",
181
+ "error_message"=>nil,
182
+ "commit_ref"=>nil,
183
+ "branch"=>"master",
184
+ "title"=>"Another production build",
185
+ "review_url"=>nil,
186
+ "published_at"=>nil,
187
+ "context"=>"production",
188
+ "deploy_time"=>93,
189
+ "committer"=>nil,
190
+ "skipped_log"=>nil,
191
+ "manual_deploy"=>false,
192
+ },
193
+ ]
194
+ end
195
+
196
+ end
197
+ end
@@ -2,11 +2,8 @@
2
2
  module Fae
3
3
  class FileUploader < CarrierWave::Uploader::Base
4
4
 
5
- # Include RMagick support:
6
- # include CarrierWave::RMagick
7
- include CarrierWave::MimeTypes
5
+ include CarrierWave::MiniMagick
8
6
 
9
- process :set_content_type
10
7
  process :save_file_size_in_model
11
8
 
12
9
  def save_file_size_in_model
@@ -21,7 +18,7 @@ module Fae
21
18
 
22
19
  # Add a white list of extensions which are allowed to be uploaded.
23
20
  # For images you might use something like this:
24
- def extension_white_list
21
+ def extension_whitelist
25
22
  %w(jpg jpeg gif png pdf)
26
23
  end
27
24
 
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
  module Fae
3
3
  class ImageUploader < CarrierWave::Uploader::Base
4
- include CarrierWave::MimeTypes
5
- include CarrierWave::RMagick
4
+
5
+ include CarrierWave::MiniMagick
6
6
 
7
7
  # saves file size to DB
8
8
  process :save_file_size_in_model
@@ -10,7 +10,7 @@ module Fae
10
10
  model.file_size = file.size
11
11
  end
12
12
 
13
- def extension_white_list
13
+ def extension_whitelist
14
14
  %w(jpg jpeg gif png ico)
15
15
  end
16
16
 
@@ -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,27 +8,35 @@ 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
29
34
  a.asset-title href=the_file.asset.url target="_blank" = the_file.asset.file.filename
30
35
 
31
- = link_to '', fae.delete_file_path(the_file.id), class: 'asset-delete js-asset-delete', remote: true, method: :delete, data: { confirm: t('fae.delete_confirmation') }
36
+ - if the_file.id.present?
37
+ = link_to '', fae.delete_file_path(the_file.id), class: 'asset-delete js-asset-delete', remote: true, method: :delete, data: { confirm: t('fae.delete_confirmation') }
38
+ - else
39
+ a.js-file-clear.asset-delete.js-asset-delete
32
40
 
33
41
  .asset-inputs style="#{'display: none;' unless the_file.asset.blank?}"
34
42
  = i.input :asset, as: :file, label: false, input_html: { data: { limit: Fae.max_file_upload_size, exceeded: t('fae.exceeded_upload_limit') } }
@@ -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
@@ -34,4 +34,4 @@ ul.search-results.js-search-results
34
34
 
35
35
  - else
36
36
 
37
- li No results
37
+ li = t('fae.navbar.no_results')
@@ -9,32 +9,35 @@ 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
21
24
  ul
22
- li: a href=fae.destroy_user_session_path Log Out
23
- li: a href=fae.settings_path Your Settings
25
+ li: a href=fae.destroy_user_session_path = t('fae.navbar.logout')
26
+ li: a href=fae.settings_path = t('fae.navbar.your_settings')
24
27
 
25
28
  li.utility-dropdown.js-utility-dropdown
26
29
  a href="#"
27
30
  i.icon-settings
28
31
  ul
29
32
  - if current_user.super_admin_or_admin?
30
- li: a href=fae.users_path Users
31
- li: a href=fae.activity_log_path Activity Log
33
+ li: a href=fae.users_path = t('fae.navbar.users')
34
+ li: a href=fae.activity_log_path = t('fae.navbar.activity_log')
32
35
  - if current_user.super_admin?
33
- li: a href=fae.option_path Root Settings
36
+ li: a href=fae.option_path = t('fae.navbar.root_settings')
34
37
  - if @option.live_url.present?
35
- li: a href=@option.live_url target="_blank" Live Site
38
+ li: a href=@option.live_url target="_blank" = t('fae.application.live_site')
36
39
  - if @option.stage_url.present?
37
- li: a href=@option.stage_url target="_blank" Stage Site
40
+ li: a href=@option.stage_url target="_blank" = t('fae.application.stage_site')
38
41
 
39
42
  li
40
43
  a href=fae.help_path
@@ -45,6 +48,6 @@ header.main-header#js-main-header
45
48
 
46
49
  .utility-search-hit-area#js-utility-search-wrapper
47
50
  .utility-search-wrapper
48
- input#js-global-search type="text" placeholder="Jump to..."
51
+ input#js-global-search type="text" placeholder=t('fae.navbar.jump_to')
49
52
 
50
53
  == render 'global_search_results', show_nav: true