Skip to content

Fix 3610 #3981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 11, 2020
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
3 changes: 2 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ workflows:
branches:
only:
- develop
- hot-fix-no-result
- hot-fix-past-challenge-search
# This is alternate dev env for parallel testing
- "build-test":
context : org-global
filters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ exports[`Matches shallow shapshot shapshot 1 1`] = `
"users": Object {},
}
}
domRef={null}
expandTag={null}
expandedTags={Array []}
newChallengeDetails={false}
Expand Down Expand Up @@ -74,6 +75,7 @@ exports[`Matches shallow shapshot shapshot 2 1`] = `
"users": Object {},
}
}
domRef={null}
expandTag={null}
expandedTags={Array []}
newChallengeDetails={false}
Expand Down Expand Up @@ -109,6 +111,7 @@ exports[`Matches shallow shapshot shapshot 3 1`] = `
"users": Object {},
}
}
domRef={null}
expandTag={null}
expandedTags={Array []}
newChallengeDetails={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ exports[`Matches shallow shapshot 1`] = `
loading={false}
newChallengeDetails={false}
openChallengesInNewTabs={false}
searchTimestamp={0}
setFilterState={[MockFunction]}
setSort={[MockFunction]}
sort=""
Expand Down Expand Up @@ -226,6 +227,7 @@ exports[`Matches shallow shapshot 2`] = `
loading={true}
newChallengeDetails={false}
openChallengesInNewTabs={false}
searchTimestamp={0}
setFilterState={[MockFunction]}
setSort={[MockFunction]}
sort=""
Expand Down Expand Up @@ -262,6 +264,7 @@ exports[`Matches shallow shapshot 3`] = `
loading={true}
newChallengeDetails={false}
openChallengesInNewTabs={false}
searchTimestamp={0}
setFilterState={[MockFunction]}
setSort={[MockFunction]}
sort=""
Expand Down
6 changes: 6 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ module.exports = {
* object should be considered outdated, and updated as soon as possible. */
USER_GROUP_MAXAGE: 24 * 60 * 60 * 1000,

/* Maximum time to wait before timeout on searching past challenges (seconds)
* when no result at all.
* Default: 30 seconds.
*/
SEARCH_TIMEOUT: 30 * 1000,

/* Filestack configuration for uploading Submissions
* These are for the development back end */
FILESTACK: {
Expand Down
56 changes: 56 additions & 0 deletions docs/TCX-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

This document describes the Topcoder issue/feature release process using TCX. This is a guide for co-pilots, QA, architects and community members. Co-pilot is the driver of the whole process from opening a ticket to the deployment.

## Code Phase

1. Create a branch from the `master` and name it as `hot-fix-fixtitle` or `feature-featuretitle`
2. Co-pilot will prepare and launch a ticket

a. Add Prize in the issue title [$SOMEAMOUT]

b. Mention PR branch, this branch should be always in sync with master or newly created as mentioned in 1

c. Add this to instruction that all the PR should pass `npm test`

d. Change label to `tcx_OpenForPickup`

e. Tag the community @topcoder-platform/tcxcommunity @topcoder-platform/topcodercompetitors
3. A competitor assings a ticket to self (`tcx_Assigned`), writes the code for the fix
4. Competitor, PR to the branch (submission) and they should change the label to `tcx_ReadyForReview`

## Review Phase

4. Co-pilot will review the code, based on review change the label to

a. `tcx_Feedback` - Feedback should be mentioned in the comments section, this may lead to asking for patch PR

b. `Code Review Passed` and `tcx_FixAccepted`- This goes to QA Deployment Phase

c. `Code Review Failed` - This goes to 1

## QA Deployment Phase

5. Based on the label `Code Review Passed`, co-pilot should request deployment to the architect. Based on whatever testing deployment environment is available to code will be deployed.

6. Once deployed on the environment co-pilot will change the label to `Ready for QA` and will inform the QA team on #community-app slack channel.

7. Based on QA feedback label should be `QA Pass` or `QA Fail`

8. `QA Fail` label will go to **Review Phase** again

9. `QA Pass` label is a candidate for production deployment

10. Co-pilot will create PR to `fix-branch > develop` branch

11. An architect will merge PR and ask for smoke testing to the QA team

12. If smoke testing goes well, co-pilot create PR to `develop > master`

13. It takes around 20 mins for deployment on any deployment.

14. QA team will verify the post-production issue fix.

15. If post-production test passes QA team will change the label to `Prod QA Pass`, Co-pilot will close this ticket

17. If post-production test fails QA team will change the label to `Prod QA Failed`

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function ChallengeCard({
sampleWinnerProfile,
selectChallengeDetailsTab,
userHandle,
domRef,
}) {
const challenge = passedInChallenge;
const {
Expand Down Expand Up @@ -110,7 +111,7 @@ function ChallengeCard({
}

return (
<div styleName="challengeCard">
<div ref={domRef} styleName="challengeCard">
<div styleName="left-panel">
<div styleName="challenge-track">
<TrackAbbreviationTooltip track={challenge.track} subTrack={challenge.subTrack}>
Expand Down Expand Up @@ -200,6 +201,7 @@ ChallengeCard.defaultProps = {
userHandle: '',
expandedTags: [],
expandTag: null,
domRef: null,
};

ChallengeCard.propTypes = {
Expand All @@ -214,6 +216,7 @@ ChallengeCard.propTypes = {
userHandle: PT.string,
expandedTags: PT.arrayOf(PT.number),
expandTag: PT.func,
domRef: PT.func,
};

export default ChallengeCard;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import _ from 'lodash';
import PT from 'prop-types';
import qs from 'qs';
import React from 'react';
import React, { useRef } from 'react';
import { config } from 'topcoder-react-utils';
import Sort from 'utils/challenge-listing/sort';
import { NO_LIVE_CHALLENGES_CONFIG, BUCKETS } from 'utils/challenge-listing/buckets';
import SortingSelectBar from 'components/SortingSelectBar';
Expand Down Expand Up @@ -44,7 +45,15 @@ export default function Bucket({
expandedTags,
expandTag,
activeBucket,
searchTimestamp,
}) {
const refs = useRef([]);
refs.current = [];
const addToRefs = (el) => {
if (el) {
refs.current.push(el);
}
};
const filter = Filter.getFilterFunction(bucket.filter);
const activeSort = sort || bucket.sorts[0];

Expand All @@ -69,7 +78,15 @@ export default function Bucket({
}
}

if (!filteredChallenges.length && !loadMore) {
let noPastResult = false;
// check if no past challenge is found after configurable amount of time has passed
if (activeBucket === BUCKETS.PAST && searchTimestamp > 0
&& !filteredChallenges.length && !refs.current.length) {
const elapsedTime = Date.now() - searchTimestamp;
noPastResult = elapsedTime > config.SEARCH_TIMEOUT;
}

if (noPastResult || (!filteredChallenges.length && !loadMore)) {
if (activeBucket === BUCKETS.ALL) {
return null;
}
Expand All @@ -93,6 +110,7 @@ export default function Bucket({
userHandle={userHandle}
expandedTags={expandedTags}
expandTag={expandTag}
domRef={addToRefs}
/>
));

Expand Down Expand Up @@ -170,6 +188,7 @@ Bucket.defaultProps = {
expandedTags: [],
expandTag: null,
activeBucket: '',
searchTimestamp: 0,
};

Bucket.propTypes = {
Expand All @@ -195,4 +214,5 @@ Bucket.propTypes = {
expandedTags: PT.arrayOf(PT.number),
expandTag: PT.func,
activeBucket: PT.string,
searchTimestamp: PT.number,
};
7 changes: 7 additions & 0 deletions src/shared/components/challenge-listing/Listing/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function Listing({
sorts,
expandedTags,
expandTag,
pastSearchTimestamp,
}) {
const buckets = getBuckets(_.get(auth.user, 'handle'));
const isChallengesAvailable = (bucket) => {
Expand All @@ -59,11 +60,13 @@ function Listing({
let keepPlaceholders = false;
let loading;
let loadMore;
let searchTimestamp;
switch (bucket) {
case BUCKETS.PAST:
keepPlaceholders = keepPastPlaceholders;
loading = loadingPastChallenges;
loadMore = loadMorePast;
searchTimestamp = pastSearchTimestamp;
break;
default:
break;
Expand Down Expand Up @@ -113,6 +116,7 @@ function Listing({
sort={sorts[bucket]}
userHandle={_.get(auth, 'user.handle')}
activeBucket={activeBucket}
searchTimestamp={searchTimestamp}
/>
)
);
Expand Down Expand Up @@ -167,6 +171,7 @@ Listing.defaultProps = {
// onTechTagClicked: _.noop,
// onExpandFilterResult: _.noop,
openChallengesInNewTabs: false,
pastSearchTimestamp: 0,
};

Listing.propTypes = {
Expand Down Expand Up @@ -200,12 +205,14 @@ Listing.propTypes = {
setFilterState: PT.func.isRequired,
setSort: PT.func.isRequired,
sorts: PT.shape().isRequired,
pastSearchTimestamp: PT.number,
};

const mapStateToProps = (state) => {
const cl = state.challengeListing;
return {
allActiveChallengesLoaded: cl.allActiveChallengesLoaded,
pastSearchTimestamp: cl.pastSearchTimestamp,
};
};

Expand Down
8 changes: 8 additions & 0 deletions src/shared/reducers/challenge-listing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,16 @@ function onGetPastChallengesDone(state, { error, payload }) {
keepPastPlaceholders = challenges.filter(ff).length - state.challenges.filter(ff).length < 10;
}

const pastSearchTimestamp = state.pastSearchTimestamp && state.pastSearchTimestamp > 0
? state.pastSearchTimestamp : Date.now();

return {
...state,
allPastChallengesLoaded: loaded.length === 0,
challenges,
keepPastPlaceholders,
loadingPastChallengesUUID: '',
pastSearchTimestamp,
};
}

Expand All @@ -237,6 +241,7 @@ function onSelectCommunity(state, { payload }) {
* challenges). */
allPastChallengesLoaded: false,
lastRequestedPageOfPastChallenges: -1,
pastSearchTimestamp: -1,
};
}

Expand Down Expand Up @@ -273,6 +278,7 @@ function onSetFilter(state, { payload }) {
* the code simple we just reset them each time a filter is modified. */
allPastChallengesLoaded: false,
lastRequestedPageOfPastChallenges: -1,
pastSearchTimestamp: -1,
};
}

Expand Down Expand Up @@ -488,6 +494,8 @@ function create(initialState) {
openChallengesCount: 0,
totalCount: 0,
},

pastSearchTimestamp: -1,
}));
}

Expand Down
4 changes: 2 additions & 2 deletions src/shared/utils/challenge-listing/buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ const BUCKET_DATA = {
export const NO_LIVE_CHALLENGES_CONFIG = {
[BUCKETS.ALL]: 'No Live Challenges found in All Challenges',
[BUCKETS.MY]: 'No challenges found in My Challenges',
[BUCKETS.OPEN_FOR_REGISTRATION]: 'No challenges found in Open for Registration',
[BUCKETS.OPEN_FOR_REGISTRATION]: 'No challenges found in Open for Registration Challenges',
[BUCKETS.ONGOING]: 'No challenges found in Ongoing Challenges',
[BUCKETS.PAST]: 'No challenges found in Past',
[BUCKETS.PAST]: 'No challenges found in Past Challenges',
[BUCKETS.SAVED_FILTER]: 'No challenges found in Saved filter Challenges',
[BUCKETS.UPCOMING]: 'No challenges found in Upcoming Challenges',
};
Expand Down