designer 0.1.2

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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +2 -0
  3. data/.gitignore +4 -0
  4. data/.travis.yml +17 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +142 -0
  7. data/LICENSE +21 -0
  8. data/README.md +102 -0
  9. data/Rakefile +27 -0
  10. data/TODO.md +6 -0
  11. data/app/assets/stylesheets/designer.scss +189 -0
  12. data/app/assets/stylesheets/designer/_texy.scss +311 -0
  13. data/app/controllers/designer/application_controller.rb +33 -0
  14. data/app/controllers/designer/editor_controller.rb +50 -0
  15. data/app/controllers/designer/images_controller.rb +66 -0
  16. data/app/helpers/designer/designer_helper.rb +95 -0
  17. data/app/javascript/designer/DefaultInput.vue +82 -0
  18. data/app/javascript/designer/components/DefaultForm.vue +65 -0
  19. data/app/javascript/designer/components/DefaultInput.vue +82 -0
  20. data/app/javascript/designer/components/MediaGallery.vue +564 -0
  21. data/app/javascript/designer/components/SortableInputArray.vue +74 -0
  22. data/app/javascript/designer/editor.js +65 -0
  23. data/app/javascript/designer/helpers.js +73 -0
  24. data/app/javascript/designer/index.js +136 -0
  25. data/app/javascript/packs/designer.js +2 -0
  26. data/app/views/designer/application/notifications.js.erb +13 -0
  27. data/app/views/designer/editor/show.html.slim +88 -0
  28. data/app/views/designer/elements/_image.html.slim +11 -0
  29. data/app/views/designer/elements/_quote.html.slim +7 -0
  30. data/app/views/designer/elements/_separator.html.slim +1 -0
  31. data/app/views/designer/elements/_text.html.slim +5 -0
  32. data/app/views/layouts/designer/application.html.slim +9 -0
  33. data/bin/test +6 -0
  34. data/bin/webpack +19 -0
  35. data/bin/webpack-dev-server +19 -0
  36. data/config/routes.rb +6 -0
  37. data/designer.gemspec +29 -0
  38. data/lib/designer.rb +10 -0
  39. data/lib/designer/attribute.rb +15 -0
  40. data/lib/designer/configuration.rb +6 -0
  41. data/lib/designer/engine.rb +35 -0
  42. data/lib/designer/version.rb +5 -0
  43. data/lib/tasks/designer.rake +20 -0
  44. data/lib/templates/dev_installer.rb +13 -0
  45. data/lib/templates/installer.rb +11 -0
  46. data/package.json +33 -0
  47. data/yarn.lock +288 -0
  48. metadata +160 -0
@@ -0,0 +1,311 @@
1
+ //
2
+ // Texy.scss
3
+ // Semantic markup for web publishing.
4
+ //
5
+ // Copyright 2018 Kam Low
6
+ // https://sourcey.com
7
+ //
8
+
9
+ @mixin texy(
10
+ $font-sans-serif: sans-serif,
11
+ $font-serif: serif,
12
+ $font-size: 18px,
13
+ $font-weight: 400,
14
+ $line-height: 32px,
15
+
16
+ $heading-weight: 600,
17
+ $heading-color: #111,
18
+
19
+ $caption-font-size: 14px,
20
+ $caption-font-weight: 400,
21
+ $caption-line-height: 1.5,
22
+ $caption-text-color: #454545,
23
+
24
+ $text-color: #333,
25
+ $link-color: #007bff,
26
+ $accent-color: #6610f2,
27
+ $separator-color: #eee,
28
+
29
+ $paragraph-margin: 1.75rem,
30
+ $block-margin: 3rem,
31
+ $pull-margin: 5rem) {
32
+
33
+ font-size: $font-size;
34
+ font-weight: $font-weight;
35
+
36
+
37
+ //
38
+ /// Headings
39
+
40
+ h1, h2, h3, h4, h5, h6 {
41
+ margin-bottom: $paragraph-margin;
42
+ font-weight: $heading-weight;
43
+ color: $heading-color;
44
+
45
+ + .block {
46
+ margin-top: 0;
47
+ }
48
+ }
49
+ h1 {
50
+ margin-top: $block-margin;
51
+ font-size: $font-size * 2;
52
+ }
53
+ h2 {
54
+ margin-top: $block-margin;
55
+ font-size: $font-size * 1.75;
56
+ }
57
+ h3 {
58
+ font-size: $font-size * 1.5;
59
+ }
60
+ h4 {
61
+ font-size: $font-size * 1.33;
62
+ }
63
+ h5 {
64
+ font-size: $font-size * 1.25;
65
+ }
66
+
67
+
68
+ //
69
+ /// Typography
70
+
71
+ p, ul, ol, > pre, > img, > center {
72
+ margin-bottom: $paragraph-margin;
73
+ }
74
+
75
+ p, li, cite, figcaption {
76
+ a {
77
+ color: inherit;
78
+ position: relative;
79
+
80
+ &:before {
81
+ content: '';
82
+ position: absolute;
83
+ left: 0;
84
+ right: 0;
85
+ bottom: -.25rem;
86
+ z-index: -1;
87
+ border-bottom: 2px solid lighten($link-color, 30%);
88
+ }
89
+
90
+ &:hover {
91
+ text-decoration: none;
92
+ color: black;
93
+
94
+ &:before {
95
+ border-color: $link-color;
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ img {
102
+ max-width: 100%;
103
+
104
+ &.block {
105
+ display: block;
106
+ }
107
+ &.left {
108
+ float: left;
109
+ margin-right: $paragraph-margin;
110
+ margin-bottom: $paragraph-margin;
111
+ }
112
+ &.right {
113
+ float: left;
114
+ margin-left: $paragraph-margin;
115
+ margin-bottom: $paragraph-margin;
116
+ }
117
+ }
118
+
119
+ hr {
120
+ border-top: 1px solid $separator-color;
121
+ margin-top: $block-margin;
122
+ margin-bottom: $block-margin;
123
+ clear: both;
124
+ }
125
+
126
+
127
+ //
128
+ /// Helpers
129
+
130
+ .block {
131
+ margin-top: $block-margin;
132
+ margin-bottom: $block-margin;
133
+ }
134
+
135
+ .center {
136
+ text-align: center;
137
+ margin-left: auto;
138
+ margin-right: auto;
139
+ }
140
+
141
+ .pull {
142
+ @include media-breakpoint-up(lg) {
143
+ margin-left: -$pull-margin;
144
+ margin-right: -$pull-margin;
145
+ }
146
+ }
147
+
148
+ .left {
149
+ float: left;
150
+ max-width: 40%;
151
+ margin-top: $block-margin * .75;
152
+ margin-bottom: $block-margin * .75;
153
+ margin-right: $block-margin;
154
+
155
+ // &.out,
156
+ // &.pull {
157
+ // margin-left: -$pull-margin;
158
+ // }
159
+ }
160
+
161
+ .right {
162
+ float: right;
163
+ max-width: 40%;
164
+ margin-top: $block-margin * .75;
165
+ margin-bottom: $block-margin * .75;
166
+ margin-left: $block-margin;
167
+
168
+ // &.out,
169
+ // &.pull {
170
+ // margin-right: -$pull-margin;
171
+ // }
172
+ }
173
+
174
+
175
+ //
176
+ /// Blockquotes
177
+
178
+ blockquote {
179
+ color: $gray-900;
180
+
181
+ img {
182
+ margin-bottom: $paragraph-margin;
183
+ }
184
+
185
+ p:only-of-type {
186
+ margin-bottom: 0;
187
+ }
188
+
189
+ cite {
190
+ font-size: $caption-font-size;
191
+ font-weight: $caption-font-weight;
192
+ line-height: $caption-line-height;
193
+ color: $caption-text-color;
194
+
195
+ &:before {
196
+ // Add a dash and space before citations
197
+ // &mdhash;  in Hexadecimal
198
+ content:'\2014\00a0';
199
+ }
200
+ }
201
+
202
+ &.left,
203
+ &.right {
204
+ border-top: 6px solid $accent-color;
205
+ border-bottom: 1px solid $text-color;
206
+ padding-top: 1.5rem;
207
+ padding-bottom: 1rem;
208
+ font-weight: 500;
209
+ line-height: 1.725;
210
+
211
+ cite {
212
+ display: block;
213
+ margin-top: 0.75rem;
214
+ font-style: italic;
215
+ }
216
+ }
217
+
218
+ &.block {
219
+ font-family: $font-serif;
220
+ font-size: $font-size * 1.25;
221
+ font-weight: 400;
222
+ font-style: italic;
223
+
224
+ border-top: 3px solid $accent-color;
225
+ border-bottom: 1px solid $separator-color;
226
+ padding-top: $paragraph-margin;
227
+ // padding-bottom: $paragraph-margin;
228
+ // margin-top: $paragraph-margin;
229
+ // margin-bottom: $paragraph-margin;
230
+
231
+ cite {
232
+ font-family: $font-sans-serif;
233
+ margin-top: 1rem;
234
+ margin-bottom: 1.25rem;
235
+ display: block;
236
+ // font-style: normal;
237
+ }
238
+ }
239
+ }
240
+
241
+
242
+ //
243
+ /// Image Figure
244
+
245
+ figure {
246
+ margin-top: $block-margin;
247
+ margin-bottom: $block-margin;
248
+
249
+ p {
250
+ margin-bottom: 0;
251
+ }
252
+
253
+ figcaption {
254
+ font-size: $caption-font-size;
255
+ font-weight: $caption-font-weight;
256
+ line-height: $caption-line-height;
257
+ color: $caption-text-color;
258
+ padding: .5rem 0 0;
259
+ // padding: .5rem 0;
260
+ // border-bottom: 2px solid $text-color;
261
+ }
262
+
263
+ // &.block {
264
+ // // margin-top: 3rem;
265
+ //
266
+ // figcaption {
267
+ // // border-color: 2px solid $separator-color;
268
+ // }
269
+ // }
270
+ }
271
+
272
+
273
+ // Full Layout
274
+ // @include media-breakpoint-up(lg) {
275
+ // }
276
+
277
+ // Mobile Layout
278
+ @include media-breakpoint-down(lg) {
279
+ figure {
280
+ &.left {
281
+ margin-left: 0 !important;
282
+ margin-right: $paragraph-margin !important;
283
+ }
284
+
285
+ &.right {
286
+ margin-left: $paragraph-margin !important;
287
+ margin-right: 0 !important;
288
+ }
289
+ }
290
+
291
+ blockquote {
292
+ &.left,
293
+ &.right {
294
+ margin: 0;
295
+ float: none;
296
+ max-width: none;
297
+
298
+ &.out,
299
+ &.pull {
300
+ margin: $paragraph-margin 0;
301
+ border-top: 3px solid $accent-color;
302
+ border-bottom: 1px solid $text-color;
303
+ }
304
+ }
305
+ }
306
+ }
307
+
308
+ // Mobile Layout
309
+ @include media-breakpoint-down(xs) {
310
+ }
311
+ }
@@ -0,0 +1,33 @@
1
+ module Designer
2
+ class ApplicationController < ActionController::Base
3
+ before_action :set_host_for_local_storage
4
+
5
+ protected
6
+
7
+ def set_host_for_local_storage
8
+ ActiveStorage::Current.host = request.base_url if Rails.application.config.active_storage.service == :local
9
+ end
10
+
11
+ helper_method :resource_name, :resource_type
12
+
13
+ def resource_name
14
+ params[:resource_name]
15
+ end
16
+
17
+ def resource_type
18
+ params[:resource_name].classify
19
+ end
20
+
21
+ def set_resource
22
+ @resource = resource_type.constantize.find(params[:id])
23
+ end
24
+
25
+ def resource_params
26
+ params.require(:resource).permit!
27
+ end
28
+
29
+ def set_host_for_local_storage
30
+ ActiveStorage::Current.host = request.base_url if Rails.application.config.active_storage.service == :local
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ require_dependency "designer/application_controller"
2
+
3
+ module Designer
4
+ class EditorController < ApplicationController
5
+ before_action :set_resource
6
+ # skip_before_action :verify_authenticity_token
7
+
8
+ def show
9
+ end
10
+
11
+ def update
12
+ if @resource.update(resource_params.merge(elements: resource_elements))
13
+ render_success
14
+ else
15
+ render_error
16
+ end
17
+ end
18
+
19
+ # def preview
20
+ # raise 'virtual'
21
+ # end
22
+
23
+ protected
24
+
25
+ def resource_elements
26
+ # BUG: The front end stringifies the elements JSON, but this is getting
27
+ # auto-parsed by Rails only in production, so check if it's a string first.
28
+ @resource_elements ||= params[:resource][:elements]&.is_a?(String) ?
29
+ JSON.parse(params[:resource][:elements]) : params[:resource][:elements]
30
+ end
31
+
32
+ def render_success message = nil
33
+ if request.xhr?
34
+ flash.now[:notice] = message || "#{resource_type.classify} saved"
35
+ render :notifications
36
+ else
37
+ render json: @resource
38
+ end
39
+ end
40
+
41
+ def render_error
42
+ if request.xhr?
43
+ flash.now[:error] = @resource.errors.full_messages.join('. ')
44
+ render :notifications, status: :unprocessable_entity
45
+ else
46
+ head :unprocessable_entity
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,66 @@
1
+ require_dependency "designer/application_controller"
2
+
3
+ module Designer
4
+ class ImagesController < ApplicationController
5
+ before_action :set_resource
6
+ before_action :set_attachment, only: [:destroy]
7
+ # skip_before_action :verify_authenticity_token
8
+
9
+ def index
10
+ render json: designer_images_json
11
+ end
12
+
13
+ def create
14
+ @resource.attachments.attach(params[:file])
15
+
16
+ render json: designer_images_json
17
+ end
18
+
19
+ def destroy
20
+ @attachment.purge_later
21
+ end
22
+
23
+ private
24
+
25
+ def set_attachment
26
+ @attachment = ActiveStorage::Attachment.where(record: @resource).joins(:blob)
27
+ .where(active_storage_blobs: {key: params[:key]}).first
28
+ end
29
+
30
+ def all_attachments
31
+ @attachments ||= ActiveStorage::Attachment.where(record: @resource).joins(:blob)
32
+ end
33
+
34
+ def designer_images_json
35
+ all_attachments.map do |attachment|
36
+ designer_image_json attachment
37
+ end
38
+ end
39
+
40
+ def designer_image_json attachment
41
+ {
42
+ key: attachment.key,
43
+ # signed_id: attachment.signed_id,
44
+ name: attachment.filename,
45
+ size: attachment.byte_size,
46
+ kind: attachment.name,
47
+ thumbnail_url: attachment.variant(resize: '100x100').processed.service_url,
48
+ delete_url: image_path(key: attachment.key, id: @resource.id, resource_name: params[:resource_name])
49
+ # sources: {
50
+ # 'Image Key' => attachment.key,
51
+ # 'Signed ID' => attachment.signed_id,
52
+ # 'Small: 256x' => Image::UrlResolver.new(attachment, {size: :small}).perform,
53
+ # 'Small Square: 256x256' => Image::UrlResolver.new(attachment, {size: :small_square}).perform,
54
+ # 'Thumb: 512x' => Image::UrlResolver.new(attachment, {size: :thumb}).perform,
55
+ # 'Thumb Square: 512x512' => Image::UrlResolver.new(attachment, {size: :thumb_square}).perform,
56
+ # 'Main: 1024x' => Image::UrlResolver.new(attachment, {size: :main}).perform,
57
+ # 'Cover: 1600x' => Image::UrlResolver.new(attachment, {size: :cover}).perform,
58
+ # 'Newsletter: 600x600' => Image::UrlResolver.new(attachment, {size: {width: 600, height: 600, crop: 'fill'}}).perform,
59
+ # 'Newsletter: 600x300' => Image::UrlResolver.new(attachment, {size: {width: 600, height: 300, crop: 'fill'}}).perform,
60
+ # 'Newsletter: 300x300' => Image::UrlResolver.new(attachment, {size: {width: 300, height: 300, crop: 'fill'}}).perform,
61
+ # 'Newsletter: 200x200' => Image::UrlResolver.new(attachment, {size: {width: 200, height: 200, crop: 'fill'}}).perform
62
+ # }
63
+ }
64
+ end
65
+ end
66
+ end