mvpkit 0.8.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/Gemfile +30 -0
- data/Gemfile.lock +329 -0
- data/LICENSE.txt +20 -0
- data/MIT-LICENSE +20 -0
- data/README.md +134 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/app/assets/javascripts/mvp/application.js +1 -0
- data/app/assets/stylesheets/mvp/application.scss +0 -0
- data/app/controllers/concerns/mvp/analytics_concern.rb +78 -0
- data/app/controllers/concerns/mvp/seo_concern.rb +25 -0
- data/app/controllers/concerns/mvp/session_concern.rb +44 -0
- data/app/controllers/mvp/analytics_controller.rb +12 -0
- data/app/controllers/mvp/seo_controller.rb +11 -0
- data/app/controllers/mvp/styleguide_controller.rb +23 -0
- data/app/helpers/minimum_viable_product/body_helper.rb +14 -0
- data/app/helpers/minimum_viable_product/bootstrap_helper.rb +38 -0
- data/app/helpers/minimum_viable_product/styleguide_helper.rb +4 -0
- data/app/models/concerns/mvp/slugification.rb +24 -0
- data/app/views/layouts/minimum_viable_product/_instrumentation.html.erb +100 -0
- data/app/views/layouts/minimum_viable_product/_meta.html.erb +37 -0
- data/app/views/layouts/minimum_viable_product/application.html.erb +19 -0
- data/app/views/minimum_viable_product/styleguide/_example.html.erb +6 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_buttons.html.erb +191 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_forms.html.erb +192 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_header.html.erb +48 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_panels.html.erb +16 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_tables.html.erb +34 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap/_typography.html.erb +51 -0
- data/app/views/minimum_viable_product/styleguide/bootstrap.html.erb +43 -0
- data/app/views/minimum_viable_product/styleguide/elements/_grouping.html.erb +1 -0
- data/app/views/minimum_viable_product/styleguide/elements/partials/_row_groups_of.html.erb +7 -0
- data/app/views/minimum_viable_product/styleguide/index.html.erb +17 -0
- data/app/views/minimum_viable_product/styleguide/layouts/basic.html.erb +4 -0
- data/app/views/minimum_viable_product/styleguide/layouts/carousel.html.erb +120 -0
- data/app/views/minimum_viable_product/styleguide/layouts/cover.html.erb +34 -0
- data/assets/js/application.js +31 -0
- data/assets/js/init/controllers.js +26 -0
- data/assets/js/init/forms.js +12 -0
- data/bin/mvp +78 -0
- data/bin/rails +12 -0
- data/config/initializers/assets.rb +2 -0
- data/config/initializers/canonical_host.rb +3 -0
- data/config/initializers/cloudinary.rb +7 -0
- data/config/initializers/geocoder.rb +9 -0
- data/config/initializers/iteration.rb +33 -0
- data/config/initializers/project.rb +1 -0
- data/config/initializers/rollbar.rb +59 -0
- data/config/initializers/routing.rb +7 -0
- data/config/initializers/spoof_ip.rb +33 -0
- data/config/initializers/ssl.rb +14 -0
- data/config/routes.rb +6 -0
- data/lib/mvp/engine.rb +22 -0
- data/lib/mvp/ext/nil.rb +5 -0
- data/lib/mvp/ext/string.rb +7 -0
- data/lib/mvpkit.rb +6 -0
- data/lib/tasks/sitemap.rake +42 -0
- data/mvpkit.gemspec +245 -0
- data/package.json +43 -0
- data/project/.gitignore +45 -0
- data/project/Gemfile +33 -0
- data/project/Gemfile.lock +437 -0
- data/project/Procfile +2 -0
- data/project/README.md +117 -0
- data/project/Rakefile +14 -0
- data/project/app/controllers/application_controller.rb +12 -0
- data/project/app/controllers/conversions_controller.rb +24 -0
- data/project/app/controllers/examples_controller.rb +2 -0
- data/project/app/controllers/home_controller.rb +7 -0
- data/project/app/decorators/.keep +0 -0
- data/project/app/helpers/application_helper.rb +24 -0
- data/project/app/mailers/.keep +0 -0
- data/project/app/models/conversion.rb +4 -0
- data/project/app/views/examples/index.html.erb +1 -0
- data/project/app/views/examples/mustache/template.mustache +1 -0
- data/project/app/views/examples/mustache.html.erb +18 -0
- data/project/app/views/home/conversion.html.erb +12 -0
- data/project/app/views/home/index.html.erb +28 -0
- data/project/app/views/layouts/_header.html.erb +16 -0
- data/project/app/views/layouts/_includes.html.erb +7 -0
- data/project/app/views/layouts/application.html.erb +17 -0
- data/project/app/views/layouts/modal.html.erb +14 -0
- data/project/assets/images/.keep +0 -0
- data/project/assets/images/favicon.ico +0 -0
- data/project/assets/javascripts/controllers/home.coffee +15 -0
- data/project/assets/javascripts/pack.js +9 -0
- data/project/assets/stylesheets/config/variables.scss +876 -0
- data/project/assets/stylesheets/layout/basic.scss +6 -0
- data/project/assets/stylesheets/layout/carousel.scss +127 -0
- data/project/assets/stylesheets/layout/cover.scss +129 -0
- data/project/assets/stylesheets/lib/spacing.scss +55 -0
- data/project/assets/stylesheets/skin/style.scss +16 -0
- data/project/assets/stylesheets/style.scss +8 -0
- data/project/bin/bundle +3 -0
- data/project/bin/rails +9 -0
- data/project/bin/rake +9 -0
- data/project/bin/setup +32 -0
- data/project/bin/spring +15 -0
- data/project/config/application.rb +32 -0
- data/project/config/boot.rb +3 -0
- data/project/config/database.yml +19 -0
- data/project/config/environment.rb +5 -0
- data/project/config/environments/development.rb +67 -0
- data/project/config/environments/production.rb +93 -0
- data/project/config/environments/test.rb +42 -0
- data/project/config/initializers/assets.rb +11 -0
- data/project/config/initializers/backtrace_silencers.rb +7 -0
- data/project/config/initializers/cookies_serializer.rb +3 -0
- data/project/config/initializers/filter_parameter_logging.rb +4 -0
- data/project/config/initializers/inflections.rb +16 -0
- data/project/config/initializers/mime_types.rb +4 -0
- data/project/config/initializers/mustache.rb +7 -0
- data/project/config/initializers/rails_admin.rb +43 -0
- data/project/config/initializers/session_store.rb +3 -0
- data/project/config/initializers/simple_form.rb +177 -0
- data/project/config/initializers/wrap_parameters.rb +14 -0
- data/project/config/locales/en.yml +23 -0
- data/project/config/locales/simple_form.en.yml +31 -0
- data/project/config/routes.rb +13 -0
- data/project/config/secrets.yml +8 -0
- data/project/config/sitemap.rb +28 -0
- data/project/config.ru +4 -0
- data/project/db/migrate/20160728235100_create_conversions.rb +9 -0
- data/project/db/schema.rb +25 -0
- data/project/db/seeds.rb +7 -0
- data/project/lib/assets/.keep +0 -0
- data/project/lib/tasks/heroku.rake +70 -0
- data/project/log/.keep +0 -0
- data/project/log/development.log +48216 -0
- data/project/log/production.log +0 -0
- data/project/package.json +44 -0
- data/project/public/404.html +67 -0
- data/project/public/422.html +67 -0
- data/project/public/500.html +66 -0
- data/project/public/assets/javascripts/448c34a56d699c29117adc64c43affeb.woff2 +0 -0
- data/project/public/assets/javascripts/89889688147bd7575d6327160d64e760.svg +288 -0
- data/project/public/assets/javascripts/e18bbf611f2a2e43afc071aa2f4e1512.ttf +0 -0
- data/project/public/assets/javascripts/f4769f9bdb7466be65088239c12046d1.eot +0 -0
- data/project/public/assets/javascripts/fa2772327f55d8198301fdb8bcfc8158.woff +0 -0
- data/project/public/assets/javascripts/pack.js +31367 -0
- data/project/public/assets/javascripts/pack.js.map +1 -0
- data/project/public/assets/pack.js +17220 -0
- data/project/public/assets/style.css +7477 -0
- data/project/vendor/assets/javascripts/.keep +0 -0
- data/project/vendor/assets/stylesheets/.keep +0 -0
- data/project/webpack.config.js +67 -0
- data/test/helper.rb +34 -0
- data/test/test_minimum_viable_product.rb +7 -0
- metadata +473 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module MVP
|
|
2
|
+
module SessionConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
COOKIE_ID = '_session'
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
helper_method :current_user
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def current_user=(user)
|
|
12
|
+
session[COOKIE_ID] = user.id
|
|
13
|
+
end
|
|
14
|
+
alias_method :sign_in, :current_user=
|
|
15
|
+
|
|
16
|
+
def current_user
|
|
17
|
+
@current_user ||= begin
|
|
18
|
+
if session[COOKIE_ID]
|
|
19
|
+
Conversion.find(session[COOKIE_ID])
|
|
20
|
+
end
|
|
21
|
+
rescue ActiveRecord::RecordNotFound
|
|
22
|
+
session[COOKIE_ID] = nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# http://blog.laaz.org/tech/2012/12/27/rails-redirect_back_or_default/
|
|
27
|
+
def store_location(path=nil)
|
|
28
|
+
session[:return_to] = case
|
|
29
|
+
when !path.nil?
|
|
30
|
+
path
|
|
31
|
+
when request.get?
|
|
32
|
+
request.url
|
|
33
|
+
else
|
|
34
|
+
request.referer
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# http://blog.laaz.org/tech/2012/12/27/rails-redirect_back_or_default/
|
|
39
|
+
def redirect_back_or_default(default=nil)
|
|
40
|
+
redirect_to(session.delete(:return_to) || default || request.referer)
|
|
41
|
+
end
|
|
42
|
+
alias_method :redirect_to_back_or_default, :redirect_back_or_default
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module MinimumViableProduct
|
|
2
|
+
class StyleguideController < ActionController::Base
|
|
3
|
+
def index
|
|
4
|
+
render layout: 'minimum_viable_product/basic'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def bootstrap
|
|
8
|
+
render layout: 'minimum_viable_product/basic'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def layout_basic
|
|
12
|
+
render template: 'minimum_viable_product/styleguide/layouts/basic', layout: 'minimum_viable_product/basic'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def layout_cover
|
|
16
|
+
render template: 'minimum_viable_product/styleguide/layouts/cover', layout: 'minimum_viable_product/cover'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def layout_carousel
|
|
20
|
+
render template: 'minimum_viable_product/styleguide/layouts/carousel', layout: 'minimum_viable_product/carousel'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module MinimumViableProduct
|
|
2
|
+
module BodyHelper
|
|
3
|
+
def body_id
|
|
4
|
+
"#{controller_name}-#{action_name}-page"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def body_classes
|
|
8
|
+
klass = []
|
|
9
|
+
klass << "#{controller_name}-pages"
|
|
10
|
+
klass << page.classes if page.classes.present?
|
|
11
|
+
klass.join(' ')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module MinimumViableProduct
|
|
2
|
+
module BootstrapHelper
|
|
3
|
+
def col_groups_of(count, collection, opts={})
|
|
4
|
+
return if collection.blank?
|
|
5
|
+
|
|
6
|
+
html = []
|
|
7
|
+
collection.in_groups_of(count).each do |groups|
|
|
8
|
+
groups.compact.each do |obj|
|
|
9
|
+
html << capture do
|
|
10
|
+
content_tag :div, class: ["col-md-#{12/count.to_f.floor}", opts[:col_class]].compact.join(' ') do
|
|
11
|
+
yield obj
|
|
12
|
+
end
|
|
13
|
+
end.html_safe
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
concat html.join.html_safe
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def row_groups_of(count, collection, opts={}, &block)
|
|
20
|
+
return if collection.blank?
|
|
21
|
+
|
|
22
|
+
html = []
|
|
23
|
+
subsetsize = (collection.count/count.to_f)
|
|
24
|
+
subsetsize.ceil.times do |i|
|
|
25
|
+
subset = collection[count*i...((count*i)+count)]
|
|
26
|
+
html << capture do
|
|
27
|
+
content_tag :div, class: ["row",opts[:row_class]].compact.join(' ') do
|
|
28
|
+
capture do
|
|
29
|
+
col_groups_of(count, subset, opts, &block)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end.html_safe
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
concat html.join.html_safe
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module MVP
|
|
2
|
+
module Slugification
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def slugify(name, opts={})
|
|
7
|
+
before_validation -> {
|
|
8
|
+
return true if self.slug.present?
|
|
9
|
+
self.slug = slugify(self.send(name.to_sym))
|
|
10
|
+
self.slug += "-#{SecureRandom.uuid}" if self.class.find_by(slug: self.slug).present?
|
|
11
|
+
}, opts
|
|
12
|
+
validates :slug, uniqueness: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def slugify(str)
|
|
19
|
+
str.gsub(/[^a-zA-Z0-9]+/,'-')
|
|
20
|
+
.gsub(/^[-]+|[-]+$/,'')
|
|
21
|
+
.downcase
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<% if ENV['ROLLBAR_CLIENT_ACCESS_TOKEN'] %>
|
|
2
|
+
<script>
|
|
3
|
+
var _rollbarConfig = {
|
|
4
|
+
accessToken: '<%= ENV['ROLLBAR_CLIENT_ACCESS_TOKEN'] %>',
|
|
5
|
+
captureUncaught: true,
|
|
6
|
+
captureUnhandledRejections: false,
|
|
7
|
+
payload: {
|
|
8
|
+
environment: "production"
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
// Rollbar Snippet
|
|
12
|
+
!function(r){function e(t){if(o[t])return o[t].exports;var n=o[t]={exports:{},id:t,loaded:!1};return r[t].call(n.exports,n,n.exports,e),n.loaded=!0,n.exports}var o={};return e.m=r,e.c=o,e.p="",e(0)}([function(r,e,o){"use strict";var t=o(1).Rollbar,n=o(2);_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://d37gvrvc0wt4s1.cloudfront.net/js/v1.9/rollbar.min.js";var a=t.init(window,_rollbarConfig),i=n(a,_rollbarConfig);a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,i)},function(r,e){"use strict";function o(r){return function(){try{return r.apply(this,arguments)}catch(e){try{console.error("[Rollbar]: Internal error",e)}catch(o){}}}}function t(r,e,o){window._rollbarWrappedError&&(o[4]||(o[4]=window._rollbarWrappedError),o[5]||(o[5]=window._rollbarWrappedError._rollbarContext),window._rollbarWrappedError=null),r.uncaughtError.apply(r,o),e&&e.apply(window,o)}function n(r){var e=function(){var e=Array.prototype.slice.call(arguments,0);t(r,r._rollbarOldOnError,e)};return e.belongsToShim=!0,e}function a(r){this.shimId=++c,this.notifier=null,this.parentShim=r,this._rollbarOldOnError=null}function i(r){var e=a;return o(function(){if(this.notifier)return this.notifier[r].apply(this.notifier,arguments);var o=this,t="scope"===r;t&&(o=new e(this));var n=Array.prototype.slice.call(arguments,0),a={shim:o,method:r,args:n,ts:new Date};return window._rollbarShimQueue.push(a),t?o:void 0})}function l(r,e){if(e.hasOwnProperty&&e.hasOwnProperty("addEventListener")){var o=e.addEventListener;e.addEventListener=function(e,t,n){o.call(this,e,r.wrap(t),n)};var t=e.removeEventListener;e.removeEventListener=function(r,e,o){t.call(this,r,e&&e._wrapped?e._wrapped:e,o)}}}var c=0;a.init=function(r,e){var t=e.globalAlias||"Rollbar";if("object"==typeof r[t])return r[t];r._rollbarShimQueue=[],r._rollbarWrappedError=null,e=e||{};var i=new a;return o(function(){if(i.configure(e),e.captureUncaught){i._rollbarOldOnError=r.onerror,r.onerror=n(i);var o,a,c="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(o=0;o<c.length;++o)a=c[o],r[a]&&r[a].prototype&&l(i,r[a].prototype)}return e.captureUnhandledRejections&&(i._unhandledRejectionHandler=function(r){var e=r.reason,o=r.promise,t=r.detail;!e&&t&&(e=t.reason,o=t.promise),i.unhandledRejection(e,o)},r.addEventListener("unhandledrejection",i._unhandledRejectionHandler)),r[t]=i,i})()},a.prototype.loadFull=function(r,e,t,n,a){var i=function(){var e;if(void 0===r._rollbarPayloadQueue){var o,t,n,i;for(e=new Error("rollbar.js did not load");o=r._rollbarShimQueue.shift();)for(n=o.args,i=0;i<n.length;++i)if(t=n[i],"function"==typeof t){t(e);break}}"function"==typeof a&&a(e)},l=!1,c=e.createElement("script"),d=e.getElementsByTagName("script")[0],p=d.parentNode;c.crossOrigin="",c.src=n.rollbarJsUrl,c.async=!t,c.onload=c.onreadystatechange=o(function(){if(!(l||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){c.onload=c.onreadystatechange=null;try{p.removeChild(c)}catch(r){}l=!0,i()}}),p.insertBefore(c,d)},a.prototype.wrap=function(r,e){try{var o;if(o="function"==typeof e?e:function(){return e||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._wrapped){r._wrapped=function(){try{return r.apply(this,arguments)}catch(e){throw e._rollbarContext=o()||{},e._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=e,e}},r._wrapped._isWrap=!0;for(var t in r)r.hasOwnProperty(t)&&(r._wrapped[t]=r[t])}return r._wrapped}catch(n){return r}};for(var d="log,debug,info,warn,warning,error,critical,global,configure,scope,uncaughtError,unhandledRejection".split(","),p=0;p<d.length;++p)a.prototype[d[p]]=i(d[p]);r.exports={Rollbar:a,_rollbarWindowOnError:t}},function(r,e){"use strict";r.exports=function(r,e){return function(o){if(!o&&!window._rollbarInitialized){var t=window.RollbarNotifier,n=e||{},a=n.globalAlias||"Rollbar",i=window.Rollbar.init(n,r);i._processShimQueue(window._rollbarShimQueue||[]),window[a]=i,window._rollbarInitialized=!0,t.processPayloads()}}}}]);
|
|
13
|
+
// End Rollbar Snippet
|
|
14
|
+
</script>
|
|
15
|
+
<% end %>
|
|
16
|
+
|
|
17
|
+
<% unless cookies[MVP::AnalyticsConcern::INVISIBLE_SESSION_COOKIE].to_b == true %>
|
|
18
|
+
<% if ENV['FACEBOOK_TRACKING_ID'] %>
|
|
19
|
+
<script>
|
|
20
|
+
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
21
|
+
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
|
22
|
+
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
|
|
23
|
+
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
|
|
24
|
+
document,'script','https://connect.facebook.net/en_US/fbevents.js');
|
|
25
|
+
|
|
26
|
+
fbq('init', '<%= ENV['FACEBOOK_TRACKING_ID'] %>');
|
|
27
|
+
fbq('track', "PageView");
|
|
28
|
+
<%= page.facebook_javascript.try(:html_safe) %>
|
|
29
|
+
</script>
|
|
30
|
+
<noscript><img height="1" width="1" style="display:none"
|
|
31
|
+
src="https://www.facebook.com/tr?id=<%= ENV['FACEBOOK_TRACKING_ID'] %>&ev=PageView&noscript=1"
|
|
32
|
+
/></noscript>
|
|
33
|
+
<!-- End Facebook Pixel Code -->
|
|
34
|
+
<% end %>
|
|
35
|
+
|
|
36
|
+
<% if ENV['SEGMENT_WRITE_KEY'] %>
|
|
37
|
+
<script type="text/javascript">
|
|
38
|
+
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.1.0";
|
|
39
|
+
analytics.load('<%= ENV['SEGMENT_WRITE_KEY'] %>');
|
|
40
|
+
|
|
41
|
+
<% analytics_identify_events.each do |event| %>
|
|
42
|
+
analytics.identify('<%= event['id'] %>', <%= event['properties'].to_json.html_safe %>);
|
|
43
|
+
<% end %>
|
|
44
|
+
<% analytics_track_events.each do |event| %>
|
|
45
|
+
analytics.track('<%= event['name'] %>', <%= event['properties'].to_json.html_safe %>);
|
|
46
|
+
<% end %>
|
|
47
|
+
|
|
48
|
+
analytics.page('<%= controller.controller_path %>.<%= controller.action_name %>', {
|
|
49
|
+
iteration: "<%= MVP::Iteration.version %>"
|
|
50
|
+
});
|
|
51
|
+
}}();
|
|
52
|
+
</script>
|
|
53
|
+
<% end %>
|
|
54
|
+
|
|
55
|
+
<% if ENV['GOOGLE_ANALYTICS_ID'] %>
|
|
56
|
+
<script>
|
|
57
|
+
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
58
|
+
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
59
|
+
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
60
|
+
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
61
|
+
ga('create', '<%= ENV['GOOGLE_ANALYTICS_ID'] %>', 'auto');
|
|
62
|
+
ga('send', 'pageview');
|
|
63
|
+
</script>
|
|
64
|
+
<% end %>
|
|
65
|
+
|
|
66
|
+
<% if ENV['HOTJAR_ID'] %>
|
|
67
|
+
<script>
|
|
68
|
+
(function(h,o,t,j,a,r){
|
|
69
|
+
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
|
70
|
+
h._hjSettings={hjid:<%= ENV['HOTJAR_ID'] %>,hjsv:5};
|
|
71
|
+
a=o.getElementsByTagName('head')[0];
|
|
72
|
+
r=o.createElement('script');r.async=1;
|
|
73
|
+
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
|
74
|
+
a.appendChild(r);
|
|
75
|
+
})(window,document,'//static.hotjar.com/c/hotjar-','.js?sv=');
|
|
76
|
+
</script>
|
|
77
|
+
<% end %>
|
|
78
|
+
|
|
79
|
+
<% if ENV['AMPLITUDE_API_KEY'] %>
|
|
80
|
+
<script type="text/javascript">
|
|
81
|
+
(function(e,t){var n=e.amplitude||{_q:[],_iq:{}};var r=t.createElement("script");r.type="text/javascript";
|
|
82
|
+
r.async=true;r.src="https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-3.0.1-min.gz.js";
|
|
83
|
+
r.onload=function(){e.amplitude.runQueuedFunctions()};var i=t.getElementsByTagName("script")[0];
|
|
84
|
+
i.parentNode.insertBefore(r,i);function s(e,t){e.prototype[t]=function(){this._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
|
|
85
|
+
return this}}var o=function(){this._q=[];return this};var a=["add","append","clearAll","prepend","set","setOnce","unset"];
|
|
86
|
+
for(var u=0;u<a.length;u++){s(o,a[u])}n.Identify=o;var c=function(){this._q=[];return this;
|
|
87
|
+
};var p=["setProductId","setQuantity","setPrice","setRevenueType","setEventProperties"];
|
|
88
|
+
for(var l=0;l<p.length;l++){s(c,p[l])}n.Revenue=c;var d=["init","logEvent","logRevenue","setUserId","setUserProperties","setOptOut","setVersionName","setDomain","setDeviceId","setGlobalUserProperties","identify","clearUserProperties","setGroup","logRevenueV2","regenerateDeviceId"];
|
|
89
|
+
function v(e){function t(t){e[t]=function(){e._q.push([t].concat(Array.prototype.slice.call(arguments,0)));
|
|
90
|
+
}}for(var n=0;n<d.length;n++){t(d[n])}}v(n);n.getInstance=function(e){e=(!e||e.length===0?"$default_instance":e).toLowerCase();
|
|
91
|
+
if(!n._iq.hasOwnProperty(e)){n._iq[e]={_q:[]};v(n._iq[e])}return n._iq[e]};e.amplitude=n;
|
|
92
|
+
})(window,document);
|
|
93
|
+
|
|
94
|
+
amplitude.getInstance().init("<%= ENV['AMPLITUDE_API_KEY'] %>");
|
|
95
|
+
<% analytics_track_events.each do |event| %>
|
|
96
|
+
amplitude.getInstance().logEvent('<%= event['name'] %>', <%= event['properties'].to_json.html_safe %>);
|
|
97
|
+
<% end %>
|
|
98
|
+
</script>
|
|
99
|
+
<% end %>
|
|
100
|
+
<% end %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<meta charset=utf-8>
|
|
2
|
+
<meta content="IE=edge" http-equiv=X-UA-Compatible>
|
|
3
|
+
<meta content="width=device-width,initial-scale=1" name=viewport>
|
|
4
|
+
<% if page.description %>
|
|
5
|
+
<meta content="<%= page.description %>" name="description">
|
|
6
|
+
<% end %>
|
|
7
|
+
<% if page.author %>
|
|
8
|
+
<meta content="<%= page.author %>" name="author">
|
|
9
|
+
<% end %>
|
|
10
|
+
<title><%= page.title %></title>
|
|
11
|
+
|
|
12
|
+
<% if page.canonical_url %>
|
|
13
|
+
<link rel="canonical" href="<%= page.canonical_url %>" />
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
16
|
+
<% if page.noindex %>
|
|
17
|
+
<meta name="robots" content="noindex">
|
|
18
|
+
<% end %>
|
|
19
|
+
|
|
20
|
+
<% if page.og_url %>
|
|
21
|
+
<meta property="og:url" content="<%= page.og_url %>" />
|
|
22
|
+
<% end %>
|
|
23
|
+
<% if page.og_type %>
|
|
24
|
+
<meta property="og:type" content="<%= page.og_type %>" />
|
|
25
|
+
<% end %>
|
|
26
|
+
<% if page.og_title || page.title %>
|
|
27
|
+
<meta property="og:title" content="<%= page.og_title || page.title %>" />
|
|
28
|
+
<% end %>
|
|
29
|
+
<% if page.og_description || page.description %>
|
|
30
|
+
<meta property="og:description" content="<%= page.og_description || page.description %>" />
|
|
31
|
+
<% end %>
|
|
32
|
+
<% if page.og_image %>
|
|
33
|
+
<meta property="og:image" content="<%= page.og_image %>" />
|
|
34
|
+
<% end %>
|
|
35
|
+
<% if page.twitter_card %>
|
|
36
|
+
<meta name="twitter:card" content="<%= page.twitter_card %>" />
|
|
37
|
+
<% end %>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE HTML>
|
|
2
|
+
<html lang='en'>
|
|
3
|
+
<head>
|
|
4
|
+
<%= render('layouts/minimum_viable_product/meta').gsub(/\n/,'').html_safe %>
|
|
5
|
+
<%= yield :meta %>
|
|
6
|
+
<%= yield :stylesheets %>
|
|
7
|
+
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]-->
|
|
8
|
+
<%= yield :javascripts %>
|
|
9
|
+
<%= csrf_meta_tags %>
|
|
10
|
+
<%= render 'layouts/minimum_viable_product/instrumentation' %>
|
|
11
|
+
</head>
|
|
12
|
+
<body id="<%= body_id %>" class="<%= body_classes %>" data-controller="<%= controller.controller_path %>" data-action="<%= controller.action_name %>" data-iteration="<%= MVP::Iteration.version %>">
|
|
13
|
+
<% if content_for? :body %>
|
|
14
|
+
<%= yield :body %>
|
|
15
|
+
<% else %>
|
|
16
|
+
<%= yield %>
|
|
17
|
+
<% end %>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
<div class="mb20">
|
|
2
|
+
<p class="mb10">
|
|
3
|
+
<button class="btn btn-default" type="button">Default</button>
|
|
4
|
+
<button class="btn btn-primary" type="button">Primary</button>
|
|
5
|
+
<button class="btn btn-success" type="button">Success</button>
|
|
6
|
+
<button class="btn btn-info" type="button">Info</button>
|
|
7
|
+
<button class="btn btn-warning" type="button">Warning</button>
|
|
8
|
+
<button class="btn btn-danger" type="button">Danger</button>
|
|
9
|
+
<button class="btn btn-link" type="button">Link</button>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p class="mb10">
|
|
13
|
+
<button class="btn btn-primary btn-lg" type="button">Large button</button>
|
|
14
|
+
<button class="btn btn-default btn-lg" type="button">Large button</button>
|
|
15
|
+
</p>
|
|
16
|
+
<p class="mb10">
|
|
17
|
+
<button class="btn btn-primary" type="button">Default button</button>
|
|
18
|
+
<button class="btn btn-default" type="button">Default button</button>
|
|
19
|
+
</p>
|
|
20
|
+
<p class="mb10">
|
|
21
|
+
<button class="btn btn-primary btn-sm" type="button">Small button</button>
|
|
22
|
+
<button class="btn btn-default btn-sm" type="button">Small button</button>
|
|
23
|
+
</p>
|
|
24
|
+
<p class="mb10">
|
|
25
|
+
<button class="btn btn-primary btn-xs" type="button">Extra small button</button>
|
|
26
|
+
<button class="btn btn-default btn-xs" type="button">Extra small button</button>
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="mb20">
|
|
31
|
+
<div aria-label="Toolbar with button groups" class="btn-toolbar" role="toolbar">
|
|
32
|
+
<div aria-label="First group" class="btn-group" role="group">
|
|
33
|
+
<button class="btn btn-default" type="button">1</button>
|
|
34
|
+
<button class="btn btn-default" type="button">2</button>
|
|
35
|
+
<button class="btn btn-default" type="button">3</button>
|
|
36
|
+
<button class="btn btn-default" type="button">4</button>
|
|
37
|
+
</div>
|
|
38
|
+
<div aria-label="Second group" class="btn-group" role="group">
|
|
39
|
+
<button class="btn btn-default" type="button">5</button>
|
|
40
|
+
<button class="btn btn-default" type="button">6</button>
|
|
41
|
+
<button class="btn btn-default" type="button">7</button>
|
|
42
|
+
</div>
|
|
43
|
+
<div aria-label="Third group" class="btn-group" role="group">
|
|
44
|
+
<button class="btn btn-default" type="button">8</button>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="mb20">
|
|
50
|
+
<div aria-label="Button group with nested dropdown" class="btn-group" role="group">
|
|
51
|
+
<button class="btn btn-default" type="button">1</button>
|
|
52
|
+
<button class="btn btn-default" type="button">2</button>
|
|
53
|
+
<div class="btn-group" role="group">
|
|
54
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-default dropdown-toggle" data-toggle="dropdown" id="btnGroupDrop1" type="button">
|
|
55
|
+
Dropdown
|
|
56
|
+
<span class="caret"></span>
|
|
57
|
+
</button>
|
|
58
|
+
<ul aria-labelledby="btnGroupDrop1" class="dropdown-menu">
|
|
59
|
+
<li>
|
|
60
|
+
<a href="#">Dropdown link</a>
|
|
61
|
+
</li>
|
|
62
|
+
<li>
|
|
63
|
+
<a href="#">Dropdown link</a>
|
|
64
|
+
</li>
|
|
65
|
+
</ul>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="mb20">
|
|
71
|
+
<div class="btn-group">
|
|
72
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">Default
|
|
73
|
+
<span class="caret"></span>
|
|
74
|
+
</button>
|
|
75
|
+
<ul class="dropdown-menu">
|
|
76
|
+
<li>
|
|
77
|
+
<a href="#">Action</a>
|
|
78
|
+
</li>
|
|
79
|
+
<li>
|
|
80
|
+
<a href="#">Another action</a>
|
|
81
|
+
</li>
|
|
82
|
+
<li>
|
|
83
|
+
<a href="#">Something else here</a>
|
|
84
|
+
</li>
|
|
85
|
+
<li class="divider" role="separator"></li>
|
|
86
|
+
<li>
|
|
87
|
+
<a href="#">Separated link</a>
|
|
88
|
+
</li>
|
|
89
|
+
</ul>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="btn-group">
|
|
92
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" type="button">Primary
|
|
93
|
+
<span class="caret"></span>
|
|
94
|
+
</button>
|
|
95
|
+
<ul class="dropdown-menu">
|
|
96
|
+
<li>
|
|
97
|
+
<a href="#">Action</a>
|
|
98
|
+
</li>
|
|
99
|
+
<li>
|
|
100
|
+
<a href="#">Another action</a>
|
|
101
|
+
</li>
|
|
102
|
+
<li>
|
|
103
|
+
<a href="#">Something else here</a>
|
|
104
|
+
</li>
|
|
105
|
+
<li class="divider" role="separator"></li>
|
|
106
|
+
<li>
|
|
107
|
+
<a href="#">Separated link</a>
|
|
108
|
+
</li>
|
|
109
|
+
</ul>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="btn-group">
|
|
112
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-success dropdown-toggle" data-toggle="dropdown" type="button">Success
|
|
113
|
+
<span class="caret"></span>
|
|
114
|
+
</button>
|
|
115
|
+
<ul class="dropdown-menu">
|
|
116
|
+
<li>
|
|
117
|
+
<a href="#">Action</a>
|
|
118
|
+
</li>
|
|
119
|
+
<li>
|
|
120
|
+
<a href="#">Another action</a>
|
|
121
|
+
</li>
|
|
122
|
+
<li>
|
|
123
|
+
<a href="#">Something else here</a>
|
|
124
|
+
</li>
|
|
125
|
+
<li class="divider" role="separator"></li>
|
|
126
|
+
<li>
|
|
127
|
+
<a href="#">Separated link</a>
|
|
128
|
+
</li>
|
|
129
|
+
</ul>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="btn-group">
|
|
132
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-info dropdown-toggle" data-toggle="dropdown" type="button">Info
|
|
133
|
+
<span class="caret"></span>
|
|
134
|
+
</button>
|
|
135
|
+
<ul class="dropdown-menu">
|
|
136
|
+
<li>
|
|
137
|
+
<a href="#">Action</a>
|
|
138
|
+
</li>
|
|
139
|
+
<li>
|
|
140
|
+
<a href="#">Another action</a>
|
|
141
|
+
</li>
|
|
142
|
+
<li>
|
|
143
|
+
<a href="#">Something else here</a>
|
|
144
|
+
</li>
|
|
145
|
+
<li class="divider" role="separator"></li>
|
|
146
|
+
<li>
|
|
147
|
+
<a href="#">Separated link</a>
|
|
148
|
+
</li>
|
|
149
|
+
</ul>
|
|
150
|
+
</div>
|
|
151
|
+
<div class="btn-group">
|
|
152
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-warning dropdown-toggle" data-toggle="dropdown" type="button">Warning
|
|
153
|
+
<span class="caret"></span>
|
|
154
|
+
</button>
|
|
155
|
+
<ul class="dropdown-menu">
|
|
156
|
+
<li>
|
|
157
|
+
<a href="#">Action</a>
|
|
158
|
+
</li>
|
|
159
|
+
<li>
|
|
160
|
+
<a href="#">Another action</a>
|
|
161
|
+
</li>
|
|
162
|
+
<li>
|
|
163
|
+
<a href="#">Something else here</a>
|
|
164
|
+
</li>
|
|
165
|
+
<li class="divider" role="separator"></li>
|
|
166
|
+
<li>
|
|
167
|
+
<a href="#">Separated link</a>
|
|
168
|
+
</li>
|
|
169
|
+
</ul>
|
|
170
|
+
</div>
|
|
171
|
+
<div class="btn-group">
|
|
172
|
+
<button aria-expanded="false" aria-haspopup="true" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" type="button">Danger
|
|
173
|
+
<span class="caret"></span>
|
|
174
|
+
</button>
|
|
175
|
+
<ul class="dropdown-menu">
|
|
176
|
+
<li>
|
|
177
|
+
<a href="#">Action</a>
|
|
178
|
+
</li>
|
|
179
|
+
<li>
|
|
180
|
+
<a href="#">Another action</a>
|
|
181
|
+
</li>
|
|
182
|
+
<li>
|
|
183
|
+
<a href="#">Something else here</a>
|
|
184
|
+
</li>
|
|
185
|
+
<li class="divider" role="separator"></li>
|
|
186
|
+
<li>
|
|
187
|
+
<a href="#">Separated link</a>
|
|
188
|
+
</li>
|
|
189
|
+
</ul>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|