wcc-contentful-app 0.4.0.pre.alpha → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -2
  3. data/README.md +11 -0
  4. data/Rakefile +125 -0
  5. data/app/assets/config/manifest.js +5 -0
  6. data/app/assets/images/down-arrow-primary.svg +3 -0
  7. data/app/assets/images/up-arrow-primary.svg +3 -0
  8. data/app/assets/javascripts/wcc/contentful/app/contact-form.js +70 -0
  9. data/app/assets/javascripts/wcc/contentful/app/index.js +1 -0
  10. data/app/assets/stylesheets/_wcc-contentful-app.scss +7 -0
  11. data/app/assets/stylesheets/components/_menu-item.scss +5 -0
  12. data/app/assets/stylesheets/sections/_faq.scss +39 -0
  13. data/app/controllers/wcc/contentful/app/contact_form_controller.rb +39 -0
  14. data/app/controllers/wcc/contentful/app/pages_controller.rb +48 -0
  15. data/app/helpers/wcc/contentful/app/menu_helper.rb +85 -0
  16. data/app/helpers/wcc/contentful/app/section_helper.rb +135 -0
  17. data/app/mailers/wcc/contentful/app/contact_mailer.rb +11 -0
  18. data/app/models/concerns/wcc/contentful/app/preview_password.rb +19 -0
  19. data/app/models/wcc/contentful/app/contact_form_submission.rb +9 -0
  20. data/app/models/wcc/contentful/app/custom_markdown_render.rb +43 -0
  21. data/app/views/components/_faq_row.html.erb +21 -0
  22. data/app/views/components/_menu-item.html.erb +41 -0
  23. data/app/views/components/_other-menu-item.html.erb +4 -0
  24. data/app/views/components/_section.html.erb +11 -0
  25. data/app/views/layouts/mailer.html.erb +9 -0
  26. data/app/views/layouts/mailer.text.erb +1 -0
  27. data/app/views/pages/show.html.erb +4 -0
  28. data/app/views/sections/_block_text.html.erb +5 -0
  29. data/app/views/sections/_code_widget.html.erb +3 -0
  30. data/app/views/sections/_contact_form.html.erb +53 -0
  31. data/app/views/sections/_faq.html.erb +36 -0
  32. data/app/views/sections/_http_error.html.erb +13 -0
  33. data/app/views/sections/_marquee_text.html.erb +12 -0
  34. data/app/views/sections/_testimonials.html.erb +38 -0
  35. data/app/views/sections/_video.html.erb +12 -0
  36. data/app/views/sections/_video_highlight.html.erb +18 -0
  37. data/app/views/wcc/contentful/app/contact_mailer/contact_form_email.html.erb +7 -0
  38. data/bin/rails +14 -0
  39. data/config/routes.rb +7 -0
  40. data/doc +1 -0
  41. data/lib/generators/wcc/model_generator.rb +16 -6
  42. data/lib/generators/wcc/templates/menu/migrations/generated_add_menus.ts +285 -0
  43. data/lib/generators/wcc/templates/menu/models/dropdown_menu.rb +19 -0
  44. data/lib/generators/wcc/templates/menu/models/menu.rb +0 -4
  45. data/lib/generators/wcc/templates/menu/models/menu_button.rb +0 -4
  46. data/lib/generators/wcc/templates/page/migrations/generated_add_pages.ts +147 -0
  47. data/lib/generators/wcc/templates/page/models/page.rb +0 -4
  48. data/lib/generators/wcc/templates/page/models/redirect.rb +19 -0
  49. data/lib/generators/wcc/templates/section-block-text/migrations/generated_add_section-block-texts.ts +40 -0
  50. data/lib/generators/wcc/templates/section-block-text/models/section_block_text.rb +19 -0
  51. data/lib/generators/wcc/templates/section-code-widget/migrations/generated_add_section-code-widget.ts +90 -0
  52. data/lib/generators/wcc/templates/section-code-widget/models/section_code_widget.rb +23 -0
  53. data/lib/generators/wcc/templates/section-contact-form/migrations/create_wcc_contentful_app_contact_form_submissions.rb +12 -0
  54. data/lib/generators/wcc/templates/section-contact-form/migrations/generated_add_section-contact-forms.ts +147 -0
  55. data/lib/generators/wcc/templates/section-contact-form/models/form_field.rb +19 -0
  56. data/lib/generators/wcc/templates/section-contact-form/models/section_contact_form.rb +19 -0
  57. data/lib/generators/wcc/templates/section-faq/migrations/generated_add_section-faqs.ts +148 -0
  58. data/lib/generators/wcc/templates/section-faq/models/section_faq.rb +19 -0
  59. data/lib/generators/wcc/templates/section-http-error/migrations/generated_add_section-http-errors.ts +87 -0
  60. data/lib/generators/wcc/templates/section-http-error/models/section_http_error.rb +19 -0
  61. data/lib/generators/wcc/templates/section-marquee-text/migrations/generated_add_section-marquee-texts.ts +64 -0
  62. data/lib/generators/wcc/templates/section-marquee-text/models/section_marquee_text.rb +19 -0
  63. data/lib/generators/wcc/templates/section-testimonial/migrations/generated_add_section-testimonials.ts +182 -0
  64. data/lib/generators/wcc/templates/section-testimonial/models/section_testimonial.rb +19 -0
  65. data/lib/generators/wcc/templates/section-video-highlight/migrations/generated_add_section-video-highlights.ts +80 -0
  66. data/lib/generators/wcc/templates/section-video-highlight/models/section_video_highlight.rb +19 -0
  67. data/lib/generators/wcc/templates/section-video/migrations/generated_add_section-videos.ts +77 -0
  68. data/lib/generators/wcc/templates/section-video/models/section_video.rb +19 -0
  69. data/lib/generators/wcc/templates/site-config/migrations/generated_add_site-configs.ts +97 -0
  70. data/lib/generators/wcc/templates/site-config/models/site_config.rb +19 -0
  71. data/lib/generators/wcc/templates/wcc_contentful.rb +1 -1
  72. data/lib/wcc/contentful/app.rb +46 -3
  73. data/lib/wcc/contentful/app/configuration.rb +60 -0
  74. data/lib/wcc/contentful/app/engine.rb +15 -0
  75. data/lib/wcc/contentful/app/exceptions.rb +9 -0
  76. data/lib/wcc/contentful/app/rails.rb +6 -0
  77. data/lib/wcc/contentful/app/version.rb +1 -1
  78. data/lib/wcc/contentful/model/dropdown_menu.rb +0 -3
  79. data/lib/wcc/contentful/model/form_field.rb +4 -0
  80. data/lib/wcc/contentful/model/menu.rb +0 -2
  81. data/lib/wcc/contentful/model/menu_button.rb +18 -5
  82. data/lib/wcc/contentful/model/page.rb +0 -4
  83. data/lib/wcc/contentful/model/redirect.rb +21 -11
  84. data/lib/wcc/contentful/model/section_contact_form.rb +42 -0
  85. data/lib/wcc/contentful/model/site_config.rb +7 -0
  86. data/wcc-contentful-app.gemspec +23 -15
  87. metadata +169 -106
  88. data/Gemfile +0 -8
  89. data/lib/generators/wcc/templates/menu/generated_add_menus.ts +0 -192
  90. data/lib/generators/wcc/templates/page/generated_add_pages.ts +0 -50
  91. data/lib/tasks/validate.rake +0 -20
  92. data/lib/wcc/contentful/app/model_validators.rb +0 -121
  93. data/lib/wcc/contentful/app/model_validators/dsl.rb +0 -166
  94. data/lib/wcc/contentful/ext/model.rb +0 -5
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This model represents the 'section-testimonials' content type in Contentful. Any linked
4
+ # entries of the 'section-testimonials' content type will be resolved as instances of this class.
5
+ # It exposes .find, .find_by, and .find_all methods to query Contentful.
6
+ class SectionTestimonials < WCC::Contentful::Model::SectionTestimonials
7
+ # Override functionality or add utilities
8
+ #
9
+ # # Example: override equality
10
+ # def ===(other)
11
+ # ...
12
+ # end
13
+ #
14
+ # # Example: override "title" attribute to always be titlecase.
15
+ # # `@title` is populated by the gem in the initializer.
16
+ # def title
17
+ # @title_titlecased ||= @title.titlecase
18
+ # end
19
+ end
@@ -0,0 +1,80 @@
1
+ import Migration, { MigrationFunction } from '@watermarkchurch/contentful-migration'
2
+
3
+ // Generated by contentful-schema-diff
4
+ // from empty-export.json
5
+ // to 7yx6ovlj39n5
6
+ export = function(migration : Migration, { makeRequest, spaceId, accessToken }) {
7
+
8
+ /************ section-video-highlight ******************/
9
+
10
+ var sectionVideoHighlight = migration.createContentType('section-video-highlight', {
11
+ displayField: 'internalTitle',
12
+ name: 'Section: Video Highlight',
13
+ description: 'Highlight a video with some text'
14
+ })
15
+
16
+ sectionVideoHighlight.createField('internalTitle', {
17
+ name: 'Internal Title (Contentful Only)',
18
+ type: 'Symbol',
19
+ localized: false,
20
+ required: true,
21
+ validations: [],
22
+ disabled: false,
23
+ omitted: true
24
+ })
25
+
26
+ sectionVideoHighlight.createField('tag', {
27
+ name: 'Tag',
28
+ type: 'Symbol',
29
+ localized: true,
30
+ required: false,
31
+ validations:
32
+ [{
33
+ size: { min: 0, max: 75 },
34
+ message: 'Tag must be short!'
35
+ }],
36
+ disabled: false,
37
+ omitted: false
38
+ })
39
+
40
+ sectionVideoHighlight.createField('title', {
41
+ name: 'Title',
42
+ type: 'Symbol',
43
+ localized: false,
44
+ required: true,
45
+ validations: [],
46
+ disabled: false,
47
+ omitted: false
48
+ })
49
+
50
+ sectionVideoHighlight.createField('subtext', {
51
+ name: 'Subtext',
52
+ type: 'Text',
53
+ localized: true,
54
+ required: false,
55
+ validations: [{ size: { min: 0, max: 500 } }],
56
+ disabled: false,
57
+ omitted: false
58
+ })
59
+
60
+ sectionVideoHighlight.createField('embedCode', {
61
+ name: 'Embed Code',
62
+ type: 'Text',
63
+ localized: false,
64
+ required: true,
65
+ validations: [],
66
+ disabled: false,
67
+ omitted: false
68
+ })
69
+
70
+ sectionVideoHighlight.changeEditorInterface('tag', 'singleLine')
71
+
72
+ sectionVideoHighlight.changeEditorInterface('title', 'singleLine')
73
+
74
+ sectionVideoHighlight.changeEditorInterface('subtext', 'markdown')
75
+
76
+ sectionVideoHighlight.changeEditorInterface('embedCode', 'markdown')
77
+
78
+ sectionVideoHighlight.changeEditorInterface('internalTitle', 'singleLine')
79
+
80
+ } as MigrationFunction
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This model represents the 'section-video-highlight' content type in Contentful. Any linked
4
+ # entries of the 'section-video-highlight' content type will be resolved as instances of this class.
5
+ # It exposes .find, .find_by, and .find_all methods to query Contentful.
6
+ class SectionVideoHighlight < WCC::Contentful::Model::SectionVideoHighlight
7
+ # Override functionality or add utilities
8
+ #
9
+ # # Example: override equality
10
+ # def ===(other)
11
+ # ...
12
+ # end
13
+ #
14
+ # # Example: override "title" attribute to always be titlecase.
15
+ # # `@title` is populated by the gem in the initializer.
16
+ # def title
17
+ # @title_titlecased ||= @title.titlecase
18
+ # end
19
+ end
@@ -0,0 +1,77 @@
1
+ import Migration, { MigrationFunction } from '@watermarkchurch/contentful-migration'
2
+
3
+ // Generated by contentful-schema-diff
4
+ // from empty-export.json
5
+ // to 7yx6ovlj39n5
6
+ export = function(migration : Migration, { makeRequest, spaceId, accessToken }) {
7
+
8
+ /************ section-video ******************/
9
+
10
+ var sectionVideo = migration.createContentType('section-video', {
11
+ displayField: 'internalTitle',
12
+ name: 'Section: Video',
13
+ description: 'Full width video with a title'
14
+ })
15
+
16
+ sectionVideo.createField('internalTitle', {
17
+ name: 'Internal Title (Contentful Only)',
18
+ type: 'Symbol',
19
+ localized: false,
20
+ required: true,
21
+ validations: [],
22
+ disabled: false,
23
+ omitted: true
24
+ })
25
+
26
+ sectionVideo.createField('title', {
27
+ name: 'Title',
28
+ type: 'Symbol',
29
+ localized: true,
30
+ required: false,
31
+ validations:
32
+ [{
33
+ size:
34
+ {
35
+ max: 255,
36
+ min: 0
37
+ }
38
+ }],
39
+ disabled: false,
40
+ omitted: false
41
+ })
42
+
43
+ sectionVideo.createField('embedCode', {
44
+ name: 'Embed Code',
45
+ type: 'Text',
46
+ localized: false,
47
+ required: true,
48
+ validations: [],
49
+ disabled: false,
50
+ omitted: false
51
+ })
52
+
53
+ sectionVideo.createField('style', {
54
+ name: 'Style',
55
+ type: 'Symbol',
56
+ localized: false,
57
+ required: false,
58
+ validations:
59
+ [{
60
+ in:
61
+ ['off white',
62
+ 'default',
63
+ 'gray']
64
+ }],
65
+ disabled: false,
66
+ omitted: false
67
+ })
68
+
69
+ sectionVideo.changeEditorInterface('title', 'singleLine')
70
+
71
+ sectionVideo.changeEditorInterface('embedCode', 'markdown')
72
+
73
+ sectionVideo.changeEditorInterface('internalTitle', 'singleLine')
74
+
75
+ sectionVideo.changeEditorInterface('style', 'dropdown')
76
+
77
+ } as MigrationFunction
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This model represents the 'section-video' content type in Contentful. Any linked
4
+ # entries of the 'section-video' content type will be resolved as instances of this class.
5
+ # It exposes .find, .find_by, and .find_all methods to query Contentful.
6
+ class SectionVideo < WCC::Contentful::Model::SectionVideo
7
+ # Override functionality or add utilities
8
+ #
9
+ # # Example: override equality
10
+ # def ===(other)
11
+ # ...
12
+ # end
13
+ #
14
+ # # Example: override "title" attribute to always be titlecase.
15
+ # # `@title` is populated by the gem in the initializer.
16
+ # def title
17
+ # @title_titlecased ||= @title.titlecase
18
+ # end
19
+ end
@@ -0,0 +1,97 @@
1
+ import Migration, { MigrationFunction } from '@watermarkchurch/contentful-migration'
2
+
3
+ // Generated by contentful-schema-diff
4
+ // from empty-export.json
5
+ // to 7yx6ovlj39n5
6
+ export = function(migration : Migration, { makeRequest, spaceId, accessToken }) {
7
+
8
+ /************ site-config ******************/
9
+
10
+ var siteConfig = migration.createContentType('site-config', {
11
+ displayField: 'internalTitle',
12
+ name: 'Site Config',
13
+ description: 'This is the top level object for the configuration of your site.'
14
+ })
15
+
16
+ siteConfig.createField('internalTitle', {
17
+ name: 'Internal Title (Contentful Only)',
18
+ type: 'Symbol',
19
+ localized: false,
20
+ required: true,
21
+ validations: [],
22
+ disabled: false,
23
+ omitted: true
24
+ })
25
+
26
+ siteConfig.createField('foreignKey', {
27
+ name: 'Foreign Key',
28
+ type: 'Symbol',
29
+ localized: false,
30
+ required: true,
31
+ validations:
32
+ [{ unique: true },
33
+ {
34
+ in: ['default'],
35
+ message: 'We only allow the default site config for this site'
36
+ }],
37
+ disabled: false,
38
+ omitted: false
39
+ })
40
+
41
+ siteConfig.createField('homepage', {
42
+ name: 'Homepage',
43
+ type: 'Link',
44
+ localized: false,
45
+ required: true,
46
+ validations: [{ linkContentType: ['page'] }],
47
+ disabled: false,
48
+ omitted: false,
49
+ linkType: 'Entry'
50
+ })
51
+
52
+ siteConfig.createField('mainNavigation', {
53
+ name: 'Main Navigation',
54
+ type: 'Link',
55
+ localized: false,
56
+ required: false,
57
+ validations: [{ linkContentType: ['menu'] }],
58
+ disabled: false,
59
+ omitted: false,
60
+ linkType: 'Entry'
61
+ })
62
+
63
+ siteConfig.createField('brand', {
64
+ name: 'Brand',
65
+ type: 'Link',
66
+ localized: false,
67
+ required: false,
68
+ validations: [{ linkContentType: ['menuButton'] }],
69
+ disabled: false,
70
+ omitted: false,
71
+ linkType: 'Entry'
72
+ })
73
+
74
+ siteConfig.createField('emailHeader', {
75
+ name: 'Email Header',
76
+ type: 'Link',
77
+ localized: false,
78
+ required: false,
79
+ validations: [{ linkMimetypeGroup: ['image'] }],
80
+ disabled: false,
81
+ omitted: false,
82
+ linkType: 'Asset'
83
+ })
84
+
85
+ siteConfig.changeEditorInterface('title', 'singleLine')
86
+
87
+ siteConfig.changeEditorInterface('foreignKey', 'radio', { helpText: 'Must be `default`' })
88
+
89
+ siteConfig.changeEditorInterface('homepage', 'entryLinkEditor')
90
+
91
+ siteConfig.changeEditorInterface('mainNavigation', 'entryLinkEditor')
92
+
93
+ siteConfig.changeEditorInterface('brand', 'entryLinkEditor')
94
+
95
+ siteConfig.changeEditorInterface('emailHeader', 'assetLinkEditor')
96
+
97
+ } as MigrationFunction
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This model represents the 'site-config' content type in Contentful. Any linked
4
+ # entries of the 'site-config' content type will be resolved as instances of this class.
5
+ # It exposes .find, .find_by, and .find_all methods to query Contentful.
6
+ class SiteConfig < WCC::Contentful::Model::SiteConfig
7
+ # Override functionality or add utilities
8
+ #
9
+ # # Example: override equality
10
+ # def ===(other)
11
+ # ...
12
+ # end
13
+ #
14
+ # # Example: override "title" attribute to always be titlecase.
15
+ # # `@title` is populated by the gem in the initializer.
16
+ # def title
17
+ # @title_titlecased ||= @title.titlecase
18
+ # end
19
+ end
@@ -7,7 +7,7 @@ WCC::Contentful.configure do |config|
7
7
  # Optional
8
8
  config.management_token = # Contentful API management token
9
9
  config.default_locale = # Set default locale, if left blank this is 'en-US'
10
- config.content_delivery = # :direct, :eager_sync, or :lazy_sync
10
+ config.store = # :direct, :eager_sync, or :lazy_sync
11
11
  end
12
12
 
13
13
  # Download content types, build models, and sync content
@@ -2,18 +2,61 @@
2
2
 
3
3
  require 'wcc/contentful/rails'
4
4
 
5
+ require_relative './app/rails'
5
6
  require_relative './app/exceptions'
6
- require_relative './app/model_validators'
7
- require_relative './ext/model'
7
+ require_relative './app/configuration'
8
8
 
9
9
  module WCC::Contentful::App
10
+ class << self
11
+ attr_reader :initialized
12
+
13
+ # Gets the current configuration, after calling WCC::Contentful::App.configure
14
+ attr_reader :configuration
15
+ end
16
+
17
+ def self.configure
18
+ if initialized || WCC::Contentful.initialized
19
+ raise WCC::Contentful::InitializationError, 'Cannot configure after initialization'
20
+ end
21
+
22
+ WCC::Contentful.configure do |wcc_contentful_config|
23
+ if @configuration&.wcc_contentful_config != wcc_contentful_config
24
+ @configuration = Configuration.new(wcc_contentful_config)
25
+ end
26
+ yield(configuration)
27
+ end
28
+
29
+ configuration.validate!
30
+
31
+ configuration
32
+ end
33
+
10
34
  def self.init!
11
- raise ArgumentError, 'Please first call WCC::Contentful.init!' unless WCC::Contentful.types
35
+ raise ArgumentError, 'Please first call WCC::Contentful::App.configure' if configuration.nil?
36
+
37
+ WCC::Contentful.init!
12
38
 
13
39
  # Extend all model types w/ validation & extra fields
14
40
  WCC::Contentful.types.each_value do |t|
15
41
  file = File.dirname(__FILE__) + "/model/#{t.name.underscore}.rb"
16
42
  require file if File.exist?(file)
17
43
  end
44
+
45
+ @db_connected =
46
+ begin
47
+ ::ActiveRecord::Base.connection_pool.with_connection(&:active?)
48
+ rescue StandardError
49
+ false
50
+ end
51
+
52
+ @configuration = WCC::Contentful::App::Configuration::FrozenConfiguration.new(
53
+ configuration,
54
+ WCC::Contentful.configuration
55
+ )
56
+ @initialized = true
57
+ end
58
+
59
+ def self.db_connected?
60
+ @db_connected
18
61
  end
19
62
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This object contains all the configuration options for the `wcc-contentful` gem.
4
+ class WCC::Contentful::App::Configuration
5
+ # TODO: things to configure in the app?
6
+ ATTRIBUTES = %i[
7
+ preview_password
8
+ ].freeze
9
+
10
+ # Sets the password that will be checked when the query string contains `preview=`,
11
+ # if it matches, then the Contentful entries are fetched via the preview API.
12
+ attr_accessor :preview_password
13
+
14
+ attr_reader :wcc_contentful_config
15
+
16
+ delegate(*WCC::Contentful::Configuration::ATTRIBUTES, to: :wcc_contentful_config)
17
+ delegate(*(WCC::Contentful::Configuration::ATTRIBUTES.map { |a| "#{a}=" }),
18
+ to: :wcc_contentful_config)
19
+
20
+ def initialize(wcc_contentful_config)
21
+ @wcc_contentful_config = wcc_contentful_config
22
+ @preview_password = ENV['CONTENTFUL_PREVIEW_PASSWORD']
23
+ end
24
+
25
+ # Validates the configuration, raising ArgumentError if anything is wrong. This
26
+ # is called by WCC::Contentful::App.init!
27
+ def validate!
28
+ wcc_contentful_config.validate!
29
+ end
30
+
31
+ def frozen?
32
+ false
33
+ end
34
+
35
+ class FrozenConfiguration
36
+ attr_reader(*ATTRIBUTES)
37
+
38
+ attr_reader :wcc_contentful_config
39
+
40
+ delegate(*WCC::Contentful::Configuration::ATTRIBUTES, to: :wcc_contentful_config)
41
+
42
+ def initialize(configuration, frozen_wcc_contentful_config)
43
+ unless frozen_wcc_contentful_config.frozen?
44
+ raise ArgumentError, 'Please first freeze the wcc_contentful_config'
45
+ end
46
+
47
+ @wcc_contentful_config = frozen_wcc_contentful_config
48
+
49
+ ATTRIBUTES.each do |att|
50
+ val = configuration.public_send(att)
51
+ val.freeze if val.respond_to?(:freeze)
52
+ instance_variable_set("@#{att}", val)
53
+ end
54
+ end
55
+
56
+ def frozen?
57
+ true
58
+ end
59
+ end
60
+ end