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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +36 -0
- data/app/assets/config/tramway_landing_manifest.js +2 -0
- data/app/assets/javascripts/justified_images.js +284 -0
- data/app/assets/javascripts/tramway/landing/application.js.coffee +3 -0
- data/app/assets/javascripts/tramway/landing/footer.js.coffee +24 -0
- data/app/assets/stylesheets/tramway/landing/application.css.sass +16 -0
- data/app/assets/stylesheets/tramway/landing/collage.css.sass +36 -0
- data/app/assets/stylesheets/tramway/landing/justified.css +13 -0
- data/app/controllers/tramway/landing/application_controller.rb +11 -0
- data/app/decorators/tramway/landing/block_decorator.rb +26 -0
- data/app/decorators/tramway/landing/block_types/cards_decorator.rb +13 -0
- data/app/decorators/tramway/landing/block_types/features_decorator.rb +9 -0
- data/app/forms/tramway/landing/block_form.rb +15 -0
- data/app/helpers/tramway/landing/application_helper.rb +8 -0
- data/app/jobs/tramway/landing/application_job.rb +6 -0
- data/app/mailers/tramway/landing/application_mailer.rb +8 -0
- data/app/models/tramway/landing/application_record.rb +7 -0
- data/app/models/tramway/landing/block.rb +24 -0
- data/app/uploaders/tramway/landing/photo_versions.rb +15 -0
- data/app/views/layouts/tramway/landing/application.html.haml +28 -0
- data/app/views/tramway/landing/blocks/block_types/_cards.html.haml +36 -0
- data/app/views/tramway/landing/blocks/block_types/_contacts.html.haml +48 -0
- data/app/views/tramway/landing/blocks/block_types/_features.html.haml +26 -0
- data/app/views/tramway/landing/blocks/block_types/_footer.html.haml +16 -0
- data/app/views/tramway/landing/blocks/block_types/_header.html.haml +22 -0
- data/app/views/tramway/landing/blocks/block_types/_page.html.haml +9 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/tramway.rb +1 -0
- data/config/locales/models.yml +19 -0
- data/config/locales/state_machines.yml +15 -0
- data/config/routes.rb +2 -0
- data/lib/tasks/tramway/landing_tasks.rake +4 -0
- data/lib/tramway/landing.rb +7 -0
- data/lib/tramway/landing/engine.rb +7 -0
- data/lib/tramway/landing/generates/install_generator.rb +21 -0
- data/lib/tramway/landing/generates/templates/add_anchor_to_tramway_landing_blocks.rb +5 -0
- data/lib/tramway/landing/generates/templates/add_description_to_tramway_landing_blocks.rb +5 -0
- data/lib/tramway/landing/generates/templates/add_navbar_link_to_tramway_landing_blocks.rb +5 -0
- data/lib/tramway/landing/generates/templates/create_tramway_landing_blocks.rb +14 -0
- data/lib/tramway/landing/version.rb +5 -0
- 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,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,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,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,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,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 @@
|
|
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,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,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
|
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: []
|