disco_app 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|