disco_app 0.9.2 → 0.9.3

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/disco_app/components/custom/rules-editor.es6.jsx +77 -20
  3. data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-empty-state.es6.jsx +3 -3
  4. data/app/assets/javascripts/disco_app/disco_app.js +0 -1
  5. data/app/assets/stylesheets/disco_app/admin/_header.scss +16 -7
  6. data/app/assets/stylesheets/disco_app/admin/_layout.scss +1 -9
  7. data/app/assets/stylesheets/disco_app/admin/_nav.scss +15 -3
  8. data/app/assets/stylesheets/disco_app/disco_app.scss +3 -0
  9. data/app/assets/stylesheets/disco_app/frame/_buttons.scss +1 -1
  10. data/app/assets/stylesheets/disco_app/frame/_forms.scss +1 -1
  11. data/app/assets/stylesheets/disco_app/frame/_type.scss +2 -9
  12. data/app/assets/stylesheets/disco_app/frame.scss +1 -0
  13. data/app/assets/stylesheets/disco_app/ui-kit/_ui-empty-state.scss +27 -0
  14. data/app/assets/stylesheets/disco_app/ui-kit/_ui-footer-help.scss +13 -10
  15. data/app/assets/stylesheets/disco_app/ui-kit/_ui-kit.scss +94 -67
  16. data/app/assets/stylesheets/disco_app/ui-kit/_ui-tabs.scss +15 -3
  17. data/app/jobs/disco_app/concerns/shop_update_job.rb +2 -5
  18. data/app/models/disco_app/concerns/shop.rb +0 -13
  19. data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +18 -2
  20. data/db/migrate/20160521135510_move_shop_to_synchronises.rb +61 -0
  21. data/lib/disco_app/engine.rb +0 -1
  22. data/lib/disco_app/version.rb +1 -1
  23. data/lib/generators/disco_app/disco_app_generator.rb +42 -3
  24. data/lib/generators/disco_app/{monitorify/templates → templates}/config/newrelic.yml +0 -0
  25. data/lib/generators/disco_app/{monitorify/templates → templates}/initializers/rollbar.rb +0 -0
  26. data/lib/generators/disco_app/templates/root/CHECKS +4 -0
  27. data/lib/tasks/shops.rake +10 -0
  28. data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +1 -1
  29. data/test/dummy/app/models/disco_app/shop.rb +1 -1
  30. data/test/dummy/config/database.gitlab-ci.yml +24 -0
  31. data/test/dummy/db/schema.rb +7 -22
  32. data/test/fixtures/disco_app/shops.yml +2 -2
  33. data/test/jobs/disco_app/app_installed_job_test.rb +1 -1
  34. data/test/jobs/disco_app/app_uninstalled_job_test.rb +1 -1
  35. metadata +8 -5
  36. data/lib/generators/disco_app/mailify/mailify_generator.rb +0 -54
  37. data/lib/generators/disco_app/monitorify/monitorify_generator.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c93d48179fec89b4944ae9428138e3c12827ba628c525af2742afa9532af6abe
4
- data.tar.gz: 944da37163b8fbfaa4db0cd5626e76a5a5ff1680284fff69cebd0dddd105d754
3
+ metadata.gz: 3e11c5ff7beaece5d87fda19c4d06bcc08ded718b71ce4050a5380c15e638be0
4
+ data.tar.gz: 7a1ceffb9b2c33f6dffe4a31b6877cbab52946cd3d37ad4396270c397dd99805
5
5
  SHA512:
6
- metadata.gz: 23e9f5235c6867c3c77557ed229ddd3de0a3b9d3660ff80a3f06c971ce10d8ab867d30fec229c836542e8865ddb24647282a0cb29049d526e52bc8fd9c641f79
7
- data.tar.gz: b3bce74312f85aff46bca48ed90d53b1344e6e82461321bc962e790c5cd9bbd9f21edb53f4e4359e1a3e7db980d0d4899142307534d190a432e4d26273c825c5
6
+ metadata.gz: 6da76ea6fd5ac63a77fe4acaf4552946416841228994d4cf6b431a094180aa63d6d07a1ef586c71c44eeca0cfc38a4da30d6f0ed1a5b62c54b28b109fcdb485f
7
+ data.tar.gz: 1a96f567be81a5bc6189bb43bb98fd34181009459b2ec085ded5ad820ea662fa7a3780a40e3103a480debe70b74914d224e20cc90a21df3a5c5e949a74801ba4
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Defines a generic RulesEditor class. This class can't be used directly, but
3
3
  * should be inherited, with the inheriting class defining a list of column
4
- * types and correponding relations and condition data types, like so:
4
+ * types and corresponding relations and condition data types, like so:
5
5
  *
6
6
  * class MyRulesEditor extends RulesEditor {};
7
7
  * MyRulesEditor.defaultProps = {
@@ -9,13 +9,7 @@
9
9
  * title: {
10
10
  * label: 'Product title',
11
11
  * column: 'title',
12
- * relations: {
13
- * is_equal_to: {
14
- * label: 'is equal to',
15
- * relation: 'is_equal_to',
16
- * type: 'text'
17
- * }
18
- * }
12
+ * relations: RulesEditor.buildRelationsObj([RulesEditor.EQUALS_STRING])
19
13
  * }
20
14
  * }
21
15
  */
@@ -29,13 +23,11 @@ class RulesEditor extends React.Component {
29
23
  super(props);
30
24
  this.state = {
31
25
  rules: props.rules.map((rule, i) => {
32
- return {
26
+ return Object.assign({}, rule, {
33
27
  column: Object.keys(this.props.columns).filter((columnKey) => {
34
28
  return this.props.columns[columnKey].column == rule.column;
35
- })[0],
36
- relation: rule.relation,
37
- condition: rule.condition
38
- }
29
+ })[0]
30
+ });
39
31
  })
40
32
  }
41
33
  }
@@ -119,6 +111,19 @@ class RulesEditor extends React.Component {
119
111
  });
120
112
  }
121
113
 
114
+ /**
115
+ * Handle a change in a rule's variables
116
+ *
117
+ * @param index
118
+ * @param name
119
+ * @param value
120
+ */
121
+ onRuleVariableChange(index, name, value) {
122
+ this.updateRule(index, {
123
+ [name]: value
124
+ });
125
+ }
126
+
122
127
  /**
123
128
  * Given the column we're changing to and the current rule, return the next
124
129
  * relation value.
@@ -165,10 +170,21 @@ class RulesEditor extends React.Component {
165
170
  * @param updates
166
171
  */
167
172
  updateRule(index, updates) {
173
+ let updatedRule = Object.assign({}, this.state.rules[index], updates);
174
+
175
+ // Ensure only valid variables are present in the rule
176
+ const columnPath = this.props.columns[updatedRule.column].column;
177
+ const columnVariables = RulesEditor.getColumnPathVariables(columnPath);
178
+ Object.keys(updatedRule).forEach(function (key) {
179
+ if ('$' === key[0] && -1 === columnVariables.indexOf(key)) {
180
+ delete updatedRule[key];
181
+ }
182
+ });
183
+
168
184
  this.setState({
169
185
  rules: [
170
186
  ...this.state.rules.slice(0, index),
171
- Object.assign({}, this.state.rules[index], updates),
187
+ updatedRule,
172
188
  ...this.state.rules.slice(index + 1)
173
189
  ]
174
190
  });
@@ -190,6 +206,7 @@ class RulesEditor extends React.Component {
190
206
  onColumnChange={this.onRuleColumnChange.bind(this, i)}
191
207
  onRelationChange={this.onRuleRelationChange.bind(this, i)}
192
208
  onConditionChange={this.onRuleConditionChange.bind(this, i)}
209
+ onVariableChange={this.onRuleVariableChange.bind(this, i)}
193
210
  ruleCount={rules.length}
194
211
  blankOk = {this.props.blankOk}
195
212
  />
@@ -198,11 +215,9 @@ class RulesEditor extends React.Component {
198
215
  // Convert the current rules JSON into a format using the correct column
199
216
  // format used by our more advanced key checker.
200
217
  const rulesJSON = JSON.stringify(this.state.rules.map((rule, i) => {
201
- return {
202
- column: this.props.columns[rule.column].column,
203
- relation: rule.relation,
204
- condition: rule.condition
205
- }
218
+ return Object.assign({}, rule, {
219
+ column: this.props.columns[rule.column].column
220
+ });
206
221
  }));
207
222
 
208
223
  return(
@@ -220,6 +235,23 @@ class RulesEditor extends React.Component {
220
235
  );
221
236
  }
222
237
 
238
+ /**
239
+ * Get the variable names present in a column definition
240
+ *
241
+ * @param column
242
+ * @returns {Array.<String>}
243
+ */
244
+ static getColumnPathVariables(column) {
245
+ return column.split(/[^$a-z_A-Z]/).filter((key) => '$' === key[0]);
246
+ }
247
+
248
+ /**
249
+ * Return a relations object, which is just the passed array
250
+ * turned into an object which is keyed by the `relation` value
251
+ *
252
+ * @param relations
253
+ * @returns {{}}
254
+ */
223
255
  static buildRelationsObj(relations) {
224
256
  var relationsObj = {};
225
257
 
@@ -264,7 +296,7 @@ RulesEditor.LESS_THAN = {
264
296
  type: 'numeric'
265
297
  };
266
298
 
267
- const RulesEditorRule = ({ rule, columns, onRemove, onColumnChange, onRelationChange, onConditionChange, ruleCount, blankOk }) => {
299
+ const RulesEditorRule = ({ rule, columns, onRemove, onColumnChange, onVariableChange, onRelationChange, onConditionChange, ruleCount, blankOk }) => {
268
300
  const { column, relation, condition } = rule;
269
301
 
270
302
  const currentColumn = columns[column];
@@ -293,6 +325,16 @@ const RulesEditorRule = ({ rule, columns, onRemove, onColumnChange, onRelationCh
293
325
  );
294
326
  }
295
327
 
328
+ const columnVariables = RulesEditor.getColumnPathVariables(currentColumn.column);
329
+
330
+ let variablesEditor = columnVariables.map(function(name) {
331
+ return (
332
+ <div className="next-grid__cell" key={name}>
333
+ <RulesEditorVariableInput name={name} value={rule[name]} onChange={onVariableChange.bind(this, name)} />
334
+ </div>
335
+ );
336
+ });
337
+
296
338
  return (
297
339
  <div>
298
340
  <div className="next-grid next-grid--no-padding next-grid--compact">
@@ -301,6 +343,7 @@ const RulesEditorRule = ({ rule, columns, onRemove, onColumnChange, onRelationCh
301
343
  <div className="next-grid__cell">
302
344
  <RulesEditorColumnSelect currentColumnName={column} columns={columns} onChange={onColumnChange} />
303
345
  </div>
346
+ {variablesEditor}
304
347
  <div className="next-grid__cell">
305
348
  <RulesEditorRelationSelect currentRelationName={relation} relations={currentColumn.relations} onChange={onRelationChange} />
306
349
  </div>
@@ -325,6 +368,20 @@ const RulesEditorColumnSelect = ({ currentColumnName, columns, onChange }) => {
325
368
  return <InputSelect options={options} value={currentColumnName} onChange={onChange} label="Field" labelHidden={true} />;
326
369
  };
327
370
 
371
+ const RulesEditorVariableInput = ({ name, value, onChange }) => {
372
+
373
+ const handleChange = (e) => {
374
+ onChange && onChange(e);
375
+ };
376
+
377
+ let label = name.substr(1).trim().replace( /([A-Z])/g, " $1" );
378
+ label = label.charAt(0).toUpperCase() + label.substr(1);
379
+
380
+ return (
381
+ <InputText value={value} onChange={handleChange} label={label} labelHidden={true} placeholder={label} required={true} />
382
+ );
383
+ };
384
+
328
385
  const RulesEditorRelationSelect = ({ currentRelationName, relations, onChange }) => {
329
386
  const options = Object.keys(relations).map((relationName) => {
330
387
  return { label: relations[relationName].label, value: relationName }
@@ -4,7 +4,7 @@ const UIEmptyState = ({ title, subtitle, image, href, label }) => {
4
4
  if(image) {
5
5
  imageSubsection = (
6
6
  <div className="ui-empty-state__subsection">
7
- <div className="ui-empty-state__items ui-empty-state__items--odd-queries ui-empty-state__items--quantity-queries">
7
+ <div className="ui-empty-state__items">
8
8
  <div className="ui-empty-state__item">
9
9
  <div className="ui-empty-state__subitems">
10
10
  <div className="ui-empty-state__subitem">
@@ -21,8 +21,8 @@ const UIEmptyState = ({ title, subtitle, image, href, label }) => {
21
21
  <div className="ui-empty-state">
22
22
  <div className="ui-empty-state__section">
23
23
  <div className="ui-empty-state__subsection">
24
- <h1 className="next-heading next-heading--xl">{title}</h1>
25
- <h2 className="next-heading next-heading--subdued">{subtitle}</h2>
24
+ <h1 className="ui-empty-state__title">{title}</h1>
25
+ <h2 className="ui-empty-state__subtitle">{subtitle}</h2>
26
26
  </div>
27
27
  {imageSubsection}
28
28
  <div className="ui-empty-state__subsection">
@@ -5,6 +5,5 @@
5
5
  */
6
6
  //= require react
7
7
  //= require react_ujs
8
- //= require bootstrap-sprockets
9
8
  //= require disco_app/shopify-turbolinks
10
9
  //= require ./ui-kit
@@ -9,7 +9,7 @@
9
9
  position: fixed;
10
10
  top: 0;
11
11
  z-index: 198;
12
- left: 230px;
12
+ left: 240px;
13
13
  right: 0;
14
14
  height: 56px;
15
15
  max-width: 100vw;
@@ -37,6 +37,12 @@
37
37
  }
38
38
 
39
39
  .header__main {
40
+ color: rgba(0,0,0,0.9);
41
+ font-size: 1.42857rem;
42
+ line-height: 1.71429rem;
43
+ font-weight: 400;
44
+ z-index: 2;
45
+ overflow: hidden;
40
46
  -webkit-box-flex: 1;
41
47
  -webkit-flex: 1 0 0%;
42
48
  -ms-flex: 1 0 0%;
@@ -45,16 +51,19 @@
45
51
  -webkit-order: 1;
46
52
  -ms-flex-order: 1;
47
53
  order: 1;
48
- font-size: 24px;
49
- text-align: left;
54
+ display: -webkit-box;
55
+ display: -webkit-flex;
56
+ display: -ms-flexbox;
57
+ display: flex;
58
+ -webkit-box-align: center;
59
+ -webkit-align-items: center;
60
+ -ms-flex-align: center;
61
+ align-items: center;
50
62
  margin: 0;
51
63
  padding: 10px 0;
52
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
53
- font-weight: 300;
64
+ text-align: left;
54
65
  white-space: nowrap;
55
66
  text-overflow: ellipsis;
56
- overflow: hidden;
57
- z-index: 2;
58
67
  }
59
68
 
60
69
  .breadcrumb {
@@ -3,14 +3,6 @@
3
3
  // Styles for admin layout.
4
4
  // --------------------------------------------------
5
5
 
6
- body {
7
- line-height: 18px;
8
- font-size: 13px;
9
- color: #31373d;
10
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
11
- text-rendering: optimizeLegibility;
12
- }
13
-
14
6
  html, body {
15
7
  height: 100%;
16
8
  margin: 0;
@@ -25,7 +17,7 @@ html, body {
25
17
  }
26
18
 
27
19
  #content {
28
- padding: 56px 0 0 230px;
20
+ padding: 56px 0 0 240px;
29
21
  width: 100%;
30
22
  box-sizing: border-box;
31
23
  outline: 0;
@@ -5,7 +5,7 @@
5
5
 
6
6
  .next-nav {
7
7
  z-index: 221;
8
- width: 230px;
8
+ width: 240px;
9
9
  position: fixed;
10
10
  top: 0;
11
11
  left: 0;
@@ -29,7 +29,7 @@
29
29
 
30
30
  .next-nav__panel--primary {
31
31
  z-index: 1;
32
- width: 230px;
32
+ width: 240px;
33
33
  background-color: #31373d;
34
34
  -webkit-transition: background-color 200ms ease;
35
35
  transition: background-color 200ms ease;
@@ -110,6 +110,15 @@
110
110
  }
111
111
 
112
112
  .next-nav__link {
113
+ color: rgba(0,0,0,0.9);
114
+ font-size: 1.07143rem;
115
+ line-height: 1.42857rem;
116
+ font-weight: 400;
117
+ text-transform: initial;
118
+ letter-spacing: initial;
119
+ -webkit-font-smoothing: antialiased;
120
+ -moz-osx-font-smoothing: grayscale;
121
+ font-weight: 500;
113
122
  color: #c3cfd8;
114
123
  padding: 0 10px 0 20px;
115
124
  height: 40px;
@@ -123,9 +132,12 @@
123
132
  align-items: center;
124
133
  background-color: transparent;
125
134
  border: none;
126
- font-size: 13px;
127
135
  cursor: pointer;
128
136
  line-height: normal;
137
+
138
+ @media screen and (min-width: 640px) {
139
+ font-size: 1rem;
140
+ }
129
141
  }
130
142
 
131
143
  .next-nav__link:hover, .next-nav__link:focus, .next-nav__link:active, .next-nav__link.next-nav__link--is-selected {
@@ -2,6 +2,9 @@
2
2
  // Styles for Disco applications.
3
3
  // --------------------------------------------------
4
4
 
5
+ // Variables
6
+ $font-family: -apple-system, "BlinkMacSystemFont", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", sans-serif;
7
+
5
8
  // Mixins and utilities.
6
9
  @import 'mixins/flexbox';
7
10
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  white-space: nowrap;
15
15
  vertical-align: middle;
16
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
16
+ font-family: $font-family;
17
17
  font-size: 13px;
18
18
 
19
19
  -webkit-user-select: none;
@@ -10,7 +10,7 @@ input[type="text"],
10
10
  input[type="url"], {
11
11
  vertical-align: top;
12
12
  height: 32px;
13
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
13
+ font-family: $font-family;
14
14
  font-size: 13px;
15
15
  padding: 5px;
16
16
  margin: 0;
@@ -2,16 +2,9 @@
2
2
  // Type
3
3
  // --------------------------------------------------
4
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
5
  // Base
13
6
  html, body {
14
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
7
+ font-family: $font-family;
15
8
  font-size: 13px;
16
9
  }
17
10
 
@@ -20,7 +13,7 @@ h1 {
20
13
  font-size: 24px;
21
14
  line-height: 32px;
22
15
  height: 32px;
23
- font-family: ProximaNovaLight,"Helvetica Neue",Helvetica,Arial,sans-serif;
16
+ font-family: $font-family;
24
17
  font-weight: 300;
25
18
  margin: 0;
26
19
  padding: 0;
@@ -1,4 +1,5 @@
1
1
  // Set variables
2
+ $font-family: -apple-system, "BlinkMacSystemFont", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", sans-serif;
2
3
  $sidebar-width: 197px;
3
4
  $header-height: 57px;
4
5
 
@@ -16,6 +16,33 @@
16
16
  }
17
17
  }
18
18
 
19
+ .ui-empty-state__title {
20
+ color: rgba(0,0,0,0.9);
21
+ font-size: 1.92857rem;
22
+ line-height: 2.57143rem;
23
+ font-weight: 400;
24
+ margin: 0 0 20px;
25
+
26
+ @media (min-width: 640px) {
27
+ font-size: 2.35714rem;
28
+ line-height: 3.14286rem;
29
+ }
30
+ }
31
+
32
+ .ui-empty-state__subtitle {
33
+ color: rgba(0,0,0,0.9);
34
+ font-size: 1.14286rem;
35
+ line-height: 1.71429rem;
36
+ font-weight: 400;
37
+ color: rgba(0,0,0,0.56);
38
+ margin: 0 0 20px;
39
+
40
+ @media (min-width: 640px) {
41
+ font-size: 1.42857rem;
42
+ line-height: 2rem;
43
+ }
44
+ }
45
+
19
46
  .ui-empty-state__section {
20
47
  padding: 60px 0;
21
48
  }
@@ -5,21 +5,24 @@
5
5
  // --------------------------------------------------
6
6
 
7
7
  .ui-footer-help {
8
- margin: 40px 0;
8
+ margin: 1.71429rem 0;
9
9
  text-align: center;
10
10
  width: 100%;
11
11
  }
12
12
 
13
13
  .ui-footer-help__content {
14
- @include inline-flex();
15
- @include align-items(center);
16
-
14
+ color: rgba(0,0,0,0.56);
15
+ display: -webkit-inline-box;
16
+ display: -webkit-inline-flex;
17
+ display: -ms-inline-flexbox;
18
+ display: inline-flex;
19
+ -webkit-box-align: center;
20
+ -webkit-align-items: center;
21
+ -ms-flex-align: center;
22
+ align-items: center;
23
+ text-align: left;
24
+ margin: 0 auto;
25
+ padding: 1.14286rem;
17
26
  border: 1px solid #d3dbe2;
18
27
  border-radius: 3px;
19
- color: #798c9c;
20
-
21
- font-size: 13px;
22
- margin: 0 auto;
23
- padding: 20px;
24
- text-align: left;
25
28
  }