From 60187e6c28b3fccb7ce30d5696c7ed66b25400c4 Mon Sep 17 00:00:00 2001 From: Quincy Larson Date: Wed, 3 May 2017 19:22:05 -0500 Subject: [PATCH] Revert "Add Youtube videos to the map (#13592)" This reverts commit 4a3fcba501fa426a45a88e2fdf41d8588ec24f3b. --- common/app/App.jsx | 12 +- common/app/redux/actions.js | 6 - common/app/redux/entities-reducer.js | 36 +----- common/app/redux/fetch-youtube-saga.js | 83 ------------ common/app/redux/index.js | 4 +- common/app/redux/types.js | 6 - common/app/routes/challenges/redux/actions.js | 1 - common/app/routes/challenges/redux/reducer.js | 6 +- common/app/routes/challenges/redux/types.js | 1 - common/app/routes/challenges/utils.js | 2 +- .../routes/challenges/views/map/Header.jsx | 4 - .../app/routes/challenges/views/map/Map.jsx | 28 ++--- .../views/map/youtube/YoutubeBlock.jsx | 118 ----------------- .../views/map/youtube/YoutubeSuperBlock.jsx | 117 ----------------- .../views/map/youtube/YoutubeVideo.jsx | 62 --------- common/app/routes/index.js | 2 - .../youtube/components/YoutubeVideo.jsx | 92 -------------- common/app/routes/youtube/index.js | 8 -- common/app/routes/youtube/styles/index.js | 8 -- server/boot/randomAPIs.js | 3 - server/boot/react.js | 3 - server/openApi/index.js | 119 ------------------ server/server.js | 4 +- 23 files changed, 14 insertions(+), 711 deletions(-) delete mode 100644 common/app/redux/fetch-youtube-saga.js delete mode 100644 common/app/routes/challenges/views/map/youtube/YoutubeBlock.jsx delete mode 100644 common/app/routes/challenges/views/map/youtube/YoutubeSuperBlock.jsx delete mode 100644 common/app/routes/challenges/views/map/youtube/YoutubeVideo.jsx delete mode 100644 common/app/routes/youtube/components/YoutubeVideo.jsx delete mode 100644 common/app/routes/youtube/index.js delete mode 100644 common/app/routes/youtube/styles/index.js delete mode 100644 server/openApi/index.js diff --git a/common/app/App.jsx b/common/app/App.jsx index fb5e239288..bb488ad925 100644 --- a/common/app/App.jsx +++ b/common/app/App.jsx @@ -6,7 +6,6 @@ import { createSelector } from 'reselect'; import ns from './ns.json'; import { fetchUser, - fetchYoutube, updateAppLang, trackEvent, loadCurrentChallenge, @@ -23,7 +22,6 @@ import { userSelector } from './redux/selectors'; const mapDispatchToProps = { closeDropdown, fetchUser, - fetchYoutube, loadCurrentChallenge, openDropdown, submitChallenge, @@ -37,13 +35,11 @@ const mapStateToProps = createSelector( state => state.app.isSignInAttempted, state => state.app.toast, state => state.challengesApp.toast, - state => state.entities.youtube, ( { user: { username, points, picture } }, isNavDropdownOpen, isSignInAttempted, toast, - youtube ) => ({ username, points, @@ -51,8 +47,7 @@ const mapStateToProps = createSelector( toast, isNavDropdownOpen, showLoading: !isSignInAttempted, - isSignedIn: !!username, - isYoutubeLoaded: Object.keys(youtube).length > 0 + isSignedIn: !!username }) ); @@ -60,10 +55,8 @@ const propTypes = { children: PropTypes.node, closeDropdown: PropTypes.func.isRequired, fetchUser: PropTypes.func, - fetchYoutube: PropTypes.func.isRequired, isNavDropdownOpen: PropTypes.bool, isSignedIn: PropTypes.bool, - isYoutubeLoaded: PropTypes.bool, loadCurrentChallenge: PropTypes.func.isRequired, openDropdown: PropTypes.func.isRequired, params: PropTypes.object, @@ -89,9 +82,6 @@ export class FreeCodeCamp extends React.Component { if (!this.props.isSignedIn) { this.props.fetchUser(); } - if (!this.props.isYoutubeLoaded) { - this.props.fetchYoutube(); - } } renderChallengeComplete() { diff --git a/common/app/redux/actions.js b/common/app/redux/actions.js index df30c432f9..6768f58627 100644 --- a/common/app/redux/actions.js +++ b/common/app/redux/actions.js @@ -145,9 +145,3 @@ export const addThemeToBody = createAction(types.addThemeToBody); export const openDropdown = createAction(types.openDropdown, noop); export const closeDropdown = createAction(types.closeDropdown, noop); - -export const fetchYoutube = createAction(types.fetchYoutube); -export const updateYoutube = createAction(types.updateYoutube); - -export const updateBlock = createAction(types.updateBlock); -export const updateSuperBlock = createAction(types.updateSuperBlock); diff --git a/common/app/redux/entities-reducer.js b/common/app/redux/entities-reducer.js index 8dcbb104c3..9e3df2c6c4 100644 --- a/common/app/redux/entities-reducer.js +++ b/common/app/redux/entities-reducer.js @@ -6,32 +6,9 @@ const initialState = { superBlock: {}, block: {}, challenge: {}, - user: {}, - youtube: {} + user: {} }; -const blocksReducer = handleActions( - { - [types.updateBlock]: (state, { payload }) => ({ - ...state, - block: payload - }), - [types.updateSuperBlock]: (state, { payload }) => ({ - ...state, - superBlock: payload - }) - }, initialState - ); - -const youtubeReducer = handleActions( - { - [types.updateYoutube]: (state, { payload }) => ({ - ...state, - ...payload - }) - }, initialState.youtube - ); - const userReducer = handleActions( { [types.updateUserPoints]: (state, { payload: { username, points } }) => ({ @@ -114,19 +91,8 @@ function metaReducer(state = initialState, action) { export default function entitiesReducer(state, action) { const newState = metaReducer(state, action); const user = userReducer(newState.user, action); - const youtube = youtubeReducer(newState.youtube, action); - const blocks = blocksReducer(newState, action); if (newState.user !== user) { return { ...newState, user }; } - if ( - newState.block !== blocks.block || - newState.superBlock !== blocks.superBlock - ) { - return { ...newState, ...blocks }; - } - if (newState.youtube !== youtube) { - return { ...newState, youtube }; - } return newState; } diff --git a/common/app/redux/fetch-youtube-saga.js b/common/app/redux/fetch-youtube-saga.js deleted file mode 100644 index 84bbce4cdd..0000000000 --- a/common/app/redux/fetch-youtube-saga.js +++ /dev/null @@ -1,83 +0,0 @@ -import { Observable } from 'rx'; - -import { get$ } from '../../utils/ajax-stream'; -import types from './types'; -import { - createErrorObservable, - updateBlock, - updateSuperBlock, - updateYoutube -} from './actions'; -import { - initMap, - updateSuperBlocks -} from '../routes/challenges/redux/actions'; -import { - createMapUi, - searchableChallengeTitles -} from '../routes/challenges/utils'; - -const { fetchYoutube } = types; -export default function fetchYoutubeSaga(action$, getState) { - return action$ - .filter(action => action.type === fetchYoutube) - .flatMap(() => { - const url = '/api/youtube'; - return get$(url) - // allow fetchChallenges to complete - .delay(1000) - .flatMap(result => { - const { youtube } = JSON.parse(result.response); - const store = getState(); - const { entities } = store; - const { block, superBlock } = entities; - const superBlockWithYoutube = { - ...superBlock, - youtube: { - blocks: Object.keys(youtube), - dashedName: 'youtube', - name: 'YouTube', - order: 9, - title: 'YouTube' - } - }; - const youtubeBlocks = Object.keys(youtube) - .map(playlist => youtube[playlist]) - .reduce((accu, current) => { - const videosForPlaylist = Object.keys(current.videos) - .map(video => current.videos[video].dashedName); - return { - ...accu, - [current.dashedName]: { - challenges: videosForPlaylist - } - }; - }, {}); - const blockWithYoutube = { - ...block, - ...youtubeBlocks - }; - const updatedEntities = { - ...entities, - block: blockWithYoutube, - superBlock: superBlockWithYoutube - }; - return Observable.of( - updateBlock(blockWithYoutube), - // update entities.superBlock - updateSuperBlock(superBlockWithYoutube), - // update challengesApp.superblocks - updateSuperBlocks(Object.keys(superBlockWithYoutube)), - updateYoutube(youtube), - initMap( - createMapUi( - updatedEntities, - Object.keys(superBlockWithYoutube), - searchableChallengeTitles(updatedEntities) - ) - ) - ); - }) - .catch(createErrorObservable); - }); -} diff --git a/common/app/redux/index.js b/common/app/redux/index.js index 4cf905e4d6..4f29ce7e0d 100644 --- a/common/app/redux/index.js +++ b/common/app/redux/index.js @@ -1,12 +1,10 @@ import fetchUserSaga from './fetch-user-saga'; import loadCurrentChallengeSaga from './load-current-challenge-saga'; -import fetchYoutubeSaga from './fetch-youtube-saga'; export { default as reducer } from './reducer'; export * as actions from './actions'; export { default as types } from './types'; export const sagas = [ fetchUserSaga, - loadCurrentChallengeSaga, - fetchYoutubeSaga + loadCurrentChallengeSaga ]; diff --git a/common/app/redux/types.js b/common/app/redux/types.js index aeef2b4738..766b695c85 100644 --- a/common/app/redux/types.js +++ b/common/app/redux/types.js @@ -17,12 +17,6 @@ export default createTypes([ 'loadCurrentChallenge', 'updateMyCurrentChallenge', - 'fetchYoutube', - 'updateYoutube', - - 'updateBlock', - 'updateSuperBlock', - 'handleError', // used to hit the server 'hardGoTo', diff --git a/common/app/routes/challenges/redux/actions.js b/common/app/routes/challenges/redux/actions.js index 8f1766dc70..ca411382b3 100644 --- a/common/app/routes/challenges/redux/actions.js +++ b/common/app/routes/challenges/redux/actions.js @@ -26,7 +26,6 @@ export const fetchChallengeCompleted = createAction( (_, challenge) => challenge, entities => ({ entities }) ); -export const updateSuperBlocks = createAction(types.updateSuperBlocks); export const closeChallengeModal = createAction(types.closeChallengeModal); export const resetUi = createAction(types.resetUi); export const updateHint = createAction(types.updateHint); diff --git a/common/app/routes/challenges/redux/reducer.js b/common/app/routes/challenges/redux/reducer.js index fc99eae324..cda99f4fb2 100644 --- a/common/app/routes/challenges/redux/reducer.js +++ b/common/app/routes/challenges/redux/reducer.js @@ -134,11 +134,7 @@ const mainReducer = handleActions( }), [types.fetchChallengesCompleted]: (state, { payload = [] }) => ({ ...state, - superBlocks: [ ...payload ] - }), - [types.updateSuperBlocks]: (state, { payload = [] }) => ({ - ...state, - superBlocks: [ ...payload ] + superBlocks: payload }), // step diff --git a/common/app/routes/challenges/redux/types.js b/common/app/routes/challenges/redux/types.js index 1c5ab7d2dd..d04cd0bb38 100644 --- a/common/app/routes/challenges/redux/types.js +++ b/common/app/routes/challenges/redux/types.js @@ -24,7 +24,6 @@ export default createTypes([ 'unlockUntrustedCode', 'closeChallengeModal', 'updateSuccessMessage', - 'updateSuperBlocks', // map 'updateFilter', diff --git a/common/app/routes/challenges/utils.js b/common/app/routes/challenges/utils.js index 68fb536668..c58dad00a0 100644 --- a/common/app/routes/challenges/utils.js +++ b/common/app/routes/challenges/utils.js @@ -506,7 +506,7 @@ export function applyFilterToMap(tree, filterRegex) { // if leaf (challenge) then test if regex is a match if (!Array.isArray(node.children)) { // does challenge name meet filter criteria? - if (filterRegex.test(node.title) || filterRegex.test(node.name)) { + if (filterRegex.test(node.title)) { // is challenge currently hidden? if (node.isHidden) { // unhide challenge, it matches diff --git a/common/app/routes/challenges/views/map/Header.jsx b/common/app/routes/challenges/views/map/Header.jsx index dde449eeb6..712189bdda 100644 --- a/common/app/routes/challenges/views/map/Header.jsx +++ b/common/app/routes/challenges/views/map/Header.jsx @@ -39,10 +39,6 @@ export class Header extends PureComponent { this.handleClearButton = this.handleClearButton.bind(this); } - componentWillUnmount() { - this.props.clearFilter(); - } - handleKeyDown(e) { if (e.keyCode === ESC) { e.preventDefault(); diff --git a/common/app/routes/challenges/views/map/Map.jsx b/common/app/routes/challenges/views/map/Map.jsx index e18eae07a7..e40701e45c 100644 --- a/common/app/routes/challenges/views/map/Map.jsx +++ b/common/app/routes/challenges/views/map/Map.jsx @@ -7,7 +7,6 @@ import { Col, Row } from 'react-bootstrap'; import MapHeader from './Header.jsx'; import SuperBlock from './Super-Block.jsx'; -import YoutubeSuperBlock from './youtube/YoutubeSuperBlock.jsx'; import { fetchChallenges } from '../../redux/actions'; import { updateTitle } from '../../../../redux/actions'; @@ -23,12 +22,12 @@ const fetchOptions = { }; const propTypes = { fetchChallenges: PropTypes.func.isRequired, - isYoutubeLoaded: PropTypes.bool, params: PropTypes.object, superBlocks: PropTypes.array, updateTitle: PropTypes.func.isRequired }; -class ShowMap extends PureComponent { + +export class ShowMap extends PureComponent { componentWillMount() { // if no params then map is open in drawer // do not update title @@ -44,23 +43,12 @@ class ShowMap extends PureComponent { if (!Array.isArray(superBlocks) || !superBlocks.length) { return
No Super Blocks
; } - return superBlocks.map(dashedName => { - if (dashedName === 'youtube') { - return ( - - ); - } - return ( - - ); - } - ); + return superBlocks.map(dashedName => ( + + )); } render() { diff --git a/common/app/routes/challenges/views/map/youtube/YoutubeBlock.jsx b/common/app/routes/challenges/views/map/youtube/YoutubeBlock.jsx deleted file mode 100644 index b66fd33736..0000000000 --- a/common/app/routes/challenges/views/map/youtube/YoutubeBlock.jsx +++ /dev/null @@ -1,118 +0,0 @@ -import React, { PropTypes } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import FA from 'react-fontawesome'; -import PureComponent from 'react-pure-render/component'; -import { Panel } from 'react-bootstrap'; - -import YoutubeVideo from './YoutubeVideo.jsx'; - -import { toggleThisPanel } from '../../../redux/actions'; -import { - makePanelOpenSelector, - makePanelHiddenSelector -} from '../../../redux/selectors'; - -const mapStateToProps = () => createSelector( - makePanelOpenSelector(), - makePanelHiddenSelector(), - (isOpen, isHidden) => { - return { - isOpen, - isHidden - }; - } -); - -const mapDispatchToProps = { - toggleThisPanel -}; - -const propTypes = { - dashedName: PropTypes.string, - isHidden: PropTypes.bool, - isOpen: PropTypes.bool, - title: PropTypes.string, - toggleThisPanel: PropTypes.func.isRequired, - videos: PropTypes.object -}; - -export class YoutubeBlock extends PureComponent { - constructor(...props) { - super(...props); - this.handleSelect = this.handleSelect.bind(this); - } - - handleSelect(eventKey, e) { - e.preventDefault(); - this.props.toggleThisPanel(eventKey); - } - - renderHeader(isOpen, title) { - return ( -
-

- - - { title } - -

-
- ); - } - - renderVideos(options) { - const { videos, dashedName: block } = options; - const videosArray = Object.keys(videos).map(video => videos[video]); - if (!videosArray.length) { - return (

No videos found for this playlist

); - } - return videosArray - .map((video, i) => ( - - )); - } - - render() { - const { - dashedName, - isOpen, - isHidden, - title, - videos - } = this.props; - if (isHidden) { - return null; - } - return ( - - { this.renderVideos({ videos, dashedName }) } - - ); - } -} - -YoutubeBlock.displayName = 'YoutubeBlock'; -YoutubeBlock.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(YoutubeBlock); diff --git a/common/app/routes/challenges/views/map/youtube/YoutubeSuperBlock.jsx b/common/app/routes/challenges/views/map/youtube/YoutubeSuperBlock.jsx deleted file mode 100644 index e2834cf590..0000000000 --- a/common/app/routes/challenges/views/map/youtube/YoutubeSuperBlock.jsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, { PropTypes } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import PureComponent from 'react-pure-render/component'; -import FA from 'react-fontawesome'; -import { Panel } from 'react-bootstrap'; - -import YoutubeBlock from './YoutubeBlock.jsx'; - -import { toggleThisPanel } from '../../../redux/actions'; -import { - makePanelOpenSelector, - makePanelHiddenSelector -} from '../../../redux/selectors'; - -const mapDispatchToProps = { - toggleThisPanel -}; -const mapStateToProps = () => { - const panelOpenSelector = makePanelOpenSelector(); - const panelHiddenSelector = makePanelHiddenSelector(); - return createSelector( - (_, props) => props.dashedName, - state => state.entities.youtube, - panelOpenSelector, - panelHiddenSelector, - (dashedName, youtube, isOpen, isHidden) => ({ - dashedName, - isOpen, - isHidden, - youtube - }) - ); -}; -const propTypes = { - dashedName: PropTypes.string, - isHidden: PropTypes.bool, - isOpen: PropTypes.bool, - toggleThisPanel: PropTypes.func.isRequired, - youtube: PropTypes.object -}; - -export class YoutubeSuperBlock extends PureComponent { - constructor(...props) { - super(...props); - this.handleSelect = this.handleSelect.bind(this); - } - - handleSelect(eventKey, e) { - e.preventDefault(); - this.props.toggleThisPanel(eventKey.slice(0).toLowerCase()); - } - - renderHeader(isOpen, title) { - return ( -

- - { title } -

- ); - } - - renderPlaylists(playlists) { - return Object.keys(playlists).map((playlist) => { - const { dashedName, title, videos } = playlists[playlist]; - return ( - - ); - }); - } - - render() { - const { - isOpen, - isHidden, - youtube - } = this.props; - const title = 'YouTube'; - if (isHidden) { - return null; - } - return ( - -
- { this.renderPlaylists(youtube) } -
-
- ); - } -} - -YoutubeSuperBlock.dsiplayName = 'YoutubeSuperBlock'; -YoutubeSuperBlock.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(YoutubeSuperBlock); diff --git a/common/app/routes/challenges/views/map/youtube/YoutubeVideo.jsx b/common/app/routes/challenges/views/map/youtube/YoutubeVideo.jsx deleted file mode 100644 index c1211f3513..0000000000 --- a/common/app/routes/challenges/views/map/youtube/YoutubeVideo.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { PropTypes } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { Link } from 'react-router'; -import PureComponent from 'react-pure-render/component'; -import classnames from 'classnames'; - -import { makePanelHiddenSelector } from '../../../redux/selectors'; - -const mapDispatchToProps = {}; - -const mapStateToProps = () => createSelector( - makePanelHiddenSelector(), - ( isHidden ) => ({ isHidden }) -); - -const propTypes = { - block: PropTypes.string, - dashedName: PropTypes.string, - isHidden: PropTypes.bool, - title: PropTypes.string -}; - -export class YoutubeVideo extends PureComponent { - render() { - const { - block: playlist, - dashedName: video, - isHidden, - title - } = this.props; - const challengeClassName = classnames({ - 'text-primary': true, - 'padded-ionic-icon': true, - 'negative-15': true, - 'challenge-title': true - }); - if (isHidden) { - return null; - } - return ( -

- - - { title } - - -

- ); - } -} - -YoutubeVideo.displayName = 'YoutubeVideo'; -YoutubeVideo.propTypes = propTypes; - -export default connect( - mapStateToProps, - mapDispatchToProps -)(YoutubeVideo); diff --git a/common/app/routes/index.js b/common/app/routes/index.js index 80c31574d0..c006b3b21e 100644 --- a/common/app/routes/index.js +++ b/common/app/routes/index.js @@ -6,7 +6,6 @@ import { import NotFound from '../components/NotFound/index.jsx'; import { addLang } from '../utils/lang'; import settingsRoute from './settings'; -import youtubeRoute from './youtube'; export default function createChildRoute(deps) { return { @@ -23,7 +22,6 @@ export default function createChildRoute(deps) { modernChallengesRoute(deps), mapRoute(deps), settingsRoute(deps), - youtubeRoute(deps), { path: '*', component: NotFound diff --git a/common/app/routes/youtube/components/YoutubeVideo.jsx b/common/app/routes/youtube/components/YoutubeVideo.jsx deleted file mode 100644 index 93519abe72..0000000000 --- a/common/app/routes/youtube/components/YoutubeVideo.jsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { PropTypes } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import PureComponent from 'react-pure-render/component'; -import { Col } from 'react-bootstrap'; -import YouTube from 'react-youtube'; - -import { updateTitle } from '../../../redux/actions'; - -import * as styles from '../styles'; - -const mapActionsToDispatch = { - updateTitle -}; -const mapStateToProps = createSelector( - (_, props) => props.params.playlist, - (_, props) => props.params.video, - state => state.entities.youtube, - (selectedPlaylist, selectedVideo, youtube = {}) => { - const playlist = youtube[selectedPlaylist]; - return { - playlist, - video: playlist.videos[selectedVideo] - }; - } -); - -const propTypes = { - playlist: PropTypes.object, - updateTitle: PropTypes.func.isRequired, - video: PropTypes.object -}; - -class YoutubeVideo extends PureComponent { - componentWillMount() { - const { updateTitle, playlist, video } = this.props; - const title = playlist.title && video.title ? - `${playlist.title} - ${video.title}` : - 'freeCodeCamp on YouTube'; - updateTitle(title); - } - componentWillReceiveProps(nextProps) { - const { updateTitle, playlist, video } = nextProps; - if (this.props.video !== video) { - updateTitle(`${playlist.title} - ${video.title}`); - } - } - - render() { - const { - playlist: { title: playlistTitle }, - video: { - description, - title: videoTitle, - videoId - } - } = this.props; - const { - descriptionContainer, - descriptionText - } = styles; - const options = { - width: '100%', - playerVars: { autoplay: 1 } - }; - return ( -
- -

- { `${playlistTitle} - ${videoTitle}` } -

-
- -
-
-

- { description } -

-
- -
- ); - } -} - -YoutubeVideo.displayName = 'YoutubeVideo'; -YoutubeVideo.propTypes = propTypes; - -export default connect(mapStateToProps, mapActionsToDispatch)(YoutubeVideo); diff --git a/common/app/routes/youtube/index.js b/common/app/routes/youtube/index.js deleted file mode 100644 index efe5a82190..0000000000 --- a/common/app/routes/youtube/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import YoutubeVideo from './components/YoutubeVideo.jsx'; - -export default function youtubeVideoRoute() { - return { - path: 'youtube/:playlist/:video', - component: YoutubeVideo - }; -} diff --git a/common/app/routes/youtube/styles/index.js b/common/app/routes/youtube/styles/index.js deleted file mode 100644 index 1a3fe08bd4..0000000000 --- a/common/app/routes/youtube/styles/index.js +++ /dev/null @@ -1,8 +0,0 @@ -export const descriptionContainer = { - display: 'flex', - justifyContent: 'center' -}; - -export const descriptionText = { - width: '90%' -}; diff --git a/server/boot/randomAPIs.js b/server/boot/randomAPIs.js index e7a92d8737..c874a98a50 100644 --- a/server/boot/randomAPIs.js +++ b/server/boot/randomAPIs.js @@ -1,8 +1,6 @@ import request from 'request'; - import constantStrings from '../utils/constantStrings.json'; import testimonials from '../resources/testimonials.json'; -import { serveYoutubeApiResponse } from '../openApi'; const githubClient = process.env.GITHUB_ID; const githubSecret = process.env.GITHUB_SECRET; @@ -12,7 +10,6 @@ module.exports = function(app) { const User = app.models.User; const noLangRouter = app.loopback.Router(); noLangRouter.get('/api/github', githubCalls); - noLangRouter.get('/api/youtube', serveYoutubeApiResponse); noLangRouter.get('/chat', chat); noLangRouter.get('/twitch', twitch); noLangRouter.get('/unsubscribe/:email', unsubscribeAll); diff --git a/server/boot/react.js b/server/boot/react.js index 619afc49f9..be4e86d8c5 100644 --- a/server/boot/react.js +++ b/server/boot/react.js @@ -30,9 +30,6 @@ export default function reactSubRouter(app) { (req, res) => res.redirect(`/challenges/${req.params.dashedName}`) ); - // youtube data not available on app load, send to the map - router.get(/youtube.*/, (req, res) => res.redirect('/map')); - // These routes are in production routes.forEach((route) => { router.get(route, serveReactApp); diff --git a/server/openApi/index.js b/server/openApi/index.js deleted file mode 100644 index 0765273c3e..0000000000 --- a/server/openApi/index.js +++ /dev/null @@ -1,119 +0,0 @@ -import { Observable } from 'rx'; -import debug from 'debug'; - -import request from 'request'; -import { dasherize } from '../utils'; - -const log = debug('fcc:openApi'); - -let dbTimestamp, cachedYoutubeResponse; - -function apiCall(uri) { - return new Promise((resolve, reject) => { - request(uri, (err, res, body) => { - if (err) { reject(err); } - resolve(body); - }); - }); -} - -function sortByDashedName(a, b) { - if (a.dashedName < b.dashedName) { return -1; } - if (a.dashedName > b.dashedName) { return 1; } - return 0; -} -const source = Observable.timer(200000, 3600000) - .selectMany(() => { - const today = new Date().getDay(); - if (dbTimestamp !== today) { - hydrateCache(); - return Observable.of(log('Updating cache')); - } - return Observable.of(null); - }); - -function hydrateCache() { - log('requesting data from openApi'); - Observable.fromPromise( - apiCall('https://glitter-organisation.gomix.me/api/v1/all') - ) - .subscribe( - result => { - const { - lastUpdated, - youtube: { playlists, videos } - } = JSON.parse(result); - dbTimestamp = lastUpdated; - const youtubeVideos = videos - .map(video => { - const { - snippet: { - title, - description, - playlistId, - resourceId: { videoId } - } - } = video; - - return { - description, - playlistId, - title, - videoId, - dashedName: dasherize(title) - }; - }); - const youtube = playlists - .map(list => { - const { - id, - snippet: { title } - } = list; - return { - id, - title, - dashedName: dasherize(title) - }; - }) - .sort(sortByDashedName) - .reduce((accu, current) => { - const videosForCurrent = youtubeVideos - .filter(video => video.playlistId === current.id) - .sort(sortByDashedName) - .reduce((accu, current) => ({ - ...accu, - [current.dashedName]: { ...current } - }), {}); - return { - ...accu, - [current.dashedName]: { - ...current, - videos: videosForCurrent - } - }; - }, {}); - cachedYoutubeResponse = { youtube }; - log('finished updating cache'); - }, - err => log(err) - ); -} - -export function startSubscription() { - log('Hydrating cache'); - hydrateCache(); - source.subscribe(() => {}); -} - -export function serveYoutubeApiResponse(req, res) { - if (cachedYoutubeResponse) { - res.json(cachedYoutubeResponse); - } else { - res.status(500).json( - { - error: 'Something went wrong at our end, please try again.' - } - ); - } -} - diff --git a/server/server.js b/server/server.js index 5fa9a87208..1f71e292f8 100755 --- a/server/server.js +++ b/server/server.js @@ -9,8 +9,7 @@ var _ = require('lodash'), boot = require('loopback-boot'), expressState = require('express-state'), path = require('path'), - setupPassport = require('./component-passport'), - openApi = require('./openApi'); + setupPassport = require('./component-passport'); // polyfill for webpack bundle splitting const requireProto = Object.getPrototypeOf(require); @@ -50,7 +49,6 @@ setupPassport(app); app.start = _.once(function() { app.listen(app.get('port'), function() { app.emit('started'); - openApi.startSubscription(); console.log( 'freeCodeCamp server listening on port %d in %s', app.get('port'),