+
+
+ {/*
-
-
*/}
+
+
+
+
+ Track
+
+
+
+ switchTrack('Des', on)}
+ />
+
+
+ switchTrack('Dev', on)}
+ />
+
+
+ switchTrack('DS', on)}
+ />
+
+
+ switchTrack('QA', on)}
+ />
+
+
+
+
+
+ { past
+ && (
+
+
+
+ Past Period
+
+
+ {
+ staticRanges.map(range => (
+
+ !r.isSelected({
+ startDate: filterState.endDateStart,
+ endDate: filterState.startDateEnd,
+ }))
+ && (!!filterState.endDateStart || !!filterState.startDateEnd)
+ ) : (
+ range.isSelected({
+ startDate: filterState.endDateStart,
+ endDate: filterState.startDateEnd,
+ })
+ )
+ }
+ onChange={() => {
+ if (range.isCustom) {
+ setFilterState({
+ ..._.clone(filterState),
+ customDate: true,
+ });
+ } else {
+ setFilterState({
+ ..._.clone(filterState),
+ endDateStart: moment(range.startDate).toISOString(),
+ startDateEnd: moment(range.endDate).toISOString(),
+ customDate: false,
+ });
+ }
+ }}
+ />
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
+
+
+ ))
+ }
+
+
+
+ )
+ }
+
+ { past && filterState.customDate
+ && (
+
+
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
+
+ {
+ const d = range.endDate ? moment(range.endDate).toISOString() : null;
+ const s = range.startDate ? moment(range.startDate).toISOString() : null;
+ setFilterState({
+ ..._.clone(filterState),
+ endDateStart: s,
+ startDateEnd: d,
+ });
+ }}
+ range={{
+ startDate: filterState.endDateStart
+ ? moment(filterState.endDateStart).toDate()
+ : null,
+ endDate: filterState.startDateEnd
+ ? moment(filterState.startDateEnd).toDate()
+ : null,
+ }}
+ />
+
+
+ )
+ }
+
+ { !isReviewOpportunitiesBucket
+ && (
+
+
+
+ Challenge Type
+
+
+ {
+ validTypes
+ .map(mapTypes)
+ .map(option => (
+
+ {
+ let { types } = filterState;
+
+ if (e.target.checked) {
+ types = types.concat(option.value);
+ } else {
+ types = types.filter(type => type !== option.value);
+ }
+
+ setFilterState({ ..._.clone(filterState), types });
+ }}
+ />
+
+
+ ))
+ }
+
+
+
+ )
+ }
+
+ {/* Only shown when the Review Opportunity bucket is selected */}
+ { isReviewOpportunitiesBucket
+ ? (
+
+
+
+
+ {
+ Object.entries(REVIEW_OPPORTUNITY_TYPES)
+ .map(([value, label]) => ({ value, label }))
+ .map(option => (
+
+ {
+ let { reviewOpportunityTypes = [] } = filterState;
+
+ if (e.target.checked) {
+ reviewOpportunityTypes = reviewOpportunityTypes
+ .concat(option.value);
+ } else {
+ reviewOpportunityTypes = reviewOpportunityTypes.filter(
+ reviewType => reviewType !== option.value,
+ );
+ }
+
+ setFilterState({ ..._.clone(filterState), reviewOpportunityTypes });
+ }}
+ />
+
+
+ ))
+ }
+
+
+
+ ) : null
+ }
+
+
+
+
@@ -292,108 +540,11 @@ export default function FiltersPanel({
/>
-
-
-
-
- {/* Only shown when the Review Opportunity bucket is selected */}
- { isReviewOpportunitiesBucket
- ? (
-
-
-
- ) : null
- }
- {/* Only shown when the All Challenges bucket is selected */}
- { isAllBucket
- ? (
-
-
-
- ) : null
- }
-
- {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
-
- {
- const d = range.endDate ? moment(range.endDate).toISOString() : null;
- const s = range.startDate ? moment(range.startDate).toISOString() : null;
- setFilterState({
- ..._.clone(filterState),
- endDateStart: s,
- startDateEnd: d,
- });
- }}
- range={{
- startDate: filterState.endDateStart
- ? moment(filterState.endDateStart).toDate()
- : null,
- endDate: filterState.startDateEnd
- ? moment(filterState.startDateEnd).toDate()
- : null,
- }}
- />
-
-
- {/*
- Save filter
- */}
);
@@ -463,8 +605,10 @@ FiltersPanel.propTypes = {
selectCommunity: PT.func.isRequired,
// selectedCommunityId: PT.string.isRequired,
setFilterState: PT.func.isRequired,
- setSearchText: PT.func.isRequired,
- validKeywords: PT.arrayOf(PT.string).isRequired,
+ // validKeywords: PT.arrayOf(PT.string).isRequired,
validTypes: PT.arrayOf(PT.shape()).isRequired,
onClose: PT.func,
+ expanded: PT.bool.isRequired,
+ setExpanded: PT.func.isRequired,
+ past: PT.bool.isRequired,
};
diff --git a/src/shared/components/challenge-listing/Filters/FiltersPanel/style.scss b/src/shared/components/challenge-listing/Filters/FiltersPanel/style.scss
index 8e44349086..60ec9b556c 100644
--- a/src/shared/components/challenge-listing/Filters/FiltersPanel/style.scss
+++ b/src/shared/components/challenge-listing/Filters/FiltersPanel/style.scss
@@ -1,24 +1,5 @@
@import '~styles/mixins';
-$panel-space-7: $base-unit + 2;
-$panel-space-10: $base-unit * 2;
-$panel-space-15: $base-unit * 3;
-$panel-space-20: $base-unit * 4;
-$panel-space-25: $base-unit * 5;
-$panel-space-30: $base-unit * 6;
-$panel-space-50: $base-unit * 10;
-$panel-space-100: $base-unit * 20;
-$panel-space-110: $base-unit * 22;
-$panel-radius-1: $corner-radius / 2;
-$panel-radius-4: $corner-radius * 2;
-
-.button {
- display: flex !important;
- font: 400 12px Arial, sans-serif !important;
- margin-bottom: 15px !important;
- width: 100px !important;
-}
-
.uppercase {
text-transform: uppercase;
}
@@ -27,10 +8,41 @@ $panel-radius-4: $corner-radius * 2;
font-weight: bold;
}
+.filter-btn {
+ @include roboto-bold;
+
+ cursor: pointer;
+ display: none;
+ height: 36px;
+ line-height: 36px;
+ font-size: 14px;
+ color: #737380;
+ padding: 0 15px;
+ background: $tc-white;
+ margin: 12px 0 0;
+ border-radius: 4px;
+
+ .FiltersIcon {
+ margin: 0 10px;
+ position: relative;
+ top: 3px;
+
+ path {
+ fill: #737380;
+ }
+ }
+
+ @include xs-to-md {
+ display: block;
+ }
+}
+
.FiltersPanel {
+ @include roboto-regular;
+
+ font-size: 11px;
+ padding: 24px;
background: white;
- padding: $panel-space-15 $panel-space-20;
- width: 100%;
position: relative;
@include xs-to-md {
@@ -47,10 +59,6 @@ $panel-radius-4: $corner-radius * 2;
overflow-y: scroll;
}
- &.hidden {
- display: none;
- }
-
.header {
display: none;
@@ -85,450 +93,328 @@ $panel-radius-4: $corner-radius * 2;
}
.buttons {
- border-left: 1px solid $tc-gray-20;
- float: right;
- padding-left: $panel-space-20;
- position: absolute;
- right: $panel-space-20;
- top: $panel-space-15;
- bottom: $panel-space-15;
-
- @include xs-to-md {
- float: none;
- display: flex;
- justify-content: center;
- position: relative;
- right: 0;
- top: $panel-space-30;
- width: 100%;
- padding-left: 0;
- border-left: none;
- margin-bottom: $panel-space-100;
- }
+ text-align: center;
button {
- display: block;
- text-transform: none;
- width: $panel-space-100 - 3;
- margin-left: 0;
-
- @include xs-to-md {
- display: inline-block;
- }
+ height: 26px;
+ min-height: 26px;
+ line-height: 26px;
+ padding: 0 14px;
}
}
}
-.filter :global .Select-input input {
- font-size: 15px;
-}
-
-.filter.dates :global .DateInput input {
- @include roboto-regular;
-
- padding: $base-unit;
- height: $panel-space-30;
- margin-bottom: 0;
- font-size: 13px;
- color: $tc-black;
- line-height: $panel-space-15 + 1;
-}
-
-// filter by keywords
-.filter {
- :global {
- .Select-placeholder {
- font-weight: 300;
- font-size: 13px;
- color: $tc-gray-50;
- line-height: $panel-space-30 - 2;
- }
-
- .Select-input {
- height: 28px;
- }
+.filters {
+ .filter-row {
+ display: flex;
+ }
- .Select-control {
- height: $panel-space-30;
- border-radius: $corner-radius;
- }
+ .filter {
+ width: 100%;
+ margin-bottom: 25px;
- .Select-input > input:not([type="checkbox"]) {
- height: $panel-space-30 - 2;
- border: none;
- box-shadow: none;
- background: transparent;
- border-radius: 0;
- transition: none;
- padding-left: 0;
- margin-bottom: 0;
-
- &:focus {
- border: none;
- box-shadow: none;
- background: transparent;
- border-radius: 0;
- transition: none;
- }
- }
+ .label {
+ @include roboto-bold;
- .Select-menu-outer {
- font-weight: 500;
- font-size: 13px;
+ display: block;
+ color: $tc-black;
+ font-size: 11px;
+ line-height: 13px;
+ margin-bottom: 4px;
}
- .Select--multi,
- .Select-value {
- @include roboto-bold;
-
- background: $tc-gray-neutral-dark !important;
- border: none !important;
- font-size: 10px;
- color: $tc-gray-80 !important;
- line-height: $panel-space-10 + 2;
- margin-top: $base-unit - 1;
- border-radius: $corner-radius + 1;
- position: relative;
+ @include xs-to-md {
+ display: flex;
+ align-items: center;
- .Select-value-label {
- padding: $base-unit - 1 $panel-space-25 $base-unit - 1 $panel-space-7;
+ .label {
+ min-width: 108px;
+ align-self: flex-start;
+ line-height: 30px;
}
- .Select-value-icon {
- position: absolute;
- right: 0;
- padding: 0 $panel-space-7;
- font-size: 14px;
- border: none;
- border-radius: 0 $corner-radius + 1 $corner-radius + 1 0;
+ .label + * {
+ flex: 1;
}
- }
- }
- &.track {
- :global {
- .Select-value {
- background: $tc-light-blue !important;
- color: $tc-white !important;
+ &.past-period,
+ &.review-type,
+ &.challenge-type {
+ .checkboxes,
+ .radios {
+ flex-direction: column;
+ }
}
}
- }
-}
-
-// filter by date
-.filter.dates {
- :global {
- .DateRangePickerInput__arrow svg {
- width: $panel-space-15;
- height: $panel-space-15;
- fill: $tc-black;
- }
-
- .DateInput {
- padding: $base-unit - 3;
- line-height: $panel-space-20;
- width: $panel-space-110 + 2;
- .DateInput__display-text,
- .DateInput__display-text--has-input {
- @include roboto-regular;
+ &.track {
+ position: relative;
+ z-index: 4;
- font-size: 13px;
- color: $tc-black;
- line-height: $panel-space-15 + 1;
- padding-left: $panel-space-25;
+ .label {
+ display: block;
}
- .DateInput__display-text {
- position: relative;
+ .switches {
+ display: flex;
+ flex-wrap: wrap;
- &::before {
- content: '';
- background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjEycHgiIGhlaWdodD0iMTJweCIgdmlld0JveD0iMCAwIDE2IDE2Ij48ZyA+PHBhdGggZmlsbD0iI0EzQTNBRCIgZD0iTTE1LDJoLTJWMWMwLTAuNi0wLjQtMS0xLTFoLTFjLTAuNiwwLTEsMC40LTEsMXYxSDZWMWMwLTAuNi0wLjQtMS0xLTFINEMzLjQsMCwzLDAuNCwzLDF2MUgxQzAuNCwyLDAsMi40LDAsM3YxMmMwLDAuNiwwLjQsMSwxLDFoMTRjMC42LDAsMS0wLjQsMS0xVjNDMTYsMi40LDE1LjYsMiwxNSwyeiBNMTQsMTRIMlY3aDEyVjE0eiIvPjwvZz48L3N2Zz4=);
- background-position: 0 0;
- background-repeat: no-repeat;
- width: $panel-space-15 - 1;
- height: $panel-space-15 - 1;
+ .filter-switch-with-label {
display: inline-block;
- position: absolute;
- left: $panel-space-7;
- top: $panel-space-7 - 1;
+ white-space: nowrap;
+ line-height: 30px;
+
+ @include xs-to-md {
+ margin-right: 0 !important;
+ }
+
+ @include sm-to-md {
+ width: 50%;
+
+ > div {
+ display: inline-flex;
+ flex-direction: row-reverse;
+ align-items: baseline;
+
+ > div {
+ margin-left: 0;
+ }
+ }
+ }
+
+ &:not(:last-child) {
+ margin-right: 10px;
+ }
+
+ > div {
+ font-size: 11px;
+
+ > div {
+ width: 23px;
+ height: 13px;
+
+ > div {
+ width: 9px;
+ height: 9px;
+ border-radius: 50%;
+ }
+ }
+ }
}
}
}
- .CalendarMonth table {
- font-weight: 400;
- }
-
- .CalendarMonth__caption {
- margin-bottom: $panel-space-10;
- }
-
- .DayPicker__week-header {
- font-weight: 400;
- }
-
- .DateRangePicker__picker {
- top: $base-unit * 9;
- }
-
- .DateInput--with-caret::before {
- top: $panel-space-30 + 4;
- }
-
- .DateInput--with-caret::after {
- top: $panel-space-30 + 5;
- }
- }
-}
-
-.filters {
- display: inline-block;
- width: 100%;
-
- @include xs-to-md {
- display: block;
- }
-
- .filter-row {
- display: flex;
- flex-direction: row;
- align-items: center;
- flex-wrap: wrap;
- margin-right: $panel-space-100 + 17;
- width: auto;
-
- @include xs-to-md {
- display: block;
- margin-right: 0;
- }
- }
-
- .filter {
- display: flex;
- align-items: center;
-
- &.keywords {
- position: relative;
- z-index: 6;
- width: 100%;
- margin-bottom: $panel-space-15;
- margin-right: $panel-space-15;
- }
-
- label {
- display: inline-block;
- font-size: 13px;
- line-height: $panel-space-15;
- margin-right: $panel-space-15;
- min-width: 96px;
- text-align: right;
-
- &.left-label {
- min-width: 58px;
+ &.past-period {
+ .label {
+ display: block;
}
- @include xs-to-md {
- text-align: left;
+ .radios {
+ display: flex;
+ flex-wrap: wrap;
- &.left-label {
+ .radio {
+ position: relative;
+ display: inline-block;
+ line-height: 30px;
+ margin-right: 24px;
min-width: 96px;
+
+ .radio-label {
+ display: inline-block;
+ padding-left: 24px;
+ white-space: nowrap;
+ line-height: 15px;
+ vertical-align: top;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 15px;
+ height: 15px;
+ border: 1px solid #aaa;
+ border-radius: 50%;
+ box-shadow: 0 1px 2px 0 rgba($tc-black, 0.29);
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ width: 7px;
+ height: 7px;
+ background: white;
+ border-radius: 50%;
+ opacity: 0;
+ }
+ }
+
+ .input-control {
+ display: none;
+
+ &:checked + .radio-label {
+ &::before {
+ background-color: #0681ff;
+ border-color: #0681ff;
+ }
+
+ &::after {
+ opacity: 1;
+ }
+ }
+ }
}
}
}
- :global(.Select) {
- display: inline-block;
- width: 100%;
- margin-bottom: 0;
-
- keywordsFilter {
- @include calc(width, '100% - 56px');
+ &.review-type,
+ &.challenge-type {
+ .label {
+ display: block;
}
- }
-
- &.track {
- position: relative;
- z-index: 4;
- display: flex;
- align-items: center;
-
- @include calc(width, '100% - 395px');
- margin-right: $panel-space-30;
+ .checkboxes {
+ display: flex;
+ flex-wrap: wrap;
- @include xs-to-md {
- width: initial;
+ .checkbox {
+ position: relative;
+ display: inline-block;
+ line-height: 30px;
+ width: 33%;
+
+ .checkbox-label {
+ display: inline-block;
+ padding-left: 24px;
+ white-space: nowrap;
+ line-height: 15px;
+ vertical-align: top;
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 15px;
+ height: 15px;
+ border: 1px solid #aaa;
+ border-radius: 2px;
+ box-shadow: 0 1px 2px 0 rgba($tc-black, 0.29);
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 3px;
+ left: 3px;
+ width: 10px;
+ height: 6px;
+ border-left: 2px solid $tc-white;
+ border-bottom: 2px solid $tc-white;
+ transform: rotate(-45deg);
+ opacity: 0;
+ }
+ }
+
+ .input-control {
+ display: none;
+
+ &:checked + .checkbox-label {
+ &::before {
+ background-color: #0681ff;
+ border-color: #0681ff;
+ }
+
+ &::after {
+ opacity: 1;
+ }
+ }
+ }
+ }
}
}
&.dates {
- position: relative;
- z-index: 1;
- display: inline-block;
- text-align: left;
-
- @include xs-to-md {
- margin-top: 20px;
- }
-
- &.hidetwomonthdatepicker {
- @media screen and (min-width: $screen-md) {
- display: none;
- }
- }
-
- &.hideonemonthdatepicker {
- @media screen and (max-width: $screen-md - 1px) {
- display: none;
+ @include sm-to-md {
+ .label + div {
+ max-width: 240px;
}
}
}
- &.status {
- @include calc(width, '50% - 45px - (12px + 112px) * 2 - 96px');
-
- order: 3; // Show after Date Picker when in lg screen mode
-
- @include xs-to-sm {
- margin-top: $panel-space-15;
- width: 100%;
+ &.filter.community {
+ .active-community {
+ font-size: 12px;
+ font-weight: normal;
}
- :global(.Select) {
- z-index: 3;
+ .registration-status {
+ color: #888894;
+ font-size: 0.7rem;
}
- min-width: 206px;
- margin-right: $panel-space-30;
-
- :global(.Select-value) {
- top: inherit;
- background: $tc-white !important;
- font-weight: 300;
- font-size: 13px;
- color: $tc-gray-50;
- line-height: $panel-space-30 - 2;
+ .community-name {
+ display: flex;
}
- @media screen and (max-width: 1024px) {
- width: 100%;
- margin-top: 15px;
+ .checkmark-icon-container {
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ text-align: center;
+ margin-left: 5px;
+ background: #5dca03;
+ border-radius: 50%;
+
+ svg {
+ width: 10px;
+ height: 10px;
+ }
}
- @media screen and (min-width: 1025px) and (max-width: 1346px) {
- margin-top: 15px;
-
- @include calc(width, '50% - 30px');
+ .community-select-item {
+ display: flex;
+ justify-content: space-between;
}
- }
- }
-}
-
-.inGroup .filter-row {
- .filter.keywords {
- @include calc(width, '50% - 30px');
- @include xs-to-md {
- width: 100%;
- }
+ .learn-more-link {
+ color: $tc-light-blue;
+ margin-left: 5px;
- margin-right: $panel-space-30;
- }
-
- .filter.community {
- @include calc(width, '50% - 30px');
-
- @include xs-to-md {
- width: 100%;
- }
-
- :global(.Select) {
- z-index: 5;
- }
-
- .active-community {
- font-size: 12px;
- font-weight: normal;
- }
-
- .registration-status {
- color: #888894;
- font-size: 0.7rem;
- }
-
- .community-name {
- display: flex;
- }
-
- .checkmark-icon-container {
- width: 16px;
- height: 16px;
- line-height: 16px;
- text-align: center;
- margin-left: 5px;
- background: #5dca03;
- border-radius: 50%;
-
- svg {
- width: 10px;
- height: 10px;
- }
- }
-
- .community-select-item {
- display: flex;
- justify-content: space-between;
- }
-
- .learn-more-link {
- color: $tc-light-blue;
- margin-left: 5px;
-
- &:hover,
- &:visited {
- color: $tc-dark-blue-110;
+ &:hover,
+ &:visited {
+ color: $tc-dark-blue-110;
+ }
}
- }
-
- :global(.Select-value) {
- line-height: 28px;
- top: inherit;
- }
- margin-bottom: $panel-space-15;
- margin-right: $panel-space-30;
- }
-
- .filter.review-type {
- // margin - (.date.input width + .date.text width) * 2 - filters.label width
- @include calc(width, '50% - 45px - (12px + 112px) * 2 - 96px');
-
- order: 3; // Show after Date Picker when in lg screen mode
-
- @include xs-to-sm {
- margin-top: $panel-space-15;
- width: 100%;
- }
+ :global {
+ .Select {
+ display: block;
+ z-index: 5;
+ }
- :global(.Select) {
- z-index: 3;
- }
+ .Select-control {
+ height: 26px;
+ border-radius: 2px;
- :global(.Select-value) {
- line-height: 28px;
- top: inherit;
- }
-
- margin-right: $panel-space-30;
- }
+ &:hover {
+ box-shadow: none;
+ }
+ }
- .filter.track {
- @include calc(width, '50% - 30px');
+ .Select.is-focused > .Select-control {
+ outline: none;
+ box-shadow: none;
+ border-color: #0681ff !important;
+ }
- @include xs-to-md {
- width: 100%;
+ .Select-menu-outer {
+ margin-top: 1px;
+ }
+ }
}
}
}
diff --git a/src/shared/components/challenge-listing/Filters/FiltersSwitch/index.jsx b/src/shared/components/challenge-listing/Filters/FiltersSwitch/index.jsx
deleted file mode 100644
index a367f4dfa4..0000000000
--- a/src/shared/components/challenge-listing/Filters/FiltersSwitch/index.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-/* eslint jsx-a11y/no-static-element-interactions:0 */
-
-/**
- * The switch for hiding/showing the filters panel.
- *
- * It is in the pressed state when the 'active' boolean property is true.
- * When the 'filtersCount' number property evaluates to true it shows this
- * number in a blue bubble, as the number of active filters.
- *
- * When the user clicks this component, it triggers the callback provided via
- * the 'onSwitch' property, passing in the demanded active state as a boolean
- * argument (it will be just a logical NOT of the 'active' property).
- */
-
-import React from 'react';
-import PT from 'prop-types';
-
-import FiltersIcon from './filters-icon.svg';
-import './style.scss';
-
-export default function FiltersSwitch({
- active,
- className: propClassName,
- filtersCount: propFiltersCount,
- onSwitch,
-}) {
- let className = 'FiltersSwitch';
- if (active) className += ' active';
-
- let filtersCount;
- if (propFiltersCount) {
- filtersCount = (
-
- {propFiltersCount}
-
- );
- }
-
- return (
-
(onSwitch ? onSwitch(!active) : null)}
- onKeyPress={() => (onSwitch ? onSwitch(!active) : null)}
- >
-
- Filters
- {filtersCount}
-
- );
-}
-
-FiltersSwitch.defaultProps = {
- active: false,
- filtersCount: 0,
- className: '',
-};
-
-FiltersSwitch.propTypes = {
- active: PT.bool,
- filtersCount: PT.number,
- onSwitch: PT.func.isRequired,
- className: PT.string,
-};
diff --git a/src/shared/components/challenge-listing/Filters/FiltersSwitch/style.scss b/src/shared/components/challenge-listing/Filters/FiltersSwitch/style.scss
deleted file mode 100644
index 45568ed6e2..0000000000
--- a/src/shared/components/challenge-listing/Filters/FiltersSwitch/style.scss
+++ /dev/null
@@ -1,43 +0,0 @@
-@import '~styles/mixins';
-$switch-space-10: $base-unit * 2;
-$switch-space-15: $base-unit * 3;
-$switch-space-100: $base-unit * 20;
-$switch-radius-2: $corner-radius;
-$switch-radius-4: $corner-radius * 2;
-
-.FiltersSwitch {
- background: $tc-white;
- border: 1px solid $tc-gray-30;
- color: $tc-black;
- min-width: $switch-space-100 + 2;
-
- .FiltersIcon {
- margin-right: $switch-space-10;
- position: relative;
- top: $base-unit - 2;
-
- path {
- fill: #5d5d66;
- }
- }
-
- &.active {
- background: $tc-gray-20;
- box-shadow: inset 0 1px 1px 0 rgba(71, 71, 79, 0.38);
- border-radius: $corner-radius;
- }
-
- .filtersCount {
- display: inline-block;
- background: $tc-dark-blue;
- width: $switch-space-15;
- height: $switch-space-15;
- border-radius: 50%;
- margin-left: $base-unit;
- line-height: $switch-space-15;
- font-size: 12px;
- color: $tc-white;
- font-weight: 400;
- text-align: center;
- }
-}
diff --git a/src/shared/components/challenge-listing/Filters/FiltersSwitch/filters-icon.svg b/src/shared/components/challenge-listing/Icons/filters-icon.svg
similarity index 100%
rename from src/shared/components/challenge-listing/Filters/FiltersSwitch/filters-icon.svg
rename to src/shared/components/challenge-listing/Icons/filters-icon.svg
diff --git a/src/shared/components/challenge-listing/Listing/Bucket/index.jsx b/src/shared/components/challenge-listing/Listing/Bucket/index.jsx
index 8946bc722e..f48d1763fa 100644
--- a/src/shared/components/challenge-listing/Listing/Bucket/index.jsx
+++ b/src/shared/components/challenge-listing/Listing/Bucket/index.jsx
@@ -10,9 +10,7 @@ import PT from 'prop-types';
import React, { useRef } from 'react';
// import { config } from 'topcoder-react-utils';
import Sort from 'utils/challenge-listing/sort';
-// import { NO_LIVE_CHALLENGES_CONFIG, BUCKETS, BUCKET_DATA }
-// from 'utils/challenge-listing/buckets';
-import { NO_LIVE_CHALLENGES_CONFIG, BUCKET_DATA } from 'utils/challenge-listing/buckets';
+import { NO_LIVE_CHALLENGES_CONFIG, BUCKETS, BUCKET_DATA } from 'utils/challenge-listing/buckets';
import SortingSelectBar from 'components/SortingSelectBar';
import Waypoint from 'react-waypoint';
// import { challenge as challengeUtils } from 'topcoder-react-lib';
@@ -64,7 +62,7 @@ export default function Bucket({
// const sortedChallenges = activeBucket === 'all' ?
// _.clone(challenges.slice(0, 10)) : _.clone(challenges);
let sortedChallenges;
- if (activeBucket === 'all' && !expanded) {
+ if ((activeBucket === BUCKETS.ALL || activeBucket === BUCKETS.ALL_PAST) && !expanded) {
if (loadMore && challenges.length > 10) {
sortedChallenges = _.clone(challenges);
} else {
@@ -81,7 +79,7 @@ export default function Bucket({
// filter: filterState,
// }, { encodeValuesOnly: true });
- const expandable = activeBucket === 'all';
+ const expandable = activeBucket === BUCKETS.ALL || activeBucket === BUCKETS.ALL_PAST;
// const filteredChallenges = [];
// for (let i = 0; i < sortedChallenges.length; i += 1) {
// if (filter(sortedChallenges[i])) {
diff --git a/src/shared/components/challenge-listing/Listing/ReviewOpportunityBucket/index.jsx b/src/shared/components/challenge-listing/Listing/ReviewOpportunityBucket/index.jsx
index dff18000ea..5da39bea16 100644
--- a/src/shared/components/challenge-listing/Listing/ReviewOpportunityBucket/index.jsx
+++ b/src/shared/components/challenge-listing/Listing/ReviewOpportunityBucket/index.jsx
@@ -97,7 +97,7 @@ export default function ReviewOpportunityBucket({
)
}
{
- loadMore && !loading ? (
+ loadMore && !loading && filterState.reviewOpportunityTypes.length ? (
) : null
}
diff --git a/src/shared/components/challenge-listing/Listing/index.jsx b/src/shared/components/challenge-listing/Listing/index.jsx
index 479684a962..aeaa710327 100644
--- a/src/shared/components/challenge-listing/Listing/index.jsx
+++ b/src/shared/components/challenge-listing/Listing/index.jsx
@@ -23,13 +23,15 @@ function Listing({
auth,
allActiveChallengesLoaded,
allMyChallengesLoaded,
+ allMyPastChallengesLoaded,
allChallengesLoaded,
allOpenForRegistrationChallengesLoaded,
challenges,
openForRegistrationChallenges,
myChallenges,
+ myPastChallenges,
allChallenges,
- // pastChallenges,
+ pastChallenges,
challengeTypes,
// userChallenges,
challengesUrl,
@@ -37,17 +39,19 @@ function Listing({
// extraBucket,
filterState,
keepPastPlaceholders,
- // loadingPastChallenges,
+ loadingPastChallenges,
loadingReviewOpportunities,
loadingMyChallenges,
+ loadingMyPastChallenges,
loadMoreMy,
+ loadMoreMyPast,
loadingAllChallenges,
loadMoreAll,
loadingOpenForRegistrationChallenges,
loadMoreOpenForRegistration,
loadingOnGoingChallenges,
loadMoreOnGoing,
- // loadMorePast,
+ loadMorePast,
loadMoreReviewOpportunities,
newChallengeDetails,
openChallengesInNewTabs,
@@ -87,6 +91,12 @@ function Listing({
let bucketChallenges = [];
let newExpanded = expanded;
switch (bucket) {
+ case BUCKETS.ALL_PAST:
+ bucketChallenges = [].concat(pastChallenges);
+ loading = loadingPastChallenges;
+ loadMore = loadMorePast;
+ newExpanded = newExpanded || (+meta.pastChallengesCount === bucketChallenges.length);
+ break;
// case BUCKETS.PAST:
// keepPlaceholders = keepPastPlaceholders;
// bucketChallenges = [].concat(pastChallenges);
@@ -100,6 +110,12 @@ function Listing({
loadMore = allMyChallengesLoaded ? null : loadMoreMy;
newExpanded = newExpanded || (+meta.myChallengesCount === bucketChallenges.length);
break;
+ case BUCKETS.MY_PAST:
+ bucketChallenges = [].concat(myPastChallenges);
+ loading = loadingMyPastChallenges;
+ loadMore = allMyPastChallengesLoaded ? null : loadMoreMyPast;
+ newExpanded = newExpanded || (+meta.myPastChallengesCount === bucketChallenges.length);
+ break;
case BUCKETS.OPEN_FOR_REGISTRATION:
bucketChallenges = [].concat(openForRegistrationChallenges);
loading = loadingOpenForRegistrationChallenges;
@@ -205,9 +221,11 @@ function Listing({
// );
// }
const loading = loadingMyChallenges
+ || loadingMyPastChallenges
|| loadingOpenForRegistrationChallenges
|| loadingOnGoingChallenges
- || loadingAllChallenges;
+ || loadingAllChallenges
+ || loadingPastChallenges;
const placeholders = [];
if (challenges.length > 0 || (activeBucket === BUCKETS.ALL && allChallenges.length > 0)) {
return (
@@ -244,8 +262,9 @@ Listing.defaultProps = {
challenges: [],
openForRegistrationChallenges: [],
myChallenges: [],
+ myPastChallenges: [],
allChallenges: [],
- // pastChallenges: [],
+ pastChallenges: [],
challengeTypes: [],
communityName: null,
// currentFilterName: '',
@@ -253,9 +272,10 @@ Listing.defaultProps = {
expandedTags: [],
expandTag: null,
// extraBucket: null,
- // loadMorePast: null,
+ loadMorePast: null,
loadMoreReviewOpportunities: null,
loadMoreMy: null,
+ loadMoreMyPast: null,
loadMoreAll: null,
loadMoreOpenForRegistration: null,
loadMoreOnGoing: null,
@@ -280,13 +300,15 @@ Listing.propTypes = {
}).isRequired,
allActiveChallengesLoaded: PT.bool.isRequired,
allMyChallengesLoaded: PT.bool.isRequired,
+ allMyPastChallengesLoaded: PT.bool.isRequired,
allChallengesLoaded: PT.bool.isRequired,
allOpenForRegistrationChallengesLoaded: PT.bool.isRequired,
challenges: PT.arrayOf(PT.shape()),
openForRegistrationChallenges: PT.arrayOf(PT.shape()),
myChallenges: PT.arrayOf(PT.shape()),
+ myPastChallenges: PT.arrayOf(PT.shape()),
allChallenges: PT.arrayOf(PT.shape()),
- // pastChallenges: PT.arrayOf(PT.shape()),
+ pastChallenges: PT.arrayOf(PT.shape()),
challengeTypes: PT.arrayOf(PT.shape()),
challengesUrl: PT.string.isRequired,
communityName: PT.string,
@@ -295,17 +317,19 @@ Listing.propTypes = {
// extraBucket: PT.string,
filterState: PT.shape().isRequired,
keepPastPlaceholders: PT.bool.isRequired,
- // loadingPastChallenges: PT.bool.isRequired,
+ loadingPastChallenges: PT.bool.isRequired,
loadingMyChallenges: PT.bool.isRequired,
+ loadingMyPastChallenges: PT.bool.isRequired,
loadingAllChallenges: PT.bool.isRequired,
loadingOpenForRegistrationChallenges: PT.bool.isRequired,
loadingOnGoingChallenges: PT.bool.isRequired,
loadingReviewOpportunities: PT.bool.isRequired,
loadMoreMy: PT.func,
+ loadMoreMyPast: PT.func,
loadMoreAll: PT.func,
loadMoreOnGoing: PT.func,
loadMoreOpenForRegistration: PT.func,
- // loadMorePast: PT.func,
+ loadMorePast: PT.func,
loadMoreReviewOpportunities: PT.func,
newChallengeDetails: PT.bool.isRequired,
openChallengesInNewTabs: PT.bool,
@@ -330,6 +354,7 @@ const mapStateToProps = (state) => {
// allActiveChallengesLoaded: cl.allActiveChallengesLoaded,
allActiveChallengesLoaded: cl.allActiveChallengesLoaded,
allMyChallengesLoaded: cl.allMyChallengesLoaded,
+ allMyPastChallengesLoaded: cl.allMyPastChallengesLoaded,
allChallengesLoaded: cl.allChallengesLoaded,
allOpenForRegistrationChallengesLoaded: cl.allOpenForRegistrationChallengesLoaded,
// pastSearchTimestamp: cl.pastSearchTimestamp,
diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/index.jsx b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/index.jsx
index 72e09649ec..4807ba85ff 100644
--- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/index.jsx
+++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/index.jsx
@@ -48,6 +48,9 @@ function Bucket({
case BUCKETS.ONGOING:
count = meta.ongoingChallengesCount;
break;
+ case BUCKETS.MY_PAST:
+ count = meta.myPastChallengesCount;
+ break;
default:
}
// }
diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss
index 2f76f10796..c71a328525 100644
--- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss
+++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/Bucket/style.scss
@@ -5,9 +5,9 @@
cursor: default;
font-weight: 600;
- @include xs-to-sm {
- background: $tc-white;
- }
+ // @include xs-to-sm {
+ // background: $tc-white;
+ // }
}
.bucket {
@@ -16,10 +16,10 @@
cursor: pointer;
padding: 0 2 * $base-unit 0 3 * $base-unit;
- @include xs-to-sm {
- font-size: 15px;
- padding: 2px 0;
- }
+ // @include xs-to-sm {
+ // font-size: 15px;
+ // padding: 2px 0;
+ // }
}
.right {
diff --git a/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx b/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx
index 0a971950fe..9d04ac7a03 100644
--- a/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx
+++ b/src/shared/components/challenge-listing/Sidebar/BucketSelector/index.jsx
@@ -33,6 +33,7 @@ export default function BucketSelector({
selectBucket,
// selectSavedFilter,
// setEditSavedFiltersMode,
+ past,
}) {
// let filteredChallenges = challenges.filter(Filter.getFilterFunction(filterState));
@@ -41,7 +42,9 @@ export default function BucketSelector({
// }
const getBucket = (bucket) => {
- const isActive = expanding ? bucket === BUCKETS.ALL : activeBucket === bucket;
+ const isActive = expanding
+ ? bucket === BUCKETS.ALL || bucket === BUCKETS.ALL_PAST
+ : activeBucket === bucket;
return (
// ));
- return (
-
- {getBucket(BUCKETS.ALL)}
- {isAuth ? getBucket(BUCKETS.MY) : null}
- {/* {extraBucket ? getBucket(extraBucket) : null} */}
- {getBucket(BUCKETS.OPEN_FOR_REGISTRATION)}
- {/* DISABLED: Until api receive fix community-app#5073 */}
- {/* {getBucket(BUCKETS.ONGOING)} */}
-
- {getBucket(BUCKETS.REVIEW_OPPORTUNITIES)}
- {/* {getBucket(BUCKETS.PAST)} */}
- {/* NOTE: We do not show upcoming challenges for now, for various reasons,
- * more political than technical ;)
- getBucket(BUCKETS.UPCOMING) */
- }
- {/* {
- savedFilters.length
- ? (
-
-
-
- My filters
-
-
setEditSavedFiltersMode(true)}
- onKeyPress={() => setEditSavedFiltersMode(true)}
- role="button"
- styleName="edit-link"
- tabIndex={0}
- >
- edit
-
+ return (!past
+ ? (
+
+ {getBucket(BUCKETS.ALL)}
+ {isAuth ? getBucket(BUCKETS.MY) : null}
+ {/* {extraBucket ? getBucket(extraBucket) : null} */}
+ {getBucket(BUCKETS.OPEN_FOR_REGISTRATION)}
+ {/* DISABLED: Until api receive fix community-app#5073 */}
+ {/* {getBucket(BUCKETS.ONGOING)} */}
+
+ {getBucket(BUCKETS.REVIEW_OPPORTUNITIES)}
+ {/* {getBucket(BUCKETS.PAST)} */}
+ {/* NOTE: We do not show upcoming challenges for now, for various reasons,
+ * more political than technical ;)
+ getBucket(BUCKETS.UPCOMING) */
+ }
+ {/* {
+ savedFilters.length
+ ? (
+
- {savedFiltersRender}
-
- ) : ''
- } */}
-
- {/* DISABLED: Until feeds.topcoder.com domain fixed community-app#4606 */}
- {/*
-
-
- Get the RSS feed
-
+ ) : ''
+ } */}
+
+ {/* DISABLED: Until feeds.topcoder.com domain fixed community-app#4606 */}
+ {/*
+
+ */}
- */}
-
+ ) : (
+
+ {getBucket(BUCKETS.ALL_PAST)}
+ {isAuth ? getBucket(BUCKETS.MY_PAST) : null}
+
+ )
);
}
@@ -133,6 +143,7 @@ BucketSelector.defaultProps = {
// extraBucket: null,
isAuth: false,
expanding: false,
+ past: false,
};
BucketSelector.propTypes = {
@@ -151,4 +162,5 @@ BucketSelector.propTypes = {
selectBucket: PT.func.isRequired,
// selectSavedFilter: PT.func.isRequired,
// setEditSavedFiltersMode: PT.func.isRequired,
+ past: PT.bool,
};
diff --git a/src/shared/components/challenge-listing/Sidebar/index.jsx b/src/shared/components/challenge-listing/Sidebar/index.jsx
index cfa51585c7..39c30dfd10 100644
--- a/src/shared/components/challenge-listing/Sidebar/index.jsx
+++ b/src/shared/components/challenge-listing/Sidebar/index.jsx
@@ -17,10 +17,11 @@
import React from 'react';
import PT from 'prop-types';
-
+import _ from 'lodash';
+import { BUCKETS } from 'utils/challenge-listing/buckets';
import BucketSelector from './BucketSelector';
// import FiltersEditor from './FiltersEditor';
-import Footer from './Footer';
+// import Footer from './Footer';
import './style.scss';
export default function SideBarFilters({
@@ -38,7 +39,7 @@ export default function SideBarFilters({
// dragState,
// editSavedFiltersMode,
// extraBucket,
- // filterState,
+ filterState,
// hideTcLinksInFooter,
isAuth,
// resetFilterName,
@@ -48,9 +49,83 @@ export default function SideBarFilters({
// setEditSavedFiltersMode,
// updateAllSavedFilters,
// updateSavedFilter,
+ setFilter,
+ past,
+ setPast,
+ previousBucketOfActiveTab,
+ previousBucketOfPastChallengesTab,
+ setPreviousBucketOfActiveTab,
+ setPreviousBucketOfPastChallengesTab,
}) {
+ const onActiveClick = () => {
+ if (!past) {
+ return;
+ }
+ setPreviousBucketOfPastChallengesTab(activeBucket);
+ setFilter({
+ ..._.omit(filterState, 'status'),
+ endDateStart: null,
+ startDateEnd: null,
+ previousStartDate: filterState.endDateStart,
+ previousEndDate: filterState.startDateEnd,
+ });
+ setPast(false);
+ if (previousBucketOfActiveTab) {
+ selectBucket(previousBucketOfActiveTab);
+ } else {
+ selectBucket(BUCKETS.OPEN_FOR_REGISTRATION);
+ }
+ };
+
+ const onPastChallengesClick = () => {
+ if (past) {
+ return;
+ }
+ setPreviousBucketOfActiveTab(activeBucket);
+ setFilter({
+ ..._.omit(filterState, 'previousStartDate', 'previousEndDate'),
+ status: 'Completed',
+ endDateStart: filterState.previousStartDate,
+ startDateEnd: filterState.previousEndDate,
+ });
+ setPast(true);
+ if (previousBucketOfPastChallengesTab) {
+ selectBucket(previousBucketOfPastChallengesTab);
+ } else {
+ selectBucket(BUCKETS.ALL_PAST);
+ }
+ };
+
return (
+
+ - {
+ if (e.key !== 'Enter') {
+ return;
+ }
+ onActiveClick();
+ }}
+ role="presentation"
+ >
+ Active
+
+ - {
+ if (e.key !== 'Enter') {
+ return;
+ }
+ onPastChallengesClick();
+ }}
+ role="presentation"
+ >
+ Past Challenges
+
+
{/* { editSavedFiltersMode ? (
{/* )} */}
-
+ {/*
*/}
);
}
@@ -97,6 +173,10 @@ SideBarFilters.defaultProps = {
// hideTcLinksInFooter: false,
isAuth: false,
expanding: false,
+ previousBucketOfActiveTab: null,
+ previousBucketOfPastChallengesTab: null,
+ setPreviousBucketOfActiveTab: () => {},
+ setPreviousBucketOfPastChallengesTab: () => {},
};
SideBarFilters.propTypes = {
@@ -115,7 +195,7 @@ SideBarFilters.propTypes = {
// dragSavedFilterStart: PT.func.isRequired,
// editSavedFiltersMode: PT.bool.isRequired,
// extraBucket: PT.string,
- // filterState: PT.shape().isRequired,
+ filterState: PT.shape().isRequired,
// hideTcLinksInFooter: PT.bool,
isAuth: PT.bool,
// resetFilterName: PT.func.isRequired,
@@ -125,4 +205,11 @@ SideBarFilters.propTypes = {
// setEditSavedFiltersMode: PT.func.isRequired,
// updateAllSavedFilters: PT.func.isRequired,
// updateSavedFilter: PT.func.isRequired,
+ setFilter: PT.func.isRequired,
+ past: PT.bool.isRequired,
+ setPast: PT.func.isRequired,
+ previousBucketOfActiveTab: PT.string,
+ previousBucketOfPastChallengesTab: PT.string,
+ setPreviousBucketOfActiveTab: PT.func,
+ setPreviousBucketOfPastChallengesTab: PT.func,
};
diff --git a/src/shared/components/challenge-listing/Sidebar/style.scss b/src/shared/components/challenge-listing/Sidebar/style.scss
index 3c2e76d24c..211df578c1 100644
--- a/src/shared/components/challenge-listing/Sidebar/style.scss
+++ b/src/shared/components/challenge-listing/Sidebar/style.scss
@@ -7,6 +7,31 @@
line-height: 30px;
width: 100%;
+ .StatusBar {
+ display: flex;
+ padding: 10px 24px 0;
+ background: #fafafb;
+ border-bottom: 1px solid #d5d5d5;
+ border-radius: 4px 4px 0 0;
+
+ .Status {
+ font-size: 12px;
+ line-height: 30px;
+ color: #151516;
+ border-bottom: 1px solid transparent;
+ cursor: pointer;
+
+ &.active {
+ font-weight: bold;
+ border-bottom-color: #43d7b0;
+ }
+ }
+
+ .Status + .Status {
+ margin-left: 30px;
+ }
+ }
+
.FilterBox {
background: $tc-white;
padding: 2 * $base-unit;
diff --git a/src/shared/components/challenge-listing/index.jsx b/src/shared/components/challenge-listing/index.jsx
index a2a3e9db12..59161b71ee 100644
--- a/src/shared/components/challenge-listing/index.jsx
+++ b/src/shared/components/challenge-listing/index.jsx
@@ -4,11 +4,11 @@
*/
// import _ from 'lodash';
-import ChallengeFilters from 'containers/challenge-listing/FilterPanel';
+import FilterPanel from 'containers/challenge-listing/FilterPanel';
+import ChallengeSearchBar from 'containers/challenge-listing/ChallengeSearchBar';
// import moment from 'moment';
import React from 'react';
import PT from 'prop-types';
-import Sticky from 'react-stickynode';
// import { challenge as challengeUtils } from 'topcoder-react-lib';
import Sidebar from 'containers/challenge-listing/Sidebar';
// import { isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
@@ -31,8 +31,9 @@ export default function ChallengeListing(props) {
challenges,
openForRegistrationChallenges,
myChallenges,
+ myPastChallenges,
allChallenges,
- // pastChallenges,
+ pastChallenges,
// communityFilter,
communityName,
defaultCommunityId,
@@ -40,7 +41,7 @@ export default function ChallengeListing(props) {
// extraBucket,
// filterState,
hideSrm,
- hideTcLinksInFooter,
+ // hideTcLinksInFooter,
keepPastPlaceholders,
// loadingChallenges,
preListingMsg,
@@ -101,8 +102,9 @@ export default function ChallengeListing(props) {
challenges={challenges}
openForRegistrationChallenges={openForRegistrationChallenges}
myChallenges={myChallenges}
+ myPastChallenges={myPastChallenges}
allChallenges={allChallenges}
- // pastChallenges={pastChallenges}
+ pastChallenges={pastChallenges}
challengesUrl={props.challengesUrl}
communityName={props.communityName}
expandedTags={props.expandedTags}
@@ -110,8 +112,9 @@ export default function ChallengeListing(props) {
// extraBucket={extraBucket}
filterState={props.filterState}
keepPastPlaceholders={keepPastPlaceholders}
- // loadingPastChallenges={props.loadingPastChallenges}
+ loadingPastChallenges={props.loadingPastChallenges}
loadingMyChallenges={props.loadingMyChallenges}
+ loadingMyPastChallenges={props.loadingMyPastChallenges}
loadingAllChallenges={props.loadingAllChallenges}
loadingOpenForRegistrationChallenges={props.loadingOpenForRegistrationChallenges}
loadingOnGoingChallenges={props.loadingOnGoingChallenges}
@@ -120,7 +123,7 @@ export default function ChallengeListing(props) {
loadMoreAll={props.loadMoreAll}
loadMoreOpenForRegistration={props.loadMoreOpenForRegistration}
loadMoreOnGoing={props.loadMoreOnGoing}
- // loadMorePast={props.loadMorePast}
+ loadMorePast={props.loadMorePast}
loadMoreReviewOpportunities={props.loadMoreReviewOpportunities}
newChallengeDetails={props.newChallengeDetails}
openChallengesInNewTabs={props.openChallengesInNewTabs}
@@ -145,33 +148,43 @@ export default function ChallengeListing(props) {
return (
-
-
-
+
- {challengeCardContainer}
+
+
-
-
-
+
+
+
+
+
+ {challengeCardContainer}
+
);
@@ -182,12 +195,12 @@ ChallengeListing.defaultProps = {
// communityFilter: null,
communityName: null,
// extraBucket: null,
- hideTcLinksInFooter: false,
+ // hideTcLinksInFooter: false,
loadMoreMy: null,
loadMoreAll: null,
loadMoreOpenForRegistration: null,
loadMoreOnGoing: null,
- // loadMorePast: null,
+ loadMorePast: null,
loadMoreReviewOpportunities: null,
newChallengeDetails: false,
openChallengesInNewTabs: false,
@@ -207,9 +220,10 @@ ChallengeListing.propTypes = {
expanding: PT.bool,
challenges: PT.arrayOf(PT.shape()).isRequired,
openForRegistrationChallenges: PT.arrayOf(PT.shape()).isRequired,
- myChallenges: PT.arrayOf(PT.arrayOf()).isRequired,
- allChallenges: PT.arrayOf(PT.arrayOf()).isRequired,
- // pastChallenges: PT.arrayOf(PT.arrayOf()).isRequired,
+ myChallenges: PT.arrayOf(PT.shape()).isRequired,
+ myPastChallenges: PT.arrayOf(PT.shape()).isRequired,
+ allChallenges: PT.arrayOf(PT.shape()).isRequired,
+ pastChallenges: PT.arrayOf(PT.shape()).isRequired,
challengesUrl: PT.string.isRequired,
// communityFilter: PT.shape(),
communityName: PT.string,
@@ -219,21 +233,22 @@ ChallengeListing.propTypes = {
// extraBucket: PT.string,
filterState: PT.shape().isRequired,
hideSrm: PT.bool.isRequired,
- hideTcLinksInFooter: PT.bool,
+ // hideTcLinksInFooter: PT.bool,
keepPastPlaceholders: PT.bool.isRequired,
// lastUpdateOfActiveChallenges: PT.number.isRequired,
// loadingChallenges: PT.bool.isRequired,
loadingMyChallenges: PT.bool.isRequired,
+ loadingMyPastChallenges: PT.bool.isRequired,
loadingAllChallenges: PT.bool.isRequired,
loadingOpenForRegistrationChallenges: PT.bool.isRequired,
loadingOnGoingChallenges: PT.bool.isRequired,
- // loadingPastChallenges: PT.bool.isRequired,
+ loadingPastChallenges: PT.bool.isRequired,
loadingReviewOpportunities: PT.bool.isRequired,
loadMoreMy: PT.func,
loadMoreAll: PT.func,
loadMoreOpenForRegistration: PT.func,
loadMoreOnGoing: PT.func,
- // loadMorePast: PT.func,
+ loadMorePast: PT.func,
loadMoreReviewOpportunities: PT.func,
newChallengeDetails: PT.bool,
openChallengesInNewTabs: PT.bool,
diff --git a/src/shared/components/challenge-listing/style.scss b/src/shared/components/challenge-listing/style.scss
index 6080cc23bf..85975c3649 100644
--- a/src/shared/components/challenge-listing/style.scss
+++ b/src/shared/components/challenge-listing/style.scss
@@ -1,20 +1,21 @@
@import '~styles/mixins';
+$challenge-space-5: $base-unit;
$challenge-space-10: $base-unit * 2;
$challenge-space-15: $base-unit * 3;
$challenge-space-20: $base-unit * 4;
$challenge-radius-4: $corner-radius * 2;
-.ChallengeCardExamples {
- &.wrapper {
- display: block;
- width: 100%;
- padding: $challenge-space-20;
+// .ChallengeCardExamples {
+// &.wrapper {
+// display: block;
+// width: 100%;
+// padding: $challenge-space-20;
- @include xs-to-sm {
- padding: $challenge-space-10;
- }
- }
-}
+// @include xs-to-sm {
+// padding: $challenge-space-10;
+// }
+// }
+// }
.ChallengeFiltersExample {
background: $tc-gray-neutral-dark;
@@ -30,42 +31,42 @@ $challenge-radius-4: $corner-radius * 2;
}
}
- .challenge-cards-container {
- width: 70%;
- padding: $challenge-space-10;
-
- @include xs-to-md {
- width: 100%;
- padding-top: 0;
- }
- }
-
- .challenges-container.SRMs-container {
- width: 70%;
- padding: $challenge-space-10;
-
- @include xs-to-md {
- width: 100%;
- padding-top: 0;
- }
-
- .title {
- @include roboto-medium;
-
- font-size: 13px;
- color: $tc-gray-80;
- line-height: $base-unit * 4;
- padding: $base-unit * 2 $base-unit * 4;
- background: $tc-gray-neutral-light;
- border-top-left-radius: $corner-radius * 2;
- border-top-right-radius: $corner-radius * 2;
- margin-top: $base-unit * 4;
-
- @include xs-to-md {
- margin-top: $base-unit * 2;
- }
- }
- }
+ // .challenge-cards-container {
+ // width: 70%;
+ // padding: $challenge-space-10;
+
+ // @include xs-to-md {
+ // width: 100%;
+ // padding-top: 0;
+ // }
+ // }
+
+ // .challenges-container.SRMs-container {
+ // width: 70%;
+ // padding: $challenge-space-10;
+
+ // @include xs-to-md {
+ // width: 100%;
+ // padding-top: 0;
+ // }
+
+ // .title {
+ // @include roboto-medium;
+
+ // font-size: 13px;
+ // color: $tc-gray-80;
+ // line-height: $base-unit * 4;
+ // padding: $base-unit * 2 $base-unit * 4;
+ // background: $tc-gray-neutral-light;
+ // border-top-left-radius: $corner-radius * 2;
+ // border-top-right-radius: $corner-radius * 2;
+ // margin-top: $base-unit * 4;
+
+ // @include xs-to-md {
+ // margin-top: $base-unit * 2;
+ // }
+ // }
+ // }
.sidebar-container-mobile {
margin: $challenge-space-20 $challenge-space-10 $challenge-space-10;
@@ -80,12 +81,16 @@ $challenge-radius-4: $corner-radius * 2;
}
.sidebar-container-desktop {
- margin: $challenge-space-20 $challenge-space-10 $challenge-space-10;
+ margin: $challenge-space-20 $challenge-space-5 $challenge-space-10;
width: 30%;
@include xs-to-md {
display: none;
}
+
+ > * + * {
+ margin-top: 12px;
+ }
}
.hidden {
diff --git a/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx b/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx
new file mode 100644
index 0000000000..bfdeeab843
--- /dev/null
+++ b/src/shared/containers/challenge-listing/ChallengeSearchBar.jsx
@@ -0,0 +1,81 @@
+/**
+ * Container for the challenge search bar.
+ */
+
+import actions from 'actions/challenge-listing/filter-panel';
+import challengeListingActions from 'actions/challenge-listing';
+import ChallengeSearchBar from 'components/challenge-listing/Filters/ChallengeSearchBar';
+import PT from 'prop-types';
+import React from 'react';
+import { isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
+import { connect } from 'react-redux';
+import _ from 'lodash';
+
+export class Container extends React.Component {
+ constructor(props) {
+ super(props);
+ this.onSearch = _.debounce(this.onSearch.bind(this), 1000);
+ }
+
+ onSearch(text) {
+ const {
+ setFilterState,
+ filterState,
+ } = this.props;
+
+ setFilterState({ ..._.clone(filterState), name: text });
+ }
+
+ render() {
+ const {
+ activeBucket,
+ searchText,
+ setSearchText,
+ } = this.props;
+
+ const isForReviewOpportunities = isReviewOpportunitiesBucket(activeBucket);
+
+ return (
+
{
+ setSearchText(text);
+ this.onSearch(text);
+ }}
+ placeholder={isForReviewOpportunities ? 'Search Review Opportunities' : 'Search for Challenge'}
+ query={searchText}
+ />
+ );
+ }
+}
+
+Container.defaultProps = {
+ searchText: '',
+};
+
+Container.propTypes = {
+ activeBucket: PT.string.isRequired,
+ filterState: PT.shape().isRequired,
+ setFilterState: PT.func.isRequired,
+ searchText: PT.string,
+ setSearchText: PT.func.isRequired,
+};
+
+function mapDispatchToProps(dispatch) {
+ const a = actions.challengeListing.filterPanel;
+ const cla = challengeListingActions.challengeListing;
+ return {
+ setSearchText: text => dispatch(a.setSearchText(text)),
+ setFilterState: s => dispatch(cla.setFilter(s)),
+ };
+}
+
+function mapStateToProps(state) {
+ const cl = state.challengeListing;
+ return {
+ activeBucket: cl.sidebar.activeBucket,
+ filterState: cl.filter,
+ searchText: state.challengeListing.filterPanel.searchText,
+ };
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(Container);
diff --git a/src/shared/containers/challenge-listing/FilterPanel.jsx b/src/shared/containers/challenge-listing/FilterPanel.jsx
index c83d7d1277..a4f3b0f1ac 100644
--- a/src/shared/containers/challenge-listing/FilterPanel.jsx
+++ b/src/shared/containers/challenge-listing/FilterPanel.jsx
@@ -1,47 +1,31 @@
/**
- * Container for the header filters panel.
+ * Container for the filters panel.
*/
-/* global window */
import actions from 'actions/challenge-listing/filter-panel';
import challengeListingActions from 'actions/challenge-listing';
+import sidebarActions from 'actions/challenge-listing/sidebar';
import communityActions from 'actions/tc-communities';
import shortId from 'shortid';
-import FilterPanel from 'components/challenge-listing/Filters/ChallengeFilters';
+import FilterPanel from 'components/challenge-listing/Filters/FiltersPanel';
import PT from 'prop-types';
import React from 'react';
-// import localStorage from 'localStorage';
-// import sidebarActions from 'actions/challenge-listing/sidebar';
-// import { BUCKETS, isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
-import { isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
+import { BUCKETS, isReviewOpportunitiesBucket } from 'utils/challenge-listing/buckets';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import qs from 'qs';
import _ from 'lodash';
+import { createStaticRanges } from 'utils/challenge-listing/date-range';
-/* The default name for user-saved challenge filters. An integer
- * number will be appended to it, when necessary, to keep filter
- * names unique. */
-// const DEFAULT_SAVED_FILTER_NAME = 'My Filter';
const MIN = 60 * 1000;
-/**
- * Returns a vacant name for the user saved filter.
- * @param {Object} state Redux state.
- * @return {String}
- */
-// function getAvailableFilterName(savedFilters) {
-// let res = DEFAULT_SAVED_FILTER_NAME;
-// let id = 0;
-// savedFilters.forEach((f) => {
-// while (res === f.name) {
-// res = `${DEFAULT_SAVED_FILTER_NAME} ${id += 1}`;
-// }
-// });
-// return res;
-// }
export class Container extends React.Component {
+ constructor(props) {
+ super(props);
+ this.initialDefaultChallengeTypes = false;
+ }
+
componentDidMount() {
const {
getKeywords,
@@ -49,10 +33,12 @@ export class Container extends React.Component {
loadingKeywords,
loadingTypes,
setFilterState,
- filterState,
+ // filterState,
communityList,
getCommunityList,
auth,
+ setPast,
+ setSearchText,
} = this.props;
if (communityList && !communityList.loadingUuid
@@ -62,31 +48,83 @@ export class Container extends React.Component {
if (!loadingTypes) getTypes();
if (!loadingKeywords) getKeywords();
-
const query = qs.parse(window.location.search.slice(1));
- if (!_.isEmpty(query) && !filterState.track) {
+
+ if (query.tracks) {
+ _.forEach(query.tracks, (value, key) => {
+ query.tracks[key] = value === 'true';
+ });
+ }
+
+ if (query.bucket) {
+ if (query.bucket === BUCKETS.ALL_PAST || query.bucket === BUCKETS.MY_PAST) {
+ setPast(true);
+ query.status = 'Completed';
+ }
+
+ if (query.bucket === BUCKETS.REVIEW_OPPORTUNITIES) {
+ this.initialDefaultChallengeTypes = true;
+ }
+
+ if (!(query.bucket === BUCKETS.ALL_PAST || query.bucket === BUCKETS.MY_PAST)) {
+ delete query.endDateStart;
+ delete query.startDateEnd;
+ }
+
+ delete query.bucket;
+ }
+
+ if (query.endDateStart || query.startDateEnd) {
+ let customDate = true;
+ createStaticRanges().forEach((range) => {
+ if (!range.isCustom && range.isSelected({
+ startDate: query.endDateStart,
+ endDate: query.startDateEnd,
+ })) {
+ customDate = false;
+ }
+ });
+ query.customDate = customDate;
+ }
+
+ if (query.types && query.types.length) {
+ this.initialDefaultChallengeTypes = true;
+ }
+
+ if (query.name) {
+ setSearchText(query.name);
+ }
+
+ if (!_.isEmpty(query)) {
setFilterState(query);
}
- // const trackStatus = localStorage.getItem('trackStatus');
- // const filterObj = trackStatus ? JSON.parse(trackStatus) : null;
- // if (filterObj) {
- // setFilterState(filterObj);
- // }
- // }
+ }
+
+ componentDidUpdate() {
+ const {
+ filterState,
+ setFilterState,
+ validTypes,
+ } = this.props;
+
+ if (validTypes.length && !this.initialDefaultChallengeTypes) {
+ this.initialDefaultChallengeTypes = true;
+ setFilterState({
+ ..._.clone(filterState),
+ types: validTypes.map(item => item.abbreviation),
+ });
+ }
}
render() {
const {
activeBucket,
communityFilters,
- // filterState,
- // isSavingFilter,
- // saveFilter,
- // savedFilters,
- // selectBucket,
- // selectedCommunityId,
setFilterState,
- // tokenV2,
+ expanded,
+ setExpanded,
+ hidden,
+ onClose,
} = this.props;
const communityFilters2 = [
{
@@ -103,37 +141,23 @@ export class Container extends React.Component {
{
- // const name = getAvailableFilterName(savedFilters);
- // const filter = {
- // ...filterState,
- // communityId: selectedCommunityId,
- // };
-
- // if (isForReviewOpportunities) filter.isForReviewOpportunities = true;
-
- // saveFilter(name, filter, tokenV2);
- // }}
setFilterState={(state) => {
setFilterState(state);
- // if (activeBucket === BUCKETS.SAVED_FILTER) {
- // selectBucket(BUCKETS.ALL);
- // } else if (activeBucket === BUCKETS.SAVED_REVIEW_OPPORTUNITIES_FILTER) {
- // selectBucket(BUCKETS.REVIEW_OPPORTUNITIES);
- // }
}}
- // isSavingFilter={isSavingFilter}
isReviewOpportunitiesBucket={isForReviewOpportunities}
activeBucket={activeBucket}
+ expanded={expanded}
+ setExpanded={setExpanded}
+ hidden={hidden}
+ onClose={onClose}
/>
);
}
}
Container.defaultProps = {
- // isSavingFilter: false,
tokenV2: '',
- // challenges: [],
+ hidden: false,
};
Container.propTypes = {
@@ -150,25 +174,28 @@ Container.propTypes = {
timestamp: PT.number.isRequired,
}).isRequired,
filterState: PT.shape().isRequired,
- // challenges: PT.arrayOf(PT.shape()),
selectedCommunityId: PT.string.isRequired,
getKeywords: PT.func.isRequired,
getTypes: PT.func.isRequired,
- // isSavingFilter: PT.bool,
- // savedFilters: PT.arrayOf(PT.shape()).isRequired,
loadingKeywords: PT.bool.isRequired,
loadingTypes: PT.bool.isRequired,
- // saveFilter: PT.func.isRequired,
- // selectBucket: PT.func.isRequired,
setFilterState: PT.func.isRequired,
auth: PT.shape().isRequired,
tokenV2: PT.string,
+ expanded: PT.bool.isRequired,
+ setExpanded: PT.func.isRequired,
+ hidden: PT.bool,
+ onClose: PT.func.isRequired,
+ validTypes: PT.arrayOf(PT.shape()).isRequired,
+ past: PT.bool.isRequired,
+ setPast: PT.func.isRequired,
+ setSearchText: PT.func.isRequired,
};
function mapDispatchToProps(dispatch) {
const a = actions.challengeListing.filterPanel;
const cla = challengeListingActions.challengeListing;
- // const sa = sidebarActions.challengeListing.sidebar;
+ const sba = sidebarActions.challengeListing.sidebar;
return {
...bindActionCreators(a, dispatch),
getTypes: () => {
@@ -184,19 +211,17 @@ function mapDispatchToProps(dispatch) {
dispatch(cla.getChallengeTagsInit());
dispatch(cla.getChallengeTagsDone());
},
- // saveFilter: (...rest) => {
- // dispatch(sa.saveFilterInit());
- // dispatch(sa.saveFilterDone(...rest));
- // },
- // selectBucket: bucket => dispatch(sa.selectBucket(bucket)),
selectCommunity: id => dispatch(cla.selectCommunity(id)),
setFilterState: s => dispatch(cla.setFilter(s)),
+ onClose: () => dispatch(a.setExpanded(false)),
+ setPast: isPast => dispatch(sba.setPast(isPast)),
};
}
function mapStateToProps(state, ownProps) {
const cl = state.challengeListing;
const tc = state.tcCommunities;
+ const sb = state.challengeListing.sidebar;
return {
...ownProps,
...state.challengeListing.filterPanel,
@@ -212,8 +237,7 @@ function mapStateToProps(state, ownProps) {
selectedCommunityId: cl.selectedCommunityId,
auth: state.auth,
tokenV2: state.auth.tokenV2,
- // isSavingFilter: cl.sidebar.isSavingFilter,
- // savedFilters: cl.sidebar.savedFilters,
+ past: sb.past,
};
}
diff --git a/src/shared/containers/challenge-listing/Listing/index.jsx b/src/shared/containers/challenge-listing/Listing/index.jsx
index ab8c52a856..a6bbeb5167 100644
--- a/src/shared/containers/challenge-listing/Listing/index.jsx
+++ b/src/shared/containers/challenge-listing/Listing/index.jsx
@@ -12,7 +12,6 @@
import _ from 'lodash';
import actions from 'actions/challenge-listing';
import challengeDetailsActions from 'actions/page/challenge-details';
-import filterPanelActions from 'actions/challenge-listing/filter-panel';
import headerActions from 'actions/topcoder_header';
import { logger, challenge as challengeUtils } from 'topcoder-react-lib';
import React from 'react';
@@ -104,14 +103,16 @@ export class ListingContainer extends React.Component {
sorts,
dropMyChallenges,
getMyChallenges,
+ dropMyPastChallenges,
+ getMyPastChallenges,
dropAllChallenges,
getAllChallenges,
getOpenForRegistrationChallenges,
getActiveChallenges,
dropActiveChallenges,
dropOpenForRegistrationChallenges,
- // dropPastChallenges,
- // getPastChallenges,
+ dropPastChallenges,
+ getPastChallenges,
} = this.props;
const oldUserId = _.get(prevProps, 'auth.user.userId');
const userId = _.get(this.props, 'auth.user.userId');
@@ -147,6 +148,16 @@ export class ListingContainer extends React.Component {
);
break;
}
+ case BUCKETS.MY_PAST: {
+ dropMyPastChallenges();
+ getMyPastChallenges(
+ 0,
+ f.back,
+ auth.tokenV3,
+ f.front,
+ );
+ break;
+ }
case BUCKETS.OPEN_FOR_REGISTRATION: {
dropOpenForRegistrationChallenges();
getOpenForRegistrationChallenges(
@@ -187,6 +198,16 @@ export class ListingContainer extends React.Component {
// );
// break;
// }
+ case BUCKETS.ALL_PAST: {
+ dropPastChallenges();
+ getPastChallenges(
+ 0,
+ f.back,
+ auth.tokenV3,
+ f.front,
+ );
+ break;
+ }
default: {
break;
}
@@ -220,7 +241,8 @@ export class ListingContainer extends React.Component {
sorts,
filter,
} = this.props;
- const filterTemp = _.clone(filter);
+ const filterTemp = _.omit(filter, 'reviewOpportunityTypes', 'customDate',
+ 'previousStartDate', 'previousEndDate');
// let communityFilter = communitiesList.data.find(
// item => item.communityId === selectedCommunityId,
// );
@@ -255,8 +277,9 @@ export class ListingContainer extends React.Component {
// getActiveChallenges,
getOpenForRegistrationChallenges,
getMyChallenges,
+ getMyPastChallenges,
getAllChallenges,
- // getPastChallenges,
+ getPastChallenges,
// lastRequestedPageOfActiveChallenges,
// lastRequestedPageOfOpenForRegistrationChallenges,
// lastRequestedPageOfMyChallenges,
@@ -295,13 +318,19 @@ export class ListingContainer extends React.Component {
auth.tokenV3,
f.front,
);
+ getMyPastChallenges(
+ 0,
+ f.back,
+ auth.tokenV3,
+ f.front,
+ );
}
- // getPastChallenges(
- // 0,
- // f.back,
- // auth.tokenV3,
- // f.front,
- // );
+ getPastChallenges(
+ 0,
+ f.back,
+ auth.tokenV3,
+ f.front,
+ );
getTotalChallengesCount(auth.tokenV3, f.front);
}
@@ -360,8 +389,9 @@ export class ListingContainer extends React.Component {
challenges,
openForRegistrationChallenges,
myChallenges,
+ myPastChallenges,
allChallenges,
- // pastChallenges,
+ pastChallenges,
challengeTypes,
challengesUrl,
challengeTags,
@@ -376,24 +406,27 @@ export class ListingContainer extends React.Component {
groupIds,
getActiveChallenges,
getMyChallenges,
+ getMyPastChallenges,
getAllChallenges,
getOpenForRegistrationChallenges,
- // getPastChallenges,
+ getPastChallenges,
getReviewOpportunities,
hideSrm,
keepPastPlaceholders,
lastRequestedPageOfMyChallenges,
+ lastRequestedPageOfMyPastChallenges,
lastRequestedPageOfAllChallenges,
lastRequestedPageOfActiveChallenges,
lastRequestedPageOfOpenForRegistrationChallenges,
- // lastRequestedPageOfPastChallenges,
+ lastRequestedPageOfPastChallenges,
lastRequestedPageOfReviewOpportunities,
// lastUpdateOfActiveChallenges,
loadingActiveChallengesUUID,
loadingOpenForRegistrationChallengesUUID,
loadingMyChallengesUUID,
+ loadingMyPastChallengesUUID,
loadingAllChallengesUUID,
- // loadingPastChallengesUUID,
+ loadingPastChallengesUUID,
loadingReviewOpportunitiesUUID,
listingOnly,
newChallengeDetails,
@@ -405,10 +438,9 @@ export class ListingContainer extends React.Component {
selectChallengeDetailsTab,
selectedCommunityId,
setFilter,
- setSearchText,
setSort,
sorts,
- hideTcLinksInSidebarFooter,
+ // hideTcLinksInSidebarFooter,
// isBucketSwitching,
// userChallenges,
meta,
@@ -418,28 +450,15 @@ export class ListingContainer extends React.Component {
const isLoggedIn = !_.isEmpty(auth.tokenV3);
- // let loadMorePast;
- // if (!allPastChallengesLoaded) {
- // loadMorePast = () => {
- // const f = this.getBackendFilter();
- // getPastChallenges(
- // 1 + lastRequestedPageOfPastChallenges,
- // f.back,
- // tokenV3,
- // f.front,
- // );
- // };
- // }
-
- // const loadMorePast = () => {
- // const f = this.getBackendFilter();
- // getPastChallenges(
- // 1 + lastRequestedPageOfPastChallenges,
- // f.back,
- // tokenV3,
- // f.front,
- // );
- // };
+ const loadMorePast = () => {
+ const f = this.getBackendFilter();
+ getPastChallenges(
+ 1 + lastRequestedPageOfPastChallenges,
+ f.back,
+ tokenV3,
+ f.front,
+ );
+ };
const loadMoreMy = () => {
const f = this.getBackendFilter();
@@ -451,6 +470,16 @@ export class ListingContainer extends React.Component {
);
};
+ const loadMoreMyPast = () => {
+ const f = this.getBackendFilter();
+ getMyPastChallenges(
+ 1 + lastRequestedPageOfMyPastChallenges,
+ f.back,
+ tokenV3,
+ f.front,
+ );
+ };
+
const loadMoreOpenForRegistration = () => {
const f = this.getBackendFilter();
getOpenForRegistrationChallenges(
@@ -526,8 +555,9 @@ export class ListingContainer extends React.Component {
challenges={challenges}
openForRegistrationChallenges={openForRegistrationChallenges}
myChallenges={myChallenges}
+ myPastChallenges={myPastChallenges}
allChallenges={allChallenges}
- // pastChallenges={pastChallenges}
+ pastChallenges={pastChallenges}
challengeTypes={challengeTypes}
challengeTags={challengeTags}
challengesUrl={challengesUrl}
@@ -540,17 +570,18 @@ export class ListingContainer extends React.Component {
// extraBucket={extraBucket}
filterState={filter}
hideSrm={hideSrm}
- hideTcLinksInFooter={hideTcLinksInSidebarFooter}
+ // hideTcLinksInFooter={hideTcLinksInSidebarFooter}
keepPastPlaceholders={keepPastPlaceholders}
// lastUpdateOfActiveChallenges={lastUpdateOfActiveChallenges}
// eslint-disable-next-line max-len
loadingMyChallenges={Boolean(loadingMyChallengesUUID)}
+ loadingMyPastChallenges={Boolean(loadingMyPastChallengesUUID)}
loadingAllChallenges={Boolean(loadingAllChallengesUUID)}
loadingOpenForRegistrationChallenges={Boolean(loadingOpenForRegistrationChallengesUUID)}
loadingOnGoingChallenges={Boolean(loadingActiveChallengesUUID)}
// eslint-disable-next-line max-len
// loadingChallenges={Boolean(loadingActiveChallengesUUID) && Boolean(loadingOpenForRegistrationChallengesUUID) && Boolean(loadingMyChallengesUUID)}
- // loadingPastChallenges={Boolean(loadingPastChallengesUUID)}
+ loadingPastChallenges={Boolean(loadingPastChallengesUUID)}
loadingReviewOpportunities={Boolean(loadingReviewOpportunitiesUUID)}
newChallengeDetails={newChallengeDetails}
openChallengesInNewTabs={openChallengesInNewTabs}
@@ -559,16 +590,16 @@ export class ListingContainer extends React.Component {
selectBucket={selectBucket}
selectChallengeDetailsTab={selectChallengeDetailsTab}
selectedCommunityId={selectedCommunityId}
- // loadMorePast={loadMorePast}
+ loadMorePast={loadMorePast}
loadMoreReviewOpportunities={loadMoreReviewOpportunities}
loadMoreMy={loadMoreMy}
+ loadMoreMyPast={loadMoreMyPast}
loadMoreAll={loadMoreAll}
loadMoreOpenForRegistration={loadMoreOpenForRegistration}
loadMoreOnGoing={loadMoreOnGoing}
reviewOpportunities={reviewOpportunities}
setFilterState={(state) => {
setFilter(state);
- setSearchText(state.name || '');
// if (activeBucket === BUCKETS.SAVED_FILTER) {
// selectBucket(BUCKETS.OPEN_FOR_REGISTRATION);
// } else if (activeBucket === BUCKETS.SAVED_REVIEW_OPPORTUNITIES_FILTER) {
@@ -592,13 +623,13 @@ export class ListingContainer extends React.Component {
ListingContainer.defaultProps = {
ChallengeListingBanner: null,
challengeTypes: [],
- // pastChallenges: [],
+ pastChallenges: [],
defaultCommunityId: '',
// extraBucket: null,
hideSrm: false,
selectedCommunityId: '',
groupIds: [''],
- hideTcLinksInSidebarFooter: false,
+ // hideTcLinksInSidebarFooter: false,
challengesUrl: '/challenges',
communityId: null,
communityName: null,
@@ -627,8 +658,9 @@ ListingContainer.propTypes = {
challenges: PT.arrayOf(PT.shape({})).isRequired, // active challenges.
openForRegistrationChallenges: PT.arrayOf(PT.shape({})).isRequired,
myChallenges: PT.arrayOf(PT.shape({})).isRequired,
+ myPastChallenges: PT.arrayOf(PT.shape({})).isRequired,
allChallenges: PT.arrayOf(PT.shape({})).isRequired,
- // pastChallenges: PT.arrayOf(PT.shape({})),
+ pastChallenges: PT.arrayOf(PT.shape({})),
challengeTypes: PT.arrayOf(PT.shape()),
challengesUrl: PT.string,
challengeTags: PT.arrayOf(PT.string).isRequired,
@@ -643,13 +675,14 @@ ListingContainer.propTypes = {
defaultCommunityId: PT.string,
dropChallenges: PT.func.isRequired,
dropMyChallenges: PT.func.isRequired,
+ dropMyPastChallenges: PT.func.isRequired,
dropAllChallenges: PT.func.isRequired,
dropOpenForRegistrationChallenges: PT.func.isRequired,
dropActiveChallenges: PT.func.isRequired,
- // dropPastChallenges: PT.func.isRequired,
+ dropPastChallenges: PT.func.isRequired,
filter: PT.shape().isRequired,
hideSrm: PT.bool,
- hideTcLinksInSidebarFooter: PT.bool,
+ // hideTcLinksInSidebarFooter: PT.bool,
communityId: PT.string,
communityName: PT.string,
communityFilters: PT.arrayOf(PT.object).isRequired,
@@ -657,24 +690,27 @@ ListingContainer.propTypes = {
getActiveChallenges: PT.func.isRequired,
getOpenForRegistrationChallenges: PT.func.isRequired,
getMyChallenges: PT.func.isRequired,
+ getMyPastChallenges: PT.func.isRequired,
getAllChallenges: PT.func.isRequired,
// getRestActiveChallenges: PT.func.isRequired,
getCommunitiesList: PT.func.isRequired,
- // getPastChallenges: PT.func.isRequired,
+ getPastChallenges: PT.func.isRequired,
getReviewOpportunities: PT.func.isRequired,
keepPastPlaceholders: PT.bool.isRequired,
lastRequestedPageOfActiveChallenges: PT.number.isRequired,
lastRequestedPageOfOpenForRegistrationChallenges: PT.number.isRequired,
lastRequestedPageOfMyChallenges: PT.number.isRequired,
+ lastRequestedPageOfMyPastChallenges: PT.number.isRequired,
lastRequestedPageOfAllChallenges: PT.number.isRequired,
- // lastRequestedPageOfPastChallenges: PT.number.isRequired,
+ lastRequestedPageOfPastChallenges: PT.number.isRequired,
lastRequestedPageOfReviewOpportunities: PT.number.isRequired,
// lastUpdateOfActiveChallenges: PT.number.isRequired,
loadingActiveChallengesUUID: PT.string.isRequired,
loadingOpenForRegistrationChallengesUUID: PT.string.isRequired,
loadingMyChallengesUUID: PT.string.isRequired,
+ loadingMyPastChallengesUUID: PT.string.isRequired,
loadingAllChallengesUUID: PT.string.isRequired,
- // loadingPastChallengesUUID: PT.string.isRequired,
+ loadingPastChallengesUUID: PT.string.isRequired,
loadingReviewOpportunitiesUUID: PT.string.isRequired,
markHeaderMenu: PT.func.isRequired,
newChallengeDetails: PT.bool,
@@ -690,7 +726,6 @@ ListingContainer.propTypes = {
expanding: PT.bool,
selectedCommunityId: PT.string,
sorts: PT.shape().isRequired,
- setSearchText: PT.func.isRequired,
setSort: PT.func.isRequired,
listingOnly: PT.bool,
groupIds: PT.arrayOf(PT.string),
@@ -714,35 +749,38 @@ const mapStateToProps = (state, ownProps) => {
return {
auth: state.auth,
// allActiveChallengesLoaded: cl.allActiveChallengesLoaded,
- // allPastChallengesLoaded: cl.allPastChallengesLoaded,
+ allPastChallengesLoaded: cl.allPastChallengesLoaded,
allReviewOpportunitiesLoaded: cl.allReviewOpportunitiesLoaded,
filter: cl.filter,
challenges: cl.challenges,
openForRegistrationChallenges: cl.openForRegistrationChallenges,
myChallenges: cl.myChallenges,
+ myPastChallenges: cl.myPastChallenges,
allChallenges: cl.allChallenges,
- // pastChallenges: cl.pastChallenges,
+ pastChallenges: cl.pastChallenges,
challengeTypes: cl.challengeTypes,
challengeTags: cl.challengeTags,
communitiesList: tc.list,
communityFilters: tc.list.data,
domain: state.domain,
// extraBucket: ownProps.extraBucket,
- hideTcLinksInSidebarFooter: ownProps.hideTcLinksInSidebarFooter,
+ // hideTcLinksInSidebarFooter: ownProps.hideTcLinksInSidebarFooter,
keepPastPlaceholders: cl.keepPastPlaceholders,
lastRequestedPageOfActiveChallenges: cl.lastRequestedPageOfActiveChallenges,
// eslint-disable-next-line max-len
lastRequestedPageOfOpenForRegistrationChallenges: cl.lastRequestedPageOfOpenForRegistrationChallenges,
lastRequestedPageOfMyChallenges: cl.lastRequestedPageOfMyChallenges,
+ lastRequestedPageOfMyPastChallenges: cl.lastRequestedPageOfMyPastChallenges,
lastRequestedPageOfAllChallenges: cl.lastRequestedPageOfAllChallenges,
- // lastRequestedPageOfPastChallenges: cl.lastRequestedPageOfPastChallenges,
+ lastRequestedPageOfPastChallenges: cl.lastRequestedPageOfPastChallenges,
lastRequestedPageOfReviewOpportunities: cl.lastRequestedPageOfReviewOpportunities,
// lastUpdateOfActiveChallenges: cl.lastUpdateOfActiveChallenges,
loadingActiveChallengesUUID: cl.loadingActiveChallengesUUID,
loadingOpenForRegistrationChallengesUUID: cl.loadingOpenForRegistrationChallengesUUID,
loadingMyChallengesUUID: cl.loadingMyChallengesUUID,
+ loadingMyPastChallengesUUID: cl.loadingMyPastChallengesUUID,
loadingAllChallengesUUID: cl.loadingAllChallengesUUID,
- // loadingPastChallengesUUID: cl.loadingPastChallengesUUID,
+ loadingPastChallengesUUID: cl.loadingPastChallengesUUID,
loadingReviewOpportunitiesUUID: cl.loadingReviewOpportunitiesUUID,
loadingChallengeTypes: cl.loadingChallengeTypes,
loadingChallengeTags: cl.loadingChallengeTags,
@@ -765,7 +803,6 @@ const mapStateToProps = (state, ownProps) => {
function mapDispatchToProps(dispatch) {
const a = actions.challengeListing;
const ah = headerActions.topcoderHeader;
- const fpa = filterPanelActions.challengeListing.filterPanel;
const sa = sidebarActions.challengeListing.sidebar;
const ca = communityActions.tcCommunity;
return {
@@ -787,7 +824,13 @@ function mapDispatchToProps(dispatch) {
dispatch(a.getMyChallengesInit(uuid, page, frontFilter));
dispatch(a.getMyChallengesDone(uuid, page, filter, token, frontFilter));
},
+ getMyPastChallenges: (page, filter, token, frontFilter) => {
+ const uuid = shortId();
+ dispatch(a.getMyPastChallengesInit(uuid, page, frontFilter));
+ dispatch(a.getMyPastChallengesDone(uuid, page, filter, token, frontFilter));
+ },
dropMyChallenges: () => dispatch(a.dropMyChallenges()),
+ dropMyPastChallenges: () => dispatch(a.dropMyPastChallenges()),
getAllChallenges: (page, filter, token, frontFilter) => {
const uuid = shortId();
dispatch(a.getAllChallengesInit(uuid, page, frontFilter));
@@ -809,12 +852,12 @@ function mapDispatchToProps(dispatch) {
dispatch(ca.getListInit(uuid));
dispatch(ca.getListDone(uuid, auth));
},
- // dropPastChallenges: () => dispatch(a.dropPastChallenges()),
- // getPastChallenges: (page, filter, token, frontFilter) => {
- // const uuid = shortId();
- // dispatch(a.getPastChallengesInit(uuid, page, frontFilter));
- // dispatch(a.getPastChallengesDone(uuid, page, filter, token, frontFilter));
- // },
+ dropPastChallenges: () => dispatch(a.dropPastChallenges()),
+ getPastChallenges: (page, filter, token, frontFilter) => {
+ const uuid = shortId();
+ dispatch(a.getPastChallengesInit(uuid, page, frontFilter));
+ dispatch(a.getPastChallengesDone(uuid, page, filter, token, frontFilter));
+ },
getReviewOpportunities: (page, token) => {
const uuid = shortId();
dispatch(a.getReviewOpportunitiesInit(uuid, page));
@@ -826,7 +869,6 @@ function mapDispatchToProps(dispatch) {
tab => dispatch(challengeDetailsActions.page.challengeDetails.selectTab(tab)),
selectCommunity: id => dispatch(a.selectCommunity(id)),
setFilter: state => dispatch(a.setFilter(state)),
- setSearchText: text => dispatch(fpa.setSearchText(text)),
setSort: (bucket, sort) => dispatch(a.setSort(bucket, sort)),
markHeaderMenu: () => dispatch(ah.setCurrentNav('Compete', 'All Challenges')),
expandTag: id => dispatch(a.expandTag(id)),
@@ -835,6 +877,7 @@ function mapDispatchToProps(dispatch) {
// dispatch(a.getUserChallengesInit(uuid));
// dispatch(a.getUserChallengesDone(userId, tokenV3));
// },
+ setPast: isPast => dispatch(sa.setPast(isPast)),
};
}
diff --git a/src/shared/containers/challenge-listing/Sidebar.jsx b/src/shared/containers/challenge-listing/Sidebar.jsx
index 034024fbac..c13bfccfff 100644
--- a/src/shared/containers/challenge-listing/Sidebar.jsx
+++ b/src/shared/containers/challenge-listing/Sidebar.jsx
@@ -4,7 +4,7 @@
// import _ from 'lodash';
import actions from 'actions/challenge-listing/sidebar';
-// import challengeListingActions from 'actions/challenge-listing';
+import challengeListingActions from 'actions/challenge-listing';
// import { config } from 'topcoder-react-utils';
// import filterPanelActions from 'actions/challenge-listing/filter-panel';
import PT from 'prop-types';
@@ -39,6 +39,15 @@ export const SidebarPureComponent = Sidebar;
// }
export class SidebarContainer extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ previousBucketOfActiveTab: null,
+ previousBucketOfPastChallengesTab: null,
+ };
+ }
+
componentDidMount() {
// const { tokenV2, getSavedFilters } = this.props;
// const token = tokenV2;
@@ -46,7 +55,7 @@ export class SidebarContainer extends React.Component {
}
render() {
- // const {
+ const {
// activeBucket,
// communityFilters,
// deleteSavedFilter,
@@ -56,12 +65,18 @@ export class SidebarContainer extends React.Component {
// selectSavedFilter,
// selectedCommunityId,
// setFilter,
- // setSearchText,
// tokenV2,
// updateAllSavedFilters,
// updateSavedFilter,
// userChallenges,
- // } = this.props;
+ past,
+ setPast,
+ } = this.props;
+
+ const {
+ previousBucketOfActiveTab,
+ previousBucketOfPastChallengesTab,
+ } = this.state;
// const buckets = getBuckets(userChallenges);
@@ -97,7 +112,6 @@ export class SidebarContainer extends React.Component {
// const { filter } = origSavedFilters[index];
// selectSavedFilter(index);
// setFilter(_.omit(filter, 'communityId'));
- // setSearchText(filter.text || '');
// selectCommunity(filter.communityId || '');
// }}
// updateAllSavedFilters={() => updateAllSavedFilters(
@@ -106,6 +120,16 @@ export class SidebarContainer extends React.Component {
// )
// }
// updateSavedFilter={filter => updateSavedFilter(filter, tokenV2)}
+ previousBucketOfActiveTab={previousBucketOfActiveTab}
+ previousBucketOfPastChallengesTab={previousBucketOfPastChallengesTab}
+ setPreviousBucketOfActiveTab={(bucket) => {
+ this.setState({ previousBucketOfActiveTab: bucket });
+ }}
+ setPreviousBucketOfPastChallengesTab={(bucket) => {
+ this.setState({ previousBucketOfPastChallengesTab: bucket });
+ }}
+ past={past}
+ setPast={setPast}
/>
);
}
@@ -117,6 +141,7 @@ SidebarContainer.defaultProps = {
// tokenV2: null,
// user: null,
// userChallenges: [],
+ expanding: false,
};
SidebarContainer.propTypes = {
@@ -131,48 +156,52 @@ SidebarContainer.propTypes = {
// savedFilters: PT.arrayOf(PT.shape()).isRequired,
// selectedCommunityId: PT.string,
// selectSavedFilter: PT.func.isRequired,
- // setFilter: PT.func.isRequired,
+ setFilter: PT.func.isRequired,
// selectCommunity: PT.func.isRequired,
- // setSearchText: PT.func.isRequired,
// tokenV2: PT.string,
// updateAllSavedFilters: PT.func.isRequired,
// updateSavedFilter: PT.func.isRequired,
// user: PT.shape(),
// userChallenges: PT.arrayOf(PT.string),
+ expanding: PT.bool,
+ past: PT.bool.isRequired,
+ setPast: PT.func.isRequired,
};
function mapDispatchToProps(dispatch) {
const a = actions.challengeListing.sidebar;
- // const cla = challengeListingActions.challengeListing;
+ const cla = challengeListingActions.challengeListing;
// const fpa = filterPanelActions.challengeListing.filterPanel;
return {
...bindActionCreators(a, dispatch),
- // setFilter: filter => dispatch(cla.setFilter(filter)),
+ setFilter: filter => dispatch(cla.setFilter(filter)),
// selectCommunity: communityId => dispatch(cla.selectCommunity(communityId)),
- // setSearchText: text => dispatch(fpa.setSearchText(text)),
};
}
-function mapStateToProps(state, ownProps) {
+function mapStateToProps(state) {
// const { activeBucket } = state.challengeListing.sidebar;
// const pending = _.keys(state.challengeListing.pendingRequests);
// updateChallengeType(
// state.challengeListing.challenges, state.challengeListing.challengeTypesMap,
// );
+ const sb = state.challengeListing.sidebar;
return {
activeBucket: state.challengeListing.sidebar.activeBucket,
// ...state.challengeListing.sidebar,
// challenges: state.challengeListing.challenges,
// disabled: (activeBucket === BUCKETS.ALL) && Boolean(pending.length),
// extraBucket: ownProps.extraBucket,
- hideTcLinksInFooter: ownProps.hideTcLinksInFooter,
- // filterState: state.challengeListing.filter,
+ // hideTcLinksInFooter: ownProps.hideTcLinksInFooter,
+ filterState: state.challengeListing.filter,
isAuth: Boolean(state.auth.user),
// communityFilters: state.tcCommunities.list.data,
// selectedCommunityId: state.challengeListing.selectedCommunityId,
// tokenV2: state.auth.tokenV2,
// user: state.auth.user,
// userChallenges: state.challengeListing.userChallenges,
+ expanding: sb.expanding,
+ past: sb.past,
};
}
diff --git a/src/shared/reducers/challenge-listing/index.js b/src/shared/reducers/challenge-listing/index.js
index fc656771f7..6b9917f20f 100644
--- a/src/shared/reducers/challenge-listing/index.js
+++ b/src/shared/reducers/challenge-listing/index.js
@@ -14,7 +14,7 @@ import {
// challenge as challengeUtils,
actions as actionsUtils,
} from 'topcoder-react-lib';
-
+import { REVIEW_OPPORTUNITY_TYPES } from 'utils/tc';
import filterPanel from './filter-panel';
import sidebar, { factory as sidebarFactory } from './sidebar';
@@ -149,6 +149,14 @@ function onGetAllChallengesInit(state, { payload }) {
};
}
+function onGetMyPastChallengesInit(state, { payload }) {
+ return {
+ ...state,
+ loadingMyPastChallengesUUID: payload.uuid,
+ lastRequestedPageOfMyPastChallenges: payload.page,
+ };
+}
+
// function onGetRestActiveChallengesInit(state, { payload }) {
// return {
// ...state,
@@ -312,37 +320,42 @@ function onGetChallengeTagsDone(state, action) {
};
}
-// function onGetPastChallengesInit(state, action) {
-// const { frontFilter, page, uuid } = action.payload;
-// const tracks = frontFilter && frontFilter.tracks;
-// if (tracks && _.isEmpty(tracks)) {
-// return {
-// ...state,
-// allPastChallengesLoaded: true,
-// loadingPastChallengesUUID: '',
-// };
-// }
+function onGetPastChallengesInit(state, action) {
+ const { frontFilter, page, uuid } = action.payload;
+ const tracks = frontFilter && frontFilter.tracks;
+ if (tracks && _.isEmpty(tracks)) {
+ return {
+ ...state,
+ allPastChallengesLoaded: true,
+ loadingPastChallengesUUID: '',
+ };
+ }
-// return {
-// ...state,
-// lastRequestedPageOfPastChallenges: page,
-// loadingPastChallengesUUID: uuid,
-// };
-// }
+ return {
+ ...state,
+ lastRequestedPageOfPastChallenges: page,
+ loadingPastChallengesUUID: uuid,
+ };
+}
-// function onGetPastChallengesDone(state, { error, payload }) {
-// if (error) {
-// logger.error(payload);
-// return state;
-// }
-// const { uuid, pastChallenges: loaded } = payload;
-// if (uuid !== state.loadingPastChallengesUUID) return state;
-// const challenges = state.pastChallenges.concat(loaded);
-// return {
-// ...state,
-// pastChallenges: challenges,
-// loadingPastChallengesUUID: '',
-// };
+function onGetPastChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const { uuid, pastChallenges: loaded } = payload;
+ if (uuid !== state.loadingPastChallengesUUID) return state;
+ const challenges = state.pastChallenges.concat(loaded);
+ return {
+ ...state,
+ pastChallenges: challenges,
+ loadingPastChallengesUUID: '',
+ allPastChallengesLoaded: challenges.length >= payload.meta.allChallengesCount,
+ meta: {
+ ...state.meta,
+ pastChallengesCount: payload.meta.allChallengesCount,
+ },
+ };
// if (error) {
// logger.error(payload);
// return state;
@@ -378,7 +391,7 @@ function onGetChallengeTagsDone(state, action) {
// loadingPastChallengesUUID: '',
// // pastSearchTimestamp,
// };
-// }
+}
function onSelectCommunity(state, { payload }) {
updateQuery({ communityId: payload || undefined });
@@ -411,6 +424,14 @@ function onSetFilter(state, { payload }) {
payload,
['tags', 'types', 'name', 'startDateEnd', 'endDateStart', 'groups', 'events', 'tracks'],
), value => (!_.isArray(value) && value && value !== '') || (_.isArray(value) && value.length > 0));
+
+ const emptyArrayAllowedFields = ['types'];
+ emptyArrayAllowedFields.forEach((field) => {
+ if (_.isEqual(payload[field], [])) {
+ filter[field] = payload[field];
+ }
+ });
+
// if (_.isPlainObject(filter.tags)) {
// filter.tags = _.values(filter.tags);
// }
@@ -615,6 +636,26 @@ function onGetAllChallengesDone(state, { error, payload }) {
};
}
+function onGetMyPastChallengesDone(state, { error, payload }) {
+ if (error) {
+ logger.error(payload);
+ return state;
+ }
+ const { uuid, myPastChallenges: loaded } = payload;
+ if (uuid !== state.loadingMyPastChallengesUUID) return state;
+ const challenges = state.myPastChallenges.concat(loaded);
+ return {
+ ...state,
+ myPastChallenges: challenges,
+ loadingMyPastChallengesUUID: '',
+ allMyPastChallengesLoaded: challenges.length >= payload.meta.allChallengesCount,
+ meta: {
+ ...state.meta,
+ myPastChallengesCount: payload.meta.allChallengesCount,
+ },
+ };
+}
+
function onGetTotalChallengesCountInit(state, { payload }) {
return {
...state,
@@ -654,25 +695,25 @@ function create(initialState) {
allMyChallengesLoaded: false,
allChallengesLoaded: false,
allOpenForRegistrationChallengesLoaded: false,
- // allPastChallengesLoaded: false,
+ allPastChallengesLoaded: false,
// allReviewOpportunitiesLoaded: false,
challenges: [],
allChallenges: [],
myChallenges: [],
openForRegistrationChallenges: [],
- // pastChallenges: [],
+ pastChallenges: [],
lastRequestedPageOfActiveChallenges: -1,
lastRequestedPageOfOpenForRegistrationChallenges: -1,
lastRequestedPageOfMyChallenges: -1,
lastRequestedPageOfAllChallenges: -1,
- // lastRequestedPageOfPastChallenges: -1,
+ lastRequestedPageOfPastChallenges: -1,
// lastRequestedPageOfReviewOpportunities: -1,
// lastUpdateOfActiveChallenges: 0,
loadingActiveChallengesUUID: '',
loadingOpenForRegistrationChallengesUUID: '',
loadingMyChallengesUUID: '',
// loadingRestActiveChallengesUUID: '',
- // loadingPastChallengesUUID: '',
+ loadingPastChallengesUUID: '',
// loadingReviewOpportunitiesUUID: '',
loadingTotalChallengesCountUUID: '',
@@ -717,18 +758,24 @@ function create(initialState) {
lastRequestedPageOfMyChallenges: -1,
loadingMyChallengesUUID: '',
}),
+ [a.dropMyPastChallenges]: state => ({
+ ...state,
+ myPastChallenges: [],
+ lastRequestedPageOfMyPastChallenges: -1,
+ loadingMyPastChallengesUUID: '',
+ }),
[a.dropAllChallenges]: state => ({
...state,
allChallenges: [],
lastRequestedPageOfAllChallenges: -1,
loadingAllChallengesUUID: '',
}),
- // [a.dropPastChallenges]: state => ({
- // ...state,
- // pastChallenges: [],
- // lastRequestedPageOfPastChallenges: -1,
- // loadingPastChallengesUUID: '',
- // }),
+ [a.dropPastChallenges]: state => ({
+ ...state,
+ pastChallenges: [],
+ lastRequestedPageOfPastChallenges: -1,
+ loadingPastChallengesUUID: '',
+ }),
[a.expandTag]: (state, { payload }) => ({
...state,
expandedTags: [...state.expandedTags, payload],
@@ -755,6 +802,9 @@ function create(initialState) {
[a.getMyChallengesInit]: onGetMyChallengesInit,
[a.getMyChallengesDone]: onGetMyChallengesDone,
+ [a.getMyPastChallengesInit]: onGetMyPastChallengesInit,
+ [a.getMyPastChallengesDone]: onGetMyPastChallengesDone,
+
[a.getAllChallengesInit]: onGetAllChallengesInit,
[a.getAllChallengesDone]: onGetAllChallengesDone,
@@ -776,8 +826,8 @@ function create(initialState) {
}),
[a.getChallengeTagsDone]: onGetChallengeTagsDone,
- // [a.getPastChallengesInit]: onGetPastChallengesInit,
- // [a.getPastChallengesDone]: onGetPastChallengesDone,
+ [a.getPastChallengesInit]: onGetPastChallengesInit,
+ [a.getPastChallengesDone]: onGetPastChallengesDone,
[a.getReviewOpportunitiesInit]: onGetReviewOpportunitiesInit,
[a.getReviewOpportunitiesDone]: onGetReviewOpportunitiesDone,
@@ -801,16 +851,18 @@ function create(initialState) {
}, _.defaults(_.clone(initialState) || {}, {
allActiveChallengesLoaded: false,
allMyChallengesLoaded: false,
+ allMyPastChallengesLoaded: false,
allOpenForRegistrationChallengesLoaded: false,
allChallengesLoaded: false,
- // allPastChallengesLoaded: false,
+ allPastChallengesLoaded: false,
allReviewOpportunitiesLoaded: false,
challenges: [],
allChallenges: [],
myChallenges: [],
openForRegistrationChallenges: [],
- // pastChallenges: [],
+ pastChallenges: [],
+ myPastChallenges: [],
recommendedChallenges: {},
challengeTypes: [],
challengeTypesMap: {},
@@ -824,7 +876,8 @@ function create(initialState) {
lastRequestedPageOfOpenForRegistrationChallenges: -1,
lastRequestedPageOfMyChallenges: -1,
lastRequestedPageOfAllChallenges: -1,
- // lastRequestedPageOfPastChallenges: -1,
+ lastRequestedPageOfMyPastChallenges: -1,
+ lastRequestedPageOfPastChallenges: -1,
lastRequestedPageOfReviewOpportunities: -1,
// lastUpdateOfActiveChallenges: 0,
@@ -832,11 +885,12 @@ function create(initialState) {
loadingOpenForRegistrationChallengesUUID: '',
loadingMyChallengesUUID: '',
loadingAllChallengesUUID: '',
+ loadingMyPastChallengesUUID: '',
loadingRecommendedChallengesUUID: '',
// loadingRestActiveChallengesUUID: '',
loadingRecommendedChallengesTechnologies: '',
loadingTotalChallengesCountUUID: '',
- // loadingPastChallengesUUID: '',
+ loadingPastChallengesUUID: '',
loadingReviewOpportunitiesUUID: '',
loadingChallengeTypes: false,
@@ -858,6 +912,7 @@ function create(initialState) {
startDateEnd: null,
endDateStart: null,
status: 'Active',
+ reviewOpportunityTypes: _.keys(REVIEW_OPPORTUNITY_TYPES),
},
selectedCommunityId: 'All',
@@ -869,6 +924,8 @@ function create(initialState) {
all: 'startDate',
// past: 'updated',
reviewOpportunities: 'review-opportunities-start-date',
+ allPast: 'startDate',
+ myPast: 'startDate',
},
srms: {
@@ -882,6 +939,8 @@ function create(initialState) {
myChallengesCount: 0,
ongoingChallengesCount: 0,
openChallengesCount: 0,
+ pastChallengesCount: 0,
+ myPastChallengesCount: 0,
totalCount: 0,
},
diff --git a/src/shared/reducers/challenge-listing/sidebar.js b/src/shared/reducers/challenge-listing/sidebar.js
index bb3822811f..b55abacb5a 100644
--- a/src/shared/reducers/challenge-listing/sidebar.js
+++ b/src/shared/reducers/challenge-listing/sidebar.js
@@ -175,6 +175,15 @@ function onSelectBucketDone(state) {
// return { ...state, savedFilters };
// }
+function onSetPast(state, { payload }) {
+ const { past } = payload;
+
+ return {
+ ...state,
+ past,
+ };
+}
+
function create(initialState = {}) {
const a = actions.challengeListing.sidebar;
return handleActions({
@@ -200,12 +209,14 @@ function create(initialState = {}) {
// editSavedFiltersMode: payload,
// }),
// [a.updateSavedFilter]: onUpdateSavedFilter,
+ [a.setPast]: onSetPast,
}, _.defaults(initialState, {
activeBucket: BUCKETS.OPEN_FOR_REGISTRATION,
// activeSavedFilter: 0,
// editSavedFiltersMode: false,
// savedFilters: [],
// isSavingFilter: false,
+ past: false,
}));
}
diff --git a/src/shared/utils/challenge-listing/buckets.js b/src/shared/utils/challenge-listing/buckets.js
index 207fc92118..7b669b85ce 100644
--- a/src/shared/utils/challenge-listing/buckets.js
+++ b/src/shared/utils/challenge-listing/buckets.js
@@ -3,6 +3,7 @@
*/
import _ from 'lodash';
+import { REVIEW_OPPORTUNITY_TYPES } from 'utils/tc';
import { SORTS } from './sort';
export const BUCKETS = {
@@ -10,11 +11,13 @@ export const BUCKETS = {
MY: 'my',
OPEN_FOR_REGISTRATION: 'openForRegistration',
ONGOING: 'ongoing',
- // PAST: 'past',
+ PAST: 'past',
// SAVED_FILTER: 'saved-filter',
// UPCOMING: 'upcoming',
REVIEW_OPPORTUNITIES: 'reviewOpportunities',
// SAVED_REVIEW_OPPORTUNITIES_FILTER: 'savedReviewOpportunitiesFilter',
+ ALL_PAST: 'allPast',
+ MY_PAST: 'myPast',
};
export const BUCKET_DATA = {
@@ -120,6 +123,20 @@ export const BUCKET_DATA = {
// // SORTS.REVIEW_OPPORTUNITIES_TITLE_A_TO_Z,
// ],
// },
+ [BUCKETS.ALL_PAST]: {
+ name: 'All Past Challenges',
+ sorts: [
+ SORTS.MOST_RECENT_START_DATE,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
+ [BUCKETS.MY_PAST]: {
+ name: 'My Past Challenges',
+ sorts: [
+ SORTS.MOST_RECENT_START_DATE,
+ SORTS.TITLE_A_TO_Z,
+ ],
+ },
};
export const NO_LIVE_CHALLENGES_CONFIG = {
@@ -130,6 +147,8 @@ export const NO_LIVE_CHALLENGES_CONFIG = {
// [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',
+ [BUCKETS.ALL_PAST]: 'No challenges found in All Past Challenges',
+ [BUCKETS.MY_PAST]: 'No challenges found in My Past Challenges',
};
/**
@@ -190,26 +209,56 @@ export function sortChangedBucket(sorts, prevSorts) {
if (sorts.all !== prevSorts.all) return 'all';
if (sorts.openForRegistration !== prevSorts.openForRegistration) return 'openForRegistration';
// if (sorts.past !== prevSorts.past) return 'past';
+ if (sorts.allPast !== prevSorts.allPast) return 'allPast';
+ if (sorts.myPast !== prevSorts.myPast) return 'myPast';
return '';
}
-export function isFilterEmpty(filter) {
- return _.isEqual(filter, {
- tracks: {
- Dev: true,
- Des: true,
- DS: true,
- QA: true,
- },
- name: '',
- tags: [],
- types: [],
- groups: [],
- events: [],
- startDateStart: null,
- endDateEnd: null,
- status: 'Active',
- });
+export function isFilterEmpty(filter, tab, bucket) {
+ let f;
+ let empty;
+
+ if (tab === 'past') {
+ f = _.pick(filter, 'tracks', 'name', 'types', 'startDateEnd', 'endDateStart');
+ empty = {
+ tracks: {
+ Dev: true,
+ Des: true,
+ DS: true,
+ QA: true,
+ },
+ name: '',
+ types: ['CH', 'F2F', 'TSK'],
+ startDateEnd: null,
+ endDateStart: null,
+ };
+ } else if (bucket === BUCKETS.REVIEW_OPPORTUNITIES) {
+ f = _.pick(filter, 'tracks', 'name', 'reviewOpportunityTypes');
+ empty = {
+ tracks: {
+ Dev: true,
+ Des: true,
+ DS: true,
+ QA: true,
+ },
+ name: '',
+ reviewOpportunityTypes: _.keys(REVIEW_OPPORTUNITY_TYPES),
+ };
+ } else {
+ f = _.pick(filter, 'tracks', 'name', 'types');
+ empty = {
+ tracks: {
+ Dev: true,
+ Des: true,
+ DS: true,
+ QA: true,
+ },
+ name: '',
+ types: ['CH', 'F2F', 'TSK'],
+ };
+ }
+
+ return _.isEqual(f, empty);
}
export default undefined;
diff --git a/src/shared/utils/challenge-listing/date-range.js b/src/shared/utils/challenge-listing/date-range.js
new file mode 100644
index 0000000000..ead001ec34
--- /dev/null
+++ b/src/shared/utils/challenge-listing/date-range.js
@@ -0,0 +1,62 @@
+import moment from 'moment';
+
+const isSameDay = (date1, date2) => {
+ if (!date1 || !date2) return false;
+ return moment(date1).isSame(moment(date2), 'day');
+};
+
+const staticRangeHandler = {
+ isSelected(range) {
+ const definedRange = { startDate: this.startDate, endDate: this.endDate };
+ return (
+ isSameDay(range.startDate, definedRange.startDate)
+ && isSameDay(range.endDate, definedRange.endDate)
+ );
+ },
+};
+
+/**
+ * Create defined date ranges
+ * @return {object[]} list of defined ranges
+ */
+export function createStaticRanges() {
+ const now = moment().utcOffset(0);
+ const pastMonth = now.clone().subtract(1, 'month');
+ const past3Months = now.clone().subtract(3, 'month');
+ const past6Months = now.clone().subtract(6, 'month');
+ const pastYear = now.clone().subtract(1, 'year');
+
+ const ranges = [
+ {
+ label: 'Past Month',
+ startDate: pastMonth.startOf('day').toDate(),
+ endDate: now.clone().endOf('day').toDate(),
+ },
+ {
+ label: 'Past 6 Months',
+ startDate: past6Months.startOf('day').toDate(),
+ endDate: now.clone().endOf('day').toDate(),
+ },
+ {
+ label: 'Custom Date',
+ startDate: null,
+ endDate: null,
+ isCustom: true,
+ },
+ {
+ label: 'Past 3 Month',
+ startDate: past3Months.startOf('day').toDate(),
+ endDate: now.clone().endOf('day').toDate(),
+ },
+ {
+ label: 'Past 1 Year',
+ startDate: pastYear.startOf('day').toDate(),
+ endDate: now.clone().endOf('day').toDate(),
+ },
+
+ ];
+
+ return ranges.map(range => ({ ...staticRangeHandler, ...range }));
+}
+
+export default createStaticRanges;
diff --git a/src/shared/utils/url.js b/src/shared/utils/url.js
index 52ad5430a8..0223f075ff 100644
--- a/src/shared/utils/url.js
+++ b/src/shared/utils/url.js
@@ -65,6 +65,16 @@ export function updateQuery(update) {
...update,
};
}
+
+ if (filterObj.bucket === BUCKETS.REVIEW_OPPORTUNITIES) {
+ delete filterObj.types;
+ }
+
+ // if (!(filterObj.bucket in [BUCKETS.ALL_PAST, BUCKETS.MY_PAST])) {
+ // delete filterObj.endDateStart;
+ // delete filterObj.startDateEnd;
+ // }
+
let query = '?';
const { hash } = window.location;
const filterArray = [];
@@ -94,6 +104,7 @@ export function updateQuery(update) {
query += `&${filterArray.join('&')}`;
}
}
+ query = `?${query.substring(1).split('&').sort().join('&')}`;
if (hash) {
query += hash;
}