pageflow-react 0.1.0
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 +7 -0
- data/.gitignore +17 -0
- data/.jshintrc +15 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +4 -0
- data/app/assets/javascripts/pageflow/react.js +8975 -0
- data/app/assets/javascripts/pageflow/react/components.js +4 -0
- data/app/views/pageflow/react/_widget.html.erb +1 -0
- data/app/views/pageflow/react/page.html.erb +7 -0
- data/js/.eslintrc +33 -0
- data/js/.gitignore +1 -0
- data/js/karma.conf.js +61 -0
- data/js/package.json +43 -0
- data/js/spec/.eslintrc +8 -0
- data/js/spec/components/background_image_spec.js +47 -0
- data/js/spec/components/page_thumbnail_spec.js +213 -0
- data/js/spec/create_container_spec.js +82 -0
- data/js/spec/resolve_spec.js +3 -0
- data/js/spec/resolvers/backbone_model_resolver_spec.js +256 -0
- data/js/spec/resolvers/create_recursive_resolver_spec.js +120 -0
- data/js/spec/resolvers/editor_file_ids_resolver_spec.js +49 -0
- data/js/spec/resolvers/i18n_resolver_spec.js +20 -0
- data/js/spec/resolvers/object_resolver_spec.js +165 -0
- data/js/spec/resolvers/page_type_resolver_spec.js +23 -0
- data/js/spec/resolvers/seed_resolver_spec.js +128 -0
- data/js/spec/stub_spec.js +16 -0
- data/js/spec/support/render_component.js +7 -0
- data/js/src/components/background_image.jsx +60 -0
- data/js/src/components/lazy_background_image.jsx +23 -0
- data/js/src/components/lazy_loaded_page_thumbnail.jsx +19 -0
- data/js/src/components/page_background.jsx +11 -0
- data/js/src/components/page_background_image.jsx +13 -0
- data/js/src/components/page_content.jsx +51 -0
- data/js/src/components/page_header.jsx +15 -0
- data/js/src/components/page_link.jsx +35 -0
- data/js/src/components/page_shadow.jsx +19 -0
- data/js/src/components/page_text.jsx +17 -0
- data/js/src/components/page_thumbnail.jsx +86 -0
- data/js/src/components/page_wrapper.jsx +11 -0
- data/js/src/components/scroller.js +43 -0
- data/js/src/create_container.jsx +53 -0
- data/js/src/create_page.jsx +38 -0
- data/js/src/create_page_component.jsx +45 -0
- data/js/src/create_page_type.js +57 -0
- data/js/src/create_resolver_root.jsx +21 -0
- data/js/src/create_widget.jsx +3 -0
- data/js/src/create_widget_type.js +12 -0
- data/js/src/index.js +69 -0
- data/js/src/mutate.js +17 -0
- data/js/src/mutations/mutation.js +5 -0
- data/js/src/mutations/update_page_link_mutation.js +30 -0
- data/js/src/mutations/update_page_mutation.js +19 -0
- data/js/src/resolve.js +45 -0
- data/js/src/resolvers/backbone_model_resolver.js +118 -0
- data/js/src/resolvers/create_recursive_resolver.js +20 -0
- data/js/src/resolvers/current_parent_page_resolver.js +38 -0
- data/js/src/resolvers/editor_chapter_resolver.js +10 -0
- data/js/src/resolvers/editor_file_ids_resolver.js +30 -0
- data/js/src/resolvers/editor_page_resolver.js +11 -0
- data/js/src/resolvers/i18n_resolver.js +11 -0
- data/js/src/resolvers/object_resolver.js +58 -0
- data/js/src/resolvers/page_type_resolver.js +12 -0
- data/js/src/resolvers/resolver.js +16 -0
- data/js/src/resolvers/seed_chapter_resolver.js +10 -0
- data/js/src/resolvers/seed_file_ids_resolver.js +11 -0
- data/js/src/resolvers/seed_page_resolver.js +11 -0
- data/js/src/resolvers/seed_resolver.js +75 -0
- data/js/src/utils/camelize.js +29 -0
- data/js/webpack.config.js +31 -0
- data/lib/pageflow-react.rb +13 -0
- data/lib/pageflow/react/engine.rb +15 -0
- data/lib/pageflow/react/page_type.rb +16 -0
- data/lib/pageflow/react/version.rb +5 -0
- data/lib/pageflow/react/widget_type.rb +21 -0
- data/pageflow-react.gemspec +29 -0
- metadata +205 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import ReactDOM from 'react-dom';
|
3
|
+
|
4
|
+
export default function(Component) {
|
5
|
+
return {
|
6
|
+
scroller: false,
|
7
|
+
|
8
|
+
enhance(pageElement) {
|
9
|
+
this._pageHooks = {...Backbone.Events};
|
10
|
+
this._isPreloaded = false;
|
11
|
+
|
12
|
+
this._render(pageElement);
|
13
|
+
},
|
14
|
+
|
15
|
+
preload(pageElement) {
|
16
|
+
this._isPreloaded = true;
|
17
|
+
this._render(pageElement);
|
18
|
+
},
|
19
|
+
|
20
|
+
activating(elelement, configuration, options) {
|
21
|
+
this._pageHooks.trigger('activating', options);
|
22
|
+
},
|
23
|
+
|
24
|
+
activated() {
|
25
|
+
this._pageHooks.trigger('activated');
|
26
|
+
},
|
27
|
+
|
28
|
+
deactivating() {
|
29
|
+
this._pageHooks.trigger('deactivating');
|
30
|
+
},
|
31
|
+
|
32
|
+
deactivated() {
|
33
|
+
this._pageHooks.trigger('deactivated');
|
34
|
+
},
|
35
|
+
|
36
|
+
resize() {
|
37
|
+
this._pageHooks.trigger('resize');
|
38
|
+
},
|
39
|
+
|
40
|
+
update(pageElement, configuration) {
|
41
|
+
pageflow.commonPageCssClasses.updateCommonPageCssClasses(pageElement, configuration);
|
42
|
+
},
|
43
|
+
|
44
|
+
cleanup(pageElement) {
|
45
|
+
ReactDOM.unmountComponentAtNode(pageElement[0]);
|
46
|
+
},
|
47
|
+
|
48
|
+
_render(pageElement) {
|
49
|
+
ReactDOM.render(React.createElement(Component, {
|
50
|
+
resolverSeed: pageflow.seed,
|
51
|
+
pageId: parseInt(pageElement.attr('id'), 10),
|
52
|
+
pageHooks: this._pageHooks,
|
53
|
+
isPreloaded: this._isPreloaded
|
54
|
+
}), pageElement[0]);
|
55
|
+
}
|
56
|
+
};
|
57
|
+
};
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
|
3
|
+
export default function(Component) {
|
4
|
+
return class extends React.Component {
|
5
|
+
static childContextTypes = {
|
6
|
+
resolverSeed: React.PropTypes.object
|
7
|
+
}
|
8
|
+
|
9
|
+
getChildContext() {
|
10
|
+
return {
|
11
|
+
resolverSeed: this.props.resolverSeed || {}
|
12
|
+
};
|
13
|
+
}
|
14
|
+
|
15
|
+
render() {
|
16
|
+
return (
|
17
|
+
<Component {...this.props} />
|
18
|
+
);
|
19
|
+
}
|
20
|
+
};
|
21
|
+
};
|
data/js/src/index.js
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
import createPage from './create_page.jsx';
|
2
|
+
import createWidget from './create_widget.jsx';
|
3
|
+
import createContainer from './create_container.jsx';
|
4
|
+
import createPageType from './create_page_type';
|
5
|
+
import createWidgetType from './create_widget_type';
|
6
|
+
import createPageComponent from './create_page_component.jsx';
|
7
|
+
import resolve from './resolve';
|
8
|
+
import mutate from './mutate';
|
9
|
+
|
10
|
+
import classNames from 'classnames';
|
11
|
+
|
12
|
+
import PageWrapper from './components/page_wrapper.jsx';
|
13
|
+
import PageBackground from './components/page_background.jsx';
|
14
|
+
import PageShadow from './components/page_shadow.jsx';
|
15
|
+
import PageContent from './components/page_content.jsx';
|
16
|
+
import PageHeader from './components/page_header.jsx';
|
17
|
+
import PageText from './components/page_text.jsx';
|
18
|
+
import BackgroundImage from './components/background_image.jsx';
|
19
|
+
import PageBackgroundImage from './components/page_background_image.jsx';
|
20
|
+
import PageLink from './components/page_link.jsx';
|
21
|
+
import PageThumbnail from './components/page_thumbnail.jsx';
|
22
|
+
import LazyLoadedPageThumbnail from './components/lazy_loaded_page_thumbnail.jsx';
|
23
|
+
|
24
|
+
import Draggable from 'react-draggable';
|
25
|
+
|
26
|
+
export default {
|
27
|
+
/** @api public */
|
28
|
+
createContainer,
|
29
|
+
|
30
|
+
/** @api public */
|
31
|
+
createPage,
|
32
|
+
|
33
|
+
/** @api public */
|
34
|
+
createWidget,
|
35
|
+
|
36
|
+
/** @api public */
|
37
|
+
createPageType,
|
38
|
+
|
39
|
+
/** @api public */
|
40
|
+
createWidgetType,
|
41
|
+
|
42
|
+
/** @api public */
|
43
|
+
createPageComponent,
|
44
|
+
|
45
|
+
/** @api public */
|
46
|
+
resolve,
|
47
|
+
|
48
|
+
/** @api public */
|
49
|
+
mutate,
|
50
|
+
|
51
|
+
classNames,
|
52
|
+
|
53
|
+
components: {
|
54
|
+
PageWrapper,
|
55
|
+
PageBackground,
|
56
|
+
PageShadow,
|
57
|
+
PageContent,
|
58
|
+
PageHeader,
|
59
|
+
PageText,
|
60
|
+
BackgroundImage,
|
61
|
+
PageBackgroundImage,
|
62
|
+
|
63
|
+
PageLink,
|
64
|
+
PageThumbnail,
|
65
|
+
LazyLoadedPageThumbnail,
|
66
|
+
|
67
|
+
Draggable
|
68
|
+
}
|
69
|
+
};
|
data/js/src/mutate.js
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
import UpdatePageMutation from './mutations/update_page_mutation';
|
2
|
+
import UpdatePageLinkMutation from './mutations/update_page_link_mutation';
|
3
|
+
|
4
|
+
var mutations = {
|
5
|
+
updatePage: UpdatePageMutation,
|
6
|
+
updatePageLink: UpdatePageLinkMutation
|
7
|
+
};
|
8
|
+
|
9
|
+
export default function(mutationName, props) {
|
10
|
+
var mutation = mutations[mutationName];
|
11
|
+
|
12
|
+
if (!mutation) {
|
13
|
+
throw `Unknown mutation ${mutationName}`;
|
14
|
+
}
|
15
|
+
|
16
|
+
return new mutation(props).perform();
|
17
|
+
};
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import Mutation from './mutation';
|
2
|
+
|
3
|
+
import pageflow from 'pageflow';
|
4
|
+
|
5
|
+
export default class extends Mutation {
|
6
|
+
perform() {
|
7
|
+
this._getPageLink().set(this.props.attributes);
|
8
|
+
}
|
9
|
+
|
10
|
+
_getPageLink() {
|
11
|
+
var pageLink = this._getPage().pageLinks().get(this.props.id);
|
12
|
+
|
13
|
+
if (!pageLink) {
|
14
|
+
throw new Error(`Could not find page link with id ${this.props.pageLinkId}.`);
|
15
|
+
}
|
16
|
+
|
17
|
+
return pageLink;
|
18
|
+
}
|
19
|
+
|
20
|
+
_getPage() {
|
21
|
+
var [pageId] = this.props.id.split(':');
|
22
|
+
var page = pageflow.pages.getByPermaId(pageId);
|
23
|
+
|
24
|
+
if (!page) {
|
25
|
+
throw new Error(`Could not find page with id ${pageId}.`);
|
26
|
+
}
|
27
|
+
|
28
|
+
return page;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import Mutation from './mutation';
|
2
|
+
|
3
|
+
import pageflow from 'pageflow';
|
4
|
+
|
5
|
+
export default class extends Mutation {
|
6
|
+
perform() {
|
7
|
+
this._getPage().configuration.set(this.props.attributes);
|
8
|
+
}
|
9
|
+
|
10
|
+
_getPage() {
|
11
|
+
var page = pageflow.pages.get(this.props.pageId);
|
12
|
+
|
13
|
+
if (!page) {
|
14
|
+
throw new Error(`Could not find page with id ${this.props.pageId}.`);
|
15
|
+
}
|
16
|
+
|
17
|
+
return page;
|
18
|
+
}
|
19
|
+
}
|
data/js/src/resolve.js
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
import EditorFileIdsResolver from './resolvers/editor_file_ids_resolver';
|
2
|
+
import EditorPageResolver from './resolvers/editor_page_resolver';
|
3
|
+
import EditorChapterResolver from './resolvers/editor_chapter_resolver';
|
4
|
+
import SeedFileIdsResolver from './resolvers/seed_file_ids_resolver';
|
5
|
+
import SeedPageResolver from './resolvers/seed_page_resolver';
|
6
|
+
import SeedChapterResolver from './resolvers/seed_chapter_resolver';
|
7
|
+
import PageTypeResolver from './resolvers/page_type_resolver';
|
8
|
+
import CurrentParentPageResolver from './resolvers/current_parent_page_resolver';
|
9
|
+
import I18nResolver from './resolvers/i18n_resolver';
|
10
|
+
|
11
|
+
var resolvers;
|
12
|
+
|
13
|
+
if (PAGEFLOW_EDITOR) {
|
14
|
+
resolvers = {
|
15
|
+
fileIds: EditorFileIdsResolver,
|
16
|
+
chapter: EditorChapterResolver,
|
17
|
+
page: EditorPageResolver
|
18
|
+
};
|
19
|
+
}
|
20
|
+
else {
|
21
|
+
resolvers = {
|
22
|
+
fileIds: SeedFileIdsResolver,
|
23
|
+
chapter: SeedChapterResolver,
|
24
|
+
page: SeedPageResolver
|
25
|
+
};
|
26
|
+
}
|
27
|
+
|
28
|
+
resolvers = {
|
29
|
+
pageType: PageTypeResolver,
|
30
|
+
currentParentPage: CurrentParentPageResolver,
|
31
|
+
i18n: I18nResolver,
|
32
|
+
...resolvers
|
33
|
+
}
|
34
|
+
|
35
|
+
export default function(resolverName, options) {
|
36
|
+
var resolver = resolvers[resolverName];
|
37
|
+
|
38
|
+
if (!resolver) {
|
39
|
+
throw `Unknown resolver ${resolverName}`;
|
40
|
+
}
|
41
|
+
|
42
|
+
return function(callback) {
|
43
|
+
return new resolver(options, callback);
|
44
|
+
}
|
45
|
+
};
|
@@ -0,0 +1,118 @@
|
|
1
|
+
import Resolver from './resolver';
|
2
|
+
import createRecursiveResolver from './create_recursive_resolver';
|
3
|
+
|
4
|
+
import camelize from '../utils/camelize';
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Resolve a foreign key to an object of attributes.
|
8
|
+
*/
|
9
|
+
class BackboneModelResolver extends Resolver {
|
10
|
+
constructor(options, callback) {
|
11
|
+
super(callback);
|
12
|
+
this._options = {
|
13
|
+
idAttribute: 'id',
|
14
|
+
attributesForProps: ['id'],
|
15
|
+
includeConfiguration: false,
|
16
|
+
...options
|
17
|
+
};
|
18
|
+
}
|
19
|
+
|
20
|
+
get(props, seed) {
|
21
|
+
this._updateModel(props, seed || {});
|
22
|
+
this._updateSubscription();
|
23
|
+
|
24
|
+
return this._getPropsFromModel();
|
25
|
+
}
|
26
|
+
|
27
|
+
dispose() {
|
28
|
+
if (this._model) {
|
29
|
+
this._stopListening(this._model);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
_updateModel(props, seed) {
|
34
|
+
this._prevModel = this._model;
|
35
|
+
this._model = this._getModel(props, seed);
|
36
|
+
}
|
37
|
+
|
38
|
+
_getModel(props, seed) {
|
39
|
+
var collection = this._options.collection(seed.ns);
|
40
|
+
return collection.findWhere(this._getIdConditions(props));
|
41
|
+
}
|
42
|
+
|
43
|
+
_getIdConditions(props) {
|
44
|
+
var conditions = {};
|
45
|
+
conditions[this._options.idAttribute] = this._getModelId(props);
|
46
|
+
return conditions;
|
47
|
+
}
|
48
|
+
|
49
|
+
_getModelId(props) {
|
50
|
+
return props[this._options.property];
|
51
|
+
}
|
52
|
+
|
53
|
+
_updateSubscription() {
|
54
|
+
if (this._prevModel === this._model) {
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
|
58
|
+
if (this._prevModel) {
|
59
|
+
this._stopListening(this._prevModel);
|
60
|
+
}
|
61
|
+
|
62
|
+
if (this._model) {
|
63
|
+
this._startListening(this._model);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
_startListening(model) {
|
68
|
+
model.on(this._getSubscribedEvents(), this._handleChange, this);
|
69
|
+
|
70
|
+
if (this._options.includeConfiguration) {
|
71
|
+
model.configuration.on('change', this._handleChange, this);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
_stopListening(model) {
|
76
|
+
model.off(null, null, this);
|
77
|
+
|
78
|
+
if (this._options.includeConfiguration) {
|
79
|
+
model.configuration.off('change', this._handleChange, this);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
_getSubscribedEvents() {
|
84
|
+
return this._options.attributesForProps
|
85
|
+
.map((attribute) => `change:${attribute}`)
|
86
|
+
.join(' ');
|
87
|
+
}
|
88
|
+
|
89
|
+
_getPropsFromModel() {
|
90
|
+
var props = null;
|
91
|
+
var model = this._model;
|
92
|
+
|
93
|
+
if (model) {
|
94
|
+
props = this._getPropsFromAttributes();
|
95
|
+
|
96
|
+
if (this._options.includeConfiguration) {
|
97
|
+
Object.assign(props, camelize.deep(model.configuration.attributes))
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
return props;
|
102
|
+
}
|
103
|
+
|
104
|
+
_getPropsFromAttributes() {
|
105
|
+
var model = this._model;
|
106
|
+
|
107
|
+
return this._options.attributesForProps.reduce((result, name) => {
|
108
|
+
if (typeof name === 'string') {
|
109
|
+
name = [camelize(name), name];
|
110
|
+
}
|
111
|
+
|
112
|
+
result[name[0]] = model.get(name[1]);
|
113
|
+
return result;
|
114
|
+
}, {})
|
115
|
+
}
|
116
|
+
};
|
117
|
+
|
118
|
+
export default createRecursiveResolver(BackboneModelResolver);
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import ObjectResolver from './object_resolver';
|
2
|
+
|
3
|
+
export default function(Resolver) {
|
4
|
+
return class {
|
5
|
+
constructor(options, callback) {
|
6
|
+
this._inner = new Resolver(options, callback);
|
7
|
+
this._objectResolver = new ObjectResolver(options.fragments, callback);
|
8
|
+
}
|
9
|
+
|
10
|
+
get(props, seed) {
|
11
|
+
const result = this._inner.get(props, seed);
|
12
|
+
return this._objectResolver.get(result, seed);
|
13
|
+
}
|
14
|
+
|
15
|
+
dispose() {
|
16
|
+
this._inner.dispose();
|
17
|
+
this._objectResolver.dispose();
|
18
|
+
}
|
19
|
+
}
|
20
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import Resolver from './resolver';
|
2
|
+
import resolve from '../resolve';
|
3
|
+
|
4
|
+
import createRecursiveResolver from './create_recursive_resolver';
|
5
|
+
|
6
|
+
class CurrentPageResolver extends Resolver {
|
7
|
+
constructor(options, callback) {
|
8
|
+
super(callback);
|
9
|
+
|
10
|
+
this._subscribeToPageChange();
|
11
|
+
this._pageResolver = resolve('page', {property: 'permaId'})(callback);
|
12
|
+
}
|
13
|
+
|
14
|
+
get(_, seed) {
|
15
|
+
return this._pageResolver.get({
|
16
|
+
permaId: this._currentParentPagePermaId(seed)
|
17
|
+
}, seed);
|
18
|
+
}
|
19
|
+
|
20
|
+
dispose() {
|
21
|
+
this._unsubscribeFromPageChange();
|
22
|
+
}
|
23
|
+
|
24
|
+
_currentParentPagePermaId(seed) {
|
25
|
+
var currentPagePermaId = pageflow.slides.currentPage().page('getPermaId');
|
26
|
+
return pageflow.entryData.getParentPagePermaIdByPagePermaId(currentPagePermaId);
|
27
|
+
}
|
28
|
+
|
29
|
+
_subscribeToPageChange() {
|
30
|
+
pageflow.events.on('page:change', this._handleChange, this);
|
31
|
+
}
|
32
|
+
|
33
|
+
_unsubscribeFromPageChange() {
|
34
|
+
pageflow.events.off('page:change', this._handleChange, this);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
|
38
|
+
export default createRecursiveResolver(CurrentPageResolver);
|