tramway-landing 1.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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/tramway_landing_manifest.js +2 -0
  6. data/app/assets/javascripts/justified_images.js +284 -0
  7. data/app/assets/javascripts/tramway/landing/application.js.coffee +3 -0
  8. data/app/assets/javascripts/tramway/landing/footer.js.coffee +24 -0
  9. data/app/assets/stylesheets/tramway/landing/application.css.sass +16 -0
  10. data/app/assets/stylesheets/tramway/landing/collage.css.sass +36 -0
  11. data/app/assets/stylesheets/tramway/landing/justified.css +13 -0
  12. data/app/controllers/tramway/landing/application_controller.rb +11 -0
  13. data/app/decorators/tramway/landing/block_decorator.rb +26 -0
  14. data/app/decorators/tramway/landing/block_types/cards_decorator.rb +13 -0
  15. data/app/decorators/tramway/landing/block_types/features_decorator.rb +9 -0
  16. data/app/forms/tramway/landing/block_form.rb +15 -0
  17. data/app/helpers/tramway/landing/application_helper.rb +8 -0
  18. data/app/jobs/tramway/landing/application_job.rb +6 -0
  19. data/app/mailers/tramway/landing/application_mailer.rb +8 -0
  20. data/app/models/tramway/landing/application_record.rb +7 -0
  21. data/app/models/tramway/landing/block.rb +24 -0
  22. data/app/uploaders/tramway/landing/photo_versions.rb +15 -0
  23. data/app/views/layouts/tramway/landing/application.html.haml +28 -0
  24. data/app/views/tramway/landing/blocks/block_types/_cards.html.haml +36 -0
  25. data/app/views/tramway/landing/blocks/block_types/_contacts.html.haml +48 -0
  26. data/app/views/tramway/landing/blocks/block_types/_features.html.haml +26 -0
  27. data/app/views/tramway/landing/blocks/block_types/_footer.html.haml +16 -0
  28. data/app/views/tramway/landing/blocks/block_types/_header.html.haml +22 -0
  29. data/app/views/tramway/landing/blocks/block_types/_page.html.haml +9 -0
  30. data/config/initializers/assets.rb +1 -0
  31. data/config/initializers/tramway.rb +1 -0
  32. data/config/locales/models.yml +19 -0
  33. data/config/locales/state_machines.yml +15 -0
  34. data/config/routes.rb +2 -0
  35. data/lib/tasks/tramway/landing_tasks.rake +4 -0
  36. data/lib/tramway/landing.rb +7 -0
  37. data/lib/tramway/landing/engine.rb +7 -0
  38. data/lib/tramway/landing/generates/install_generator.rb +21 -0
  39. data/lib/tramway/landing/generates/templates/add_anchor_to_tramway_landing_blocks.rb +5 -0
  40. data/lib/tramway/landing/generates/templates/add_description_to_tramway_landing_blocks.rb +5 -0
  41. data/lib/tramway/landing/generates/templates/add_navbar_link_to_tramway_landing_blocks.rb +5 -0
  42. data/lib/tramway/landing/generates/templates/create_tramway_landing_blocks.rb +14 -0
  43. data/lib/tramway/landing/version.rb +5 -0
  44. metadata +86 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bc98a307ccf33e690b805a6adfeb1b7f110be1269bae2a02a90d3f7c1a0cc6e9
4
+ data.tar.gz: 5b85a0739fbc0da2ff548f1f79ff5a2dede5b5f0796f2e09fd36ce145825bf14
5
+ SHA512:
6
+ metadata.gz: e8fedc657c02b00f46af054ddf56a81c78acf2ef148b6eeb79ba375911702c0a7194e80de56f15743bd4aa4db4ce5474871db00eb596a9469e56eac06aedff9e
7
+ data.tar.gz: f8d3d47ccc3dc8f1787b1ed027ddbd3deecbde84031b1b42a1cb1f39d47543c42ca5372e3287e53b7147f551487f3a09d234303e3671f67458bdff3f28745a92
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Pavel Kalashnikov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Tramway::Landing
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'tramway-landing'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install tramway-landing
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Tramway::Landing'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'test'
31
+ t.pattern = 'test/**/*_test.rb'
32
+ t.verbose = false
33
+ end
34
+
35
+
36
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/tramway/landing .js
2
+ //= link_directory ../stylesheets/tramway/landing .css
@@ -0,0 +1,284 @@
1
+ /*jshint white:false*/
2
+ /* global jQuery: true*/
3
+ // the semi-colon before function invocation is a safety net against concatenated
4
+ // scripts and/or other plugins which may not be closed properly.
5
+ ;
6
+ (function($, window, document, undefined) {
7
+ 'use strict';
8
+ // undefined is used here as the undefined global variable in ECMAScript 3 is
9
+ // mutable (ie. it can be changed by someone else). undefined isn't really being
10
+ // passed in so we can ensure the value of it is truly undefined. In ES5, undefined
11
+ // can no longer be modified.
12
+
13
+ // window and document are passed through as local variable rather than global
14
+ // as this (slightly) quickens the resolution process and can be more efficiently
15
+ // minified (especially when both are regularly referenced in your plugin).
16
+
17
+ // Create the defaults once
18
+ var pluginName = 'justifiedImages';
19
+
20
+
21
+ // The actual plugin constructor
22
+
23
+ function Plugin(element, options) {
24
+ this.element = element;
25
+ this.$el = $(element);
26
+ this._name = pluginName;
27
+ this.init(options);
28
+ }
29
+
30
+ Plugin.prototype = {
31
+ defaults: {
32
+ template: function(data) {
33
+ return '<div class="photo-container" style="height:' + data.displayHeight + 'px;margin-right:' + data.marginRight + 'px;">' +
34
+ '<img class="image-thumb" src="' + data.src + '" style="width:' + data.displayWidth + 'px;height:' + data.displayHeight + 'px;" >' +
35
+ '</div>';
36
+ },
37
+ appendBlocks : function(){ return []; },
38
+ rowHeight: 150,
39
+ maxRowHeight: 350,
40
+ handleResize: false,
41
+ margin: 1,
42
+ imageSelector: 'image-thumb',
43
+ imageContainer: 'photo-container'
44
+ },
45
+ init: function(options) {
46
+ this.options = $.extend({}, this.defaults, options);
47
+ this.displayImages();
48
+ if (this.options.handleResize) {
49
+ this.handleResize();
50
+ }
51
+ },
52
+ getBlockInRow: function(rowNum){
53
+ var appendBlocks = this.options.appendBlocks();
54
+ for (var i = 0; i < appendBlocks.length; i++) {
55
+ var block = appendBlocks[i];
56
+ if(block.rowNum === rowNum){
57
+ return block;
58
+ }
59
+ }
60
+ },
61
+ displayImages: function() {
62
+ var self = this,
63
+ ws = [],
64
+ rowNum = 0,
65
+ baseLine = 0,
66
+ limit = this.options.images.length,
67
+ photos = this.options.images,
68
+ rows = [],
69
+ totalWidth = 0,
70
+ appendBlocks = this.options.appendBlocks();
71
+ var w = this.$el.width();
72
+ var border = parseInt(this.options.margin, 10);
73
+ var d = this.$el,
74
+ h = parseInt(this.options.rowHeight, 10);
75
+
76
+ $.each(this.options.images, function(index, image) {
77
+ var size = self.options.getSize(image);
78
+ var wt = parseInt(size.width, 10);
79
+ var ht = parseInt(size.height, 10);
80
+ if (ht !== h) {
81
+ wt = Math.floor(wt * (h / ht));
82
+ }
83
+ totalWidth += wt;
84
+ ws.push(wt);
85
+ });
86
+
87
+ $.each(appendBlocks, function(index, block){
88
+ totalWidth += block.width;
89
+ });
90
+ var perRowWidth = totalWidth / Math.ceil(totalWidth / w);
91
+ console.log('rows', Math.ceil(totalWidth / w));
92
+ var tw = 0;
93
+ while (baseLine < limit) {
94
+ var row = {
95
+ width: 0,
96
+ photos: []
97
+ },
98
+ c = 0,
99
+ block = this.getBlockInRow(rows.length + 1);
100
+ if(block){
101
+ row.width += block.width;
102
+ tw += block.width;
103
+ }
104
+ while ((tw + ws[baseLine + c] / 2 <= perRowWidth * (rows.length + 1)) && (baseLine + c < limit)) {
105
+ tw += ws[baseLine + c];
106
+ row.width += ws[baseLine + c];
107
+ row.photos.push({
108
+ width: ws[baseLine + c],
109
+ photo: photos[baseLine + c]
110
+ });
111
+ c++;
112
+ }
113
+ baseLine += c;
114
+ rows.push(row);
115
+ }
116
+ console.log(rows.length, rows);
117
+ /*for (var i = 1; i < rows.length; i++) {
118
+ var row = rows[i];
119
+ for (var j = 0; j < row.photos.length; j++) {
120
+ var photo = row.photos[j].photo;
121
+ };
122
+ }*/
123
+ for (var i = 0; i < rows.length; i++) {
124
+ var row = rows[i],
125
+ lastRow = false;
126
+ rowNum = i + 1;
127
+ if (this.options.maxRows && rowNum > this.options.maxRows) {
128
+ break;
129
+ }
130
+ if (i === rows.length - 1) {
131
+ lastRow = true;
132
+ }
133
+ tw = -1 * border;
134
+ var newBlock = this.getBlockInRow(lastRow ? -1 : rowNum), availableRowWidth = w;
135
+ if(newBlock){
136
+ availableRowWidth -= newBlock.width;
137
+ tw = 0;
138
+ }
139
+
140
+ // Ratio of actual width of row to total width of images to be used.
141
+ var r = availableRowWidth / row.width, //Math.min(w / row.width, this.options.maxScale),
142
+ c = row.photos.length;
143
+
144
+ // new height is not original height * ratio
145
+ var ht = Math.min(Math.floor(h * r), parseInt(this.options.maxRowHeight,10));
146
+ r = ht / this.options.rowHeight;
147
+ var domRow = $('<div/>', {
148
+ 'class': 'picrow'
149
+ });
150
+ domRow.height(ht + border);
151
+ d.append(domRow);
152
+
153
+ var imagesHtml = '';
154
+ for (var j = 0; j < row.photos.length; j++) {
155
+ var photo = row.photos[j].photo;
156
+ // Calculate new width based on ratio
157
+ var wt = Math.floor(row.photos[j].width * r);
158
+ tw += wt + border;
159
+
160
+ imagesHtml += this.renderPhoto(photo, {
161
+ src: this.options.thumbnailPath(photo, wt, ht),
162
+ width: wt,
163
+ height: ht
164
+ }, newBlock ? false : j === row.photos.length - 1);
165
+ }
166
+ if(imagesHtml === ''){
167
+ domRow.remove();
168
+ continue;
169
+ }
170
+
171
+ domRow.html(imagesHtml);
172
+
173
+
174
+
175
+ if ((Math.abs(tw - availableRowWidth) < 0.05 * availableRowWidth)) {
176
+ // if total width is slightly smaller than
177
+ // actual div width then add 1 to each
178
+ // photo width till they match
179
+ var k = 0;
180
+ while (tw < availableRowWidth) {
181
+ var div1 = domRow.find('.' + this.options.imageContainer + ':nth-child(' + (k + 1) + ')'),
182
+ img1 = div1.find('.' + this.options.imageSelector);
183
+ img1.width(img1.width() + 1);
184
+ k = (k + 1) % c;
185
+ tw++;
186
+ }
187
+ // if total width is slightly bigger than
188
+ // actual div width then subtract 1 from each
189
+ // photo width till they match
190
+ k = 0;
191
+ while (tw > availableRowWidth) {
192
+ var div2 = domRow.find('.' + this.options.imageContainer + ':nth-child(' + (k + 1) + ')'),
193
+ img2 = div2.find('.' + this.options.imageSelector);
194
+ img2.width(img2.width() - 1);
195
+ k = (k + 1) % c;
196
+ tw--;
197
+ }
198
+ } else{
199
+ if( availableRowWidth - tw > 0.05 * availableRowWidth ){
200
+ var diff = availableRowWidth-tw,
201
+ adjustedDiff = 0,
202
+ images = domRow.find('.' + this.options.imageContainer),
203
+ marginTop = 0;
204
+ for(var l = 0 ; l < images.length ; l++ ){
205
+ var currentDiff = diff / (images.length),
206
+ imgDiv = images.eq(l),
207
+ img = imgDiv.find('.' + this.options.imageSelector),
208
+ imageWidth = img.width(),
209
+ imageHeight = img.height();
210
+ if( i === images.length - 1 ){
211
+ currentDiff = diff - adjustedDiff;
212
+ }
213
+ img.width( imageWidth + currentDiff );
214
+ img.height( ( imageHeight / imageWidth ) * (imageWidth + currentDiff) );
215
+ marginTop = (imageHeight - img.height()) / 2;
216
+ img.css('margin-top', marginTop);
217
+ adjustedDiff += currentDiff;
218
+ }
219
+ }
220
+ }
221
+
222
+ if(newBlock){
223
+ $('<div />', {
224
+ class : this.options.imageContainer + ' added-block',
225
+ css : {
226
+ width : newBlock.width,
227
+ height: ht
228
+ },
229
+ html : newBlock.html
230
+ }).appendTo(domRow);
231
+ }
232
+ }
233
+ },
234
+ renderPhoto: function(image, obj, isLast) {
235
+ var data = {},
236
+ d;
237
+ d = $.extend({}, image, {
238
+ src: obj.src,
239
+ displayWidth: obj.width,
240
+ displayHeight: obj.height,
241
+ marginRight: isLast ? 0 : this.options.margin
242
+ });
243
+ if (this.options.dataObject) {
244
+ data[this.options.dataObject] = d;
245
+ } else {
246
+ data = d;
247
+ }
248
+ return this.options.template(data);
249
+ },
250
+ handleResize: function() {},
251
+ refresh: function(options) {
252
+ this.options = $.extend({}, this.defaults, options);
253
+ this.$el.empty();
254
+ this.displayImages();
255
+ }
256
+ };
257
+
258
+
259
+ // A really lightweight plugin wrapper around the constructor,
260
+ // preventing against multiple instantiations
261
+ $.fn[pluginName] = function(option) {
262
+ var args = arguments,
263
+ result;
264
+
265
+ this.each(function() {
266
+ var $this = $(this),
267
+ data = $.data(this, 'plugin_' + pluginName),
268
+ options = typeof option === 'object' && option;
269
+ if (!data) {
270
+ $this.data('plugin_' + pluginName, (data = new Plugin(this, options)));
271
+ }else{
272
+ if (typeof option === 'string') {
273
+ result = data[option].apply(data, Array.prototype.slice.call(args, 1));
274
+ } else {
275
+ data.refresh.call(data, options);
276
+ }
277
+ }
278
+ });
279
+
280
+ // To enable plugin returns values
281
+ return result || this;
282
+ };
283
+
284
+ })(jQuery, window, document);
@@ -0,0 +1,3 @@
1
+ #= require jquery
2
+ #= require jquery_ujs
3
+ #= require_tree .
@@ -0,0 +1,24 @@
1
+ #= require justified_images
2
+
3
+ $(document).ready ->
4
+ $('.logo_collage1').empty().justifiedImages
5
+ images: photos
6
+ rowHeight: 200
7
+ maxRowHeight: 400
8
+ thumbnailPath: (photo, width, height) ->
9
+ purl = photo.url_s
10
+ if photo.url_n and (width > photo.width_s * 1.2 or height > photo.height_s * 1.2)
11
+ purl = photo.url_n
12
+ if photo.url_m and (width > photo.width_n * 1.2 or height > photo.height_n * 1.2)
13
+ purl = photo.url_m
14
+ if photo.url_z and (width > photo.width_m * 1.2 or height > photo.height_m * 1.2)
15
+ purl = photo.url_z
16
+ if photo.url_l and (width > photo.width_z * 1.2 or height > photo.height_z * 1.2)
17
+ purl = photo.url_l
18
+ purl
19
+ getSize: (photo) ->
20
+ {
21
+ width: photo.width_s
22
+ height: photo.height_s
23
+ }
24
+ margin: 1
@@ -0,0 +1,16 @@
1
+ /*
2
+ *= require_tree .
3
+ *= require_self
4
+ */
5
+
6
+ html, body, header, #intro
7
+ height: 100%
8
+
9
+ #intro
10
+ background-repeat: no-repeat
11
+ background-position: center center
12
+ background-attachment: fixed
13
+ -webkit-background-size: cover
14
+ -moz-background-size: cover
15
+ -o-background-size: cover
16
+ background-size: cover
@@ -0,0 +1,36 @@
1
+ .logo_collage
2
+ line-height: 0
3
+ -webkit-column-count: 5
4
+ -webkit-column-gap: 0px
5
+ -moz-column-count: 5
6
+ -moz-column-gap: 0px
7
+ column-count: 5
8
+ column-gap: 0px
9
+ img
10
+ width: 100% !important
11
+ height: auto !important
12
+ margin: 1px
13
+
14
+ @media (max-width: 1200px)
15
+ .logo_collage
16
+ -moz-column-count: 4
17
+ -webkit-column-count: 4
18
+ column-count: 4
19
+
20
+ @media (max-width: 1000px)
21
+ .logo_collage
22
+ -moz-column-count: 3
23
+ -webkit-column-count: 3
24
+ column-count: 3
25
+
26
+ @media (max-width: 800px)
27
+ .logo_collage
28
+ -moz-column-count: 2
29
+ -webkit-column-count: 2
30
+ column-count: 2
31
+
32
+ @media (max-width: 400px)
33
+ .logo_collage
34
+ -moz-column-count: 1
35
+ -webkit-column-count: 1
36
+ column-count: 1
@@ -0,0 +1,13 @@
1
+
2
+ .image-container{
3
+ position: relative;
4
+ }
5
+ .photo-container{
6
+ float: left;
7
+ position: relative;
8
+ overflow: hidden;
9
+ }
10
+ .image-thumb{
11
+ position: relative;
12
+ background-color: #eee;
13
+ }
@@ -0,0 +1,11 @@
1
+ module Tramway
2
+ module Landing
3
+ class ApplicationController < ActionController::Base
4
+ protect_from_forgery with: :exception
5
+
6
+ def application
7
+ ::Tramway::Core::Application.first
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ class Tramway::Landing::BlockDecorator < ::Tramway::Core::ApplicationDecorator
2
+ class << self
3
+ def collections
4
+ [ :all ]
5
+ end
6
+
7
+ def list_attributes
8
+ [ :position, :view_state ]
9
+ end
10
+ end
11
+
12
+ delegate :position, to: :object
13
+
14
+ def view_state
15
+ object.human_view_state_name
16
+ end
17
+
18
+ def view_state_button_color(event)
19
+ case event
20
+ when :publish
21
+ :primary
22
+ when :hide
23
+ :secondary
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ class Tramway::Landing::BlockTypes::CardsDecorator < ::Tramway::Core::ApplicationDecorator
2
+ def image; end
3
+
4
+ def title; end
5
+
6
+ def description; end
7
+
8
+ def button; end
9
+
10
+ def icon; end
11
+
12
+ def path; end
13
+ end
@@ -0,0 +1,9 @@
1
+ class Tramway::Landing::BlockTypes::FeaturesDecorator < ::Tramway::Core::ApplicationDecorator
2
+ def icon; end
3
+
4
+ def image; end
5
+
6
+ def title; end
7
+
8
+ def text; end
9
+ end
@@ -0,0 +1,15 @@
1
+ class Tramway::Landing::BlockForm < ::Tramway::Core::ApplicationForm
2
+ properties :title, :background, :view_state, :block_type, :position, :navbar_link, :anchor, :description
3
+
4
+ def initialize(object)
5
+ form_object = super object
6
+ form_properties title: :string,
7
+ background: :file,
8
+ position: :numeric,
9
+ block_type: :default,
10
+ navbar_link: :default,
11
+ anchor: :string,
12
+ description: :default
13
+ form_object
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ module Tramway
2
+ module Landing
3
+ module ApplicationHelper
4
+ include Tramway::Admin::RussianCasesHelper
5
+ include Tramway::Profiles::LinksHelper
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module Tramway
2
+ module Landing
3
+ class ApplicationJob < ActiveJob::Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Tramway
2
+ module Landing
3
+ class ApplicationMailer < ActionMailer::Base
4
+ default from: 'from@example.com'
5
+ layout 'mailer'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Tramway
2
+ module Landing
3
+ class ApplicationRecord < ::Tramway::Core::ApplicationRecord
4
+ self.abstract_class = true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ class Tramway::Landing::Block < ::Tramway::Landing::ApplicationRecord
2
+ enumerize :block_type, in: [ :header, :footer, :page, :cards, :features, :contacts, :news ]
3
+ enumerize :navbar_link, in: [ :exist, :not_exist ], default: :not_exist
4
+
5
+ mount_uploader :background, PhotoUploader
6
+
7
+ state_machine :view_state, initial: :published do
8
+ state :published
9
+ state :hidden
10
+
11
+ event :publish do
12
+ transition hidden: :published
13
+ end
14
+
15
+ event :hide do
16
+ transition published: :hidden
17
+ end
18
+ end
19
+
20
+ scope :on_main_page, -> { active.where(view_state: :published).order :position }
21
+ scope :with_navbar_link, -> { where navbar_link: :exist }
22
+ scope :header, -> { on_main_page.where(block_type: :header).first }
23
+ scope :footer, -> { on_main_page.where(block_type: :footer).first }
24
+ end
@@ -0,0 +1,15 @@
1
+ module Tramway::Landing::PhotoVersions
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ version :card do
6
+ process resize_to_fill: [400, 400, 'North']
7
+ end
8
+
9
+ version :horizontal do
10
+ process resize_to_fill: [1600, 700, 'Center']
11
+ end
12
+ end
13
+ end
14
+
15
+ PhotoUploader.include Tramway::Landing::PhotoVersions
@@ -0,0 +1,28 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %meta{content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}
5
+ %title
6
+ = yield :title
7
+ = stylesheet_link_tag "tramway/landing/application", media: "all"
8
+ = javascript_include_tag "tramway/landing/application"
9
+ = javascript_include_tag "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js", integrity: "sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl", crossorigin: "anonymous"
10
+ = javascript_include_tag "https://code.jquery.com/jquery-3.2.1.slim.min.js", integrity: "sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN", crossorigin: "anonymous"
11
+ = javascript_include_tag "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js", integrity: "sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q", crossorigin: "anonymous"
12
+ = csrf_meta_tags
13
+ = yield :head_content
14
+ %body
15
+ = stylesheet_link_tag 'https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.4.5/css/mdb.min.css'
16
+ = javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.4.5/js/mdb.js'
17
+ = javascript_include_tag 'https://cdn.rawgit.com/CezarLuiz0/anchor.js/master/dist/anchor.min.js'
18
+ - if @blocks&.any?
19
+ = render "tramway/landing/blocks/block_types/header", block: @blocks.header
20
+ %main{ class: ('mt-5' if @blocks&.any?) }
21
+ .container
22
+ - if @blocks&.any?
23
+ - (@blocks - [@blocks.header] - [@blocks.footer]).each do |block|
24
+ = render "tramway/landing/blocks/block_types/#{block.block_type}", block: block
25
+ .container-fluid
26
+ = yield
27
+ - if @blocks&.any?
28
+ = render "tramway/landing/blocks/block_types/footer", block: @blocks.footer
@@ -0,0 +1,36 @@
1
+ .container.text-center
2
+ %h2.mb-4.font-weight-bold
3
+ = block.title
4
+ %p.grey-text
5
+ = block.description
6
+ .row{ id: block.anchor }
7
+ -# FIXME bad guy mode ON
8
+ - eval("@collection_#{block.anchor}").each do |item|
9
+ .col-lg-4.col-md-12.mb-4
10
+ - if item.path.present?
11
+ = link_to item.path do
12
+ .card.link
13
+ .view.overlay.hm-white-slight
14
+ = image_tag item.image, class: 'img-fluid'
15
+ = link_to '#' do
16
+ .mask
17
+ .card-body
18
+ %h4.card-title
19
+ = item.title
20
+ %p.card-text
21
+ = item.description
22
+ - if item.button.present?
23
+ = link_to item.button.text, item.button.url, class: 'btn btn-primary'
24
+ - else
25
+ .card
26
+ .view.overlay.hm-white-slight
27
+ = image_tag item.image, class: 'img-fluid'
28
+ = link_to '#' do
29
+ .mask
30
+ .card-body
31
+ %h4.card-title
32
+ = item.title
33
+ %p.card-text
34
+ = item.description
35
+ - if item.button.present?
36
+ = link_to item.button.text, item.button.url, class: 'btn btn-primary'
@@ -0,0 +1,48 @@
1
+ %script{ src: 'https://maps.google.com/maps/api/js?key=AIzaSyDC054dWb7cQ_mULJk3d1UBK6pN8msCx1g' }
2
+ :javascript
3
+ function regular_map() {
4
+ var var_location = new google.maps.LatLng(#{yield(:latitude)}, #{yield(:longtitude)});
5
+
6
+ var var_mapoptions = {
7
+ center: var_location,
8
+ zoom: 14
9
+ };
10
+
11
+ var var_map = new google.maps.Map(document.getElementById("map-container"),
12
+ var_mapoptions);
13
+
14
+ var var_marker = new google.maps.Marker({
15
+ position: var_location,
16
+ map: var_map,
17
+ title: "New York"
18
+ });
19
+ }
20
+ google.maps.event.addDomListener(window, 'load', regular_map);
21
+ #contact
22
+ %h2.mb-5.font-weight-bold.text-center
23
+ = block.title
24
+ .row
25
+ .col-lg-5.col-md-12
26
+ - @application.social_networks.each do |profile|
27
+ %ul.list-group
28
+ %li.list-group-item
29
+ = profile_link profile
30
+ .col-lg-7.col-md-12
31
+ .row.text-center
32
+ - if yield(:address).present?
33
+ .col-lg-4.col-md-12.mb-3
34
+ %p
35
+ = fa_icon :map, class: 'fa-lx mr-2 grey-text'
36
+ = yield :address
37
+ - if yield(:schedule).present?
38
+ .col-lg-4.col-md-6.mb-3
39
+ %p
40
+ = fa_icon :building, class: 'fa-lx mr-2 grey-text'
41
+ = yield :schedule
42
+ - if yield(:phone).present?
43
+ .col-lg-4.col-md-6.mb-3
44
+ %p
45
+ = tel_tag yield(:phone) do
46
+ = fa_icon :phone, class: 'fa-lx mr-2 grey-text'
47
+ = yield :phone
48
+ #map-container.z-depth-1-half.map-container{ style: 'height: 400px' }
@@ -0,0 +1,26 @@
1
+ %main.mt-5
2
+ .container
3
+ %section#best-features.text-center{ id: block.anchor }
4
+ %h2.mb-4.font-weight-bold
5
+ = block.title
6
+ .row.d-flex.justify-content-center.mb-4
7
+ .col-md-8
8
+ %p.grey-text
9
+ = block.description
10
+ .row
11
+ - eval("@collection_#{block.anchor}").each do |item|
12
+ .col-md-4.mb-1
13
+ - if item.icon.present?
14
+ %i.fa.fa-camera-retro.fa-4x.orange-text{ class: "fa-#{item.icon}" }
15
+ - else
16
+ = image_tag item.image
17
+ %h4.my-4
18
+ = item.title
19
+ %p.grey-text
20
+ = item.text
21
+ %hr.my-5/
22
+ %section#examples
23
+ %hr.my-5/
24
+ %section#gallery
25
+ %hr.my-5/
26
+ %section#contact
@@ -0,0 +1,16 @@
1
+ = javascript_include_tag 'tramway/landing/footer'
2
+ %footer.page-footer.indigo.center-on-small-only
3
+ .container-fluid
4
+ .row
5
+ .col-md-6
6
+ %h5.title
7
+ = yield :application_name
8
+ %p
9
+ = yield :application_tagline
10
+ .logo_collage.effect-parent
11
+ = yield :footer_logos
12
+ .col-md-6
13
+ = yield :footer_links
14
+ .footer-copyright
15
+ .container-fluid
16
+ = link_to copyright(2018, yield(:application_name)), yield(:application_url)
@@ -0,0 +1,22 @@
1
+ %header
2
+ %nav.navbar.navbar-expand-lg.navbar-dark.indigo.scrolling-navbar.fixed-top
3
+ = link_to yield(:application_name), '#', class: 'navbar-brand'
4
+
5
+ %button.navbar-toggler{ type: :button, data: { toggle: :collapse, target: '#navbarSupportedContent' }, aria: { controls: 'navbarSupportedContent', expanded: 'false', label: 'Toggle navigation' } }
6
+ = fa_icon :bars
7
+ .collapse.navbar-collapse#navbarSupportedContent
8
+ %ul.navbar-nav.mr-auto
9
+ - @blocks.with_navbar_link.each do |block|
10
+ = menu_item block.title, "##{block.anchor}"
11
+ #intro.view.hm-black-strong{ style: "background-image: url('#{block.background.url}')" }
12
+ .container-fluid.full-bg-img.d-flex.align-items-center.justify-content-center
13
+ .row.d-flex.justify-content-center
14
+ .col-md-10.text-center
15
+ %h2.display-3.font-bold.white-text.mb-2
16
+ = yield(:application_name)
17
+ %hr.hr-light
18
+ %h4.white-text.my-4
19
+ = yield(:application_tagline)
20
+ - @blocks.with_navbar_link.each do |block|
21
+ %button.btn.btn-outline-white.waves-effect.waves-light.header-buttons{ type: :button, data: { anchor: "##{block.anchor}" } }
22
+ = block.title
@@ -0,0 +1,9 @@
1
+ .row
2
+ .col-md-7
3
+ = image_tag block.background, class: 'img-fluid'
4
+ .col-md-5
5
+ %h2
6
+ = block.title
7
+ %hr
8
+ %p
9
+ = block.description
@@ -0,0 +1 @@
1
+ Rails.application.config.assets.precompile += %w( tramway/landing/footer.js )
@@ -0,0 +1 @@
1
+ ::Tramway::Admin.set_available_models ::Tramway::Landing::Block
@@ -0,0 +1,19 @@
1
+ ru:
2
+ activerecord:
3
+ models:
4
+ tramway/landing/block: Блок
5
+ attributes:
6
+ tramway/landing/block:
7
+ title: Название
8
+ background: Изображение на фоне
9
+ position: Позиция на странице
10
+ block_type: Тип блока
11
+ view_state: Видимость на сайте
12
+ cases:
13
+ tramway/landing/block:
14
+ plural: Блоки
15
+ genitive: блок
16
+ enumerize:
17
+ tramway/landing/block:
18
+ block_type:
19
+ header: Начальный
@@ -0,0 +1,15 @@
1
+ ru:
2
+ collections:
3
+ tramway/landing/block:
4
+ published: Опубликованные
5
+ hidden: Скрытые
6
+ activerecord:
7
+ state_machines:
8
+ tramway/landing/block:
9
+ view_state:
10
+ states:
11
+ published: Виден
12
+ hidden: Скрытый
13
+ events:
14
+ publish: Показать на сайте
15
+ hide: Скрыть с сайта
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Tramway::Landing::Engine.routes.draw do
2
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :tramway_landing do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,7 @@
1
+ require "tramway/landing/engine"
2
+ require 'tramway/landing/generates/install_generator'
3
+
4
+ module Tramway
5
+ module Landing
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Tramway
2
+ module Landing
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Tramway::Landing
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails/generators'
2
+ require 'tramway/core/generators/install_generator'
3
+
4
+ module Tramway::Landing::Generators
5
+ class InstallGenerator < ::Tramway::Core::Generators::InstallGenerator
6
+ include Rails::Generators::Migration
7
+ source_root File.expand_path('../templates', __FILE__)
8
+
9
+ def self.next_migration_number(path)
10
+ next_migration_number = current_migration_number(path) + 1
11
+ ActiveRecord::Migration.next_migration_number next_migration_number
12
+ end
13
+
14
+ def copy_migrations
15
+ migration_template 'create_tramway_landing_blocks.rb', 'db/migrate/create_tramway_landing_blocks.rb'
16
+ migration_template 'add_navbar_link_to_tramway_landing_blocks.rb', 'db/migrate/add_navbar_link_to_tramway_landing_blocks.rb'
17
+ migration_template 'add_anchor_to_tramway_landing_blocks.rb', 'db/migrate/add_anchor_to_tramway_landing_blocks.rb'
18
+ migration_template 'add_description_to_tramway_landing_blocks.rb', 'db/migrate/add_description_to_tramway_landing_blocks.rb'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ class AddAnchorToTramwayLandingBlocks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :tramway_landing_blocks, :anchor, :text
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddDescriptionToTramwayLandingBlocks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :tramway_landing_blocks, :description, :text
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddNavbarLinkToTramwayLandingBlocks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ add_column :tramway_landing_blocks, :navbar_link, :text, default: :not_exist
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ class CreateTramwayLandingBlocks < ActiveRecord::Migration[5.1]
2
+ def change
3
+ create_table :tramway_landing_blocks do |t|
4
+ t.text :title
5
+ t.text :background
6
+ t.text :block_type
7
+ t.integer :position
8
+ t.text :state, default: :active
9
+ t.text :view_state, default: :hidden
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ module Tramway
2
+ module Landing
3
+ VERSION = '1.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tramway-landing
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Pavel Kalashnikov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Landing Engine for your Rails projects
14
+ email:
15
+ - kalashnikovisme@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - MIT-LICENSE
21
+ - README.md
22
+ - Rakefile
23
+ - app/assets/config/tramway_landing_manifest.js
24
+ - app/assets/javascripts/justified_images.js
25
+ - app/assets/javascripts/tramway/landing/application.js.coffee
26
+ - app/assets/javascripts/tramway/landing/footer.js.coffee
27
+ - app/assets/stylesheets/tramway/landing/application.css.sass
28
+ - app/assets/stylesheets/tramway/landing/collage.css.sass
29
+ - app/assets/stylesheets/tramway/landing/justified.css
30
+ - app/controllers/tramway/landing/application_controller.rb
31
+ - app/decorators/tramway/landing/block_decorator.rb
32
+ - app/decorators/tramway/landing/block_types/cards_decorator.rb
33
+ - app/decorators/tramway/landing/block_types/features_decorator.rb
34
+ - app/forms/tramway/landing/block_form.rb
35
+ - app/helpers/tramway/landing/application_helper.rb
36
+ - app/jobs/tramway/landing/application_job.rb
37
+ - app/mailers/tramway/landing/application_mailer.rb
38
+ - app/models/tramway/landing/application_record.rb
39
+ - app/models/tramway/landing/block.rb
40
+ - app/uploaders/tramway/landing/photo_versions.rb
41
+ - app/views/layouts/tramway/landing/application.html.haml
42
+ - app/views/tramway/landing/blocks/block_types/_cards.html.haml
43
+ - app/views/tramway/landing/blocks/block_types/_contacts.html.haml
44
+ - app/views/tramway/landing/blocks/block_types/_features.html.haml
45
+ - app/views/tramway/landing/blocks/block_types/_footer.html.haml
46
+ - app/views/tramway/landing/blocks/block_types/_header.html.haml
47
+ - app/views/tramway/landing/blocks/block_types/_page.html.haml
48
+ - config/initializers/assets.rb
49
+ - config/initializers/tramway.rb
50
+ - config/locales/models.yml
51
+ - config/locales/state_machines.yml
52
+ - config/routes.rb
53
+ - lib/tasks/tramway/landing_tasks.rake
54
+ - lib/tramway/landing.rb
55
+ - lib/tramway/landing/engine.rb
56
+ - lib/tramway/landing/generates/install_generator.rb
57
+ - lib/tramway/landing/generates/templates/add_anchor_to_tramway_landing_blocks.rb
58
+ - lib/tramway/landing/generates/templates/add_description_to_tramway_landing_blocks.rb
59
+ - lib/tramway/landing/generates/templates/add_navbar_link_to_tramway_landing_blocks.rb
60
+ - lib/tramway/landing/generates/templates/create_tramway_landing_blocks.rb
61
+ - lib/tramway/landing/version.rb
62
+ homepage: https://github.com/kalashnikovisme/tramway-landing
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.7.3
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Landing Engine for your Rails projects
86
+ test_files: []