lanes 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/Gemfile +2 -3
  4. data/client/lanes/boot.jsx +1 -1
  5. data/client/lanes/index.js +0 -11
  6. data/client/lanes/jest/matchers.js +14 -0
  7. data/{lib/js/jest/mocks.js → client/lanes/jest/mocks/fetch.js} +1 -1
  8. data/client/lanes/models/base.js +0 -32
  9. data/client/lanes/screens/definition.js +7 -8
  10. data/client/lanes/screens/index.js +24 -240
  11. data/client/lanes/workspace/menu.jsx +3 -34
  12. data/client/lanes/workspace/screen.jsx +3 -3
  13. data/config/routes.rb +2 -0
  14. data/config/screens.rb +2 -2
  15. data/lanes.gemspec +10 -7
  16. data/lib/lanes/access/authentication_provider.rb +4 -4
  17. data/lib/lanes/api.rb +1 -0
  18. data/lib/lanes/api/default_routes.rb +1 -1
  19. data/lib/lanes/api/handlers/screens.rb +26 -0
  20. data/lib/lanes/api/helper_methods.rb +5 -4
  21. data/lib/lanes/cli.rb +7 -0
  22. data/lib/lanes/command/app.rb +4 -6
  23. data/lib/lanes/command/client_config.rb +59 -0
  24. data/lib/lanes/command/generate_model.rb +4 -4
  25. data/lib/lanes/command/jest.rb +14 -29
  26. data/lib/lanes/command/model_attribute.rb +6 -1
  27. data/lib/lanes/command/named_command.rb +1 -0
  28. data/lib/lanes/command/puma.rb +56 -0
  29. data/lib/lanes/command/server.rb +21 -18
  30. data/lib/lanes/command/webpack.rb +54 -0
  31. data/lib/lanes/extension.rb +0 -7
  32. data/lib/lanes/guard_tasks.rb +21 -20
  33. data/lib/lanes/rake_tasks.rb +13 -0
  34. data/lib/lanes/reloadable_sinatra.rb +24 -0
  35. data/lib/lanes/screen.rb +15 -6
  36. data/lib/lanes/spec_helper.rb +70 -136
  37. data/lib/lanes/version.rb +1 -1
  38. data/package.json +1 -1
  39. data/spec/server/api/controller_base_spec.rb +61 -53
  40. data/spec/server/spec_helper.rb +37 -45
  41. data/templates/client/models/model.js +17 -0
  42. data/templates/config/database.yml +2 -1
  43. data/templates/config/jest.config.json +14 -0
  44. data/templates/config/jest/babel-transform.js +47 -0
  45. data/templates/config/routes.rb +3 -2
  46. data/templates/config/webpack.config.js +1 -1
  47. data/templates/js/jest.config.json +2 -10
  48. data/templates/spec/client/models/model.spec.js +10 -0
  49. data/templates/spec/client/setup.js +9 -0
  50. data/templates/spec/server/spec_helper.rb +3 -11
  51. metadata +40 -41
  52. data/lib/js/jest.config.json +0 -14
  53. data/lib/js/jest/fileMock.js +0 -1
  54. data/lib/js/jest/setup.js +0 -26
  55. data/lib/js/jest/stubs/screen-definitions.js +0 -0
  56. data/lib/js/jest/styleMock.js +0 -1
  57. data/lib/js/webpack.config.js +0 -93
  58. data/lib/lanes/hot_reload_plugin.rb +0 -47
  59. data/lib/lanes/webpack.rb +0 -73
  60. data/spec/server/api/coffeescript_processor_spec.rb +0 -116
  61. data/templates/client/models/Model.coffee +0 -17
  62. data/templates/spec/client/models/ModelSpec.coffee +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e996b32bc8dc10aa628ae2eaf9683e14f070ae9
4
- data.tar.gz: 7b1e8f708c347328a33e5962068db0df86669ad6
3
+ metadata.gz: fa9dfa9407c5c84e02cac8d1ec0aba080ba79f3b
4
+ data.tar.gz: 6e04d2ad5c485bb3b216b8a0a4b272f7c6ed7f47
5
5
  SHA512:
6
- metadata.gz: 841d9120509bc907ea6e434068b82346e37efdf9ed85baefa2e3f1293c3e947af65ed3c53ae4060f47e89caddcff2e02c72e9c4f785ce869b86a2651dd31fb49
7
- data.tar.gz: 9828cea8c1618a6635b090a19c93260b6ffe1939484325b2e4f26d41040cd786319a9d3893bb692e867a198cd6c0a31f6f461ecdff714ee0948df79c2e31f52d
6
+ metadata.gz: e15bcd8e90226888c02d1fb4a174aba4211a422740d6844f3d6ef22543c48715c540f35c900398a54d500d53a4320e0002dc9a6e2d46a4c0df9e72416fa8268b
7
+ data.tar.gz: d08bb632d089915d690715f11b63277526886db844fa0ceef43a64f755d3af94c712f8f065b5ff6f6f8d89f2f9756269ef0b322e8ae5913a1eab68327f595852
@@ -1,3 +1,5 @@
1
+ Metrics/LineLength:
2
+ Max: 100
1
3
 
2
4
  StringLiterals:
3
5
  Enabled: false
data/Gemfile CHANGED
@@ -3,9 +3,8 @@ source 'https://rubygems.org'
3
3
  gem "yard-activerecord",
4
4
  git: 'https://github.com/nathanstitt/yard-activerecord',
5
5
  branch: 'develop'
6
- gem "active_record_mocks",
7
- git: 'https://github.com/active_record_mocks',
8
- branch: 'develop'
6
+
7
+ gem "temping"
9
8
 
10
9
  gem 'puma'
11
10
  gem 'pry-byebug'
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import ReactDOM from 'react-dom';
3
3
  import whenDomReady from 'when-dom-ready';
4
- import { delay } from 'lodash'
4
+ import { delay } from 'lodash';
5
5
  import { AppContainer } from 'react-hot-loader';
6
6
  import { withAsyncComponents } from 'react-async-component';
7
7
 
@@ -1,12 +1 @@
1
- //= require ./lib
2
- //= require ./extension
3
- //= require ./models
4
- //= require ./Config
5
- //= require ./react
6
- //= require ./components
7
- //= require ./screens
8
- //= require ./extension/LateLoaded
9
- //= require ./Boot
10
-
11
- import Config from './config';
12
1
  import Boot from './boot';
@@ -0,0 +1,14 @@
1
+ module.exports = {
2
+
3
+ toHaveRendered(wrapper, selector) {
4
+ const matchCount = wrapper.find(selector).length;
5
+ const result = { pass: 1 === matchCount };
6
+ if (result.pass) {
7
+ result.message = `${selector} was found`;
8
+ } else {
9
+ result.message = `Expected wrapper to contain '${selector}' only once, but it was found ${matchCount} times`;
10
+ }
11
+ return result;
12
+ },
13
+
14
+ };
@@ -49,4 +49,4 @@ fetch.mockResponses = (...responses) => {
49
49
  // Default mock is just a empty string.
50
50
  fetch.mockResponse('');
51
51
 
52
- module.exports = { fetch };
52
+ module.exports = fetch;
@@ -24,30 +24,6 @@ export {
24
24
  field, session, identifier,
25
25
  } from './decorators';
26
26
 
27
- // const ModelsMap = new Map();
28
-
29
- // lookupModelUsing((propertyName, propertyOptions = {}) =>
30
- // ModelsMap[propertyOptions.className] ||
31
- // ModelsMap[capitalize(propertyName)] ||
32
- // ModelsMap[capitalize(singular(propertyName))],
33
- // );
34
-
35
- // rememberModelUsing((klass) => {
36
- // invariant(
37
- // klass.identifiedBy,
38
- // `${klass.name} lacks a static identifiedBy property, use model decorator to auto-set it`,
39
- // );
40
- // ModelsMap[klass.identifiedBy] = klass;
41
- // });
42
-
43
- // const REPLACEABLE_PROP_TYPES = {
44
- // hasMany: true, array: true,
45
- // };
46
-
47
- // function propIsReplacable(prop) {
48
- // return !!REPLACEABLE_PROP_TYPES[prop.type] || REPLACEABLE_PROP_TYPES[get(prop, 'options.type')];
49
- // }
50
-
51
27
  export {
52
28
  observable, computed,
53
29
  };
@@ -57,14 +33,6 @@ export class BaseModel {
57
33
  return findModel(name);
58
34
  }
59
35
 
60
- // static get replaceableKeys() {
61
- // const replaceable = [];
62
- // this.$schema.forEach((prop, name) => {
63
- // if (propIsReplacable(prop)) { replaceable.push(name); }
64
- // });
65
- // return replaceable;
66
- // }
67
-
68
36
  static get assignableKeys() {
69
37
  return this.$schema.keys();
70
38
  }
@@ -1,5 +1,5 @@
1
1
  import { autorun, observable } from 'mobx';
2
- import { get, delay, extend, filter } from 'lodash';
2
+ import { get, delay, extend, filter, map, uniq } from 'lodash';
3
3
 
4
4
  import { classify, logger } from '../lib/util';
5
5
  import Config from '../config'
@@ -16,14 +16,13 @@ import Group from './group';
16
16
  import { createAsyncComponent } from 'react-async-component';
17
17
 
18
18
  export { createAsyncComponent };
19
+ import Registry from './index';
19
20
 
20
- const All = observable.map();
21
+ import Groups from './group';
21
22
 
22
23
  @modelDecorator('lanes/screen/definition')
23
24
  export default class ScreenDefinition extends BaseModel {
24
25
 
25
- static all = All;
26
-
27
26
  @identifier({ type: 'string' }) id;
28
27
  @session title;
29
28
  @session url_prefix;
@@ -37,17 +36,17 @@ export default class ScreenDefinition extends BaseModel {
37
36
  @session model;
38
37
  @session({ type: 'object' }) component;
39
38
  @session asset;
40
- // @session({ type: 'array' }) assets;
39
+
41
40
  @session url;
42
41
 
43
42
  static register(json, comp) {
44
- let screen = All.get(json.id);
43
+ let screen = Registry.all.get(json.id);
45
44
  if (screen) {
46
45
  screen.update(json);
47
46
  } else {
48
47
  screen = new ScreenDefinition(json);
49
- All.set(screen.id, screen);
50
- const group = Group.forId(screen.group_id);
48
+ Registry.all.set(screen.id, screen);
49
+ const group = Groups.forId(screen.group_id);
51
50
  if (group) { group.screens.push(screen); }
52
51
  }
53
52
  screen.component = comp;
@@ -1,252 +1,36 @@
1
- import { computed } from 'mobx';
2
- import { compact } from 'lodash';
3
- import Instance from './instance';
4
- import Definition from './definition';
1
+ import { observable, autorun } from 'mobx';
2
+ import { map, uniq } from 'lodash';
5
3
  import Group from './group';
6
- import { createAsyncComponent } from 'react-async-component';
4
+ import Config from '../config';
5
+ import Sync from '../models/sync';
7
6
 
8
- export default {
7
+ import user from '../user';
9
8
 
10
- @computed get active() {
11
- return Instance.active;
12
- },
9
+ const Screens = observable({
13
10
 
14
- @computed get groups() {
15
- return Group.all;
16
- },
11
+ all: observable.map(),
17
12
 
18
- @computed get displaying() {
19
- return Instance.displaying;
20
- },
13
+ active: observable.array(),
21
14
 
15
+ groups: observable.map(),
22
16
 
23
- getDefinition(screenId) {
24
- return Definition.all.get(screenId);
17
+ get activeGroups() {
18
+ return uniq(map(this.active, s => Group.forId(s.group_id)));
25
19
  },
26
20
 
27
- setBrowserLocation(location) {
28
- let instance;
29
- const [instanceId, screenId, ...args] = Array.from(compact(location.pathname.split('/')));
30
- if (!screenId) { return; }
31
- if (instanceId) {
32
- instance = Instance.displaying.findInstance(screenId, instanceId);
33
- } else {
34
- instance = Instance.displaying.find((instance) => instance.screen.id === screenId);
35
- }
36
- if (instance) {
37
- instance.active = true;
38
- } else {
39
- this.display(screenId, { args });
40
- }
21
+ refresh() {
22
+ Sync.perform(`${Config.api_path}/lanes/screens`).then(({ data: { screens: screenIds } }) => {
23
+ this.active.replace(map(screenIds, id => this.all.get(id)));
24
+ });
41
25
  },
42
26
 
43
- // display(screenId, props = {}) {
44
- // const screen = Definition.all.get(screenId);
45
- // if (!screen) {
46
- // msg = `Unable to find screen definition for ${screenId}`;
47
- // logger.warn(msg);
48
- // Promise.reject(msg);
49
- // }
50
- // return new Instance({ screen, props, active: true });
51
- // },
52
- };
53
-
54
- // import { autorun, observable } from 'mobx';
55
- // import { get, delay, extend } from 'lodash';
56
-
57
- // import { classify, warn } from '../lib/util';
58
- // import RequestAssets from '../lib/RequestAssets';
59
-
60
- // import {
61
- // BaseModel, modelDecorator, session,
62
- // belongsTo, identifier, computed,
63
- // } from '../models/base';
64
- // import User from '../User';
65
-
66
- // import ScreenDefinition from './definition';
67
-
68
- // let Displaying;
69
- // let All;
70
-
71
-
72
- // All = observable.map([]);
73
- // const registerScreen = (json) => {
74
- // const definition = new ScreenDefinition(json);
75
- // All.set(json.id, definition);
76
- // return definition;
77
- // }
78
-
79
- // const registerGroup = (json) => {
80
- // const group = new Group(json)
81
- // Groups.set(json.id, new Group(json));
82
- // return group;
83
- // }
84
-
85
- // export { All, registerScreen, registerGroup };
86
-
87
-
88
- // @modelDecorator('ScreenViewSet')
89
- // class ScreenViewSet extends BaseModel {
90
-
91
- // // static model = ScreenView;
92
-
93
-
94
- // active() {
95
- // return this.findWhere({ active: true });
96
- // }
97
-
98
- // constructor(models, options) {
99
- // super();
100
- // if (options == null) { options = {}; }
101
- // autorun(this::onUserChange);
102
- // }
103
-
104
- // onUserChange() {
105
- // if (User.isLoggedIn) {
106
- // get(User, 'options.initial_screens', []).forEach(
107
- // screenId => All.get(screenId).display(),
108
- // );
109
- // } else {
110
- // this.reset();
111
- // }
112
- // }
113
-
114
- // remove(model) {
115
- // const index = this.indexOf(model);
116
- // super.remove(...arguments);
117
- // if (model.active && this.length) {
118
- // this.at(_.min([index, this.length - 1])).active = true;
119
- // }
120
- // model.active = false;
121
- // return this;
122
- // }
123
-
124
- // @computed onActiveChange(changed, active) {
125
- // if (!changed.active) { return; }
126
- // return this.each(function(screen) {
127
- // if (screen !== changed) { return screen.set({ active: false }); }
128
- // });
129
- // }
130
-
131
- // activateNext() { return this._moveActive(+1); }
132
- // activatePrev() { return this._moveActive(-1); }
133
-
134
- // _moveActive(inc) {
135
- // if (this.length === 1) { return; }
136
- // let current = this.findIndexWhere({ active: true });
137
- // if (current === -1) { return; }
138
- // if ((inc > 0) && (current === (this.length - 1))) {
139
- // current = -1;
140
- // }
141
- // if ((inc < 0) && (current === 0)) {
142
- // current = this.length;
143
- // }
144
- // return this.at(current + inc).active = true;
145
- // }
146
-
147
- // findInstance(screenId, instanceId) {
148
- // return this.find(instance => (instance.screen.id === screenId) && (instance.id === instanceId));
149
- // }
150
- // }
151
-
152
- //ScreenViewSet.initClass();
153
-
154
- // @SerializableModel
155
- // class ScreenSet extends BaseModel {
156
-
157
- // @observable.map models;
158
-
159
- // // static initClass() {
160
- // // this.prototype.model = ScreenDefinition;
161
- // // this.prototype.register = Lanes.emptyFn;
162
- // // }
163
-
164
- // get(id) {
165
-
166
- // }
167
-
168
- // addScreen(screen) {
169
- // const screen = this.add( screen );
170
- // return screen.set({active:true});
171
- // }
172
-
173
- // isLoading() {
174
- // return !!this.findWhere({loading: true});
175
- // }
176
- // }
177
-
178
-
179
-
180
-
181
-
182
- // @modelDecorator('MenuGroupSet')
183
- // class MenuGroupSet extends BaseModel {
184
- // // static initClass() {
185
- // // this.prototype.model = MenuGroup;
186
- // // }
187
-
188
- // constructor() {
189
- // super(...arguments);
190
- // }
191
-
192
- // available() {
193
- // return this.cache || (this.cache = new Lanes.Models.SubCollection(this, {
194
- // filter(group) {
195
- // group.screens().filter();
196
- // return group.screens().length > 0;
197
- // }
198
- // }));
199
- // }
200
- // }
201
-
202
-
203
- // Lanes.Screens.display_id = function(screen_id) {
204
- // const definition = Lanes.Screens.Definitions.all.get(screen_id);
205
- // if (definition) {
206
- // return definition.display();
207
- // } else {
208
- // return Lanes.warn(`Unable to find definition for screen ${screen_id}`);
209
- // }
210
- // };
211
-
212
-
213
- // Definitions = {
214
-
215
- // displaying: new ScreenViewSet([], { single_active_only: true }),
216
- // groups: new MenuGroupSet,
217
- // register(spec) {
218
- // return this.all.add( spec );
219
- // },
220
- // setBrowserLocation(location) {
221
- // let instance;
222
- // const [instanceId, screenId, ...args] = Array.from(_.compact(location.pathname.split('/')));
223
- // if (!screenId) { return; }
224
-
225
- // if (instanceId && ( instance = this.displaying.findInstance(screenId, instanceId) )) {
226
- // return instance.active = true;
227
- // } else {
228
- // return __guard__(this.all.get(screenId), x => x.display({id: instanceId, props: {args}}));
229
- // }
230
- // }
231
-
232
- // };
233
-
234
- // Lanes.current_user.on("change:isLoggedIn", function(user) {
235
- // Lanes.Screens.Definitions.groups.each(group => delete group.cache);
236
- // delete Lanes.Screens.Definitions.groups.cache;
237
-
238
- // if (!user.isLoggedIn) {
239
- // return Lanes.Screens.Definitions.displaying.reset();
240
- // }
241
- // });
27
+ });
28
+ export default Screens;
242
29
 
243
- // function __guardMethod__(obj, methodName, transform) {
244
- // if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
245
- // return transform(obj, methodName);
246
- // } else {
247
- // return undefined;
248
- // }
249
- // }
250
- // function __guard__(value, transform) {
251
- // return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
252
- // }
30
+ let previousLoggedIn = null;
31
+ autorun(() => {
32
+ if (user.isLoggedIn !== previousLoggedIn){
33
+ previousLoggedIn = user.isLoggedIn;
34
+ Screens.refresh();
35
+ }
36
+ });
@@ -16,11 +16,10 @@ import Icon from '../components/icon';
16
16
  import User from '../user';
17
17
 
18
18
  const OnLogoutClick = (ev) => {
19
- debugger
20
19
  ev.stopPropagation();
21
20
  ev.preventDefault();
22
21
  User.logout();
23
- }
22
+ };
24
23
 
25
24
  function Logout() {
26
25
  return (
@@ -32,19 +31,8 @@ function Logout() {
32
31
  );
33
32
  }
34
33
 
34
+ @observer
35
35
  export default class WorkspaceMenu extends React.Component {
36
- /* renderGroup(group) {
37
- * return (
38
- * <ScreenGroup {...this.props} model={group} key={group.id} />
39
- * );
40
- * }
41
-
42
- * logOut(ev) {
43
- * ev.preventDefault();
44
- * return (
45
- * Lanes.current_user.logout()
46
- * );
47
- * }*/
48
36
 
49
37
  render() {
50
38
  return (
@@ -55,7 +43,7 @@ export default class WorkspaceMenu extends React.Component {
55
43
  <Header justify="between" size="large" pad={{ horizontal: 'medium' }}>
56
44
  Logo
57
45
  </Header>
58
- {Screens.groups.map(g => <Group key={g.id} group={g} />)}
46
+ {Screens.activeGroups.map(g => <Group key={g.id} group={g} />)}
59
47
  <Footer size="large" primary pad={{ horizontal: 'medium' }}>
60
48
  <Logout />
61
49
  </Footer>
@@ -63,22 +51,3 @@ export default class WorkspaceMenu extends React.Component {
63
51
  );
64
52
  }
65
53
  }
66
-
67
- /*
68
- *
69
- * <div className="screens-menu">
70
- * <div className="screens-menu-content">
71
- * <ul className="navigation">
72
- * {Screens.groups.map(g => <Group key={g.id} group={g} />)}
73
- * </ul>
74
- * </div>
75
- * <ul className="navigation">
76
- * <li
77
- * className="group logout"
78
- * data-tooltip-message="Log Out"
79
- * data-placement="right"
80
- * >
81
- * <Logout />
82
- * </li>
83
- * </ul>
84
- * </div>*/