hippo-fw 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc.js +0 -3
- data/.nvmrc +1 -2
- data/.ruby-version +1 -1
- data/Rakefile +1 -1
- data/client/hippo/access/login-dialog.jsx +2 -0
- data/client/hippo/boot.jsx +12 -0
- data/client/hippo/components/asset.jsx +5 -1
- data/client/hippo/components/asset.scss +1 -0
- data/client/hippo/components/data-list.jsx +6 -4
- data/client/hippo/components/data-table.jsx +7 -6
- data/client/hippo/components/data-table/header-cell.jsx +2 -0
- data/client/hippo/components/date-time.jsx +12 -2
- data/client/hippo/components/form/api.js +12 -0
- data/client/hippo/components/form/fields.jsx +8 -1
- data/client/hippo/components/form/fields/checkbox-wrapper.jsx +2 -0
- data/client/hippo/components/form/fields/date-wrapper.jsx +2 -0
- data/client/hippo/components/form/fields/form-field.scss +2 -0
- data/client/hippo/components/form/fields/label.jsx +2 -0
- data/client/hippo/components/form/fields/react-tags.scss +170 -0
- data/client/hippo/components/form/fields/select-wrapper.jsx +2 -0
- data/client/hippo/components/form/fields/tags-wrapper.jsx +46 -0
- data/client/hippo/components/form/fields/text-wrapper.jsx +9 -1
- data/client/hippo/components/form/fields/textarea-wrapper.jsx +15 -0
- data/client/hippo/components/form/wrapper.jsx +21 -1
- data/client/hippo/components/help.jsx +21 -0
- data/client/hippo/components/master-detail.jsx +2 -0
- data/client/hippo/components/network-activity-overlay.jsx +3 -1
- data/client/hippo/components/popout-window.jsx +126 -0
- data/client/hippo/components/query-builder.jsx +9 -117
- data/client/hippo/components/query-builder/boolean-picker.jsx +28 -0
- data/client/hippo/components/query-builder/clause-filter.jsx +58 -0
- data/client/hippo/components/query-builder/clause.jsx +98 -0
- data/client/hippo/components/query-builder/date-picker.jsx +23 -0
- data/client/hippo/components/query-builder/query-builder.scss +7 -0
- data/client/hippo/components/record-finder.jsx +2 -0
- data/client/hippo/components/record-finder/query-layer.jsx +5 -1
- data/client/hippo/components/save-button.jsx +7 -1
- data/client/hippo/components/screen.jsx +2 -0
- data/client/hippo/components/text-editor.jsx +4 -5
- data/client/hippo/components/text-editor/display-modes/Button.jsx +5 -2
- data/client/hippo/components/text-editor/display-modes/ToggleEdit.jsx +2 -1
- data/client/hippo/components/text-editor/display-modes/ToggleInsert.jsx +2 -1
- data/client/hippo/components/text-editor/display-modes/ToggleLayout.jsx +2 -1
- data/client/hippo/components/text-editor/display-modes/TogglePreview.jsx +2 -1
- data/client/hippo/components/text-editor/display-modes/ToggleResize.jsx +2 -1
- data/client/hippo/components/text-editor/display-modes/index.js +7 -7
- data/client/hippo/components/text-editor/image-plugin/Component/Display/index.js +4 -2
- data/client/hippo/components/text-editor/image-plugin/Component/Form/index.js +2 -0
- data/client/hippo/components/text-editor/renderer.jsx +2 -0
- data/client/hippo/components/text-editor/text-editor.scss +13 -4
- data/client/hippo/components/time-zone-select.jsx +2 -0
- data/client/hippo/components/tool-tip.jsx +2 -0
- data/client/hippo/extensions/base.js +2 -0
- data/client/hippo/extensions/hippo.js +2 -0
- data/client/hippo/lib/__mocks__/request-assets.js +1 -2
- data/client/hippo/lib/bootstrap.js +2 -0
- data/client/hippo/lib/computed-properties.js +24 -0
- data/client/hippo/lib/date-range.js +13 -2
- data/client/hippo/lib/request-assets.js +3 -2
- data/client/hippo/lib/smooth-scroll.js +2 -0
- data/client/hippo/lib/util.js +1 -2
- data/client/hippo/models/asset.js +2 -0
- data/client/hippo/models/base.js +5 -2
- data/client/hippo/models/collection.js +2 -0
- data/client/hippo/models/config.js +3 -1
- data/client/hippo/models/pub_sub.js +2 -0
- data/client/hippo/models/pub_sub/channel.js +2 -0
- data/client/hippo/models/pub_sub/map.js +2 -0
- data/client/hippo/models/query.js +21 -12
- data/client/hippo/models/query/array-result.js +52 -16
- data/client/hippo/models/query/clause.js +11 -4
- data/client/hippo/models/query/field.js +2 -1
- data/client/hippo/models/query/info.js +7 -1
- data/client/hippo/models/query/operator.js +2 -0
- data/client/hippo/models/query/result.js +2 -0
- data/client/hippo/models/query/types.js +4 -0
- data/client/hippo/models/sync.js +2 -0
- data/client/hippo/models/system-setting.js +1 -15
- data/client/hippo/models/tenant.js +23 -7
- data/client/hippo/react/Root.jsx +2 -0
- data/client/hippo/react/component-not-found.jsx +2 -0
- data/client/hippo/screens/definition.js +2 -0
- data/client/hippo/screens/group.js +2 -0
- data/client/hippo/screens/instance.js +5 -1
- data/client/hippo/screens/system-settings.jsx +19 -5
- data/client/hippo/screens/system-settings/mailer-config.jsx +4 -2
- data/client/hippo/screens/system-settings/system-settings.scss +1 -1
- data/client/hippo/screens/system-settings/tenant.jsx +4 -2
- data/client/hippo/screens/user-management.jsx +2 -0
- data/client/hippo/screens/user-management/edit-form.jsx +2 -0
- data/client/hippo/testing/screens.js +10 -2
- data/client/hippo/user.js +4 -0
- data/client/hippo/workspace/index.jsx +3 -1
- data/client/hippo/workspace/menu-group.jsx +2 -0
- data/client/hippo/workspace/menu-option.jsx +2 -0
- data/client/hippo/workspace/menu.jsx +6 -3
- data/client/hippo/workspace/navbar.jsx +2 -0
- data/client/hippo/workspace/screen.jsx +2 -0
- data/client/hippo/workspace/styles.scss +5 -1
- data/command-reference-files/initial/.eslintrc.js +0 -3
- data/command-reference-files/initial/Gemfile +1 -1
- data/config/routes.rb +3 -1
- data/db/seed.rb +1 -1
- data/hippo-fw.gemspec +2 -2
- data/lib/hippo/api/controller_base.rb +2 -1
- data/lib/hippo/api/handlers/asset.rb +3 -2
- data/lib/hippo/api/handlers/tenant.rb +4 -6
- data/lib/hippo/api/helper_methods.rb +5 -7
- data/lib/hippo/api/route_set.rb +3 -2
- data/lib/hippo/asset.rb +4 -0
- data/lib/hippo/command/console.rb +1 -1
- data/lib/hippo/concerns/asset_uploader.rb +9 -4
- data/lib/hippo/concerns/queries.rb +3 -3
- data/lib/hippo/extension.rb +14 -4
- data/lib/hippo/extension/definition.rb +5 -1
- data/lib/hippo/logger.rb +26 -27
- data/lib/hippo/mailer.rb +19 -7
- data/lib/hippo/system_settings.rb +10 -4
- data/lib/hippo/templates/liquid.rb +1 -0
- data/lib/hippo/templates/liquid/pluralize.rb +16 -0
- data/lib/hippo/tenant.rb +17 -1
- data/lib/hippo/user.rb +10 -9
- data/lib/hippo/version.rb +1 -1
- data/lib/hippo/webpack.rb +22 -2
- data/package-lock.json +5462 -883
- data/package.json +9 -11
- data/spec/client/access/login-dialog.spec.jsx +2 -2
- data/spec/client/components/__snapshots__/query-builder.spec.jsx.snap +1 -1
- data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +1 -1
- data/spec/client/components/master-detail.spec.jsx +2 -1
- data/spec/client/components/query-builder.spec.jsx +3 -3
- data/spec/client/extension/base.spec.js +2 -0
- data/spec/client/models/base.spec.js +5 -3
- data/spec/client/models/query.spec.js +18 -6
- data/spec/client/models/sync.spec.js +2 -1
- data/spec/client/models/system-setting.spec.js +0 -12
- data/spec/client/screens/user-management.spec.jsx +1 -2
- data/spec/client/test-models.js +10 -0
- data/spec/server/api/tenant_change_spec.rb +1 -2
- data/spec/server/asset_spec.rb +2 -2
- data/templates/js/config-data.js +1 -1
- data/templates/spec/factories/model.rb +1 -1
- data/views/hippo_root_view.erb +1 -3
- metadata +17 -6
- data/client/hippo/components/text-editor/display-modes/SaveState.jsx +0 -17
@@ -10,6 +10,7 @@ import Display from '../Display';
|
|
10
10
|
@inject('model', 'images_attribute')
|
11
11
|
@observer
|
12
12
|
export default class Form extends React.PureComponent {
|
13
|
+
|
13
14
|
get assets() {
|
14
15
|
return this.props.model[this.props.images_attribute];
|
15
16
|
}
|
@@ -37,4 +38,5 @@ export default class Form extends React.PureComponent {
|
|
37
38
|
</div>
|
38
39
|
);
|
39
40
|
}
|
41
|
+
|
40
42
|
}
|
@@ -9,6 +9,7 @@ import 'ory-editor-core/lib/index.css';
|
|
9
9
|
|
10
10
|
@observer
|
11
11
|
export default class TextEditorRenderer extends React.PureComponent {
|
12
|
+
|
12
13
|
static defaultProps = {
|
13
14
|
assets: observable.array(),
|
14
15
|
}
|
@@ -34,4 +35,5 @@ export default class TextEditorRenderer extends React.PureComponent {
|
|
34
35
|
</Provider>
|
35
36
|
);
|
36
37
|
}
|
38
|
+
|
37
39
|
}
|
@@ -8,6 +8,7 @@
|
|
8
8
|
|
9
9
|
.text-editor-content {
|
10
10
|
flex: 1;
|
11
|
+
overflow: auto;
|
11
12
|
}
|
12
13
|
|
13
14
|
|
@@ -25,12 +26,17 @@
|
|
25
26
|
margin-bottom: 0;
|
26
27
|
}
|
27
28
|
|
28
|
-
.content-image {
|
29
|
-
|
30
|
-
|
29
|
+
.content-image-wrapper {
|
30
|
+
.image-drop-zone {
|
31
|
+
text-align: center;
|
32
|
+
}
|
33
|
+
.content-image {
|
34
|
+
max-width: 100%;
|
35
|
+
width: auto;
|
36
|
+
height: auto;
|
37
|
+
}
|
31
38
|
}
|
32
39
|
|
33
|
-
|
34
40
|
button:not(.grommetux-button) {
|
35
41
|
min-width: inherit;
|
36
42
|
padding: 0;
|
@@ -44,5 +50,8 @@
|
|
44
50
|
.active {
|
45
51
|
border-bottom: 2px solid $focus-border-color;
|
46
52
|
}
|
53
|
+
button + button {
|
54
|
+
margin-left: 0.5rem;
|
55
|
+
}
|
47
56
|
}
|
48
57
|
}
|
@@ -9,6 +9,7 @@ import moment from 'moment-timezone';
|
|
9
9
|
|
10
10
|
@observer
|
11
11
|
export default class TimeZoneSelect extends React.PureComponent {
|
12
|
+
|
12
13
|
static propTypes = {
|
13
14
|
value: PropTypes.string,
|
14
15
|
onChange: PropTypes.func.isRequired,
|
@@ -57,4 +58,5 @@ export default class TimeZoneSelect extends React.PureComponent {
|
|
57
58
|
/>
|
58
59
|
);
|
59
60
|
}
|
61
|
+
|
60
62
|
}
|
@@ -6,6 +6,7 @@ import 'react-tippy/dist/tippy.css';
|
|
6
6
|
// Use a wrapper component even though it doesn't really add any functionality
|
7
7
|
// In the future we'll add a Manager wrapper so that multiple tooltips cannot be shown at once
|
8
8
|
export default class ToolTip extends React.PureComponent {
|
9
|
+
|
9
10
|
render() {
|
10
11
|
const { children, ...tipProps } = this.props;
|
11
12
|
return (
|
@@ -16,4 +17,5 @@ export default class ToolTip extends React.PureComponent {
|
|
16
17
|
</Tippy>
|
17
18
|
);
|
18
19
|
}
|
20
|
+
|
19
21
|
}
|
@@ -6,6 +6,7 @@ import RootView from '../workspace/root-view';
|
|
6
6
|
export { identifiedBy, identifier } from '../models/base';
|
7
7
|
|
8
8
|
export class BaseExtension {
|
9
|
+
|
9
10
|
@observable data;
|
10
11
|
|
11
12
|
static register() {
|
@@ -27,4 +28,5 @@ export class BaseExtension {
|
|
27
28
|
rootView() {
|
28
29
|
return RootView;
|
29
30
|
}
|
31
|
+
|
30
32
|
}
|
@@ -7,6 +7,7 @@ const ERROR = Symbol('ERROR');
|
|
7
7
|
const COMPLETE = Symbol('COMPLETE');
|
8
8
|
|
9
9
|
export default class Bootstrap {
|
10
|
+
|
10
11
|
constructor(options = {}) {
|
11
12
|
this.options = options;
|
12
13
|
this.callbacks = { onReady: [] };
|
@@ -41,4 +42,5 @@ export default class Bootstrap {
|
|
41
42
|
this.status = COMPLETE;
|
42
43
|
this.callbacks.onReady.map(cb => cb(host, data));
|
43
44
|
}
|
45
|
+
|
44
46
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { forIn } from 'lodash';
|
2
|
+
import { computed } from 'mobx';
|
3
|
+
|
4
|
+
export function addComputedProperty(obj, name, fn) {
|
5
|
+
Object.defineProperty(obj, name, {
|
6
|
+
configurable: true,
|
7
|
+
get() {
|
8
|
+
const getter = computed(fn, { context: this });
|
9
|
+
Object.defineProperty(this, name, {
|
10
|
+
configurable: false,
|
11
|
+
get: () => getter.get(),
|
12
|
+
});
|
13
|
+
return getter.get();
|
14
|
+
},
|
15
|
+
});
|
16
|
+
}
|
17
|
+
|
18
|
+
export function addMethods(properties) {
|
19
|
+
return (collection) => {
|
20
|
+
forIn(properties, (fn, prop) => {
|
21
|
+
addComputedProperty(collection, prop, fn);
|
22
|
+
});
|
23
|
+
};
|
24
|
+
}
|
@@ -1,10 +1,16 @@
|
|
1
|
-
import
|
1
|
+
import moment from 'moment';
|
2
|
+
import { observable, computed } from 'mobx';
|
3
|
+
import { isString, isEmpty, map, isNaN } from 'lodash';
|
2
4
|
import {
|
3
5
|
identifiedBy,
|
4
6
|
} from 'mobx-decorated-models';
|
5
7
|
|
6
8
|
@identifiedBy('date-range')
|
7
9
|
export default class DateRange {
|
10
|
+
|
11
|
+
@observable start;
|
12
|
+
@observable end;
|
13
|
+
|
8
14
|
constructor(range) {
|
9
15
|
if (isString(range) && !isEmpty(range)) {
|
10
16
|
[this.start, this.end] = map(range.split('...'), d => new Date(d));
|
@@ -15,7 +21,7 @@ export default class DateRange {
|
|
15
21
|
}
|
16
22
|
|
17
23
|
toJSON() {
|
18
|
-
if (this.start && this.end) {
|
24
|
+
if (this.start && this.end && !isNaN(this.start) && !isNaN(this.end)) {
|
19
25
|
// this strange format is what PG user and is therefore what active record expects
|
20
26
|
return `[${this.start.toISOString()},${this.end.toISOString()})`;
|
21
27
|
}
|
@@ -25,4 +31,9 @@ export default class DateRange {
|
|
25
31
|
static serialize(range) {
|
26
32
|
return (range ? range.toJSON() : '');
|
27
33
|
}
|
34
|
+
|
35
|
+
@computed get isCurrent() {
|
36
|
+
return moment(this.end).isAfter() && moment(this.start).isBefore();
|
37
|
+
}
|
38
|
+
|
28
39
|
}
|
@@ -3,6 +3,7 @@ import { loadCSS, loadJS } from './loader';
|
|
3
3
|
import { logger } from './util';
|
4
4
|
|
5
5
|
class AssetLoader {
|
6
|
+
|
6
7
|
constructor(urls, cb) {
|
7
8
|
let finished = 0;
|
8
9
|
const completed = {};
|
@@ -21,6 +22,7 @@ class AssetLoader {
|
|
21
22
|
}
|
22
23
|
});
|
23
24
|
}
|
25
|
+
|
24
26
|
}
|
25
27
|
|
26
28
|
export default function RequestAssets(...urlArgs) {
|
@@ -33,6 +35,5 @@ export default function RequestAssets(...urlArgs) {
|
|
33
35
|
}
|
34
36
|
logger.warn(`${keys(failures).join(',')} failed to load`);
|
35
37
|
return reject(failures);
|
36
|
-
})
|
37
|
-
);
|
38
|
+
}));
|
38
39
|
}
|
@@ -17,6 +17,7 @@ const POSITION = function(start, end, elapsed, duration) {
|
|
17
17
|
};
|
18
18
|
|
19
19
|
export default class SmoothScroll {
|
20
|
+
|
20
21
|
constructor(link, destination, options = {}) {
|
21
22
|
this.link = link;
|
22
23
|
this.destination = destination;
|
@@ -65,4 +66,5 @@ export default class SmoothScroll {
|
|
65
66
|
}
|
66
67
|
return step();
|
67
68
|
}
|
69
|
+
|
68
70
|
}
|
data/client/hippo/lib/util.js
CHANGED
@@ -34,8 +34,7 @@ export function titleize(words) {
|
|
34
34
|
if ('string' !== typeof words) { return words; }
|
35
35
|
return (words)
|
36
36
|
.replace(/[\W_]/g, ' ')
|
37
|
-
.replace(/\S+/g, word => (word.charAt(0).toUpperCase() + word.slice(1))
|
38
|
-
);
|
37
|
+
.replace(/\S+/g, word => (word.charAt(0).toUpperCase() + word.slice(1)));
|
39
38
|
}
|
40
39
|
|
41
40
|
export function underscored(str) {
|
@@ -15,6 +15,7 @@ const UPDATE_METHODS = { POST: true, PUT: true, PATCH: true };
|
|
15
15
|
|
16
16
|
@identifiedBy('hippo/asset')
|
17
17
|
export default class Asset extends BaseModel {
|
18
|
+
|
18
19
|
@identifier id;
|
19
20
|
@field order;
|
20
21
|
|
@@ -127,4 +128,5 @@ export default class Asset extends BaseModel {
|
|
127
128
|
return json;
|
128
129
|
});
|
129
130
|
}
|
131
|
+
|
130
132
|
}
|
data/client/hippo/models/base.js
CHANGED
@@ -29,6 +29,7 @@ export {
|
|
29
29
|
};
|
30
30
|
|
31
31
|
export class BaseModel {
|
32
|
+
|
32
33
|
static get propType() {
|
33
34
|
return PropTypes.instanceOf(this);
|
34
35
|
}
|
@@ -43,7 +44,7 @@ export class BaseModel {
|
|
43
44
|
|
44
45
|
static get propertyOptions() {
|
45
46
|
const options = {};
|
46
|
-
this.$schema.forEach((val, name) =>
|
47
|
+
this.$schema.forEach((val, name) => { options[name] = val.options; });
|
47
48
|
return options;
|
48
49
|
}
|
49
50
|
|
@@ -59,7 +60,8 @@ export class BaseModel {
|
|
59
60
|
}
|
60
61
|
|
61
62
|
static get Collection() {
|
62
|
-
|
63
|
+
if (!this.$collection) { this.$collection = new ModelCollection(this); }
|
64
|
+
return this.$collection;
|
63
65
|
}
|
64
66
|
|
65
67
|
constructor(attrs) {
|
@@ -136,6 +138,7 @@ export class BaseModel {
|
|
136
138
|
destroy(options = {}) {
|
137
139
|
return Sync.forModel(this, extend(options, { action: 'destroy' }));
|
138
140
|
}
|
141
|
+
|
139
142
|
}
|
140
143
|
|
141
144
|
export default BaseModel;
|
@@ -44,6 +44,7 @@ function extendAry(modelClass, models = [], options = {}) {
|
|
44
44
|
}
|
45
45
|
|
46
46
|
export default class ModelCollection {
|
47
|
+
|
47
48
|
constructor(model) {
|
48
49
|
this.$model = model;
|
49
50
|
this.$collection = extendAry(model, [], {}, this);
|
@@ -52,4 +53,5 @@ export default class ModelCollection {
|
|
52
53
|
create(models = [], options = {}) {
|
53
54
|
return extendAry(this.$model, models, options, this);
|
54
55
|
}
|
56
|
+
|
55
57
|
}
|
@@ -7,6 +7,7 @@ import Extensions from '../extensions';
|
|
7
7
|
const STORAGE_KEY = 'hippo-user-data';
|
8
8
|
|
9
9
|
export default class Config {
|
10
|
+
|
10
11
|
@persist @observable api_host = get(window, 'location.origin', '');
|
11
12
|
@persist @observable api_path = '/api';
|
12
13
|
@persist @observable access_token;
|
@@ -23,7 +24,7 @@ export default class Config {
|
|
23
24
|
static create(hydrationConfig) {
|
24
25
|
const hydrate = createHydrator(hydrationConfig);
|
25
26
|
const ConfigInstance = new Config();
|
26
|
-
hydrate('config', ConfigInstance).then(() =>
|
27
|
+
hydrate('config', ConfigInstance).then(() => { ConfigInstance.isIntialized = true; });
|
27
28
|
return ConfigInstance;
|
28
29
|
}
|
29
30
|
|
@@ -56,4 +57,5 @@ export default class Config {
|
|
56
57
|
this.access_token = null;
|
57
58
|
if (this.user) { this.user.reset(); }
|
58
59
|
}
|
60
|
+
|
59
61
|
}
|
@@ -77,6 +77,7 @@ export function stop() {
|
|
77
77
|
}
|
78
78
|
|
79
79
|
export class PubSubAtom {
|
80
|
+
|
80
81
|
constructor(model) {
|
81
82
|
this.model = model;
|
82
83
|
if (model.identifierFieldValue) {
|
@@ -100,6 +101,7 @@ export class PubSubAtom {
|
|
100
101
|
reportObserved() {
|
101
102
|
if (this.atom) { this.atom.reportObserved(); }
|
102
103
|
}
|
104
|
+
|
103
105
|
}
|
104
106
|
|
105
107
|
export function observePubSub(...models) {
|
@@ -5,6 +5,7 @@ import { logger } from '../../lib/util';
|
|
5
5
|
const CHANNEL_SPLITTER = new RegExp('^(.*):(.*)/([^/]+)$');
|
6
6
|
|
7
7
|
export default class PubSubCableChannel {
|
8
|
+
|
8
9
|
constructor(pub_sub) {
|
9
10
|
this.callbacks = observable.map();
|
10
11
|
this.channel = pub_sub.cable.subscriptions.create(
|
@@ -53,4 +54,5 @@ export default class PubSubCableChannel {
|
|
53
54
|
this.pub_sub.onModelChange(modelId, id, omit(data, 'channel'));
|
54
55
|
}
|
55
56
|
}
|
57
|
+
|
56
58
|
}
|
@@ -2,6 +2,7 @@ import invariant from 'invariant';
|
|
2
2
|
import { isEmpty, mapValues } from 'lodash';
|
3
3
|
|
4
4
|
export default class PubSubMap {
|
5
|
+
|
5
6
|
constructor(modelKlass, channel) {
|
6
7
|
this.channel = channel;
|
7
8
|
this.channel_prefix = modelKlass.identifiedBy;
|
@@ -54,4 +55,5 @@ export default class PubSubMap {
|
|
54
55
|
models.splice(indx, 1);
|
55
56
|
}
|
56
57
|
}
|
58
|
+
|
57
59
|
}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { get, isString, find, extend, toPairs } from 'lodash';
|
2
|
-
import { action, reaction, observe, observable } from 'mobx';
|
2
|
+
import { toJS, action, reaction, observe, observable } from 'mobx';
|
3
|
+
import objectHash from 'object-hash';
|
3
4
|
import {
|
4
5
|
BaseModel, identifiedBy, field, belongsTo, hasMany, identifier, computed, session,
|
5
6
|
} from './base';
|
6
|
-
|
7
7
|
import Info from './query/info';
|
8
8
|
import Types from './query/types';
|
9
9
|
import Operator from './query/operator';
|
@@ -14,6 +14,7 @@ import ArrayResult from './query/array-result';
|
|
14
14
|
// needs to inherit from Base so network events will be listened to
|
15
15
|
@identifiedBy('hippo/query')
|
16
16
|
export default class Query extends BaseModel {
|
17
|
+
|
17
18
|
@belongsTo src;
|
18
19
|
|
19
20
|
@identifier id;
|
@@ -37,12 +38,6 @@ export default class Query extends BaseModel {
|
|
37
38
|
@hasMany({ model: Operator, inverseOf: 'query' }) operators;
|
38
39
|
@hasMany({ model: Field, inverseOf: 'query' }) fields;
|
39
40
|
|
40
|
-
@action
|
41
|
-
setSort({ field: f, ascending }) {
|
42
|
-
this.sortField = f;
|
43
|
-
this.sortAscending = ascending;
|
44
|
-
}
|
45
|
-
|
46
41
|
constructor(attrs = {}) {
|
47
42
|
for (let i = 0; i < get(attrs, 'fields.length', 0); i += 1) {
|
48
43
|
if (isString(attrs.fields[i])) {
|
@@ -52,10 +47,12 @@ export default class Query extends BaseModel {
|
|
52
47
|
super(attrs);
|
53
48
|
[
|
54
49
|
{ id: 'like', label: 'Starts With', types: Types.LIKE_QUERY_TYPES },
|
55
|
-
{ id: 'eq', label: 'Equals' },
|
50
|
+
{ id: 'eq', label: 'Equals', types: Types.EQUAL_TYPES },
|
51
|
+
{ id: 'between', label: 'Between', types: Types.BETWEEN_TYPES },
|
56
52
|
{ id: 'contains', label: 'Contains', types: Types.LIKE_QUERY_TYPES },
|
57
53
|
{ id: 'lt', label: 'Less Than', types: Types.LESS_THAN_QUERY_TYPES },
|
58
54
|
{ id: 'gt', label: 'More Than', types: Types.LESS_THAN_QUERY_TYPES },
|
55
|
+
|
59
56
|
].forEach(op => this.operators.push(op));
|
60
57
|
this.info = new Info(this);
|
61
58
|
this.results = new ArrayResult({ query: this });
|
@@ -68,13 +65,22 @@ export default class Query extends BaseModel {
|
|
68
65
|
if (attrs.sort) {
|
69
66
|
const [fieldId, dir] = toPairs(attrs.sort)[0];
|
70
67
|
this.sortField = find(this.fields, { id: fieldId });
|
71
|
-
this.sortAscending = ('ASC' === dir);
|
68
|
+
this.sortAscending = ('ASC' === dir.toUpperCase());
|
72
69
|
}
|
73
70
|
observe(this, 'autoFetch', this._onAutoFetchChange);
|
74
71
|
}
|
75
72
|
|
73
|
+
@action
|
74
|
+
setSort({ field: f, ascending }) {
|
75
|
+
this.sortField = f;
|
76
|
+
this.sortAscending = ascending;
|
77
|
+
}
|
78
|
+
|
76
79
|
@computed get fingerprint() {
|
77
|
-
return
|
80
|
+
return objectHash({
|
81
|
+
so: toJS(this.syncOptions),
|
82
|
+
vc: this.info.valuedClauses.map(c => c.fingerprint),
|
83
|
+
});
|
78
84
|
}
|
79
85
|
|
80
86
|
open() {
|
@@ -123,8 +129,11 @@ export default class Query extends BaseModel {
|
|
123
129
|
if (this.autoFetchDisposer) { return; }
|
124
130
|
this.autoFetchDisposer = reaction(
|
125
131
|
() => this.fingerprint,
|
126
|
-
|
132
|
+
() => {
|
133
|
+
this.results.reset().fetch();
|
134
|
+
},
|
127
135
|
{ delay: 100, compareStructural: true, fireImmediately: true },
|
128
136
|
);
|
129
137
|
}
|
138
|
+
|
130
139
|
}
|