-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'devel' of https://github.com/TelescopeJS/Telescope into…
… devel
- Loading branch information
Showing
18 changed files
with
287 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,104 @@ | ||
import { Components, registerComponent, withDocument, withCurrentUser } from 'meteor/nova:core'; | ||
import React from 'react'; | ||
import { Components, registerComponent, withDocument, withCurrentUser, getActions, withMutation } from 'meteor/nova:core'; | ||
import Posts from 'meteor/nova:posts'; | ||
import React, { Component, PropTypes } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { bindActionCreators } from 'redux'; | ||
|
||
const PostsPage = (props) => { | ||
class PostsPage extends Component { | ||
|
||
render() { | ||
if (this.props.loading) { | ||
|
||
return <div className="posts-page"><Components.Loading/></div> | ||
|
||
} else { | ||
|
||
const post = this.props.document; | ||
|
||
if (props.loading) { | ||
const htmlBody = {__html: post.htmlBody}; | ||
|
||
return <div className="posts-page"><Components.Loading/></div> | ||
return ( | ||
<div className="posts-page"> | ||
<Components.HeadTags url={Posts.getLink(post)} title={post.title} image={post.thumbnailUrl} description={post.excerpt} /> | ||
|
||
<Components.PostsItem post={post} currentUser={this.props.currentUser} /> | ||
|
||
} else { | ||
{post.htmlBody ? <div className="posts-page-body" dangerouslySetInnerHTML={htmlBody}></div> : null} | ||
|
||
const post = props.document; | ||
<Components.PostsCommentsThread terms={{postId: post._id}} /> | ||
|
||
const htmlBody = {__html: post.htmlBody}; | ||
|
||
return ( | ||
<div className="posts-page"> | ||
<Components.HeadTags url={Posts.getLink(post)} title={post.title} image={post.thumbnailUrl} description={post.excerpt} /> | ||
</div> | ||
); | ||
|
||
} | ||
} | ||
|
||
// triggered after the component did mount on the client | ||
async componentDidMount() { | ||
try { | ||
|
||
// destructure the relevant props | ||
const { | ||
// from the parent component, used in withDocument, GraphQL HOC | ||
documentId, | ||
// from connect, Redux HOC | ||
setViewed, | ||
postsViewed, | ||
// from withMutation, GraphQL HOC | ||
increasePostViewCount, | ||
} = this.props; | ||
|
||
// a post id has been found & it's has not been seen yet on this client session | ||
if (documentId && !postsViewed.includes(documentId)) { | ||
|
||
<Components.PostsItem post={post} currentUser={props.currentUser} /> | ||
|
||
{post.htmlBody ? <div className="posts-page-body" dangerouslySetInnerHTML={htmlBody}></div> : null} | ||
|
||
<Components.PostsCommentsThread terms={{postId: post._id}} /> | ||
|
||
</div> | ||
) | ||
// trigger the asynchronous mutation with postId as an argument | ||
await increasePostViewCount({postId: documentId}); | ||
|
||
// once the mutation is done, update the redux store | ||
setViewed(documentId); | ||
} | ||
|
||
} catch(error) { | ||
console.log(error); // eslint-disable-line | ||
} | ||
} | ||
}; | ||
} | ||
|
||
PostsPage.displayName = "PostsPage"; | ||
|
||
PostsPage.propTypes = { | ||
document: React.PropTypes.object | ||
documentId: PropTypes.string, | ||
document: PropTypes.object, | ||
postsViewed: PropTypes.array, | ||
setViewed: PropTypes.func, | ||
increasePostViewCount: PropTypes.func, | ||
} | ||
|
||
const options = { | ||
const queryOptions = { | ||
collection: Posts, | ||
queryName: 'postsSingleQuery', | ||
fragmentName: 'PostsPage', | ||
}; | ||
|
||
registerComponent('PostsPage', PostsPage, withCurrentUser, [withDocument, options]); | ||
const mutationOptions = { | ||
name: 'increasePostViewCount', | ||
args: {postId: 'String'}, | ||
}; | ||
|
||
const mapStateToProps = state => ({ postsViewed: state.postsViewed }); | ||
const mapDispatchToProps = dispatch => bindActionCreators(getActions().postsViewed, dispatch); | ||
|
||
registerComponent( | ||
// component name used by Nova | ||
'PostsPage', | ||
// React component | ||
PostsPage, | ||
// HOC to give access to the current user | ||
withCurrentUser, | ||
// HOC to load the data of the document, based on queryOptions & a documentId props | ||
[withDocument, queryOptions], | ||
// HOC to provide a single mutation, based on mutationOptions | ||
withMutation(mutationOptions), | ||
// HOC to give access to the redux store & related actions | ||
connect(mapStateToProps, mapDispatchToProps) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import Categories from './modules.js'; | ||
import Categories, { getCategories, getCategoriesAsOptions } from './modules.js'; | ||
|
||
export default Categories; | ||
export { getCategories, getCategoriesAsOptions }; | ||
export default Categories; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import Categories from './modules.js'; | ||
import Categories, { getCategories, getCategoriesAsOptions } from './modules.js'; | ||
|
||
import './server/load_categories.js'; | ||
|
||
export default Categories; | ||
export { getCategories, getCategoriesAsOptions }; | ||
export default Categories; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { addCallback, getSetting } from 'meteor/nova:core'; | ||
import { sendGoogleAnalyticsRequest, mutationAnalyticsAsync } from './helpers'; | ||
import Analytics from 'analytics-node'; | ||
|
||
// add client-side callback: log a ga request on page view | ||
addCallback('router.onUpdate', sendGoogleAnalyticsRequest); | ||
|
||
|
||
// get the segment write key from the settings | ||
const useSegment = getSetting('useSegment'); | ||
const writeKey = getSetting('segmentWriteKey'); | ||
|
||
// the settings obviously tells to use segment | ||
// and segment write key is defined & isn't the placeholder from sample_settings.json | ||
if (useSegment && writeKey && writeKey !== '456bar') { | ||
const analyticsInstance = new Analytics(writeKey); | ||
|
||
// generate callbacks on collection ... | ||
['users', 'posts', 'comments', 'categories'].map(collection => { | ||
// ... for each common mutation | ||
return ['new', 'edit', 'remove'].map(mutation => { | ||
|
||
const hook = `${collection}.${mutation}`; | ||
|
||
addCallback(`${hook}.async`, function AnalyticsTracking(...args) { | ||
|
||
// a note on what's happenning below: | ||
// the first argument is always the document we are interested in | ||
// the second to last argument is always the current user | ||
// on edit.async, the argument on index 1 is always the previous document | ||
// see nova:lib/mutations.js for more informations | ||
|
||
// remove unnecessary 'previousDocument' if operating on a collection.edit hook | ||
if (hook.includes('edit')) { | ||
args.splice(1,1); | ||
} | ||
|
||
const [document, currentUser, ...rest] = args; // eslint-disable-line no-unused-vars | ||
|
||
return mutationAnalyticsAsync(analyticsInstance, hook, document, currentUser); | ||
}); | ||
|
||
// return the hook name, used for debug | ||
return hook; | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import Events from './collection.js'; | ||
import { initGoogleAnalytics } from './helpers.js'; | ||
import './callbacks.js'; | ||
|
||
import './client/analytics.js'; | ||
// init google analytics on the client module | ||
initGoogleAnalytics(); | ||
|
||
export default Events; | ||
export default Events; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { getSetting } from 'meteor/nova:core'; | ||
|
||
/* | ||
We provide a special support for Google Analytics. | ||
If you want to enable GA page viewing / tracking, go to | ||
your settings file and update the "public > googleAnalyticsId" | ||
field with your GA unique identifier (UA-xxx...). | ||
*/ | ||
|
||
export const sendGoogleAnalyticsRequest = () => { | ||
if (window && window.ga) { | ||
window.ga('send', 'pageview', { | ||
'page': window.location.pathname | ||
}); | ||
} | ||
}; | ||
|
||
export const initGoogleAnalytics = () => { | ||
|
||
// get the google analytics id from the settings | ||
const googleAnalyticsId = getSetting("googleAnalyticsId"); | ||
|
||
// the google analytics id exists & isn't the placeholder from sample_settings.json | ||
if (googleAnalyticsId && googleAnalyticsId !== "foo123") { | ||
|
||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ | ||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), | ||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) | ||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); | ||
|
||
const cookieDomain = document.domain === "localhost" ? "none" : "auto"; | ||
|
||
window.ga('create', googleAnalyticsId, cookieDomain); | ||
|
||
// trigger first request once analytics are initialized | ||
sendGoogleAnalyticsRequest(); | ||
} | ||
}; | ||
|
||
/* | ||
We provide a special support for Segment, using analytics-node | ||
See https://segment.com/docs/sources/server/node/ | ||
*/ | ||
|
||
export const mutationAnalyticsAsync = (analytics, hook, document, user) => { | ||
|
||
if (hook.includes('users')) { | ||
// if the mutation is related to users, use analytics.identify | ||
// see https://segment.com/docs/sources/server/node/#identify | ||
|
||
// note: on users.new.async, user is undefined | ||
const userId = user ? user._id : document._id; | ||
|
||
const data = { | ||
userId, | ||
traits: document, | ||
}; | ||
|
||
// uncomment for debug | ||
// console.log(`// dispatching identify on "${hook}" (user ${userId})`); | ||
// console.log(data); | ||
|
||
analytics.identify(data); | ||
|
||
} else { | ||
// else use analytics.track | ||
// see https://segment.com/docs/sources/server/node/#track | ||
|
||
const data = { | ||
userId: user._id, | ||
event: hook, | ||
properties: document, | ||
}; | ||
|
||
// uncomment for debug | ||
// console.log(`// dispatching track on "${hook}"`); | ||
// console.log(data); | ||
|
||
analytics.track(data); | ||
} | ||
} |
Oops, something went wrong.