diff --git a/.babelrc b/.babelrc index 7c7a3c8..660010c 100644 --- a/.babelrc +++ b/.babelrc @@ -4,6 +4,7 @@ "@babel/preset-es2015" ], "plugins": [ - "@babel/plugin-transform-async-to-generator" + "@babel/plugin-transform-async-to-generator", + "@babel/plugin-proposal-object-rest-spread" ] } \ No newline at end of file diff --git a/js/thread.js b/js/thread.js index 7865182..be3a9f8 100644 --- a/js/thread.js +++ b/js/thread.js @@ -69,13 +69,7 @@ return { missing: [], isPermalink: (Reddit.permalink !== undefined && Reddit.permalink !== ""), - to36: function(id){ - return parseInt(id).toString(36); - }, - - to10: function(id){ - return parseInt(id, 36); - }, + addComments: function(json){ diff --git a/package-lock.json b/package-lock.json index 5391967..9ed4427 100644 --- a/package-lock.json +++ b/package-lock.json @@ -243,12 +243,27 @@ "integrity": "sha512-SiP9hU9L6OAIog8Mywyh5aplF1WjbDa5Z+PMfN3Gld4JnDWqO3HbXHf8Oau298xzpDwpz77dHWV963tUqRzuMA==", "dev": true }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.0.0-beta.37", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0-beta.37.tgz", + "integrity": "sha512-VwS0evYuXYcDdxK66fPPiye1mbktFpE5KXE/nsQiris3jsnRPVzP+7l9Fn/8ZvRmS31WcjJTjziKyNfGaOFGeg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.37" + } + }, "@babel/plugin-syntax-jsx": { "version": "7.0.0-beta.37", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0-beta.37.tgz", "integrity": "sha512-5ZER7tkR6E1V/lUOTLqxrBDm1KWbEsMppdHsvKdtHxY5WXlW1TCtvKwhr9dradrl8HA+9tIekL2k724f6kMw6Q==", "dev": true }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.0.0-beta.37", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0-beta.37.tgz", + "integrity": "sha512-p3jG3QXmtrQ01DS/Dy3MqF2065VR6tnDirVatdx5bLKsHKHf+TPVevwxgAo0nOWx3IFCVjRyrRsWL2Z7n3bqgw==", + "dev": true + }, "@babel/plugin-transform-arrow-functions": { "version": "7.0.0-beta.37", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.37.tgz", @@ -2194,6 +2209,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=", + "dev": true + }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -5361,8 +5382,12 @@ "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" }, "lodash.assign": { "version": "4.2.0", @@ -7386,6 +7411,19 @@ "prop-types": "15.6.0" } }, + "react-redux": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz", + "integrity": "sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw==", + "requires": { + "hoist-non-react-statics": "2.3.1", + "invariant": "2.2.2", + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "prop-types": "15.6.0" + } + }, "react-router": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", @@ -7552,6 +7590,26 @@ } } }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.1.0" + } + }, + "redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=", + "dev": true, + "requires": { + "deep-diff": "0.3.8" + } + }, "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", @@ -8833,6 +8891,11 @@ "whet.extend": "0.9.9" } }, + "symbol-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz", + "integrity": "sha512-dQoid9tqQ+uotGhuTKEY11X4xhyYePVnqGSoSm3OGKh2E8LZ6RPULp1uXTctk33IeERlrRJYoVSBglsL05F5Uw==" + }, "tapable": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", diff --git a/package.json b/package.json index 393d0c0..c98956a 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,15 @@ "@babel/polyfill": "^7.0.0-beta.37", "react": "^16.2.0", "react-dom": "^16.2.0", + "react-redux": "^5.0.6", "react-router-dom": "^4.2.2", + "redux": "^3.7.2", "whatwg-fetch": "^2.0.3" }, "devDependencies": { "@babel/cli": "^7.0.0-beta.37", "@babel/core": "^7.0.0-beta.37", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0-beta.37", "@babel/plugin-transform-async-to-generator": "^7.0.0-beta.37", "@babel/preset-es2015": "^7.0.0-beta.37", "@babel/preset-react": "^7.0.0-beta.37", @@ -47,6 +50,7 @@ "html-loader": "^0.5.4", "html-webpack-plugin": "^2.30.1", "node-sass": "^4.7.2", + "redux-logger": "^3.0.6", "sass-loader": "^6.0.6", "uglifyjs-webpack-plugin": "^1.1.6", "webpack": "^3.10.0", diff --git a/src/js/App.js b/src/js/App.js index e1f4096..5e4df91 100644 --- a/src/js/App.js +++ b/src/js/App.js @@ -9,7 +9,7 @@ import { import Menu from 'components/Menu' import {About, Thread, Subreddit} from 'pages' -export default class App extends React.Component { +class App extends React.Component { constructor(props) { super(props) @@ -26,7 +26,7 @@ export default class App extends React.Component { return ( <> - + @@ -36,4 +36,6 @@ export default class App extends React.Component { ) } -} \ No newline at end of file +} + +export default App \ No newline at end of file diff --git a/src/js/components/Comment.js b/src/js/components/Comment.js new file mode 100644 index 0000000..e69de29 diff --git a/src/js/components/Menu.js b/src/js/components/Menu.js index 1980d4c..c0ab3d6 100644 --- a/src/js/components/Menu.js +++ b/src/js/components/Menu.js @@ -1,8 +1,10 @@ import React from 'react' import {Link} from 'react-router-dom' import StatusBox from 'components/StatusBox' +import { setStatusLoading, setStatusSuccess, setStatusError } from 'state' +import {connect} from 'react-redux' -export default class Menu extends React.Component { +class Menu extends React.Component { render () { return (
@@ -15,9 +17,24 @@ export default class Menu extends React.Component { about - +
) } - -} \ No newline at end of file +} + +const mapStateToProps = (state) => { + return { + status: state.status + } +} + +const mapDispatchToProps = (dispatch) => { + return { + setStatusSuccess: text => dispatch(setStatusSuccess(text)), + setStatusLoading: text => dispatch(setStatusLoading(text)), + setStatusError: text => dispatch(setStatusError(text)), + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Menu) \ No newline at end of file diff --git a/src/js/components/StatusBox.js b/src/js/components/StatusBox.js index f69d5d1..971b5c0 100644 --- a/src/js/components/StatusBox.js +++ b/src/js/components/StatusBox.js @@ -5,9 +5,9 @@ export default class StatusBox extends React.Component { return (
{this.props.text && -

{lol}

} +

{this.props.text}

} {this.props.image && - } + }
) } diff --git a/src/js/index.js b/src/js/index.js index 4297f28..125897f 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -1,10 +1,26 @@ import '../sass/main.sass' import React from 'react' import ReactDOM from 'react-dom' - +import { Provider } from 'react-redux' +import { store } from 'state' import App from './App' ReactDOM.render( - , + + + , document.getElementById("app") -) \ No newline at end of file +) + +// console.log(store.getState()) + +import {setStatusError} from 'state' +// store.subscribe(() => console.log(store.getState())) + + store.dispatch(setStatusError('Hello world')) + store.dispatch(setStatusError('Hi again :)')) + + +// import {json} from 'utils' +// import {test} from 'pushshift' +// test('7q2k2g').then(console.log) \ No newline at end of file diff --git a/src/js/pushshift/index.js b/src/js/pushshift/index.js index e69de29..db13cdd 100644 --- a/src/js/pushshift/index.js +++ b/src/js/pushshift/index.js @@ -0,0 +1,37 @@ +const baseURL = 'https://elastic.pushshift.io' +const submissionURL = baseURL + '/rs/submissions/_search?source=' +const commentURL = baseURL + '/rc/comments/_search?source=' +const commentIDsURL = 'https://api.pushshift.io/reddit/submission/comment_ids/' + +import { json, toBase10, toBase36 } from 'utils' + +export const getCommentIDs = threadID => { + return fetch(commentIDsURL + threadID) + .then(json) + .then(results => { + return results.data + }) +} + +export const test = threadID => { + const elasticQuery = { + query: { + term: { + link_id: toBase10(threadID) + } + }, + size: 10000, + } + + return fetch(commentURL + JSON.stringify(elasticQuery)) + .then(json) + .then(results => { + results.hits.hits.map(result => { + result._source.link_id = toBase36(result._source.link_id ) + result._source.parent_id = toBase36(result._source.parent_id) + result._source.id = toBase36(result._id) + + return result._source + }) + }) +} \ No newline at end of file diff --git a/src/js/reddit/index.js b/src/js/reddit/index.js index 98d89ee..7d9ace2 100644 --- a/src/js/reddit/index.js +++ b/src/js/reddit/index.js @@ -16,7 +16,7 @@ const tokenInit = { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }, method: 'POST', - body: 'grant_type='+encodeURIComponent('https://oauth.reddit.com/grants/installed_client')+'&device_id=DO_NOT_TRACK_THIS_DEVICE' + body: `grant_type=${encodeURIComponent('https://oauth.reddit.com/grants/installed_client')}&device_id=DO_NOT_TRACK_THIS_DEVICE` } const fetchToken = () => { @@ -32,30 +32,27 @@ const fetchToken = () => { }) } -export default { - comments(subreddit, threadID) { - return fetchToken() - } -} +export const getComments = (subreddit, threadID) => { + return fetchToken() + .then(() => { + return Promise.all([ + fetch(URLs.thread, Reddit.init) + .then(Fetch2.json) + .then(ThreadHTML.createThread) + .catch(function(error) { + return Promise.reject("Could not get thread from Reddit"); + }), -// Reddit.fetchToken() -// .then(function(){ -// return Promise.all([ -// fetch(URLs.thread, Reddit.init) -// .then(Fetch2.json) -// .then(ThreadHTML.createThread) -// .catch(function(error) { -// return Promise.reject("Could not get thread from Reddit"); -// }), - -// fetch(URLs.pushshiftIDs) -// .then(Fetch2.json) -// .then(_.property("data")) -// .catch(function(error) { -// return Promise.reject("Could not get removed comment IDs"); -// }), -// ]) -// }) + fetch(URLs.pushshiftIDs) + .then(Fetch2.json) + .then(_.property("data")) + .catch(function(error) { + return Promise.reject("Could not get removed comment IDs"); + }), + ]) + }) +} + // .then(function(results) { // var thread = results[0]; // Comments.allIDs = results[1]; diff --git a/src/js/state/index.js b/src/js/state/index.js new file mode 100644 index 0000000..67b5930 --- /dev/null +++ b/src/js/state/index.js @@ -0,0 +1,13 @@ +import { createStore, combineReducers, applyMiddleware } from 'redux' +import logger from 'redux-logger' + +import { statusReducer } from './status' +export { setStatusLoading, setStatusSuccess, setStatusError } from './status' + +const reducer = combineReducers({ + status: statusReducer +}) + + + +export const store = createStore(reducer, applyMiddleware(logger)) \ No newline at end of file diff --git a/src/js/state/status.js b/src/js/state/status.js new file mode 100644 index 0000000..2de0152 --- /dev/null +++ b/src/js/state/status.js @@ -0,0 +1,54 @@ +const images = { + loading: '/images/loading.gif', + error: '/images/error.png', + success: '/images/done.png' +} + +// Action types +const STATUS_SET_LOADING = 'STATUS_SET_LOADING' +const STATUS_SET_SUCCESS = 'STATUS_SET_SUCCESS' +const STATUS_SET_ERROR = 'STATUS_SET_ERROR' + +// Action creators +export const setStatusLoading = (payload = '') => { + return {type: STATUS_SET_LOADING, payload} +} + +export const setStatusSuccess = (payload = '') => { + return {type: STATUS_SET_SUCCESS, payload} +} + +export const setStatusError = (payload = '') => { + return {type: STATUS_SET_ERROR, payload} +} + +// Init state +const initialStatusState = { + text: null, + image: null +} + +export const statusReducer = (state = initialStatusState, action) => { + switch (action.type) { + case STATUS_SET_SUCCESS: + return { + ...state, + text: action.payload, + image: images.success + } + case STATUS_SET_LOADING: + return { + ...state, + text: action.payload, + image: images.loading + } + case STATUS_SET_ERROR: + return { + ...state, + text: action.payload, + image: images.error + } + default: + return state + } +} \ No newline at end of file diff --git a/src/js/utils.js b/src/js/utils/index.js similarity index 83% rename from src/js/utils.js rename to src/js/utils/index.js index f72a805..cf473a9 100644 --- a/src/js/utils.js +++ b/src/js/utils/index.js @@ -2,23 +2,18 @@ import SnuOwnd from 'libraries/snuownd.js' const markdown = SnuOwnd.getParser() +// Change bases +export const toBase36 = number => parseInt(number).toString(36) +export const toBase10 = numberString => parseInt(numberString, 36) + // Default thumbnails for reddit threads export const redditThumbnails = ['self', 'default', 'image', 'nsfw'] -// Images for the status box in right side of header -export const statusImages = { - loading: '/images/loading.gif', - error: '/images/error.png', - success: '/images/done.png' -} - // JSON parsing for fetch export const json = x => x.json() // Parse comments -export const parse = text => { - return markdown.render(text) -} +export const parse = text => markdown.render(text) // UTC -> "Reddit time format" (e.g. 5 hours ago, just now, etc...) export const prettyDate = createdUTC => { @@ -26,7 +21,7 @@ export const prettyDate = createdUTC => { const secondDiff = currentUTC - createdUTC const dayDiff = Math.floor(secondDiff / 86400) - if(dayDiff < 0) return "" + if(dayDiff < 0) return "" if(dayDiff == 0) { if(secondDiff < 10) return "just now" if(secondDiff < 60) return secondDiff + " seconds ago"