diff --git a/__tests__/shared/components/GUIKit/Datepicker/__snapshots__/index.jsx.snap b/__tests__/shared/components/GUIKit/Datepicker/__snapshots__/index.jsx.snap index 4d015bc53b..cbf30591eb 100644 --- a/__tests__/shared/components/GUIKit/Datepicker/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/GUIKit/Datepicker/__snapshots__/index.jsx.snap @@ -38,6 +38,8 @@ exports[`Default render 1`] = ` isRTL={false} keepFocusOnInput={false} keepOpenOnDateSelect={false} + maxDate={null} + minDate={null} monthFormat="MMMM YYYY" navNext={ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/server/tc-communities/tco22/metadata.json b/src/server/tc-communities/tco22/metadata.json new file mode 100644 index 0000000000..8fb39face2 --- /dev/null +++ b/src/server/tc-communities/tco22/metadata.json @@ -0,0 +1,20 @@ +{ + "challengeFilter": { + "events": ["tco22"] + }, + "communityId": "tco22", + "communityName": "TCO22", + "groupIds": [], + "hideSearch": true, + "logos": [{ + "img": "/community-app-assets/themes/tco/TCO22.svg", + "url": "https://tco22.topcoder.com" + }], + "menuItems": [{ + "navigationMenu": "5zZw57ZcKXWfOwwWbk5VnL" + }], + "newsFeed": "http://www.topcoder.com/feed", + "subdomains": ["tco22"], + "description": "2022 Topcoder Open. The Ultimate Programming & Design Tournament", + "image": "tco22.jpg" +} diff --git a/src/shared/components/Contentful/ArticleCard/ArticleCard.jsx b/src/shared/components/Contentful/ArticleCard/ArticleCard.jsx index 38e99630a3..b627dcab1c 100644 --- a/src/shared/components/Contentful/ArticleCard/ArticleCard.jsx +++ b/src/shared/components/Contentful/ArticleCard/ArticleCard.jsx @@ -250,7 +250,7 @@ class ArticleCard extends React.Component { { showArticleInfo() && (

- {themeName === 'Article large' ?  .  : null} + {themeName === 'Article large' && contentAuthor && contentAuthor.length > 0 ?  .  : null} { contentAuthor && contentAuthor.length > 0 ? ( - From - - { onSelectStartDate(date); }} + { + if (date instanceof Date) onSelectStartDate(moment(date)); + }} + size="xs" + isOutsideRange={day => moment().isBefore(day)} + displayFormat="M/DD/YYYY" + hideCustomInputIcon + errorMsg={startDate > endDate ? 'From should be before end' : null} /> - - - { onSelectEndDate(date); }} +

+ { + if (date instanceof Date) onSelectEndDate(moment(date)); + }} + size="xs" + isOutsideRange={day => moment().isSameOrBefore(day)} + displayFormat="M/DD/YYYY" + hideCustomInputIcon />
); diff --git a/src/shared/components/Contentful/SearchPageFilter/FilterDate/themes/default.scss b/src/shared/components/Contentful/SearchPageFilter/FilterDate/themes/default.scss index b143056b1c..b9c53cbabd 100644 --- a/src/shared/components/Contentful/SearchPageFilter/FilterDate/themes/default.scss +++ b/src/shared/components/Contentful/SearchPageFilter/FilterDate/themes/default.scss @@ -2,58 +2,20 @@ $text-black: #2a2a2a; -@mixin ellipsis { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - min-width: 0; -} - .container { @include roboto-regular; display: flex; flex-direction: row; color: $text-black; - background-color: $tc-white; - border-radius: 6px; - border: 1px solid #aaa; position: relative; - width: 100%; - align-items: center; - padding-left: 10px; font-size: 14px; - height: 38px; - max-width: 235px; - - :global { - .SingleDatePicker { - width: 90px; - margin-left: 6px; - } - - input { - height: 21px !important; - margin: 0 !important; - padding: 0 !important; - font-size: 14px !important; - border: none !important; - box-shadow: none !important; - } - } -} - -.title { - position: absolute; - color: #aaa; - font-size: 12px; - background: $tc-white; - padding: 0 7px; - left: 8px; - top: -7px; } .separator { - margin-left: 3px; - margin-right: 3px; + margin: 0 6px; + width: 6px; + height: 1px; + background-color: $text-black; + margin-top: 20px; } diff --git a/src/shared/components/Contentful/SearchPageFilter/SearchPageFilter.jsx b/src/shared/components/Contentful/SearchPageFilter/SearchPageFilter.jsx index b7978b243a..2a1e53b739 100644 --- a/src/shared/components/Contentful/SearchPageFilter/SearchPageFilter.jsx +++ b/src/shared/components/Contentful/SearchPageFilter/SearchPageFilter.jsx @@ -201,7 +201,7 @@ SearchPageFilterInner.defaultProps = { onApply: () => { }, selectedAuthor: DEF_SELECTED_AUTHOR, authorList: [DEF_SELECTED_AUTHOR], - startDate: moment('2001-01-02'), + startDate: moment('2001-01-01'), endDate: moment(), tags: [], selectedCategory: '', diff --git a/src/shared/components/Contentful/SearchPageFilter/themes/default.scss b/src/shared/components/Contentful/SearchPageFilter/themes/default.scss index fdf55054c5..82c931c883 100644 --- a/src/shared/components/Contentful/SearchPageFilter/themes/default.scss +++ b/src/shared/components/Contentful/SearchPageFilter/themes/default.scss @@ -30,7 +30,7 @@ $green-color: #137d60; } .track-date-container { - margin-top: 27px; + margin-top: 43px; } .author-container { diff --git a/src/shared/components/Contentful/TracksFilter/TracksDate/index.jsx b/src/shared/components/Contentful/TracksFilter/TracksDate/index.jsx index bbf0eacb0c..9a17208c53 100644 --- a/src/shared/components/Contentful/TracksFilter/TracksDate/index.jsx +++ b/src/shared/components/Contentful/TracksFilter/TracksDate/index.jsx @@ -24,7 +24,7 @@ export function TracksDateInner(props) { { onSelectStartDate(date); }} + onChange={(date) => { if (date instanceof Date) onSelectStartDate(date); }} size="xs" isOutsideRange={day => moment().isSameOrBefore(day)} /> @@ -32,7 +32,7 @@ export function TracksDateInner(props) { { onSelectEndDate(date); }} + onChange={(date) => { if (date instanceof Date) onSelectEndDate(date); }} size="xs" isOutsideRange={day => moment().isSameOrBefore(day)} /> diff --git a/src/shared/components/GUIKit/Datepicker/index.jsx b/src/shared/components/GUIKit/Datepicker/index.jsx index 3ac949e4c7..93ee05bb66 100644 --- a/src/shared/components/GUIKit/Datepicker/index.jsx +++ b/src/shared/components/GUIKit/Datepicker/index.jsx @@ -27,6 +27,11 @@ function Datepicker({ required, size, isOutsideRange, + hideCustomInputIcon, + isDayBlocked, + displayFormat, + minDate, + maxDate, }) { const sizeStyle = size === 'lg' ? 'lgSize' : 'xsSize'; const [date, setDate] = useState(value ? moment(value) : null); @@ -43,7 +48,7 @@ function Datepicker({ > } + customInputIcon={hideCustomInputIcon ? null : } date={date} onDateChange={(changedDate) => { setDate(changedDate); @@ -58,13 +63,16 @@ function Datepicker({ numberOfMonths={1} navPrev={} navNext={} - displayFormat="MMM DD, YYYY" + displayFormat={displayFormat} daySize={width > 600 ? 47 : 35} renderDayContents={d => (
{d.date ? d.date() : ''}
)} enableOutsideDays firstDayOfWeek={1} weekDayFormat="ddd" isOutsideRange={isOutsideRange} + isDayBlocked={isDayBlocked} + minDate={minDate} + maxDate={maxDate} /> {label ? ( @@ -86,6 +94,11 @@ Datepicker.defaultProps = { required: false, size: 'lg', isOutsideRange: day => moment().isSameOrAfter(day), + hideCustomInputIcon: false, + isDayBlocked: () => false, + displayFormat: 'MMM DD, YYYY', + minDate: null, + maxDate: null, }; Datepicker.propTypes = { @@ -97,6 +110,11 @@ Datepicker.propTypes = { required: PT.bool, size: PT.oneOf(['xs', 'lg']), isOutsideRange: PT.func, + hideCustomInputIcon: PT.bool, + isDayBlocked: PT.func, + displayFormat: PT.string, + minDate: PT.instanceOf(moment), + maxDate: PT.instanceOf(moment), }; export default Datepicker; diff --git a/src/shared/containers/EDU/Search.jsx b/src/shared/containers/EDU/Search.jsx index b16fcfdf12..7218cc350e 100644 --- a/src/shared/containers/EDU/Search.jsx +++ b/src/shared/containers/EDU/Search.jsx @@ -2,7 +2,6 @@ * Container for EDU Portal search page. */ import _ from 'lodash'; -import moment from 'moment'; import React from 'react'; import { config, isomorphy } from 'topcoder-react-utils'; import MetaTags from 'components/MetaTags'; @@ -67,8 +66,8 @@ export default class EDUSearch extends React.Component { const queryUpdate = { author: filterState.selectedAuthor, tags: filterState.tags, - startDate: filterState.startDate.format(), - endDate: filterState.endDate.format(), + startDate: filterState.startDate.format('YYYY-MM-DD'), + endDate: filterState.endDate.format('YYYY-MM-DD'), track: filterState.selectedCategory ? filterState.selectedCategory.title : null, tax: filterState.selectedCategory ? _.map( _.filter(filterState.selectedCategory.items, item => item.selected), @@ -125,8 +124,8 @@ export default class EDUSearch extends React.Component { onApply={this.onApplyFilter} selectedAuthor={query.author} tags={query.tags} - startDate={query.startDate ? moment(query.startDate) : undefined} - endDate={query.endDate ? moment(query.endDate) : undefined} + startDate={query.startDate ? query.startDate : undefined} + endDate={query.endDate ? query.endDate : undefined} selectedCategory={query.track} categories={tree} /> diff --git a/src/shared/routes/Communities/Routes.jsx b/src/shared/routes/Communities/Routes.jsx index 5f3d42ce6f..920791339e 100644 --- a/src/shared/routes/Communities/Routes.jsx +++ b/src/shared/routes/Communities/Routes.jsx @@ -38,6 +38,7 @@ import tco18 from './TCO18'; import tco19 from './TCO19'; import tco20 from './TCO20'; import tco21 from './TCO21'; +import tco22 from './TCO22'; import Mobile from './Mobile'; import Zurich from './Zurich'; import Comcast from './Comcast'; @@ -64,6 +65,7 @@ const TCOs = { tco19, tco20, tco21, + tco22, }; export default function Communities({ diff --git a/src/shared/routes/Communities/TCO22/Routes.jsx b/src/shared/routes/Communities/TCO22/Routes.jsx new file mode 100644 index 0000000000..7bbb11754e --- /dev/null +++ b/src/shared/routes/Communities/TCO22/Routes.jsx @@ -0,0 +1,60 @@ +/** + * Routing of TCO22 Community. + */ + +import Error404 from 'components/Error404'; +import PT from 'prop-types'; +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; +import ContentfulRoute from 'components/Contentful/Route'; +import ContentfulMenu from 'components/Contentful/Menu'; +import Profile from 'routes/Profile'; +import ProfileStats from 'routes/ProfileStats'; +import Settings from 'routes/Settings'; + +export default function TCO22({ base, meta }) { + return ( +
+ { + meta.menuItems ? ( + + ) : null + } + + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})`} + /> + } + exact + path={`${base}/members/:handle([\\w\\-\\[\\].{}]{2,15})/details`} + /> + } + path={`${base}/settings`} + /> + } + id="6Ewcb5fkc67JOMhud6RoBs" + /> + +
+ ); +} + +TCO22.defaultProps = { + base: '', +}; + +TCO22.propTypes = { + base: PT.string, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/routes/Communities/TCO22/index.jsx b/src/shared/routes/Communities/TCO22/index.jsx new file mode 100644 index 0000000000..661df77231 --- /dev/null +++ b/src/shared/routes/Communities/TCO22/index.jsx @@ -0,0 +1,32 @@ +/** + * Loader for the community's code chunks. + */ + +import LoadingIndicator from 'components/LoadingIndicator'; +import path from 'path'; +import PT from 'prop-types'; +import React from 'react'; +import { AppChunk, webpack } from 'topcoder-react-utils'; + +export default function ChunkLoader({ base, meta }) { + return ( + import(/* webpackChunkName: "tco22-community/chunk" */ './Routes') + .then(({ default: Routes }) => ( + + )) + } + renderPlaceholder={() => } + renderServer={() => { + const Routes = webpack.requireWeak(path.resolve(__dirname, './Routes')); + return ; + }} + /> + ); +} + +ChunkLoader.propTypes = { + base: PT.string.isRequired, + meta: PT.shape().isRequired, +}; diff --git a/src/shared/services/contentful.js b/src/shared/services/contentful.js index c8509fe9da..289830d0a7 100644 --- a/src/shared/services/contentful.js +++ b/src/shared/services/contentful.js @@ -340,11 +340,7 @@ class Service { } if (track) query['fields.trackCategory'] = track; if (!_.isEmpty(tags)) { - if (tags.length === 1) { - query['fields.tags[match]'] = tags.join(','); - } else { - query.query = tags.join(' '); - } + query['fields.tags[all]'] = tags.join(','); } if (startDate) query['fields.creationDate[gte]'] = startDate; if (endDate) query['fields.creationDate[lte]'] = endDate;