diff --git a/__tests__/__snapshots__/index.js.snap b/__tests__/__snapshots__/index.js.snap index e3c1ee59..a245f5f1 100644 --- a/__tests__/__snapshots__/index.js.snap +++ b/__tests__/__snapshots__/index.js.snap @@ -74,6 +74,12 @@ Object { "getStatsHistoryDone": [Function], "getStatsHistoryInit": [Function], "getStatsInit": [Function], + "getSubtrackChallengesDone": [Function], + "getSubtrackChallengesInit": [Function], + "getUserMarathonDone": [Function], + "getUserMarathonInit": [Function], + "getUserSrmDone": [Function], + "getUserSrmInit": [Function], }, "profile": Object { "addSkillDone": [Function], @@ -200,6 +206,7 @@ Object { "countReset": [Function], "debug": [Function], "dir": [Function], + "dirxml": [Function], "error": [Function], "group": [Function], "groupCollapsed": [Function], diff --git a/package.json b/package.json index 9f0ec4c7..39d4295b 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "lint:js": "./node_modules/.bin/eslint --ext .js,.jsx .", "test": "npm run lint && npm run jest" }, - "version": "0.4.1", + "version": "0.4.2", "dependencies": { "auth0-js": "^6.8.4", "isomorphic-fetch": "^2.2.1", diff --git a/src/actions/members.js b/src/actions/members.js index ab64ee92..d42543a4 100644 --- a/src/actions/members.js +++ b/src/actions/members.js @@ -3,6 +3,7 @@ * @desc Actions related to members data. */ +import qs from 'qs'; import { createActions } from 'redux-actions'; import { getService } from '../services/members'; import { getService as getUserService } from '../services/user'; @@ -200,6 +201,144 @@ async function getStatsDistributionDone(handle, track, subTrack, uuid, tokenV3) return { data, handle, uuid }; } +/** + * @static + * @desc Create an action that signals beginning of subtrack challenges loading. + * @param {String} handle Member handle. + * @param {String} uuid Operation UUID. + * @return {Action} + */ +async function getSubtrackChallengesInit(handle, uuid) { + return { handle, uuid }; +} + +/** + * @static + * @desc Create an action that loads the member subtrack challenges. + * @param {String} uuid Operation UUID. + * @param {String} handle Member handle. + * @param {String} tokenV3 v3 auth token. + * @param {String} track Main track name. + * @param {String} subTrack Subtrack name. + * @param {Number} start page. + * @param {Number} page size. + * @param {Boolean} whether to refresh. + * @return {Action} + */ +async function getSubtrackChallengesDone( + uuid, handle, tokenV3, track, subTrack, pageNum, pageSize, + refresh, +) { + const filter = { + status: 'completed', + hasUserSubmittedForReview: 'true', + track, + subTrack, + }; + + const params = {}; + params.orderBy = 'submissionEndDate desc'; + params.limit = pageSize; + params.offset = pageNum * pageSize; + + const service = getChallengesService(tokenV3); + return service.getUserChallenges(handle, filter, params) + .then(res => ({ + uuid, + challenges: res.challenges, + refresh, + handle, + })); +} + +/** + * @static + * @desc Create an action that signals beginning of member SRM loading. + * @param {String} handle Member handle. + * @param {String} uuid Operation UUID. + * @return {Action} + */ +async function getUserSRMInit(handle, uuid) { + return { handle, uuid }; +} + +/** + * @static + * @desc Create an action that loads the member SRM. + * @param {String} uuid Operation UUID. + * @param {String} handle Member handle. + * @param {String} tokenV3 v3 auth token. + * @param {Number} start page. + * @param {Number} page size. + * @param {Boolean} whether to refresh. + * @return {Action} + */ +async function getUserSRMDone( + uuid, handle, tokenV3, pageNum, pageSize, + refresh, +) { + const filter = { + status: 'past', + isRatedForSRM: 'true', + }; + + const params = { + filter: qs.stringify(filter, { encode: false }), + limit: pageSize, + offset: pageNum * pageSize, + }; + + const service = getChallengesService(tokenV3); + return service.getUserSrms(handle, params).then(res => ({ + uuid, + srms: res, + refresh, + handle, + })); +} + +/** + * @static + * @desc Create an action that signals beginning of member marathon loading. + * @param {String} handle Member handle. + * @param {String} uuid Operation UUID. + * @return {Action} + */ +async function getUserMarathonInit(handle, uuid) { + return { handle, uuid }; +} + +/** + * @static + * @desc Create an action that loads the member marathon. + * @param {String} uuid Operation UUID. + * @param {String} handle Member handle. + * @param {String} tokenV3 v3 auth token. + * @param {Number} start page. + * @param {Number} page size. + * @param {Boolean} whether to refresh. + * @return {Action} + */ +async function getUserMarathonDone( + uuid, handle, tokenV3, pageNum, pageSize, + refresh, +) { + const filter = { status: 'PAST', isRatedForMM: 'true' }; + const params = {}; + params.orderBy = 'endDate desc'; + params.limit = pageSize; + params.offset = pageNum * pageSize; + + const service = getChallengesService(tokenV3); + return service.getUserMarathonMatches(handle, filter, params) + .then(res => ({ + uuid, + marathons: res, + refresh, + handle, + })); +} + export default createActions({ MEMBERS: { DROP: drop, @@ -216,5 +355,11 @@ export default createActions({ GET_STATS_DISTRIBUTION_DONE: getStatsDistributionDone, GET_ACTIVE_CHALLENGES_INIT: getActiveChallengesInit, GET_ACTIVE_CHALLENGES_DONE: getActiveChallengesDone, + GET_SUBTRACK_CHALLENGES_INIT: getSubtrackChallengesInit, + GET_SUBTRACK_CHALLENGES_DONE: getSubtrackChallengesDone, + GET_USER_SRM_INIT: getUserSRMInit, + GET_USER_SRM_DONE: getUserSRMDone, + GET_USER_MARATHON_INIT: getUserMarathonInit, + GET_USER_MARATHON_DONE: getUserMarathonDone, }, }); diff --git a/src/reducers/members.js b/src/reducers/members.js index 0a297c6b..f4cce8cf 100644 --- a/src/reducers/members.js +++ b/src/reducers/members.js @@ -282,6 +282,150 @@ function onGetActiveChallengesDone(state, { error, payload }) { }; } +/** + * Inits the loading of member subtrack challenges. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetSubtrackChallengesInit(state, { payload }) { + const { handle, uuid } = payload; + return { + ...state, + [handle]: { ...state[handle], loadingSubTrackChallengesUUID: uuid }, + }; +} + +/** + * Finalizes the loading of member subtrack challenges. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetSubtrackChallengesDone(state, { error, payload }) { + if (error) { + logger.error('Failed to get member subtrack challenges', payload); + fireErrorMessage('Failed to get member subtrack challenges', ''); + return state; + } + + const { + uuid, + challenges, + refresh, + handle, + } = payload; + if (uuid !== state[handle].loadingSubTrackChallengesUUID) return state; + + return { + ...state, + [handle]: { + ...state[handle], + subtrackChallenges: (state[handle].subtrackChallenges && !refresh) + ? [...state[handle].subtrackChallenges, ...challenges] + : challenges, + // if current query returns 0 item, mark it completed + subtrackChallengesHasMore: challenges && challenges.length > 0, + loadingSubTrackChallengesUUID: '', + }, + }; +} + +/** + * Inits the loading of member SRMs. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetUserSRMInit(state, { payload }) { + const { handle, uuid } = payload; + return { + ...state, + [handle]: { ...state[handle], loadingSRMUUID: uuid }, + }; +} + +/** + * Finalizes the loading of member SRMs. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetUserSRMDone(state, { error, payload }) { + if (error) { + logger.error('Failed to get member SRMs', payload); + fireErrorMessage('Failed to get member SRMs', ''); + return state; + } + + const { + uuid, + srms, + refresh, + handle, + } = payload; + if (uuid !== state[handle].loadingSRMUUID) return state; + + return { + ...state, + [handle]: { + ...state[handle], + userSRMs: (state[handle].userSRMs && !refresh) ? [...state[handle].userSRMs, ...srms] : srms, + userSRMHasMore: srms && srms.length > 0, // if current query returns 0 item, mark it completed + loadingSRMUUID: '', + }, + }; +} + +/** + * Inits the loading of member marathons. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetUserMarathonInit(state, { payload }) { + const { handle, uuid } = payload; + return { + ...state, + [handle]: { ...state[handle], loadingMarathonUUID: uuid }, + }; +} + +/** + * Finalizes the loading of member marathons. + * @param {Object} state + * @param {Object} action + * @return {Object} New state. + */ +function onGetUserMarathonDone(state, { error, payload }) { + if (error) { + logger.error('Failed to get member marathons', payload); + fireErrorMessage('Failed to get member marathons', ''); + return state; + } + + const { + uuid, + marathons, + refresh, + handle, + } = payload; + if (uuid !== state[handle].loadingMarathonUUID) return state; + + return { + ...state, + [handle]: { + ...state[handle], + userMarathons: (state[handle].userMarathons && !refresh) + ? [...state[handle].userMarathons, ...marathons.challenges] + : marathons.challenges, + // if current query returns 0 item, mark it completed + userMarathonHasMore: marathons && marathons.challenges && marathons.challenges.length > 0, + loadingMarathonUUID: '', + }, + }; +} + /** * Creates a new Members reducer with the specified initial state. * @param {Object} initialState Optional. Initial state. @@ -304,6 +448,12 @@ function create(initialState = {}) { [a.getStatsDistributionDone]: onGetStatsDistributionDone, [a.getActiveChallengesInit]: onGetActiveChallengesInit, [a.getActiveChallengesDone]: onGetActiveChallengesDone, + [a.getSubtrackChallengesInit]: onGetSubtrackChallengesInit, + [a.getSubtrackChallengesDone]: onGetSubtrackChallengesDone, + [a.getUserSrmInit]: onGetUserSRMInit, + [a.getUserSrmDone]: onGetUserSRMDone, + [a.getUserMarathonInit]: onGetUserMarathonInit, + [a.getUserMarathonDone]: onGetUserMarathonDone, }, initialState); }