cas-cms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +43 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/config/cas_manifest.js +2 -0
  6. data/app/assets/images/cas/black-star.svg +4 -0
  7. data/app/assets/images/cas/check.svg +4 -0
  8. data/app/assets/images/cas/dropzone-in.svg +4 -0
  9. data/app/assets/images/cas/loading.gif +0 -0
  10. data/app/assets/images/cas/white-star.svg +4 -0
  11. data/app/assets/javascripts/cas/application.js +51 -0
  12. data/app/assets/javascripts/cas/fileupload_manifest.js +269 -0
  13. data/app/assets/javascripts/cas/plugins/cas_image_gallery.js +353 -0
  14. data/app/assets/javascripts/cas/vendor/file_upload/canvas-to-blob.min.js +2 -0
  15. data/app/assets/javascripts/cas/vendor/file_upload/jquery.fileupload-image.js +326 -0
  16. data/app/assets/javascripts/cas/vendor/file_upload/jquery.fileupload-process.js +178 -0
  17. data/app/assets/javascripts/cas/vendor/file_upload/jquery.fileupload.js +1482 -0
  18. data/app/assets/javascripts/cas/vendor/file_upload/jquery.iframe-transport.js +224 -0
  19. data/app/assets/javascripts/cas/vendor/file_upload/jquery.ui.widget.js +572 -0
  20. data/app/assets/javascripts/cas/vendor/file_upload/load-image.all.min.js +2 -0
  21. data/app/assets/javascripts/cas/vendor/jquery.ui.touch-punch.min.js +11 -0
  22. data/app/assets/javascripts/cas/vendor/selectize.min.js +3 -0
  23. data/app/assets/stylesheets/cas/application.sass +17 -0
  24. data/app/assets/stylesheets/cas/colors.sass +6 -0
  25. data/app/assets/stylesheets/cas/form.sass +99 -0
  26. data/app/assets/stylesheets/cas/layout.sass +68 -0
  27. data/app/assets/stylesheets/cas/mixins.sass +34 -0
  28. data/app/assets/stylesheets/cas/plugins/attachments_form.sass +16 -0
  29. data/app/assets/stylesheets/cas/plugins/image_gallery.sass +128 -0
  30. data/app/assets/stylesheets/cas/tables.sass +13 -0
  31. data/app/assets/stylesheets/cas/typography.sass +27 -0
  32. data/app/assets/stylesheets/cas/vendors/selectize.default.css +394 -0
  33. data/app/assets/stylesheets/cas/vendors/simplegrid.css +298 -0
  34. data/app/controllers/cas/api/files_controller.rb +88 -0
  35. data/app/controllers/cas/application_controller.rb +17 -0
  36. data/app/controllers/cas/devise/sessions_controller.rb +9 -0
  37. data/app/controllers/cas/file_uploads_controller.rb +14 -0
  38. data/app/controllers/cas/sections/application_controller.rb +23 -0
  39. data/app/controllers/cas/sections/categories_controller.rb +47 -0
  40. data/app/controllers/cas/sections/contents_controller.rb +144 -0
  41. data/app/controllers/cas/sections_controller.rb +7 -0
  42. data/app/controllers/cas/users_controller.rb +61 -0
  43. data/app/helpers/cas/application_helper.rb +4 -0
  44. data/app/helpers/cas/form_helper.rb +11 -0
  45. data/app/jobs/cas/application_job.rb +4 -0
  46. data/app/jobs/cas/images/delete_job.rb +11 -0
  47. data/app/jobs/cas/images/promote_job.rb +11 -0
  48. data/app/jobs/cas/increment_pageviews_job.rb +11 -0
  49. data/app/models/cas/application_record.rb +5 -0
  50. data/app/models/cas/category.rb +6 -0
  51. data/app/models/cas/content.rb +59 -0
  52. data/app/models/cas/media_file.rb +77 -0
  53. data/app/models/cas/section.rb +10 -0
  54. data/app/models/cas/site.rb +5 -0
  55. data/app/models/cas/user.rb +39 -0
  56. data/app/uploaders/file_uploader.rb +26 -0
  57. data/app/views/cas/devise/sessions/new.html.erb +24 -0
  58. data/app/views/cas/sections/categories/_form.html.erb +19 -0
  59. data/app/views/cas/sections/categories/edit.html.erb +5 -0
  60. data/app/views/cas/sections/categories/index.html.erb +28 -0
  61. data/app/views/cas/sections/categories/new.html.erb +5 -0
  62. data/app/views/cas/sections/contents/_form_attachments.html.erb +42 -0
  63. data/app/views/cas/sections/contents/_form_attachments_template.html.erb +11 -0
  64. data/app/views/cas/sections/contents/_form_for_content.html.erb +85 -0
  65. data/app/views/cas/sections/contents/_form_for_survey.html.erb +36 -0
  66. data/app/views/cas/sections/contents/_form_images.html.erb +86 -0
  67. data/app/views/cas/sections/contents/edit.html.erb +6 -0
  68. data/app/views/cas/sections/contents/index.html.erb +71 -0
  69. data/app/views/cas/sections/contents/new.html.erb +5 -0
  70. data/app/views/cas/sections/index.html.erb +21 -0
  71. data/app/views/cas/shared/_error_messages.html.erb +12 -0
  72. data/app/views/cas/users/_form.html.erb +11 -0
  73. data/app/views/cas/users/edit.html.erb +2 -0
  74. data/app/views/cas/users/index.html.erb +34 -0
  75. data/app/views/cas/users/new.html.erb +2 -0
  76. data/app/views/layouts/cas/application.html.erb +71 -0
  77. data/config/initializers/acts_as_taggable.rb +1 -0
  78. data/config/initializers/devise.rb +277 -0
  79. data/config/initializers/shrine.rb +50 -0
  80. data/config/initializers/simple_form.rb +169 -0
  81. data/config/locales/devise.en.yml +64 -0
  82. data/config/locales/pt-BR.yml +242 -0
  83. data/config/locales/simple_form.en.yml +31 -0
  84. data/config/routes.rb +31 -0
  85. data/db/migrate/20170129212144_create_cas_sites.rb +15 -0
  86. data/db/migrate/20170219172958_create_cas_sections.rb +12 -0
  87. data/db/migrate/20170219175007_create_cas_contents.rb +17 -0
  88. data/db/migrate/20170612204500_create_cas_users.rb +14 -0
  89. data/db/migrate/20170613174724_create_cas_media_files.rb +20 -0
  90. data/db/migrate/20170613175912_create_cas_categories.rb +14 -0
  91. data/db/migrate/20170614171928_add_columns_to_cas_contents.rb +12 -0
  92. data/db/migrate/20170614172904_add_column_to_cas_sections.rb +6 -0
  93. data/db/migrate/20170615235532_add_devise_to_cas_users.rb +49 -0
  94. data/db/migrate/20170616011202_remove_password_from_cas_users.rb +5 -0
  95. data/db/migrate/20170618014204_v3_migration_fields.rb +30 -0
  96. data/db/migrate/20170623182702_add_column_category_id_to_cas_content.rb +6 -0
  97. data/db/migrate/20170624024648_rename_url_to_path_in_files.rb +7 -0
  98. data/db/migrate/20170625192119_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +36 -0
  99. data/db/migrate/20170625192120_add_missing_unique_indices.acts_as_taggable_on_engine.rb +26 -0
  100. data/db/migrate/20170625192121_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +20 -0
  101. data/db/migrate/20170625192122_add_missing_taggable_index.acts_as_taggable_on_engine.rb +15 -0
  102. data/db/migrate/20170625192123_change_collation_for_tag_names.acts_as_taggable_on_engine.rb +15 -0
  103. data/db/migrate/20170625192124_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb +23 -0
  104. data/db/migrate/20170713210101_add_location_to_cas_content.rb +5 -0
  105. data/db/migrate/20170714043036_add_url_to_content.rb +5 -0
  106. data/db/migrate/20170718201535_add_embedded_to_content.rb +5 -0
  107. data/db/migrate/20170801171952_categories_with_jsonb_metadata.rb +6 -0
  108. data/db/migrate/20170801173256_add_published_at_to_cas_contents.rb +6 -0
  109. data/db/migrate/20170801175407_add_description_to_cas_categories.rb +5 -0
  110. data/db/migrate/20170830000000_add_data_search_extensions.rb +17 -0
  111. data/db/migrate/20170830000001_add_search_index_to_cas_contents.rb +20 -0
  112. data/db/migrate/20170830000002_use_uuid_with_acts_as_taggable_references.rb +17 -0
  113. data/db/migrate/20170919181809_pageviews_default_to_zero.rb +9 -0
  114. data/db/migrate/20171201191059_add_domains_to_cas_site.rb +6 -0
  115. data/lib/cas.rb +22 -0
  116. data/lib/cas/config.rb +42 -0
  117. data/lib/cas/engine.rb +33 -0
  118. data/lib/cas/form_field.rb +54 -0
  119. data/lib/cas/remote_callbacks.rb +36 -0
  120. data/lib/cas/section_config.rb +84 -0
  121. data/lib/cas/setup.rb +43 -0
  122. data/lib/cas/version.rb +3 -0
  123. data/lib/devise/custom_failure.rb +16 -0
  124. data/lib/tasks/cas_tasks.rake +4 -0
  125. data/lib/templates/erb/scaffold/_form.html.erb +13 -0
  126. metadata +560 -0
@@ -0,0 +1,298 @@
1
+ /*
2
+ Simple Grid
3
+ Project Page - http://thisisdallas.github.com/Simple-Grid/
4
+ Author - Dallas Bass
5
+ Site - http://dallasbass.com
6
+ */
7
+
8
+
9
+ [class*='grid'],
10
+ [class*='col-'],
11
+ [class*='mobile-'],
12
+ .grid:after {
13
+ -webkit-box-sizing: border-box;
14
+ -moz-box-sizing: border-box;
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ [class*='col-'] {
19
+ float: left;
20
+ min-height: 1px;
21
+ padding-right: 20px; /* column-space */
22
+ }
23
+
24
+ [class*='col-'] [class*='col-']:last-child {
25
+ padding-right: 0;
26
+ }
27
+
28
+ .grid {
29
+ width: 100%;
30
+ max-width: 1140px;
31
+ min-width: 748px; /* when using padded grid on ipad in portrait mode, width should be viewport-width - padding = (768 - 20) = 748. actually, it should be even smaller to allow for padding of grid containing element */
32
+ margin: 0 auto;
33
+ overflow: hidden;
34
+ }
35
+
36
+ .grid:after {
37
+ content: "";
38
+ display: table;
39
+ clear: both;
40
+ }
41
+
42
+ .grid .grid {
43
+ min-width: auto;
44
+ }
45
+
46
+ .grid-pad {
47
+ padding-top: 20px;
48
+ padding-left: 20px; /* grid-space to left */
49
+ padding-right: 0; /* grid-space to right: (grid-space-left - column-space) e.g. 20px-20px=0 */
50
+ }
51
+
52
+ .push-right {
53
+ float: right;
54
+ }
55
+
56
+ /* Content Columns */
57
+
58
+ .col-1-1 {
59
+ width: 100%;
60
+ }
61
+ .col-2-3, .col-8-12 {
62
+ width: 66.66%;
63
+ }
64
+
65
+ .col-1-2, .col-6-12 {
66
+ width: 50%;
67
+ }
68
+
69
+ .col-1-3, .col-4-12 {
70
+ width: 33.33%;
71
+ }
72
+
73
+ .col-1-4, .col-3-12 {
74
+ width: 25%;
75
+ }
76
+
77
+ .col-1-5 {
78
+ width: 20%;
79
+ }
80
+
81
+ .col-1-6, .col-2-12 {
82
+ width: 16.667%;
83
+ }
84
+
85
+ .col-1-7 {
86
+ width: 14.28%;
87
+ }
88
+
89
+ .col-1-8 {
90
+ width: 12.5%;
91
+ }
92
+
93
+ .col-1-9 {
94
+ width: 11.1%;
95
+ }
96
+
97
+ .col-1-10 {
98
+ width: 10%;
99
+ }
100
+
101
+ .col-1-11 {
102
+ width: 9.09%;
103
+ }
104
+
105
+ .col-1-12 {
106
+ width: 8.33%
107
+ }
108
+
109
+ /* Layout Columns */
110
+
111
+ .col-11-12 {
112
+ width: 91.66%
113
+ }
114
+
115
+ .col-10-12 {
116
+ width: 83.333%;
117
+ }
118
+
119
+ .col-9-12 {
120
+ width: 75%;
121
+ }
122
+
123
+ .col-5-12 {
124
+ width: 41.66%;
125
+ }
126
+
127
+ .col-7-12 {
128
+ width: 58.33%
129
+ }
130
+
131
+ /* Pushing blocks */
132
+
133
+ .push-2-3, .push-8-12 {
134
+ margin-left: 66.66%;
135
+ }
136
+
137
+ .push-1-2, .push-6-12 {
138
+ margin-left: 50%;
139
+ }
140
+
141
+ .push-1-3, .push-4-12 {
142
+ margin-left: 33.33%;
143
+ }
144
+
145
+ .push-1-4, .push-3-12 {
146
+ margin-left: 25%;
147
+ }
148
+
149
+ .push-1-5 {
150
+ margin-left: 20%;
151
+ }
152
+
153
+ .push-1-6, .push-2-12 {
154
+ margin-left: 16.667%;
155
+ }
156
+
157
+ .push-1-7 {
158
+ margin-left: 14.28%;
159
+ }
160
+
161
+ .push-1-8 {
162
+ margin-left: 12.5%;
163
+ }
164
+
165
+ .push-1-9 {
166
+ margin-left: 11.1%;
167
+ }
168
+
169
+ .push-1-10 {
170
+ margin-left: 10%;
171
+ }
172
+
173
+ .push-1-11 {
174
+ margin-left: 9.09%;
175
+ }
176
+
177
+ .push-1-12 {
178
+ margin-left: 8.33%
179
+ }
180
+
181
+ @media handheld, only screen and (max-width: 767px) {
182
+ .grid {
183
+ width: 100%;
184
+ min-width: 0;
185
+ margin-left: 0;
186
+ margin-right: 0;
187
+ padding-left: 20px; /* grid-space to left */
188
+ padding-right: 10px; /* grid-space to right: (grid-space-left - column-space) e.g. 20px-10px=10px */
189
+ }
190
+
191
+ [class*='col-'] {
192
+ width: auto;
193
+ float: none;
194
+ margin: 10px 0;
195
+ padding-left: 0;
196
+ padding-right: 10px; /* column-space */
197
+ }
198
+
199
+ [class*='col-'] [class*='col-'] {
200
+ padding-right: 0;
201
+ }
202
+
203
+ /* Mobile Layout */
204
+
205
+ [class*='mobile-col-'] {
206
+ float: left;
207
+ margin: 0 0 10px;
208
+ padding-left: 0;
209
+ padding-right: 10px; /* column-space */
210
+ padding-bottom: 0;
211
+ }
212
+
213
+ .mobile-col-1-1 {
214
+ width: 100%;
215
+ }
216
+ .mobile-col-2-3, .mobile-col-8-12 {
217
+ width: 66.66%;
218
+ }
219
+
220
+ .mobile-col-1-2, .mobile-col-6-12 {
221
+ width: 50%;
222
+ }
223
+
224
+ .mobile-col-1-3, .mobile-col-4-12 {
225
+ width: 33.33%;
226
+ }
227
+
228
+ .mobile-col-1-4, .mobile-col-3-12 {
229
+ width: 25%;
230
+ }
231
+
232
+ .mobile-col-1-5 {
233
+ width: 20%;
234
+ }
235
+
236
+ .mobile-col-1-6, .mobile-col-2-12 {
237
+ width: 16.667%;
238
+ }
239
+
240
+ .mobile-col-1-7 {
241
+ width: 14.28%;
242
+ }
243
+
244
+ .mobile-col-1-8 {
245
+ width: 12.5%;
246
+ }
247
+
248
+ .mobile-col-1-9 {
249
+ width: 11.1%;
250
+ }
251
+
252
+ .mobile-col-1-10 {
253
+ width: 10%;
254
+ }
255
+
256
+ .mobile-col-1-11 {
257
+ width: 9.09%;
258
+ }
259
+
260
+ .mobile-col-1-12 {
261
+ width: 8.33%
262
+ }
263
+
264
+ /* Layout Columns */
265
+
266
+ .mobile-col-11-12 {
267
+ width: 91.66%
268
+ }
269
+
270
+ .mobile-col-10-12 {
271
+ width: 83.333%;
272
+ }
273
+
274
+ .mobile-col-9-12 {
275
+ width: 75%;
276
+ }
277
+
278
+ .mobile-col-5-12 {
279
+ width: 41.66%;
280
+ }
281
+
282
+ .mobile-col-7-12 {
283
+ width: 58.33%
284
+ }
285
+
286
+ .hide-on-mobile {
287
+ display: none !important;
288
+ width: 0;
289
+ height: 0;
290
+ }
291
+
292
+ .center-on-mobile {
293
+ text-align: center;
294
+ float: none;
295
+ margin-left: auto;
296
+ margin-right: auto;
297
+ }
298
+ }
@@ -0,0 +1,88 @@
1
+ class Cas::Api::FilesController < Cas::ApplicationController
2
+ skip_before_action :authenticate_user!
3
+
4
+ def create
5
+ if ENV.fetch("S3_BUCKET")
6
+ service = "s3"
7
+ end
8
+ metadata = resource_params[:attributes][:metadata]
9
+ file = ::Cas::MediaFile.new(
10
+ service: service,
11
+ size: metadata[:original][:metadata][:size].to_i,
12
+ original_name: metadata[:original][:metadata][:filename],
13
+ mime_type: metadata[:original][:metadata][:mime_type],
14
+ media_type: resource_params[:attributes][:media_type],
15
+ file: metadata.to_json,
16
+ attachable: attachable_record
17
+ )
18
+ file.save
19
+ Cas::RemoteCallbacks.callbacks[:after_file_upload].call(file)
20
+ render json: {
21
+ data: {
22
+ id: file.id.to_s,
23
+ type: "media-files",
24
+ attributes: {
25
+ url: file.url(version: :original, use_cdn: false).to_s,
26
+ "original-name": file.original_name
27
+ }
28
+ }
29
+ }
30
+ end
31
+
32
+ def destroy
33
+ files = ::Cas::MediaFile.where(id: params[:id].split(","))
34
+ success = nil
35
+ ActiveRecord::Base.transaction do
36
+ success = files.each(&:destroy).all?
37
+ end
38
+
39
+ if success
40
+ render json: {}, status: 204
41
+ else
42
+ render json: {}, status: 400
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def resource_params
49
+ r = params
50
+ .require(:data)
51
+ .permit(
52
+ attributes: [
53
+ :cover,
54
+ :media_type,
55
+ metadata: [
56
+ original: [
57
+ :id,
58
+ :storage,
59
+ metadata: [:size, :filename, :mime_type, 'mime-type']
60
+ ]
61
+ ]
62
+ ],
63
+ relationships: [
64
+ attachable: [
65
+ data: [:id, :type]
66
+ ]
67
+ ]
68
+ )
69
+
70
+ if r[:attributes][:metadata].present?
71
+ if r[:attributes][:metadata][:original][:metadata][:mime_type].blank?
72
+ r[:attributes][:metadata][:original][:metadata][:mime_type] = r[:attributes][:metadata][:original][:metadata][:"mime-type"]
73
+ end
74
+ r[:attributes][:metadata][:original][:metadata].delete(:"mime-type")
75
+ end
76
+ r
77
+ end
78
+
79
+ def attachable_record
80
+ rel = resource_params[:relationships]
81
+ if rel.present?
82
+ attachable = resource_params[:relationships][:attachable][:data]
83
+ if attachable[:type] == 'contents' && attachable[:id].present?
84
+ @attachable ||= Cas::Content.find(attachable[:id])
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,17 @@
1
+ module Cas
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ before_action :authenticate_user!
5
+ before_action :set_current_user
6
+
7
+ private
8
+
9
+ def set_current_user
10
+ @current_user = current_user
11
+ end
12
+
13
+ def set_domain
14
+ @domain ||= (ENV["DOMAIN"] || request.domain)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ module Cas
2
+ module Devise
3
+ class SessionsController < ::Devise::SessionsController
4
+ def after_sign_out_path_for(resource_or_scope)
5
+ cas.root_path
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ class Cas::FileUploadsController < Cas::ApplicationController
2
+ skip_before_action :authenticate_user!
3
+ skip_before_filter :verify_authenticity_token
4
+
5
+ def create
6
+ file = params.fetch(:file)
7
+ uploader = ::FileUploader.new(:store)
8
+ uploaded_file = uploader.upload(file)
9
+ url = uploaded_file.url(public: true, host: ENV.fetch("CDN_HOST", nil))
10
+ render json: {
11
+ location: url
12
+ }
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module Cas
2
+ class Sections::ApplicationController < ApplicationController
3
+ before_action :load_section
4
+
5
+ private
6
+
7
+ def load_section
8
+ @section ||= ::Cas::Section.friendly.find(params[:section_id])
9
+ end
10
+
11
+ def scope_content_by_role(model_relation = ::Cas::Content)
12
+ # Only admins and editors can see other people's content
13
+ if !current_user.admin? && !current_user.editor?
14
+ model_relation = model_relation.where(author_id: current_user.id)
15
+ end
16
+ model_relation
17
+ end
18
+
19
+ def load_categories
20
+ @categories ||= @section.categories
21
+ end
22
+ end
23
+ end