gaco_cms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +48 -0
  3. data/Rakefile +10 -0
  4. data/app/assets/builds/gaco_cms.css +18257 -0
  5. data/app/assets/builds/gaco_cms.js +43235 -0
  6. data/app/assets/builds/gaco_cms.js.map +7 -0
  7. data/app/assets/builds/gaco_cms_front.css +18237 -0
  8. data/app/assets/builds/gaco_cms_front.js +10722 -0
  9. data/app/assets/builds/gaco_cms_front.js.map +7 -0
  10. data/app/assets/javascripts/gaco_cms/base.js +24 -0
  11. data/app/assets/javascripts/gaco_cms/controllers/confirm_controller.ts +20 -0
  12. data/app/assets/javascripts/gaco_cms/controllers/deletable_row_controller.ts +46 -0
  13. data/app/assets/javascripts/gaco_cms/controllers/editor_controller.ts +58 -0
  14. data/app/assets/javascripts/gaco_cms/controllers/file_input_controller.ts +82 -0
  15. data/app/assets/javascripts/gaco_cms/controllers/modal_controller.ts +73 -0
  16. data/app/assets/javascripts/gaco_cms/controllers/remote_content_controller.ts +27 -0
  17. data/app/assets/javascripts/gaco_cms/controllers/repeatable_field_controller.ts +26 -0
  18. data/app/assets/javascripts/gaco_cms/controllers/sortable_controller.ts +27 -0
  19. data/app/assets/javascripts/gaco_cms/controllers/toggle_field_controller.ts +37 -0
  20. data/app/assets/javascripts/gaco_cms/controllers/translatable_controller.ts +86 -0
  21. data/app/assets/javascripts/gaco_cms/lib/progress_bar.ts +7 -0
  22. data/app/assets/javascripts/gaco_cms/lib/request.ts +21 -0
  23. data/app/assets/javascripts/gaco_cms/lib/turbo_request.ts +61 -0
  24. data/app/assets/javascripts/gaco_cms/stimulus.ts +9 -0
  25. data/app/assets/javascripts/gaco_cms.js +7 -0
  26. data/app/assets/javascripts/gaco_cms_front.js +3 -0
  27. data/app/assets/stylesheets/gaco_cms/bootstrap_custom.scss +15 -0
  28. data/app/assets/stylesheets/gaco_cms/shared.scss +22 -0
  29. data/app/assets/stylesheets/gaco_cms.css.scss +8 -0
  30. data/app/assets/stylesheets/gaco_cms_front.css.scss +6 -0
  31. data/app/controllers/concerns/gaco_cms/turbo_concern.rb +52 -0
  32. data/app/controllers/gaco_cms/admin/base_controller.rb +20 -0
  33. data/app/controllers/gaco_cms/admin/field_groups_controller.rb +87 -0
  34. data/app/controllers/gaco_cms/admin/field_groups_manager_controller.rb +66 -0
  35. data/app/controllers/gaco_cms/admin/field_groups_renderer_controller.rb +33 -0
  36. data/app/controllers/gaco_cms/admin/fields_controller.rb +20 -0
  37. data/app/controllers/gaco_cms/admin/page_types_controller.rb +56 -0
  38. data/app/controllers/gaco_cms/admin/pages_controller.rb +70 -0
  39. data/app/controllers/gaco_cms/admin/themes_controller.rb +55 -0
  40. data/app/controllers/gaco_cms/admin_controller.rb +47 -0
  41. data/app/controllers/gaco_cms/front_controller.rb +39 -0
  42. data/app/helpers/gaco_cms/application_helper.rb +26 -0
  43. data/app/jobs/gaco_cms/application_job.rb +6 -0
  44. data/app/mailers/gaco_cms/application_mailer.rb +8 -0
  45. data/app/models/concerns/gaco_cms/fields_assignable.rb +40 -0
  46. data/app/models/concerns/gaco_cms/union_scope.rb +14 -0
  47. data/app/models/gaco_cms/application_record.rb +25 -0
  48. data/app/models/gaco_cms/draft_record.rb +16 -0
  49. data/app/models/gaco_cms/field.rb +78 -0
  50. data/app/models/gaco_cms/field_group.rb +55 -0
  51. data/app/models/gaco_cms/field_value.rb +77 -0
  52. data/app/models/gaco_cms/media_file.rb +22 -0
  53. data/app/models/gaco_cms/page.rb +57 -0
  54. data/app/models/gaco_cms/page_type.rb +38 -0
  55. data/app/models/gaco_cms/theme.rb +28 -0
  56. data/app/services/gaco_cms/application_service.rb +33 -0
  57. data/app/services/gaco_cms/shortcode_parser.rb +217 -0
  58. data/app/services/gaco_cms/theme_content_generator.rb +55 -0
  59. data/app/views/gaco_cms/admin/base/index.html.haml +4 -0
  60. data/app/views/gaco_cms/admin/field_groups_manager/_field.html.haml +53 -0
  61. data/app/views/gaco_cms/admin/field_groups_manager/_group.html.haml +54 -0
  62. data/app/views/gaco_cms/admin/field_groups_manager/index.html.haml +14 -0
  63. data/app/views/gaco_cms/admin/field_groups_renderer/_field.html.haml +31 -0
  64. data/app/views/gaco_cms/admin/field_groups_renderer/_fields_frame.html.haml +16 -0
  65. data/app/views/gaco_cms/admin/field_groups_renderer/_group.html.haml +24 -0
  66. data/app/views/gaco_cms/admin/field_groups_renderer/default_value/_page.html.haml +3 -0
  67. data/app/views/gaco_cms/admin/field_groups_renderer/fields/_editor.html.haml +3 -0
  68. data/app/views/gaco_cms/admin/field_groups_renderer/fields/_file.html.haml +4 -0
  69. data/app/views/gaco_cms/admin/field_groups_renderer/fields/_page.html.haml +3 -0
  70. data/app/views/gaco_cms/admin/field_groups_renderer/fields/_text_area.html.haml +3 -0
  71. data/app/views/gaco_cms/admin/field_groups_renderer/fields/_text_field.html.haml +3 -0
  72. data/app/views/gaco_cms/admin/field_groups_renderer/index.html.haml +20 -0
  73. data/app/views/gaco_cms/admin/page_types/form.html.haml +27 -0
  74. data/app/views/gaco_cms/admin/page_types/index.html.haml +27 -0
  75. data/app/views/gaco_cms/admin/pages/edit.html.haml +57 -0
  76. data/app/views/gaco_cms/admin/pages/index.html.haml +23 -0
  77. data/app/views/gaco_cms/admin/pages/new.html.haml +16 -0
  78. data/app/views/gaco_cms/admin/themes/edit.html.haml +36 -0
  79. data/app/views/gaco_cms/admin/themes/index.html.haml +24 -0
  80. data/app/views/gaco_cms/admin/themes/new.html.haml +21 -0
  81. data/app/views/layouts/gaco_cms/_breadcrumb.html.haml +7 -0
  82. data/app/views/layouts/gaco_cms/_flash_messages.html.haml +13 -0
  83. data/app/views/layouts/gaco_cms/admin.haml +55 -0
  84. data/config/routes.rb +26 -0
  85. data/db/migrate/20230202133738_create_cms_pages.rb +16 -0
  86. data/db/migrate/20230202134840_create_cms_field_groups.rb +17 -0
  87. data/db/migrate/20230202135314_create_cms_fields.rb +21 -0
  88. data/db/migrate/20230202135739_create_cms_field_values.rb +16 -0
  89. data/db/migrate/20230202181744_create_cms_media_files.rb +10 -0
  90. data/db/migrate/20230206231547_create_cms_page_types.rb +23 -0
  91. data/db/migrate/20230209090008_create_cms_themes.rb +19 -0
  92. data/lib/gaco_cms/config.rb +19 -0
  93. data/lib/gaco_cms/engine.rb +31 -0
  94. data/lib/gaco_cms/version.rb +5 -0
  95. data/lib/gaco_cms.rb +18 -0
  96. data/lib/generators/gaco_cms/install_generator.rb +16 -0
  97. data/lib/generators/gaco_cms/install_template/gaco_cms.rb +11 -0
  98. data/lib/generators/gaco_cms/install_template/themes/default/index.html.haml +2 -0
  99. data/lib/generators/gaco_cms/install_template/themes/default/layouts/application.html.haml +34 -0
  100. data/lib/generators/gaco_cms/install_template/themes/default/page.html.haml +2 -0
  101. data/lib/tasks/auto_annotate_models.rake +59 -0
  102. data/lib/tasks/gaco_cms_tasks.rake +5 -0
  103. metadata +174 -0
@@ -0,0 +1,8 @@
1
+ @import './gaco_cms/bootstrap_custom';
2
+ @import 'bootstrap/scss/bootstrap';
3
+
4
+ $fa-font-path: 'assets/gaco_cms/fontawesome/webfonts';
5
+ @import '@fortawesome/fontawesome-free/scss/fontawesome';
6
+ @import "@fortawesome/fontawesome-free/scss/solid.scss";
7
+
8
+ @import './gaco_cms/shared';
@@ -0,0 +1,6 @@
1
+ @import './gaco_cms/bootstrap_custom';
2
+ @import 'bootstrap/scss/bootstrap';
3
+
4
+ $fa-font-path: 'assets/gaco_cms/fontawesome/webfonts';
5
+ @import '@fortawesome/fontawesome-free/scss/fontawesome';
6
+ @import "@fortawesome/fontawesome-free/scss/solid.scss";
@@ -0,0 +1,52 @@
1
+ module GacoCms
2
+ module TurboConcern
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ around_action :parse_turbo_frame, if: -> { turbo_frame_id && request.get? }
6
+ end
7
+
8
+ private
9
+
10
+ def turbo_frame_id
11
+ request.headers['Turbo-Frame']
12
+ end
13
+
14
+ # fix: automatically render content turbo frame caller tag
15
+ def parse_turbo_frame
16
+ begin
17
+ yield
18
+ render_turbo_content(turbo_frame_id) { response.body }
19
+ end
20
+ end
21
+
22
+ def render_turbo_content(target, &block)
23
+ response.content_type = 'text/vnd.turbo-stream.html'
24
+ content = "#{block.call}#{turbo_flash_messages}"
25
+ response.body = turbo_stream_with(:update, content, target: target)
26
+ end
27
+
28
+ # @param e (Exception)
29
+ def print_turbo_error(e)
30
+ Rails.logger.error e.message
31
+ Rails.logger.error e.backtrace.join("\n")
32
+ dev_msg = Rails.env.production? ? '' : " ==> #{e.message}"
33
+ flash[:error] = "#{t('common.internal_error')}. #{dev_msg}"
34
+ end
35
+
36
+ # @return [String]
37
+ def turbo_flash_messages
38
+ flash_messages = render_to_string(partial: '/layouts/gaco_cms/flash_messages')
39
+ return '' unless flash_messages.present?
40
+
41
+ content = turbo_stream_with(:update, flash_messages, target: :toasts)
42
+ flash.clear # clear streamed flash messages
43
+ content
44
+ end
45
+
46
+ def turbo_stream_with(action, content, target: nil, targets: nil)
47
+ "<turbo-stream action='#{action}' #{"target='#{target}'" if target} #{"targets='#{targets}'" if targets}>
48
+ <template>#{content}</template>
49
+ </turbo-stream>"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class BaseController < GacoCms::AdminController
6
+ skip_before_action :verify_authenticity_token, only: :upload_file
7
+
8
+ def upload_file
9
+ file = GacoCms::MediaFile.new(file: params[:file])
10
+ if file.save
11
+ render json: { location: file.url }
12
+ else
13
+ render json: { error: file.errors.full_message.join(', ') }
14
+ end
15
+ end
16
+
17
+ def index; end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class FieldGroupsController < BaseController
6
+ before_action :set_group, except: %i[index new create new_field]
7
+ before_action { add_breadcrumb(FieldGroup.human_name(count: 2), url_for(action: :index)) }
8
+
9
+ def index
10
+ @groups = FieldGroup.ordered.all
11
+ end
12
+
13
+ def new
14
+ @group = FieldGroup.new
15
+ render :form
16
+ end
17
+
18
+ def create
19
+ group = FieldGroup.new(group_params)
20
+ if group.save
21
+ redirect_to url_for(action: :index), notice: 'Group saved'
22
+ else
23
+ render inline: group.errors.full_messages.join(', ')
24
+ end
25
+ end
26
+
27
+ def edit
28
+ render :form
29
+ end
30
+
31
+ def update
32
+ if @group.update(group_params)
33
+ redirect_to url_for(action: :index), notice: 'Group updated'
34
+ else
35
+ render inline: @group.errors.full_messages.join(', ')
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @group.destroy!
41
+ redirect_to url_for(action: :index), notice: 'Group destroyed'
42
+ end
43
+
44
+ def tpl
45
+ locals = { group: @group, field_values: FieldValue.none, group_no: Time.current.to_i }
46
+ render partial: '/gaco_cms/admin/fields/render/group', locals: locals
47
+ end
48
+
49
+ def new_field
50
+ field = Field.new(kind: params[:kind])
51
+ render partial: 'field', locals: { field: field }
52
+ end
53
+
54
+ private
55
+
56
+ def group_params
57
+ fix_record_param
58
+ fix_fields_params
59
+ params.require(:gaco_cms_field_group)
60
+ .permit(:key, :record_id, :record_type, :repeat, :position,
61
+ title: permitted_locales, description: permitted_locales,
62
+ fields_attributes: [:id, :kind, :key, :repeat, :required,
63
+ :translatable, :position, :_destroy,
64
+ { title: permitted_locales, def_value: permitted_locales,
65
+ description: permitted_locales }])
66
+ end
67
+
68
+ def set_group
69
+ @group = FieldGroup.find(params[:id])
70
+ end
71
+
72
+ def fix_record_param
73
+ record = params[:gaco_cms_field_group].delete(:record).to_s
74
+ params[:gaco_cms_field_group][:record_type], params[:gaco_cms_field_group][:record_id] = record.split('/')
75
+ end
76
+
77
+ def fix_fields_params
78
+ items = (params[:fields_attributes] || {}).values
79
+ items.each do |item|
80
+ def_val = item[:def_value]
81
+ item[:def_value] = { en: def_val } if def_val && !def_val.is_a?(Hash)
82
+ end
83
+ params[:gaco_cms_field_group][:fields_attributes] = items
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class FieldGroupsManagerController < BaseController
6
+ before_action :set_record, only: %i[index update]
7
+
8
+ # @option record_type [String]
9
+ # @option record_id [Integer]
10
+ # @option reload_frame [String]
11
+ def index
12
+ @groups = @record.field_groups
13
+ end
14
+
15
+ def group_tpl
16
+ @group = FieldGroup.new
17
+ render partial: 'group', locals: { group: @group }
18
+ end
19
+
20
+ # @option kind [String]
21
+ def field_tpl
22
+ field = Field.new(kind: params[:kind])
23
+ render partial: 'field', locals: { field: field, parent_name: params[:parent_name] }
24
+ end
25
+
26
+ def update
27
+ if @record.update(groups_params)
28
+ render inline: ''
29
+ else
30
+ render inline: @record.errors.full_messages.join(', ')
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # TODO: whitelist record_types
37
+ def set_record
38
+ @record = params[:record_type].constantize.find(params[:record_id])
39
+ end
40
+
41
+ def groups_params
42
+ fix_groups_fields
43
+ fix_fields_params
44
+ fields_attrs = [:id, :kind, :key, :repeat, :required, :translatable, :position, :_destroy,
45
+ :title, :description, { def_value: permitted_locales }]
46
+ params.require(:groups_manager)
47
+ .permit(field_groups_attributes: [:id, :key, :record_id, :record_type, :repeat, :position, :_destroy, :template,
48
+ :title, :description, fields_attributes: fields_attrs])
49
+ end
50
+
51
+ def fix_groups_fields
52
+ params[:groups_manager][:field_groups_attributes] = params[:groups_manager][:field_groups_attributes].values
53
+ end
54
+
55
+ def fix_fields_params
56
+ params[:groups_manager][:field_groups_attributes].each do |group_attrs|
57
+ group_attrs[:fields_attributes] = (group_attrs[:fields_attributes] || {}).values
58
+ group_attrs[:fields_attributes].each do |field_attr|
59
+ def_val = field_attr[:def_value]
60
+ field_attr[:def_value] = { en: def_val } if def_val && !def_val.is_a?(Hash)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class FieldGroupsRendererController < BaseController
6
+ before_action :set_record, only: %i[index update]
7
+
8
+ def index
9
+ @groups = @record.field_groups
10
+ @groups = @record.page_type.field_groups if params[:parent] && @record.is_a?(Page)
11
+ end
12
+
13
+ def render_group
14
+ group = FieldGroup.find(params[:group_id])
15
+ locals = { group: group, field_values: FieldValue.none, group_no: Time.current.to_i }
16
+ render partial: 'group', locals: locals
17
+ end
18
+
19
+ def render_field
20
+ field = Field.find(params[:field_id])
21
+ value = field.field_values.new(group_no: params[:group_no])
22
+ render partial: 'field', locals: { value: value }
23
+ end
24
+
25
+ private
26
+
27
+ # TODO: whitelist record_types
28
+ def set_record
29
+ @record = params[:record_type].constantize.find(params[:record_id])
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class FieldsController < BaseController
6
+ before_action :set_field
7
+
8
+ def tpl
9
+ value = @field.field_values.new(group_no: params[:group_no])
10
+ render partial: '/gaco_cms/admin/fields/render/field', locals: { value: value }
11
+ end
12
+
13
+ private
14
+
15
+ def set_field
16
+ @field = Field.find(params[:id])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class PageTypesController < BaseController
6
+ before_action :set_page_type, only: %i[edit update destroy]
7
+ before_action { add_breadcrumb(PageType.human_name(count: 2), url_for(action: :index)) }
8
+
9
+ def index
10
+ @page_types = PageType.all.title_ordered
11
+ end
12
+
13
+ def new
14
+ @page_type = PageType.new
15
+ render :form
16
+ end
17
+
18
+ def create
19
+ page_type = PageType.new(page_type_params)
20
+ if page_type.save
21
+ redirect_to url_for(action: :index), notice: 'PageType saved'
22
+ else
23
+ render inline: page_type.errors.full_message.join(', ')
24
+ end
25
+ end
26
+
27
+ def edit
28
+ render :form
29
+ end
30
+
31
+ def update
32
+ if @page_type.update(page_type_params)
33
+ redirect_to url_for(action: :index), notice: 'PageType saved'
34
+ else
35
+ render inline: @page_type.errors.full_message.join(', ')
36
+ end
37
+ end
38
+
39
+ def destroy
40
+ @page_type.destroy!
41
+ redirect_to url_for(action: :index), notice: 'PageType destroyed'
42
+ end
43
+
44
+ private
45
+
46
+ def page_type_params
47
+ params.require(:gaco_cms_page_type)
48
+ .permit(:key, :template, title: permitted_locales)
49
+ end
50
+
51
+ def set_page_type
52
+ @page_type = PageType.find(params[:id])
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class PagesController < BaseController
6
+ before_action :set_page_type
7
+ before_action :set_page, only: %i[edit update destroy]
8
+ before_action :set_breadcrumb
9
+
10
+ def index
11
+ @pages = @page_type.pages.title_ordered
12
+ end
13
+
14
+ def new
15
+ @page = @page_type.pages.new
16
+ end
17
+
18
+ def create
19
+ page = @page_type.pages.new(page_params)
20
+ if page.save
21
+ redirect_to url_for(action: :edit, id: page), notice: 'Page created'
22
+ else
23
+ render inline: page.errors.full_messages.join(', ')
24
+ end
25
+ end
26
+
27
+ def edit; end
28
+
29
+ def update
30
+ if @page.update(page_params)
31
+ render inline: ''
32
+ else
33
+ render inline: @page.errors.full_messages.join(', ')
34
+ end
35
+ end
36
+
37
+ def destroy
38
+ @page.destroy!
39
+ redirect_to url_for(action: :index), notice: 'Page destroyed'
40
+ end
41
+
42
+ private
43
+
44
+ def page_params
45
+ fix_fields_values_param(:gaco_cms_page)
46
+ params.require(:gaco_cms_page)
47
+ .permit(:key, :template, :photo_url,
48
+ content: permitted_locales, summary: permitted_locales, title: permitted_locales,
49
+ field_values_attributes: permitted_field_values_params)
50
+ end
51
+
52
+ def set_page
53
+ @page = @page_type.pages.find(params[:id])
54
+ end
55
+
56
+ def set_page_type
57
+ @page_type = PageType.find(params[:page_type_id])
58
+ end
59
+
60
+ def set_breadcrumb
61
+ type_id = @page_type ? @page_type.id : @page.page_type_id
62
+ name = @page_type ? @page_type.title : @page.page_type.title
63
+ add_breadcrumb(name, edit_gaco_cms_admin_page_type_path(type_id))
64
+
65
+ url = gaco_cms_admin_page_type_pages_path(page_type_id: @page_type ? @page_type.id : @page.page_type_id)
66
+ add_breadcrumb(Page.human_name(count: 2), url)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module Admin
5
+ class ThemesController < BaseController
6
+ before_action :set_theme, except: %i[index new create]
7
+ before_action { add_breadcrumb(Theme.human_name(count: 2), url_for(action: :index)) }
8
+
9
+ def index
10
+ @themes = Theme.ordered.all
11
+ end
12
+
13
+ def new
14
+ @theme = Theme.new
15
+ end
16
+
17
+ def create
18
+ theme = Theme.new(theme_params)
19
+ if theme.save
20
+ redirect_to url_for(action: :edit, id: theme), notice: 'Theme created'
21
+ else
22
+ render inline: theme.errors.full_messages.join(', ')
23
+ end
24
+ end
25
+
26
+ def edit; end
27
+
28
+ def update
29
+ if @theme.update(theme_params)
30
+ render inline: ''
31
+ else
32
+ render inline: @theme.errors.full_messages.join(', ')
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ @theme.destroy!
38
+ redirect_to url_for(action: :index), notice: 'Theme destroyed'
39
+ end
40
+
41
+ private
42
+
43
+ def theme_params
44
+ fix_fields_values_param(:gaco_cms_theme)
45
+ params.require(:gaco_cms_theme)
46
+ .permit(:key, :title, :active,
47
+ field_values_attributes: permitted_field_values_params)
48
+ end
49
+
50
+ def set_theme
51
+ @theme = Theme.find(params[:id])
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ class AdminController < GacoCms::Config.parent_backend_controller.constantize
5
+ include GacoCms::TurboConcern
6
+ before_action :gaco_check_authentication
7
+ before_action { add_breadcrumb(:home, gaco_cms_admin_path) }
8
+ layout :gaco_set_layout
9
+ helper_method :ajax_request?
10
+
11
+ private
12
+
13
+ layout :gaco_set_layout
14
+ def gaco_set_layout
15
+ ajax_request? ? false : 'gaco_cms/admin'
16
+ end
17
+
18
+ def ajax_request?
19
+ request.headers[:xhr].present? || request.headers['Turbo-Frame']
20
+ end
21
+
22
+ def add_breadcrumb(label, url = nil)
23
+ @breadcrumbs ||= []
24
+ @breadcrumbs << [label, url]
25
+ end
26
+
27
+ def permitted_locales
28
+ I18n.available_locales
29
+ end
30
+
31
+ def permitted_field_values_params
32
+ [:id, :field_id, :group_no, :position, :_destroy, { value: permitted_locales }]
33
+ end
34
+
35
+ def fix_fields_values_param(param_key)
36
+ values = params[:field_values_attributes]&.values || []
37
+ values.each do |v|
38
+ v[:value] = { I18n.locale => v[:value] } unless v[:value].is_a?(Hash)
39
+ end
40
+ params[param_key][:field_values_attributes] = values
41
+ end
42
+
43
+ def gaco_check_authentication
44
+ # TODO: check admin authentication
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ class FrontController < GacoCms::Config.parent_front_controller.constantize
5
+ layout :gaco_set_layout
6
+ before_action :gaco_set_locale
7
+ helper_method :theme_path_for
8
+ helper_method :current_theme
9
+
10
+ def index
11
+ render theme_path_for(:index)
12
+ end
13
+
14
+ def page
15
+ key = params[:page_id]
16
+ @page = Page.by_key(key) || Page.find(key)
17
+ render theme_path_for(:page)
18
+ end
19
+
20
+ private
21
+
22
+ def gaco_set_layout
23
+ instance_eval(&Config.front_layout)
24
+ end
25
+
26
+ def gaco_set_locale
27
+ session[:gaco_locale] = params[:locale] if params[:locale].present?
28
+ I18n.locale = session[:gaco_locale] if session[:gaco_locale]
29
+ end
30
+
31
+ def theme_path_for(tpl = params[:action])
32
+ "themes/#{current_theme.key}/#{tpl}"
33
+ end
34
+
35
+ def current_theme
36
+ @current_theme ||= Theme.current
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module ApplicationHelper
5
+ def form_title(model)
6
+ model.id ? "Edit #{model.class.human_name}" : "New #{model.class.human_name}"
7
+ end
8
+
9
+ def page_url_for(id)
10
+ Rails.application.routes.url_helpers.gaco_cms_page_path(page_id: id)
11
+ end
12
+ module_function :page_url_for
13
+
14
+ def required_label(form, key, args = {}, &block)
15
+ append = args[:optional] ? capture { block&.call } : "<small>#{capture { block&.call }}(*)</small>"
16
+ form.label(key, args) { |l| "#{args[:label] || l} #{append}".html_safe } # rubocop:disable Rails/OutputSafety
17
+ end
18
+
19
+ def self.translated_value_for(data)
20
+ data = { en: data } unless data.is_a?(Hash)
21
+ data[I18n.locale].presence ||
22
+ data[I18n.default_locale].presence ||
23
+ data.values.find(&:present?)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ class ApplicationJob < ActiveJob::Base
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ class ApplicationMailer < ActionMailer::Base
5
+ default from: 'from@example.com'
6
+ layout 'mailer'
7
+ end
8
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module FieldsAssignable
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ has_many :field_groups, -> { ordered }, as: :record, inverse_of: :record, dependent: :destroy
8
+ has_many :fields, through: :field_groups
9
+ has_many :field_values, dependent: :destroy, as: :record, inverse_of: :record
10
+ accepts_nested_attributes_for :field_values, allow_destroy: true
11
+ accepts_nested_attributes_for :field_groups, allow_destroy: true
12
+ end
13
+
14
+ def the_value(key, cache: true)
15
+ callback = proc { field_values.ordered.find_by(field_key: key)&.the_value }
16
+ return callback.call unless cache
17
+
18
+ Rails.cache.fetch(cache_key_locale(:the_value, key), expires_at: Time.current.end_of_day, &callback)
19
+ end
20
+
21
+ def the_values(key, cache: true)
22
+ callback = proc { field_values.ordered.where(field_key: key).map(&:the_value) }
23
+ return callback.call unless cache
24
+
25
+ Rails.cache.fetch(cache_key_locale(:the_values, key), expires_at: Time.current.end_of_day, &callback)
26
+ end
27
+
28
+ def the_grouped_values(*keys, cache: true)
29
+ callback = proc do
30
+ field_values.where(field_key: keys).grouped.map do |fields|
31
+ fields.map { |f| [f.field_key, f.the_value] }.to_h
32
+ end
33
+ end
34
+ return callback.call unless cache
35
+
36
+ cache_key = cache_key_locale(:the_grouped_values, keys.join('-'))
37
+ Rails.cache.fetch(cache_key, expires_at: Time.current.end_of_day, &callback)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GacoCms
4
+ module UnionScope
5
+ extend ActiveSupport::Concern
6
+ included do
7
+ def self.union_scope(*scopes)
8
+ id_column = "#{table_name}.id"
9
+ sub_query = scopes.map { |s| s.reorder(nil).select(id_column).to_sql }.compact.join(' UNION ')
10
+ where("#{id_column} IN (#{sub_query})")
11
+ end
12
+ end
13
+ end
14
+ end