wcc-contentful-app 0.4.0.pre.rc → 1.0.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -2
  3. data/Guardfile +1 -1
  4. data/README.md +11 -0
  5. data/Rakefile +121 -0
  6. data/app/assets/config/manifest.js +5 -0
  7. data/app/assets/images/down-arrow-primary.svg +3 -0
  8. data/app/assets/images/up-arrow-primary.svg +3 -0
  9. data/app/assets/javascripts/wcc/contentful/app/contact-form.js +70 -0
  10. data/app/assets/javascripts/wcc/contentful/app/index.js +1 -0
  11. data/app/assets/stylesheets/_wcc-contentful-app.scss +7 -0
  12. data/app/assets/stylesheets/components/_menu-item.scss +5 -0
  13. data/app/assets/stylesheets/sections/_faq.scss +39 -0
  14. data/app/controllers/wcc/contentful/app/contact_form_controller.rb +39 -0
  15. data/app/controllers/wcc/contentful/app/pages_controller.rb +48 -0
  16. data/app/helpers/wcc/contentful/app/menu_helper.rb +85 -0
  17. data/app/helpers/wcc/contentful/app/section_helper.rb +135 -0
  18. data/app/mailers/wcc/contentful/app/contact_mailer.rb +11 -0
  19. data/app/models/concerns/wcc/contentful/app/preview_password.rb +19 -0
  20. data/app/models/wcc/contentful/app/contact_form_submission.rb +9 -0
  21. data/app/models/wcc/contentful/app/custom_markdown_render.rb +43 -0
  22. data/app/views/components/_faq_row.html.erb +21 -0
  23. data/app/views/components/_menu-item.html.erb +41 -0
  24. data/app/views/components/_other-menu-item.html.erb +4 -0
  25. data/app/views/components/_section.html.erb +11 -0
  26. data/app/views/layouts/mailer.html.erb +9 -0
  27. data/app/views/layouts/mailer.text.erb +1 -0
  28. data/app/views/pages/show.html.erb +4 -0
  29. data/app/views/sections/_block_text.html.erb +5 -0
  30. data/app/views/sections/_code_widget.html.erb +3 -0
  31. data/app/views/sections/_contact_form.html.erb +53 -0
  32. data/app/views/sections/_faq.html.erb +36 -0
  33. data/app/views/sections/_http_error.html.erb +13 -0
  34. data/app/views/sections/_marquee_text.html.erb +12 -0
  35. data/app/views/sections/_testimonials.html.erb +38 -0
  36. data/app/views/sections/_video.html.erb +12 -0
  37. data/app/views/sections/_video_highlight.html.erb +18 -0
  38. data/app/views/wcc/contentful/app/contact_mailer/contact_form_email.html.erb +7 -0
  39. data/bin/rails +14 -0
  40. data/config/routes.rb +7 -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 +15 -15
  87. metadata +164 -103
  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,38 @@
1
+ <div class="row">
2
+ <div class="col">
3
+ <% section.testimonials&.each do |testimonial|
4
+ next unless testimonial %>
5
+ <div class="section-testimonials__item">
6
+ <% if testimonial.photo %>
7
+ <div class="section-testimonials__item-sidebar"
8
+ style="background-image: url(<%= testimonial.photo.file.url %>);">
9
+ </div>
10
+ <% end %>
11
+ <div class="section-testimonials__item-card">
12
+ <% if testimonial.quote.present? %>
13
+ <div
14
+ class="section-testimonials__item-card-quote
15
+ safe-line-break"><%= safe_line_break(testimonial.quote) %></div>
16
+ <% end %>
17
+ <div class="section-testimonials__item-card-meta">
18
+ <% if testimonial.photo %>
19
+ <%= image_tag(testimonial.photo.file.url,
20
+ alt: testimonial.photo.description || testimonial.photo.title,
21
+ class: 'section-testimonials__item-card-meta-photo') %>
22
+ <% end %>
23
+
24
+ <h3 class="section-testimonials__item-card-meta-name">
25
+ <%= testimonial.name %>
26
+ </h3>
27
+ <% if testimonial.mini_bio %>
28
+ <div class="section-testimonials__item-card-meta-bio">
29
+ <%= markdown(testimonial.mini_bio) %>
30
+ </div>
31
+ <% end %>
32
+ </div>
33
+ </div>
34
+ </div><!--quotation-->
35
+
36
+ <% end %>
37
+ </div><!--column-->
38
+ </div><!--row-->
@@ -0,0 +1,12 @@
1
+ <div class="row justify-content-center">
2
+ <div class="col col-lg-10">
3
+ <div class="section-video-content">
4
+ <% if section.title.present? %>
5
+ <h2 class="section-video-content__title"><%= section.title %></h2>
6
+ <% end %>
7
+ <div class="section-video-content__video embed-responsive embed-responsive-16by9">
8
+ <%= raw section.embed_code %>
9
+ </div>
10
+ </div>
11
+ </div>
12
+ </div>
@@ -0,0 +1,18 @@
1
+ <div class="row justify-content-center">
2
+ <div class="section-video-highlight__info col-xs-12 col-md-6">
3
+ <% if section.tag.present? %>
4
+ <span class="section-video-highlight__tag"><%= section.tag %></span>
5
+ <% end %>
6
+ <h2 class="section-video-highlight__title"><%= section.title %></h2>
7
+ <% if section.subtext.present? %>
8
+ <div class="section-video-highlight__subtext">
9
+ <%= markdown(section.subtext) %>
10
+ </div>
11
+ <% end %>
12
+ </div>
13
+ <div class="section-video-highlight__video col-xs-12 col-md-6">
14
+ <div class="embed-responsive embed-responsive-16by9">
15
+ <%= raw section.embed_code %>
16
+ </div>
17
+ </div>
18
+ </div><!--row-->
@@ -0,0 +1,7 @@
1
+
2
+ <h1>Contact Us Form Submission</h1>
3
+ <% @form_data.each do |key, value| %>
4
+ <p>
5
+ <%= key %> -> <%= value %>
6
+ </p>
7
+ <% end %>
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/wcc/contentful/app/engine', __dir__)
7
+ APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
8
+
9
+ # Set up gems listed in the Gemfile.
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
11
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
12
+
13
+ require 'rails/all'
14
+ require 'rails/engine/commands'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ WCC::Contentful::App::Engine.routes.draw do
4
+ get '/*slug', to: 'wcc/contentful/app/pages#show'
5
+ root 'wcc/contentful/app/pages#index'
6
+ post '/contact_form', to: 'wcc/contentful/app/contact_form#create', as: :contact_form
7
+ end
@@ -5,14 +5,19 @@ module Wcc
5
5
  source_root File.expand_path('templates', __dir__)
6
6
  argument :model, type: :string
7
7
 
8
- VALID_MODELS = %w[menu page].freeze
8
+ VALID_MODELS =
9
+ Dir.glob("#{__dir__}/templates/*")
10
+ .select { |f| File.directory? f }
11
+ .map { |f| File.basename f }
12
+ .sort
13
+ .freeze
9
14
 
10
15
  def initialize(*)
11
16
  super
12
17
 
13
18
  return if VALID_MODELS.include?(singular)
14
19
 
15
- raise ArgumentError, "Model must be #{VALID_MODELS.to_sentence}"
20
+ raise ArgumentError, "Model must be one of #{VALID_MODELS.to_sentence}"
16
21
  end
17
22
 
18
23
  def ensure_migration_tools_installed
@@ -21,8 +26,9 @@ module Wcc
21
26
  package = JSON.parse(File.read('package.json'))
22
27
  deps = package['dependencies']
23
28
 
24
- unless deps.try(:[], 'contentful-migration-cli').present?
25
- run 'npm install --save watermarkchurch/migration-cli ts-node typescript contentful-export'
29
+ unless deps.try(:[], '@watermarkchurch/contentful-migration').present?
30
+ run 'npm install --save @watermarkchurch/contentful-migration ts-node ' \
31
+ 'typescript contentful-export'
26
32
  end
27
33
  end
28
34
  end
@@ -64,9 +70,13 @@ module Wcc
64
70
  copy_file 'wcc_contentful.rb', 'config/initializers/wcc_contentful.rb'
65
71
  end
66
72
 
67
- def create_model_migration
68
- copy_file "#{singular}/generated_add_#{plural}.ts",
73
+ def create_model_migrations
74
+ copy_file "#{singular}/migrations/generated_add_#{plural}.ts",
69
75
  "db/migrate/#{timestamp}01_generated_add_#{plural}.ts"
76
+
77
+ Dir.glob("#{__dir__}/templates/#{singular}/migrations/*.rb").each do |f|
78
+ copy_file f, "db/migrate/#{timestamp}_#{File.basename(f)}"
79
+ end
70
80
  end
71
81
 
72
82
  def drop_model_overrides_in_app_models
@@ -0,0 +1,285 @@
1
+ import Migration from '@watermarkchurch/contentful-migration';
2
+
3
+ export = function(migration: Migration, { makeRequest, spaceId, accessToken }) {
4
+ var menu = migration.createContentType('menu', {
5
+ displayField: 'internalTitle',
6
+ name: 'Menu',
7
+ description:
8
+ 'A Menu contains a number of Menu Buttons or other Menus, which will be rendered as drop-downs.'
9
+ });
10
+
11
+ menu.createField('internalTitle', {
12
+ name: 'Internal Title (Contentful Only)',
13
+ type: 'Symbol',
14
+ localized: false,
15
+ required: true,
16
+ validations: [],
17
+ disabled: false,
18
+ omitted: true
19
+ });
20
+
21
+ menu.createField('name', {
22
+ name: 'Menu Name',
23
+ type: 'Symbol',
24
+ localized: false,
25
+ required: true,
26
+ validations: [],
27
+ disabled: false,
28
+ omitted: false
29
+ });
30
+
31
+ menu.createField('items', {
32
+ name: 'Items',
33
+ type: 'Array',
34
+ localized: false,
35
+ required: false,
36
+ validations: [],
37
+ disabled: false,
38
+ omitted: false,
39
+ items: {
40
+ type: 'Link',
41
+ validations: [
42
+ {
43
+ linkContentType: ['dropdownMenu', 'menuButton'],
44
+ message: 'The items must be either buttons or drop-down menus.'
45
+ }
46
+ ],
47
+ linkType: 'Entry'
48
+ }
49
+ });
50
+
51
+ menu.changeEditorInterface('name', 'singleLine');
52
+ menu.changeEditorInterface('items', 'entryLinksEditor');
53
+ menu.changeEditorInterface('internalTitle', 'singleLine');
54
+
55
+ var menubutton = migration.createContentType('menuButton', {
56
+ displayField: 'internalTitle',
57
+ name: 'Menu Button',
58
+ description:
59
+ 'A Menu Button is a clickable button that goes on a Menu. It has a link to a Page or a URL.'
60
+ });
61
+
62
+ menubutton.createField('internalTitle', {
63
+ name: 'Internal Title (Contentful Only)',
64
+ type: 'Symbol',
65
+ localized: false,
66
+ required: true,
67
+ validations: [],
68
+ disabled: false,
69
+ omitted: true
70
+ });
71
+
72
+ menubutton.createField('text', {
73
+ name: 'Text',
74
+ type: 'Symbol',
75
+ localized: false,
76
+ required: false,
77
+ validations: [
78
+ {
79
+ size: {
80
+ min: 1,
81
+ max: 60
82
+ },
83
+ message:
84
+ 'A Menu Button should have a very short text field - ideally a single word. Please limit the text to 60 characters.'
85
+ }
86
+ ],
87
+ disabled: false,
88
+ omitted: false
89
+ });
90
+
91
+ menubutton.createField('icon', {
92
+ name: 'Icon',
93
+ type: 'Link',
94
+ localized: false,
95
+ required: false,
96
+ validations: [
97
+ {
98
+ linkMimetypeGroup: ['image']
99
+ }
100
+ ],
101
+ disabled: false,
102
+ omitted: false,
103
+ linkType: 'Asset'
104
+ });
105
+
106
+ menubutton.createField('materialIcon', {
107
+ name: 'Material Icon',
108
+ type: 'Symbol',
109
+ localized: false,
110
+ required: false,
111
+ validations: [
112
+ {
113
+ regexp: {
114
+ pattern: '^\\w+$',
115
+ flags: null
116
+ },
117
+ message:
118
+ "The icon name must be one of the icons in Google's Material Design library: https://material.io/tools/icons/"
119
+ }
120
+ ],
121
+ disabled: false,
122
+ omitted: false
123
+ });
124
+
125
+ menubutton.createField('externalLink', {
126
+ name: 'External Link',
127
+ type: 'Symbol',
128
+ localized: false,
129
+ required: false,
130
+ validations: [
131
+ {
132
+ regexp: {
133
+ pattern:
134
+ '^([^\\s\\:]+):(\\/\\/)?(\\w+:{0,1}\\w*@)?(([^\\s\\/#]+\\.)+[^\\s\\/#]+)(:[0-9]+)?(\\/|(\\/|\\#)([\\w#!:.?+=&%@!\\-\\/]+))?$|^(\\/|(\\/|\\#)([\\w#!:.?+=&%@!\\-\\/]+))$'
135
+ },
136
+ message:
137
+ "The external link must be a URL like 'https://www.watermark.org/', a mailto url like 'mailto:info@watermark.org', or a relative URL like '#location-on-page'"
138
+ }
139
+ ],
140
+ disabled: false,
141
+ omitted: false
142
+ });
143
+
144
+ menubutton.createField('link', {
145
+ name: 'Page Link',
146
+ type: 'Link',
147
+ localized: false,
148
+ required: false,
149
+ validations: [
150
+ {
151
+ linkContentType: ['page'],
152
+ message: 'The Page Link must be a link to a Page which has a slug.'
153
+ }
154
+ ],
155
+ disabled: false,
156
+ omitted: false,
157
+ linkType: 'Entry'
158
+ });
159
+
160
+ menubutton.createField('sectionLink', {
161
+ name: 'Section Link',
162
+ type: 'Link',
163
+ localized: false,
164
+ required: false,
165
+ validations: [
166
+ {
167
+ linkContentType: [
168
+ 'section-conference-speakers',
169
+ 'section-email-signup',
170
+ 'section-event-schedule',
171
+ 'section-faq',
172
+ 'section-hero',
173
+ 'section-hotels',
174
+ 'section-pricing',
175
+ 'section-social-links',
176
+ 'section-video-about'
177
+ ]
178
+ }
179
+ ],
180
+ disabled: false,
181
+ omitted: false,
182
+ linkType: 'Entry'
183
+ });
184
+
185
+ menubutton.createField('style', {
186
+ name: 'Style',
187
+ type: 'Symbol',
188
+ localized: false,
189
+ required: false,
190
+ validations: [
191
+ {
192
+ in: ['default', 'white-border']
193
+ }
194
+ ],
195
+ disabled: false,
196
+ omitted: false
197
+ });
198
+
199
+ menubutton.changeEditorInterface('text', 'singleLine');
200
+ menubutton.changeEditorInterface('icon', 'assetLinkEditor');
201
+ menubutton.changeEditorInterface('externalLink', 'singleLine', {
202
+ helpText:
203
+ 'Provide a URL to something on another website, a `mailto:` link to an email address, or a deep link into an app.'
204
+ });
205
+ menubutton.changeEditorInterface('link', 'entryLinkEditor');
206
+ menubutton.changeEditorInterface('internalTitle', 'singleLine');
207
+ menubutton.changeEditorInterface('style', 'dropdown');
208
+ menubutton.changeEditorInterface('sectionLink', 'entryLinkEditor', {
209
+ helpText:
210
+ 'If provided, this will link the user to the specific section on a page. You must use this in combination with Page Link.'
211
+ });
212
+ menubutton.changeEditorInterface('materialIcon', 'singleLine', {
213
+ helpText:
214
+ 'As an alternative to the Media icon, you can select an icon from here: https://material.io/tools/icons/'
215
+ });
216
+
217
+ var dropdownmenu = migration.createContentType('dropdownMenu', {
218
+ displayField: 'internalTitle',
219
+ name: 'Dropdown Menu',
220
+ description:
221
+ 'A Dropdown Menu can be attached to a main menu to show additional menu items on click.'
222
+ });
223
+
224
+ dropdownmenu.createField('internalTitle', {
225
+ name: 'Internal Title (Contentful Only)',
226
+ type: 'Symbol',
227
+ localized: false,
228
+ required: true,
229
+ validations: [],
230
+ disabled: false,
231
+ omitted: true
232
+ });
233
+
234
+ dropdownmenu.createField('name', {
235
+ name: 'Menu Name',
236
+ type: 'Symbol',
237
+ localized: false,
238
+ required: false,
239
+ validations: [],
240
+ disabled: false,
241
+ omitted: false
242
+ });
243
+
244
+ dropdownmenu.createField('label', {
245
+ name: 'Menu Label',
246
+ type: 'Link',
247
+ localized: false,
248
+ required: false,
249
+ validations: [
250
+ {
251
+ linkContentType: ['menuButton']
252
+ }
253
+ ],
254
+ disabled: false,
255
+ omitted: false,
256
+ linkType: 'Entry'
257
+ });
258
+
259
+ dropdownmenu.createField('items', {
260
+ name: 'Items',
261
+ type: 'Array',
262
+ localized: false,
263
+ required: false,
264
+ validations: [],
265
+ disabled: false,
266
+ omitted: false,
267
+ items: {
268
+ type: 'Link',
269
+ validations: [
270
+ {
271
+ linkContentType: ['menuButton']
272
+ }
273
+ ],
274
+ linkType: 'Entry'
275
+ }
276
+ });
277
+
278
+ dropdownmenu.changeEditorInterface('name', 'singleLine', {
279
+ helpText:
280
+ "If you don't set a menu label, this is the text that will appear on the button that opens the dropdown menu. If you do set a menu label, that will control the text."
281
+ });
282
+ dropdownmenu.changeEditorInterface('label', 'entryLinkEditor');
283
+ dropdownmenu.changeEditorInterface('items', 'entryLinksEditor');
284
+ dropdownmenu.changeEditorInterface('internalTitle', 'singleLine');
285
+ };
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This model represents the 'dropdownMenu' content type in Contentful. Any linked
4
+ # entries of the 'dropdownMenu' 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 DropdownMenu < WCC::Contentful::Model::DropdownMenu
7
+ # Override functionality or add utilities
8
+ #
9
+ # # Example: override equality
10
+ # def ===(other)
11
+ # ...
12
+ # end
13
+ #
14
+ # # Example: override "name" attribute to always be camelized.
15
+ # # `@name` is populated by the gem in the initializer.
16
+ # def name
17
+ # @name_camelized ||= @name.camelize(true)
18
+ # end
19
+ end