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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/disco_app/components/custom/rules-editor.es6.jsx +77 -20
- data/app/assets/javascripts/disco_app/components/ui-kit/ui-layout/ui-empty-state.es6.jsx +3 -3
- data/app/assets/javascripts/disco_app/disco_app.js +0 -1
- data/app/assets/stylesheets/disco_app/admin/_header.scss +16 -7
- data/app/assets/stylesheets/disco_app/admin/_layout.scss +1 -9
- data/app/assets/stylesheets/disco_app/admin/_nav.scss +15 -3
- data/app/assets/stylesheets/disco_app/disco_app.scss +3 -0
- data/app/assets/stylesheets/disco_app/frame/_buttons.scss +1 -1
- data/app/assets/stylesheets/disco_app/frame/_forms.scss +1 -1
- data/app/assets/stylesheets/disco_app/frame/_type.scss +2 -9
- data/app/assets/stylesheets/disco_app/frame.scss +1 -0
- data/app/assets/stylesheets/disco_app/ui-kit/_ui-empty-state.scss +27 -0
- data/app/assets/stylesheets/disco_app/ui-kit/_ui-footer-help.scss +13 -10
- data/app/assets/stylesheets/disco_app/ui-kit/_ui-kit.scss +94 -67
- data/app/assets/stylesheets/disco_app/ui-kit/_ui-tabs.scss +15 -3
- data/app/jobs/disco_app/concerns/shop_update_job.rb +2 -5
- data/app/models/disco_app/concerns/shop.rb +0 -13
- data/app/resources/disco_app/admin/resources/concerns/shop_resource.rb +18 -2
- data/db/migrate/20160521135510_move_shop_to_synchronises.rb +61 -0
- data/lib/disco_app/engine.rb +0 -1
- data/lib/disco_app/version.rb +1 -1
- data/lib/generators/disco_app/disco_app_generator.rb +42 -3
- data/lib/generators/disco_app/{monitorify/templates → templates}/config/newrelic.yml +0 -0
- data/lib/generators/disco_app/{monitorify/templates → templates}/initializers/rollbar.rb +0 -0
- data/lib/generators/disco_app/templates/root/CHECKS +4 -0
- data/lib/tasks/shops.rake +10 -0
- data/test/dummy/app/jobs/disco_app/app_uninstalled_job.rb +1 -1
- data/test/dummy/app/models/disco_app/shop.rb +1 -1
- data/test/dummy/config/database.gitlab-ci.yml +24 -0
- data/test/dummy/db/schema.rb +7 -22
- data/test/fixtures/disco_app/shops.yml +2 -2
- data/test/jobs/disco_app/app_installed_job_test.rb +1 -1
- data/test/jobs/disco_app/app_uninstalled_job_test.rb +1 -1
- metadata +8 -5
- data/lib/generators/disco_app/mailify/mailify_generator.rb +0 -54
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e11c5ff7beaece5d87fda19c4d06bcc08ded718b71ce4050a5380c15e638be0
|
4
|
+
data.tar.gz: 7a1ceffb9b2c33f6dffe4a31b6877cbab52946cd3d37ad4396270c397dd99805
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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="
|
25
|
-
<h2 className="
|
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">
|
@@ -9,7 +9,7 @@
|
|
9
9
|
position: fixed;
|
10
10
|
top: 0;
|
11
11
|
z-index: 198;
|
12
|
-
left:
|
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
|
-
|
49
|
-
|
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
|
-
|
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
|
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:
|
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:
|
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
|
|
@@ -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:
|
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:
|
16
|
+
font-family: $font-family;
|
24
17
|
font-weight: 300;
|
25
18
|
margin: 0;
|
26
19
|
padding: 0;
|
@@ -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:
|
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
|
-
|
15
|
-
|
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
|
}
|