Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Challenge Listing Part 2 - Filters #50

Merged
merged 1 commit into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module.exports = {
DEBOUNCE_ON_CHANGE_TIME: 150,
},
API: {
V5: 'https://api.topcoder-dev.com/v5',
V3: 'https://api.topcoder-dev.com/v3',
V5: "https://api.topcoder-dev.com/v5",
V3: "https://api.topcoder-dev.com/v3",
},
URL: {
COMMUNITY_APP: 'https://community-app.topcoder-dev.com',
COMMUNITY_APP: "https://community-app.topcoder-dev.com",
}
}
3 changes: 3 additions & 0 deletions config/jest/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const config = require("config");

global.process.env = {...global.process.env, ...config};
6 changes: 4 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ module.exports = {
"^.+\\.(j|t)sx?$": "babel-jest",
},
moduleNameMapper: {
"\\.(css)$": "identity-obj-proxy",
"\\.svg$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|scss)$": "identity-obj-proxy",
"\\.(png|eot|otf|ttf|woff|woff2|svg)$": "<rootDir>/__mocks__/fileMock.js",

},
setupFilesAfterEnv: [
"../node_modules/@testing-library/jest-dom/dist/index.js",
"../config/jest/setup.js",
],
};
629 changes: 366 additions & 263 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.7.6",
"@babel/preset-react": "^7.7.4",
"@babel/runtime": "^7.8.7",
"@testing-library/jest-dom": "^5.5.0",
"@testing-library/react": "^9.4.0",
"@types/jest": "^25.2.1",
Expand Down Expand Up @@ -59,13 +58,16 @@
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/runtime": "^7.13.10",
"@reach/router": "^1.3.4",
"autoprefixer": "^8.6.5",
"express": "^4.17.1",
"joi": "^17.4.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"moment-duration-format": "^2.3.2",
"qs": "^6.10.1",
"rc-tooltip": "^4.2.3",
"react": "^16.12.0",
"react-date-range": "^1.1.3",
"react-dom": "^16.12.0",
Expand Down
67 changes: 51 additions & 16 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
/**
* Main App component
*/
import React, { useState, useEffect, useLayoutEffect } from "react";
import { Router, useNavigate } from "@reach/router";
import React, { useState, useLayoutEffect, useEffect, useRef } from "react";
import { Router, useLocation } from "@reach/router";
import Challenges from "./containers/Challenges";
import Filter from "./containers/Filter";
import Menu from "./components/Menu";
import { disableSidebarForRoute } from "@topcoder/micro-frontends-navbar-app";
import AuthDemo from "./components/AuthDemo";
import NoSidebarDemo from "./components/NoSidebarDemo";
import * as constants from "./constants";
import actions from "./actions";
import * as utils from "./utils";
import store from "./store";
import { initialChallengeFilter } from "./reducers/filter";
import _ from "lodash";

import "./styles/react-date-range/default.scss";
import "./styles/react-date-range/styles.scss";
import "react-date-range/dist/theme/default.css";
import "react-date-range/dist/styles.css";
import "rc-tooltip/assets/bootstrap.css";

import "./styles/main.scss";

const App = () => {
const [selectedMenuItem, setSelectedMenuItem] = useState(null);
const navigateTo = useNavigate();

useLayoutEffect(() => {
disableSidebarForRoute("/earn/*");
}, []);

useEffect(() => {
const path = utils.menu.getMenuItemUrlPath(
constants.NAV_MENU,
selectedMenuItem
);
if (path) {
navigateTo(path);
}
}, [selectedMenuItem]);

const menu = (
<Menu
menu={constants.NAV_MENU}
Expand All @@ -46,6 +39,48 @@ const App = () => {
/>
);

const location = useLocation();

const getChallengesDebounced = useRef(_.debounce((f) => f(), 500));

useEffect(() => {
if (!location.search) {
store.dispatch(actions.challenges.getChallenges(initialChallengeFilter));
return;
}

if (location.pathname === "/earn/find/challenges") {
const params = utils.url.parseUrlQuery(location.search);
const toUpdate = utils.challenge.createChallengeFilter(params);

if (!toUpdate.types) toUpdate.types = [];
if (!toUpdate.tracks) toUpdate.tracks = [];
if (!toUpdate.bucket) toUpdate.bucket = "";

const updatedFilter = { ...initialChallengeFilter, ...toUpdate };
const currentFilter = store.getState().filter.challenge;
const diff = !_.isEqual(updatedFilter, currentFilter);
if (diff) {
store.dispatch(actions.filter.updateFilter(updatedFilter));
}
getChallengesDebounced.current(() =>
store.dispatch(actions.challenges.getChallenges(updatedFilter))
);
}
}, [location]);

useEffect(() => {
const name = utils.menu.getNameByPath(
constants.NAV_MENU,
location.pathname
);
if (name) {
setSelectedMenuItem(name);
} else {
setSelectedMenuItem(null);
}
}, [location]);

return (
<div className="layout">
<aside className="sidebar">
Expand Down
8 changes: 0 additions & 8 deletions src/actions/auth.js

This file was deleted.

86 changes: 44 additions & 42 deletions src/actions/challenges.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ async function doGetChallenges(filter) {
return service.getChallenges(filter);
}

async function getActiveChallenges(filter) {
const activeFilter = {
async function getAllActiveChallenges(filter) {
const allActiveFilter = {
...util.createChallengeCriteria(filter),
...util.createActiveChallengeCriteria(),
...util.createAllActiveChallengeCriteria(),
};
return doGetChallenges(activeFilter);
return doGetChallenges(allActiveFilter);
}

async function getOpenForRegistrationChallenges(filter) {
Expand All @@ -23,66 +23,68 @@ async function getOpenForRegistrationChallenges(filter) {
return doGetChallenges(openForRegistrationFilter);
}

async function getPastChallenges(filter) {
const pastFilter = {
async function getClosedChallenges(filter) {
const closedFilter = {
...util.createChallengeCriteria(filter),
...util.createPastChallengeCriteria(),
...util.createClosedChallengeCriteria(),
};
return doGetChallenges(pastFilter);
return doGetChallenges(closedFilter);
}

function doFilterBySubSommunities(challenges) {
return challenges;
}
function doFilterByPrizeFrom(challenges) {
return challenges;
}
function doFilterByPrizeTo(challenges) {
return challenges;
async function getOpenForRegistrationCount(filter) {
const openForRegistrationCountCriteria = {
...util.createChallengeCriteria(filter),
...util.createOpenForRegistrationCountCriteria(),
};
return doGetChallenges(openForRegistrationCountCriteria);
}

async function getChallenges(filter, change) {
const FILTER_BUCKETS = constants.FILTER_BUCKETS;
async function getChallenges(filter) {
const ALL_ACTIVE_CHALLENGES_BUCKET = constants.FILTER_BUCKETS[0];
const OPEN_FOR_REGISTRATION_BUCKET = constants.FILTER_BUCKETS[1];
const CLOSED_CHALLENGES = constants.FILTER_BUCKETS[2];

let challenges;
let challengesFiltered;
let total;
let filterChange = change;
let openForRegistrationCount;

const getChallengesByBucket = async (f) => {
const promises = [];
switch (f.bucket) {
case FILTER_BUCKETS[0]:
return getActiveChallenges(f);
case FILTER_BUCKETS[1]:
return getOpenForRegistrationChallenges(f);
case FILTER_BUCKETS[2]:
return getPastChallenges(f);
case ALL_ACTIVE_CHALLENGES_BUCKET:
promises.push(getAllActiveChallenges(f));
break;
case OPEN_FOR_REGISTRATION_BUCKET:
promises.push(getOpenForRegistrationChallenges(f));
break;
case CLOSED_CHALLENGES:
promises.push(getClosedChallenges(f));
break;
default:
return [];
return [util.createEmptyResult(), 0];
}
promises.push(getOpenForRegistrationCount(f));
return Promise.all(promises).then((result) => [
result[0],
result[1].meta.total,
]);
};

if (!util.checkRequiredFilterAttributes(filter)) {
return { challenges: [], challengesFiltered: [], total: 0 };
}

if (!filterChange) {
const chs = await getChallengesByBucket(filter);
return { challenges: chs, challengesFiltered: chs, total: chs.meta.total };
}

if (util.shouldFetchChallenges(filterChange)) {
challenges = await getChallengesByBucket(filter);
return {
challenges: [],
challengesFiltered: [],
total: 0,
openForRegistrationCount: 0,
};
}

[challenges, openForRegistrationCount] = await getChallengesByBucket(filter);
challengesFiltered = challenges;
total = challenges.meta.total;
if (util.shouldFilterChallenges(filterChange)) {
challengesFiltered = doFilterBySubSommunities(challengesFiltered);
challengesFiltered = doFilterByPrizeFrom(challengesFiltered);
challengesFiltered = doFilterByPrizeTo(challengesFiltered);
}

return { challenges, challengesFiltered, total };
return { challenges, challengesFiltered, total, openForRegistrationCount };
}

export default createActions({
Expand Down
13 changes: 13 additions & 0 deletions src/actions/filter.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import { createActions } from "redux-actions";
import * as utils from "../utils";

function updateFilter(partialUpdate) {
return partialUpdate;
}

function clearChallengeFilter(defaultFilter) {
return defaultFilter;
}

function updateChallengeQuery(filter) {
const params = utils.challenge.createChallengeParams(filter);
utils.url.updateQuery(params);
return params;
}

export default createActions({
UPDATE_FILTER: updateFilter,
CLEAR_CHALLENGE_FILTER: clearChallengeFilter,
UPDATE_CHALLENGE_QUERY: updateChallengeQuery,
});
2 changes: 2 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import challenges from "./challenges";
import filter from "./filter";
import lookup from "./lookup";
import init from "./initApp";

export default {
challenges,
filter,
lookup,
init,
};
9 changes: 9 additions & 0 deletions src/actions/initApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createActions } from "redux-actions";

function initApp(initialFilter) {
return initialFilter;
}

export default createActions({
INIT_APP: initApp,
});
Loading