disco_app 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a29063430cb2904c29bf74567496355a5f70d5e4e5d942d8f9ad8341ee99f935
4
- data.tar.gz: c1ad2a5cf842f792213ef025f948057132bfdede2c78945d965edc925ad3f62f
3
+ metadata.gz: f6bcc38c1a00ea30bb3a0fe0a319b7fbedb26c3e022247a8e2cd5bac114459a4
4
+ data.tar.gz: f5b6885baebbeea7b2d5173803822a175bad1be09b2e65db1d8e0376e1fbf306
5
5
  SHA512:
6
- metadata.gz: 6dd9ac41a62be53b26c1ab0d7aa30d0078a1adbc0ae7cb5342567bca85764da13eba2b6a3cb5dbcfc4867dd8ea7e433811eaa9131549d85a43b2d75fe7a09a89
7
- data.tar.gz: 2c06d93aaae37aa4d52b39ae35727e0ebf1bfd9c86f252bbd9bb910e61088c74aaba02037675b8da29beb50b4a8f485ba8f54ac9f0a508c88cb1b2cc05fcb8bc
6
+ metadata.gz: d9bb6a2e5e899768eb3954830140a73adf764275eb9e8f7e1635b6a32e7596b1bfbe0f77591c62e7845f2f640904651d81fe5f6606a358ecfe64ee55149c47dd
7
+ data.tar.gz: ae895af6f73f42668c2d6b9b2458a81481194becd38d4f9c44e30560a7905d7e8e3d12fff6a5806e18beb3b4082e020a28c95361f356c0ab7df6e54487da0b82
@@ -4,4 +4,4 @@
4
4
  * Assumes that jQuery will be loaded in the parent application.js.
5
5
  */
6
6
  //= require bootstrap-sprockets
7
- //= require_tree .
7
+ //= require disco_app/shopify-turbolinks
@@ -0,0 +1,152 @@
1
+ /**
2
+ * frame.js
3
+ *
4
+ * The FrameApp object is a lightweight Javascript object intended to mock the `postMessage` endpoint for Embedded Apps
5
+ * in the Shopify Admin panel. Eventually, we hope to mock all of the functionality provided by the Shopify Embedded App
6
+ * SDK.
7
+ */
8
+ (function() {
9
+
10
+ window.FrameApp = (function() {
11
+
12
+ FrameApp.name = 'Shopify Dev Frame';
13
+
14
+ function FrameApp() {}
15
+
16
+
17
+ /* Initialisation, configuration and helpers.
18
+ ================================================== */
19
+
20
+ /**
21
+ * Initialise the FrameApp - load configuration, set up event handlers.
22
+ *
23
+ * @param config
24
+ * @returns {*}
25
+ */
26
+ FrameApp.init = function(config) {
27
+ var _this = this;
28
+ if (config == null) {
29
+ config = {};
30
+ }
31
+ this.loadConfig(config);
32
+
33
+ // Use addEventListener if available, otherwise fall back to attachEvent.
34
+ if (window.addEventListener) {
35
+ this.iframe.addEventListener("load", FrameApp.__iframeLoadCallback, false);
36
+ return window.addEventListener("message", FrameApp.__addEventMessageCallback, false);
37
+ }
38
+
39
+ this.iframe.attachEvent("load", FrameApp.__iframeLoadCallback);
40
+ return window.attachEvent("onMessage", FrameApp.__addEventMessageCallback);
41
+ };
42
+
43
+ /**
44
+ * Load configuration for the FrameApp. Set defaults if not provided.
45
+ * @param config
46
+ */
47
+ FrameApp.loadConfig = function(config) {
48
+ this.shopOrigin = config.shopOrigin;
49
+ this.debug = !!config.debug;
50
+ this.iframe = config.iframe;
51
+ if (!this.iframe) {
52
+ this.log("FrameApp error: no <iframe> specified.");
53
+ }
54
+ FrameApp.log('FrameApp configuration loaded.');
55
+ };
56
+
57
+ /**
58
+ * Log a message to the console, if the app was configured in debug mode.
59
+ *
60
+ * @param message
61
+ * @param force
62
+ * @returns {*}
63
+ */
64
+ FrameApp.log = function(message, force) {
65
+ if ((typeof console !== "undefined" && console !== null ? console.log : void 0) && (this.debug || force)) {
66
+ return console.log(message);
67
+ }
68
+ };
69
+
70
+
71
+ /* Message sending and event handling.
72
+ ================================================== */
73
+
74
+ FrameApp.__messageHandlers = {};
75
+
76
+ /**
77
+ * Post a message to the <iframe>.
78
+ *
79
+ * @param message
80
+ * @param data
81
+ * @returns {*}
82
+ */
83
+ FrameApp.postMessage = function(message, data) {
84
+ var json;
85
+ json = JSON.stringify({
86
+ message: message,
87
+ data: data
88
+ });
89
+ FrameApp.log("FrameApp client sent " + json + " to ShopifyApp.");
90
+ return this.iframe.contentWindow.postMessage(json, '*');
91
+ };
92
+
93
+ /**
94
+ * Add a handler for a received message.
95
+ *
96
+ * @param message
97
+ * @param fn
98
+ * @returns {Number|*}
99
+ * @private
100
+ */
101
+ FrameApp.__addMessageHandler = function(message, fn) {
102
+ if (typeof message === "function") {
103
+ fn = message;
104
+ message = void 0;
105
+ }
106
+ if (!FrameApp.__messageHandlers[message]) {
107
+ FrameApp.__messageHandlers[message] = [];
108
+ }
109
+ return FrameApp.__messageHandlers[message].push(fn);
110
+ };
111
+
112
+ /**
113
+ * Callback triggered when a postMessage message is received.
114
+ *
115
+ * @param e
116
+ * @returns {*}
117
+ * @private
118
+ */
119
+ FrameApp.__addEventMessageCallback = function(e) {
120
+ var handler, handlers, message, submitForm, _i, _len;
121
+ FrameApp.log("FrameApp client received " + e.data + " from " + e.origin);
122
+ message = JSON.parse(e.data);
123
+ handlers = [];
124
+ if (FrameApp.__messageHandlers[message.message]) {
125
+ handlers = handlers.concat(FrameApp.__messageHandlers[message.message]);
126
+ }
127
+ if (FrameApp.__messageHandlers[void 0]) {
128
+ handlers = handlers.concat(FrameApp.__messageHandlers[void 0]);
129
+ }
130
+ for (_i = 0, _len = handlers.length; _i < _len; _i++) {
131
+ handler = handlers[_i];
132
+ handler(message.message, message.data);
133
+ }
134
+ };
135
+
136
+ /**
137
+ * Callback triggered when our iFrame is loaded.
138
+ *
139
+ * @param e
140
+ * @private
141
+ */
142
+ FrameApp.__iframeLoadCallback = function(e) {
143
+ FrameApp.postMessage('Shopify.API.initialize', {
144
+ 'hi': 'there!'
145
+ });
146
+ };
147
+
148
+ return FrameApp;
149
+
150
+ }).call(this);
151
+
152
+ }).call(this);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * disco_app/shopify-turbolinks.js
3
+ * Some tweaks to help Turbolinks play nicely with the Embedded App SDK.
4
+ */
5
+ jQuery(document).on('page:load', function(e) {
6
+ ShopifyApp.pushState(window.location.pathname);
7
+ });
@@ -329,7 +329,7 @@ $screen-md-max: ($screen-lg-min - 1) !default;
329
329
  //** Number of columns in the grid.
330
330
  $grid-columns: 24;
331
331
  //** Padding between columns. Gets divided in half for the left and right.
332
- $grid-gutter-width: 12px;
332
+ $grid-gutter-width: 20px;
333
333
  // Navbar collapse
334
334
  //** Point at which the navbar becomes uncollapsed.
335
335
  $grid-float-breakpoint: $screen-sm-min !default;
@@ -30,6 +30,14 @@
30
30
  padding: 20px;
31
31
  }
32
32
 
33
+ .next-card__section ~ .next-card__section {
34
+ border-top: 1px solid #ebeef0;
35
+ }
36
+
37
+ .next-card__section--no-bottom-padding {
38
+ padding-bottom: 0;
39
+ }
40
+
33
41
  .next-card--aside,
34
42
  .next-card--disabled {
35
43
  background-color: #f5f6f7;
@@ -0,0 +1,53 @@
1
+ //
2
+ // Replicate the styles for Shopify Admin tabs.
3
+ // --------------------------------------------------
4
+
5
+ .next-tab__list {
6
+ padding: 0;
7
+ margin: 0;
8
+ list-style: none;
9
+ background-color: #f5f6f7;
10
+ overflow: visible;
11
+ border-radius: 3px 3px 0 0;
12
+
13
+ flex-wrap: nowrap;
14
+ display: flex;
15
+ align-items: stretch;
16
+
17
+ > li {
18
+ position: relative;
19
+ flex-grow: 0;
20
+ flex-shrink: 0;
21
+ display: flex;
22
+ align-items: stretch;
23
+
24
+ &:first-child .next-tab {
25
+ border-top-left-radius: 3px;
26
+ }
27
+ }
28
+ }
29
+
30
+ .next-tab {
31
+ padding: 15px 20px;
32
+ text-decoration: none;
33
+ color: #798c9c;
34
+ border-right: 1px solid #ebeef0;
35
+ border-bottom: 1px solid #ebeef0;
36
+ text-align: center;
37
+ line-height: 1;
38
+ cursor: pointer;
39
+ position: relative;
40
+ font-size: 13px;
41
+ flex-grow: 1;
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+
46
+ &.next-tab--is-active {
47
+ background-color: #ffffff;
48
+ color: #31373d;
49
+ border-bottom-color: #ffffff;
50
+ cursor: default;
51
+ text-decoration: none;
52
+ }
53
+ }
@@ -11,3 +11,4 @@
11
11
  @import 'disco/cards';
12
12
  @import 'disco/buttons';
13
13
  @import 'disco/forms';
14
+ @import 'disco/tabs';
@@ -0,0 +1,54 @@
1
+ //
2
+ // Buttons
3
+ // --------------------------------------------------
4
+
5
+ // Base button
6
+ .btn {
7
+ cursor: pointer;
8
+ display: inline-block;
9
+ height: 32px;
10
+ line-height: 30px;
11
+ padding: 0 9px;
12
+ border-radius: 4px;
13
+
14
+ white-space: nowrap;
15
+ vertical-align: middle;
16
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
17
+ font-size: 13px;
18
+
19
+ -webkit-user-select: none;
20
+ -moz-user-select: none;
21
+ -o-user-select: none;
22
+ user-select: none;
23
+ -webkit-appearance: none;
24
+
25
+ &:hover {
26
+ text-decoration: none;
27
+ }
28
+ }
29
+
30
+ // Default button
31
+ .btn, .btn-default {
32
+ background-color: #fcfcfc;
33
+ border: 1px solid #e3e3e3;
34
+ color: #479ccf;
35
+
36
+ &:hover, &:focus, &.focus {
37
+ background-color: #efefef;
38
+ border-color: #d6d6d6;
39
+ color: #479ccf;
40
+ }
41
+ }
42
+
43
+ // Primary button
44
+ .btn-primary {
45
+ background-color: #479ccf;
46
+ border: 1px solid #2f82b4;
47
+ color: #fff;
48
+
49
+ &:hover, &:focus, &.focus {
50
+ background-color: #3491c8;
51
+ border-color: #2a74a0;
52
+ color: #fff;
53
+ }
54
+ }
@@ -0,0 +1,26 @@
1
+ //
2
+ // Forms
3
+ // --------------------------------------------------
4
+
5
+ form {
6
+ margin: 40px 0;
7
+ }
8
+
9
+ input[type="text"],
10
+ input[type="url"], {
11
+ vertical-align: top;
12
+ height: 32px;
13
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
14
+ font-size: 13px;
15
+ padding: 5px;
16
+ margin: 0;
17
+ border: 1px solid #ccc;
18
+ display: inline-block;
19
+ color: #222;
20
+ border-radius: 4px;
21
+
22
+ &:focus, &.focus {
23
+ border: 1px solid #479ccf;
24
+ outline: 0;
25
+ }
26
+ }
@@ -0,0 +1,77 @@
1
+ //
2
+ // Layout
3
+ // --------------------------------------------------
4
+
5
+ * {
6
+ -webkit-box-sizing: border-box;
7
+ -moz-box-sizing: border-box;
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ #sidebar {
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ bottom: 0;
16
+ width: $sidebar-width;
17
+
18
+ background: #31373d;
19
+ box-shadow: -1px 0 0 #2b3136 inset;
20
+ }
21
+
22
+ #header {
23
+ position: absolute;
24
+ top: 0;
25
+ left: $sidebar-width;
26
+ right: 0;
27
+ height: $header-height;
28
+
29
+ background: #ffffff;
30
+ border-bottom: 1px solid #e6e6e6;
31
+ border-color: rgba(0,0,0, .07);
32
+ }
33
+
34
+ #header-title {
35
+ position: absolute;
36
+ bottom: 12px;
37
+ left: 20px;
38
+
39
+ max-width: 718px;
40
+ white-space: nowrap;
41
+ text-overflow: ellipsis;
42
+ overflow: hidden;
43
+ }
44
+
45
+ #header-title-icon {
46
+ margin: 5px 10px 0 0;
47
+ float: left;
48
+ }
49
+
50
+ #header-actions {
51
+ position: absolute;
52
+ bottom: 12px;
53
+ right: 20px;
54
+
55
+ .btn {
56
+ margin: 0 0 0 5px;
57
+ }
58
+ }
59
+
60
+ #content-wrapper {
61
+ position: absolute;
62
+ top: $header-height;
63
+ left: $sidebar-width;
64
+ bottom: 0;
65
+ right: 0;
66
+ }
67
+
68
+ #content {
69
+ width: 100%;
70
+ height: 100%;
71
+ border: none;
72
+ }
73
+
74
+ #iframe {
75
+ padding: 40px 0;
76
+ text-align: center;
77
+ }
@@ -0,0 +1,32 @@
1
+ //
2
+ // Type
3
+ // --------------------------------------------------
4
+
5
+ @font-face {
6
+ font-family: 'ProximaNovaLight';
7
+ src: local('ProximaNovaLight'), local('ProximaNova-Light');
8
+ font-weight: normal;
9
+ font-style: normal;
10
+ }
11
+
12
+ // Base
13
+ html, body {
14
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
15
+ font-size: 13px;
16
+ }
17
+
18
+ // Headers
19
+ h1 {
20
+ font-size: 24px;
21
+ line-height: 32px;
22
+ height: 32px;
23
+ font-family: ProximaNovaLight,"Helvetica Neue",Helvetica,Arial,sans-serif;
24
+ font-weight: 300;
25
+ margin: 0;
26
+ padding: 0;
27
+ }
28
+
29
+ // Text utilities
30
+ .text-muted {
31
+ color: #ccc;
32
+ }
@@ -0,0 +1,9 @@
1
+ // Set variables
2
+ $sidebar-width: 197px;
3
+ $header-height: 57px;
4
+
5
+ // Include components
6
+ @import "frame/layout";
7
+ @import "frame/type";
8
+ @import "frame/buttons";
9
+ @import "frame/forms";
@@ -0,0 +1,9 @@
1
+ class DiscoApp::FrameController < ActionController::Base
2
+
3
+ layout nil
4
+
5
+ def frame
6
+
7
+ end
8
+
9
+ end
@@ -1,4 +1,9 @@
1
- module DiscoApp
2
- module ApplicationHelper
1
+ module DiscoApp::ApplicationHelper
2
+
3
+ def link_to_shopify_admin(shop, name, admin_path, options = {})
4
+ options[:onclick] = "ShopifyApp.redirect('#{admin_path}'); return false;"
5
+ options[:'data-no-turbolink'] = true
6
+ link_to(name, "https://#{shop.shopify_domain}/admin/#{admin_path}", options)
3
7
  end
8
+
4
9
  end
@@ -0,0 +1,36 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dev Frame</title>
5
+ <%= stylesheet_link_tag 'disco_app/frame', media: 'all' %>
6
+ <%= javascript_include_tag 'disco_app/frame' %>
7
+ </head>
8
+ <body>
9
+ <!-- Left Sidebar -->
10
+ <aside id="sidebar"></aside>
11
+
12
+ <!-- Header Bar -->
13
+ <header id="header">
14
+ <h1 id="header-title">
15
+ <img id="header-title-icon" src="<%= image_path('disco_app/icon.svg') %>" width="20" height="20" />
16
+ Shopify Dev Frame
17
+ </h1>
18
+ <div id="header-actions">
19
+ <!-- No action. -->
20
+ </div>
21
+ </header>
22
+
23
+ <!-- Content iFrame -->
24
+ <section id="content-wrapper">
25
+ <iframe id="content" src="/"></iframe>
26
+ </section>
27
+
28
+ <!-- Setup FrameApp. -->
29
+ <script type="text/javascript">
30
+ FrameApp.init({
31
+ debug: true,
32
+ iframe: document.getElementById('content')
33
+ });
34
+ </script>
35
+ </body>
36
+ </html>
@@ -5,9 +5,7 @@
5
5
  <%= content_for :card_header %>
6
6
  </header>
7
7
  <% end %>
8
- <section class="next-card__section">
9
- <%= content_for :card_content %>
10
- </section>
8
+ <%= content_for :card_content %>
11
9
  <% if content_for?(:card_footer) %>
12
10
  <footer class="next-card__footer">
13
11
  <%= content_for :card_footer %>
@@ -36,6 +36,6 @@
36
36
  </script>
37
37
  <% end %>
38
38
 
39
- <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
39
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true, 'data-turbolinks-eval' => false %>
40
40
  </body>
41
41
  </html>
data/config/routes.rb CHANGED
@@ -16,4 +16,11 @@ DiscoApp::Engine.routes.draw do
16
16
  get 'uninstalling' => :uninstalling, as: :uninstalling
17
17
  end
18
18
 
19
+ # Make the embedded app frame emulator available in development.
20
+ if Rails.env.development?
21
+ controller :frame do
22
+ get 'frame' => :frame, as: :frame
23
+ end
24
+ end
25
+
19
26
  end
@@ -5,7 +5,19 @@ require 'turbolinks'
5
5
 
6
6
  module DiscoApp
7
7
  class Engine < ::Rails::Engine
8
+
8
9
  isolate_namespace DiscoApp
9
10
  engine_name 'disco_app'
11
+
12
+ # Ensure DiscoApp helpers are available throughout application.
13
+ config.to_prepare do
14
+ ApplicationController.helper(DiscoApp::ApplicationHelper)
15
+ end
16
+
17
+ # Ensure our frame assets are included for precompilation.
18
+ initializer 'disco_app.assets.precompile' do |app|
19
+ app.config.assets.precompile += %w(disco_app/frame.css disco_app/frame.js)
20
+ end
21
+
10
22
  end
11
23
  end
@@ -1,3 +1,3 @@
1
1
  module DiscoApp
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disco_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin Ballard
@@ -244,19 +244,28 @@ files:
244
244
  - Rakefile
245
245
  - app/assets/images/disco_app/icon.svg
246
246
  - app/assets/javascripts/disco_app/disco_app.js
247
+ - app/assets/javascripts/disco_app/frame.js
248
+ - app/assets/javascripts/disco_app/shopify-turbolinks.js
247
249
  - app/assets/stylesheets/disco_app/bootstrap/_custom.scss
248
250
  - app/assets/stylesheets/disco_app/bootstrap/_variables.scss
249
251
  - app/assets/stylesheets/disco_app/disco/_buttons.scss
250
252
  - app/assets/stylesheets/disco_app/disco/_cards.scss
251
253
  - app/assets/stylesheets/disco_app/disco/_forms.scss
252
254
  - app/assets/stylesheets/disco_app/disco/_sections.scss
255
+ - app/assets/stylesheets/disco_app/disco/_tabs.scss
253
256
  - app/assets/stylesheets/disco_app/disco/_type.scss
254
257
  - app/assets/stylesheets/disco_app/disco/mixins/_flexbox.scss
255
258
  - app/assets/stylesheets/disco_app/disco_app.scss
259
+ - app/assets/stylesheets/disco_app/frame.scss
260
+ - app/assets/stylesheets/disco_app/frame/_buttons.scss
261
+ - app/assets/stylesheets/disco_app/frame/_forms.scss
262
+ - app/assets/stylesheets/disco_app/frame/_layout.scss
263
+ - app/assets/stylesheets/disco_app/frame/_type.scss
256
264
  - app/controllers/disco_app/app_proxy_controller.rb
257
265
  - app/controllers/disco_app/authenticated_controller.rb
258
266
  - app/controllers/disco_app/carrier_request_controller.rb
259
267
  - app/controllers/disco_app/charges_controller.rb
268
+ - app/controllers/disco_app/frame_controller.rb
260
269
  - app/controllers/disco_app/install_controller.rb
261
270
  - app/controllers/disco_app/webhooks_controller.rb
262
271
  - app/helpers/disco_app/application_helper.rb
@@ -280,6 +289,7 @@ files:
280
289
  - app/views/disco_app/charges/activate.html.erb
281
290
  - app/views/disco_app/charges/create.html.erb
282
291
  - app/views/disco_app/charges/new.html.erb
292
+ - app/views/disco_app/frame/frame.html.erb
283
293
  - app/views/disco_app/install/installing.html.erb
284
294
  - app/views/disco_app/install/uninstalling.html.erb
285
295
  - app/views/disco_app/proxy_errors/404.html.erb