diff --git a/.circleci/config.yml b/.circleci/config.yml index a471781f57..6180803b84 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -230,6 +230,7 @@ workflows: filters: branches: only: + - milestone-20200917 - develop # This is alternate dev env for parallel testing - "build-test": @@ -251,6 +252,7 @@ workflows: filters: branches: only: + - integration-v5-challenge-api - hot-fix # This is stage env for production QA releases - "build-prod-staging": @@ -258,7 +260,7 @@ workflows: filters: branches: only: - - feature-contentful + - develop # Production builds are exectuted # when PR is merged to the master # Don't change anything in this configuration diff --git a/package.json b/package.json index d284ae8360..c02656c845 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "tc-accounts": "git+https://github.com/appirio-tech/accounts-app.git#dev", "tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3", "tc-ui": "^1.0.12", - "topcoder-react-lib": "1.0.3", + "topcoder-react-lib": "1.0.4", "topcoder-react-ui-kit": "2.0.0", "topcoder-react-utils": "0.7.8", "turndown": "^4.0.2", diff --git a/src/shared/components/Contentful/Article/Article.jsx b/src/shared/components/Contentful/Article/Article.jsx index 150d213290..c9078713ea 100644 --- a/src/shared/components/Contentful/Article/Article.jsx +++ b/src/shared/components/Contentful/Article/Article.jsx @@ -15,7 +15,10 @@ import LoadingIndicator from 'components/LoadingIndicator'; import YouTubeVideo from 'components/YouTubeVideo'; import moment from 'moment'; import localStorage from 'localStorage'; -import { config, Link, isomorphy } from 'topcoder-react-utils'; +import { Helmet } from 'react-helmet'; +import { + config, Link, isomorphy, +} from 'topcoder-react-utils'; import qs from 'qs'; // SVGs and assets import GestureIcon from 'assets/images/icon-gesture.svg'; @@ -110,9 +113,27 @@ export default class Article extends React.Component { if (isomorphy.isClientSide()) { shareUrl = encodeURIComponent(window.location.href); } + const description = htmlToText.fromString( + ReactDOMServer.renderToString(markdown(fields.content)), + { + ignoreHref: true, + ignoreImage: true, + singleNewLineParagraphs: true, + uppercaseHeadings: false, + }, + ).substring(0, CONTENT_PREVIEW_LENGTH); return ( + + {fields.title} + + + + + + + {/* Banner */} { fields.featuredImage ? ( diff --git a/src/shared/components/Contentful/SearchBar/SearchBar.jsx b/src/shared/components/Contentful/SearchBar/SearchBar.jsx index 9444c56777..d23301d0ed 100644 --- a/src/shared/components/Contentful/SearchBar/SearchBar.jsx +++ b/src/shared/components/Contentful/SearchBar/SearchBar.jsx @@ -56,6 +56,7 @@ export class SearchBarInner extends Component { this.getSuggestionList = this.getSuggestionList.bind(this); this.handleSearchChange = this.handleSearchChange.bind(this); this.handleClickOutside = this.handleClickOutside.bind(this); + this.onKeyDown = this.onKeyDown.bind(this); // using debounce to avoid processing or requesting too much this.updateSuggestionListWithNewSearch = _.debounce( this.updateSuggestionListWithNewSearch.bind(this), 400, @@ -71,6 +72,29 @@ export class SearchBarInner extends Component { document.removeEventListener('mousedown', this.handleClickOutside); } + onKeyDown(e) { + const { inputlVal, selectedFilter } = this.state; + if (inputlVal && e.which === 13) { + const searchQuery = {}; + if (this.searchFieldRef && this.searchFieldRef.value) { + if (selectedFilter.name === 'Tags') { + searchQuery.tags = [this.searchFieldRef.value]; + } + if (selectedFilter.name === 'All') { + searchQuery.phrase = this.searchFieldRef.value; + } + if (selectedFilter.name === 'Title') { + searchQuery.title = this.searchFieldRef.value; + } + } + if (selectedFilter.name !== 'Author') { + window.location.href = `${config.TC_EDU_BASE_PATH}${config.TC_EDU_SEARCH_PATH}?${qs.stringify(searchQuery)}`; + } else { + window.location.href = `${config.TC_EDU_BASE_PATH}${config.TC_EDU_SEARCH_PATH}?author=${inputlVal}`; + } + } + } + /** * Set the search field ref */ @@ -136,6 +160,7 @@ export class SearchBarInner extends Component { isShowSuggestion, suggestionList, selectedFilter, + noResults, } = this.state; const searchQuery = {}; @@ -151,7 +176,8 @@ export class SearchBarInner extends Component { } } - return (suggestionList && !_.isEmpty(suggestionList) && isShowSuggestion && ( + // eslint-disable-next-line no-nested-ternary + return suggestionList && !_.isEmpty(suggestionList) && isShowSuggestion ? (
- )); + ) : noResults ? ( +
+ No Results +
+ ) : null; } handleClickOutside(e) { @@ -379,7 +412,10 @@ export class SearchBarInner extends Component { .then((results) => { // Nothing found? if (!results.total) { - this.setState({ suggestionList: {} }); + this.setState({ + suggestionList: {}, + noResults: true, + }); return; } // Author query? @@ -387,7 +423,7 @@ export class SearchBarInner extends Component { const suggestionList = { Author: _.map(results.items, item => ({ ...item.fields })), }; - this.setState({ suggestionList }); + this.setState({ suggestionList, noResults: false }); return; } // ALL && Tags @@ -395,7 +431,7 @@ export class SearchBarInner extends Component { this.setState({ suggestionList }); }); } else { - this.setState({ suggestionList: {} }); + this.setState({ suggestionList: {}, noResults: false }); } } @@ -419,6 +455,7 @@ export class SearchBarInner extends Component { contentAuthor: contentAuthor.fields, externalArticle: fields.externalArticle, contentUrl: fields.contentUrl, + slug: fields.slug, }; }), 'type', @@ -471,6 +508,7 @@ export class SearchBarInner extends Component { document.addEventListener('mousedown', this.handleClickOutside); }} onChange={this.handleSearchChange} + onKeyDown={this.onKeyDown} />
-

- {currentPhase.name} -

{ - challenge.status !== 'COMPLETED' ? ( + currentPhase && ( +

+ {currentPhase.name} +

+ ) + } + { + challenge.status !== 'Completed' ? (

{days > 0 && (`${days}D`)} @@ -111,7 +118,7 @@ export default function SubmissionManagement(props) { Manage your submissions

{ - isDesign && ( + isDesign && currentPhase && (

{currentPhase.name} @@ -159,7 +166,7 @@ export default function SubmissionManagement(props) { ) }

- {now.isBefore(challenge.submissionEndDate) && ( + {now.isBefore(submissionEndDate) && (
{ - if (value && _.includes(topGearCommunity.groupIds, key)) { + _.forOwn(groups, (value) => { + if (value && _.includes(topGearCommunity.groupIds, value)) { isChallengeBelongToTopgearGroup = true; return false; } diff --git a/src/shared/components/tc-communities/communities/cognitive/GetStarted/index.jsx b/src/shared/components/tc-communities/communities/cognitive/GetStarted/index.jsx index 06a89d98e4..02ae891b1c 100644 --- a/src/shared/components/tc-communities/communities/cognitive/GetStarted/index.jsx +++ b/src/shared/components/tc-communities/communities/cognitive/GetStarted/index.jsx @@ -20,8 +20,6 @@ import cardImg02 from import MarchMadnessBanner from '../MarchMadnessBanner'; -import NewsSignup from '../NewsSignup'; - import style from './style.scss'; export default function GetStarted({ baseUrl }) { @@ -88,7 +86,6 @@ export default function GetStarted({ baseUrl }) { />
- ); } diff --git a/src/shared/components/tc-communities/communities/cognitive/Home/index.jsx b/src/shared/components/tc-communities/communities/cognitive/Home/index.jsx index 58ff7af8ba..3ff47f6eb3 100644 --- a/src/shared/components/tc-communities/communities/cognitive/Home/index.jsx +++ b/src/shared/components/tc-communities/communities/cognitive/Home/index.jsx @@ -16,7 +16,6 @@ import { config, Link } from 'topcoder-react-utils'; import davePhotoUrl from 'assets/images/communities/cognitive/home/dave.jpg'; import IbmCloudBanner from '../IbmCloudBanner'; -import NewsletterSignup from '../NewsSignup'; import style from './style.scss'; @@ -317,8 +316,6 @@ export default function Home({
- - ); } diff --git a/src/shared/components/tc-communities/communities/cognitive/IbmCloudPage/index.jsx b/src/shared/components/tc-communities/communities/cognitive/IbmCloudPage/index.jsx index d0f62893df..5c0aa6c7ad 100644 --- a/src/shared/components/tc-communities/communities/cognitive/IbmCloudPage/index.jsx +++ b/src/shared/components/tc-communities/communities/cognitive/IbmCloudPage/index.jsx @@ -4,7 +4,6 @@ import React from 'react'; import Differences from './Differences'; import HeadBanner from './HeadBanner'; import JoinBlock from './JoinBlock'; -import NewsSignup from '../NewsSignup'; export default function IbmCloudPage() { return ( @@ -16,8 +15,6 @@ export default function IbmCloudPage() { {/* Hidden by the request from Trevor: the transition process won't start * until Feb 12. */} {/* */} - - ); } diff --git a/src/shared/components/tc-communities/communities/cognitive/NewsSignup/index.jsx b/src/shared/components/tc-communities/communities/cognitive/NewsSignup/index.jsx deleted file mode 100644 index 1f7b3f820a..0000000000 --- a/src/shared/components/tc-communities/communities/cognitive/NewsSignup/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import NewsletterSignup from 'components/tc-communities/NewsletterSignup'; -import React from 'react'; -import { config } from 'topcoder-react-utils'; - -import newsletterImg from - 'assets/images/communities/cognitive/newsletter.jpg'; - -import theme from './theme.scss'; - -export default function NewsSignup() { - return ( - - ); -} diff --git a/src/shared/components/tc-communities/communities/cognitive/NewsSignup/theme.scss b/src/shared/components/tc-communities/communities/cognitive/NewsSignup/theme.scss deleted file mode 100644 index f2eea78697..0000000000 --- a/src/shared/components/tc-communities/communities/cognitive/NewsSignup/theme.scss +++ /dev/null @@ -1,46 +0,0 @@ -@import "../themes/mixins"; - -.container { - @include container; - - &::before { - background: none !important; - } -} - -.content { - align-items: flex-end; - display: flex; - flex-direction: column; - position: relative; - margin: auto !important; - max-width: $screen-lg !important; - width: 100%; -} - -.form { - border-radius: 0 !important; - height: 40px !important; -} - -.formButton { - min-width: 125px; -} - -.formEmail { - border-radius: 4px !important; - height: 40px !important; - margin-right: 10px !important; -} - -.text { - @include tc-body-md; - - color: white !important; -} - -.title { - @include tc-heading-lg; - - color: white !important; -} diff --git a/src/shared/components/tc-communities/communities/cognitive/Resources/index.jsx b/src/shared/components/tc-communities/communities/cognitive/Resources/index.jsx index a5615de19b..7f1b6c5dd1 100644 --- a/src/shared/components/tc-communities/communities/cognitive/Resources/index.jsx +++ b/src/shared/components/tc-communities/communities/cognitive/Resources/index.jsx @@ -24,7 +24,6 @@ import MsgsSvg from import { Button, PrimaryButton } from 'topcoder-react-ui-kit'; import FaqItem from './FaqItem'; -import NewsSignup from '../NewsSignup'; import style from './style.scss'; @@ -324,7 +323,6 @@ export default function Resources({ - ); } diff --git a/src/shared/containers/EDU/Home.jsx b/src/shared/containers/EDU/Home.jsx index 275efaab6c..30c8455a26 100644 --- a/src/shared/containers/EDU/Home.jsx +++ b/src/shared/containers/EDU/Home.jsx @@ -3,6 +3,7 @@ */ import React from 'react'; import { config } from 'topcoder-react-utils'; +import { Helmet } from 'react-helmet'; import Viewport from 'components/Contentful/Viewport'; import SearchBar from 'components/Contentful/SearchBar/SearchBar'; import { getService } from 'services/contentful'; @@ -45,6 +46,13 @@ export default class EDUHome extends React.Component { const { taxonomy } = this.state; return (
+ + THRIVE - Grow with us. Tutorials and workshops that matter. + + + + + {/* Banner */}
diff --git a/src/shared/containers/EDU/Search.jsx b/src/shared/containers/EDU/Search.jsx index b49128c77a..6b311aa68e 100644 --- a/src/shared/containers/EDU/Search.jsx +++ b/src/shared/containers/EDU/Search.jsx @@ -13,6 +13,7 @@ import { updateQuery } from 'utils/url'; import qs from 'qs'; import LoadingIndicator from 'components/LoadingIndicator'; import SearchPageFilter from 'components/Contentful/SearchPageFilter/SearchPageFilter'; +import { Helmet } from 'react-helmet'; // Partials import ResultTabs from './partials/ResultTabs'; // CSS @@ -91,6 +92,13 @@ export default class EDUSearch extends React.Component { if (!taxonomy) return ; return (
+ + THRIVE - Search {`${query.title}`} + + + + + {/* Banner */}
diff --git a/src/shared/containers/EDU/Tracks.jsx b/src/shared/containers/EDU/Tracks.jsx index 0a1b4c8398..d98099191e 100644 --- a/src/shared/containers/EDU/Tracks.jsx +++ b/src/shared/containers/EDU/Tracks.jsx @@ -14,6 +14,7 @@ import qs from 'qs'; import TracksTree from 'components/Contentful/TracksTree/TracksTree'; import LoadingIndicator from 'components/LoadingIndicator'; import TracksFilter from 'components/Contentful/TracksFilter/TracksFilter'; +import { Helmet } from 'react-helmet'; // SVGs & Assets import Dev from 'assets/images/img-development.png'; import Design from 'assets/images/img_design.png'; @@ -167,6 +168,13 @@ export default class EDUTracks extends React.Component { if (!taxonomy) return ; return (
+ + THRIVE - {`${query.track}`} + + + + + {/* Banner */}
)) - ) : (

Nothing Found

) + ) : (

No results found

) } { articles.total > articles.items.length ? ( @@ -193,7 +193,7 @@ export default class ResultTabs extends React.Component { )) }
- ) : (

Nothing Found

) + ) : (

No results found

) } { videos.total > videos.items.length ? ( @@ -225,7 +225,7 @@ export default class ResultTabs extends React.Component { /> ); }) - ) : (

Nothing Found

) + ) : (

No results found

) } { posts.total > posts.items.length ? ( diff --git a/src/shared/containers/challenge-detail/index.jsx b/src/shared/containers/challenge-detail/index.jsx index 3bb14e4c1b..fb27c202ca 100644 --- a/src/shared/containers/challenge-detail/index.jsx +++ b/src/shared/containers/challenge-detail/index.jsx @@ -244,7 +244,7 @@ class ChallengeDetailPageContainer extends React.Component { } const { track } = nextProps.challenge; - if (track === COMPETITION_TRACKS.DESIGN && thriveArticles.length === 0) { + if (track !== COMPETITION_TRACKS.DESIGN && thriveArticles.length === 0) { // filter all tags with value 'Other' const tags = _.filter(nextProps.challenge.tags, tag => tag !== 'Other'); if (tags.length > 0) { @@ -558,8 +558,8 @@ class ChallengeDetailPageContainer extends React.Component { hasRegistered={challenge.isRegistered} unregistering={unregistering} submissionEnded={submissionEnded} - isMM - isLegacyMM + isMM={isMM} + isLegacyMM={isLegacyMM} loadingMMSubmissionsForChallengeId={loadingMMSubmissionsForChallengeId} auth={auth} loadMMSubmissions={loadMMSubmissions} diff --git a/src/shared/services/contentful.js b/src/shared/services/contentful.js index 4508f76d6d..60fc4a5a50 100644 --- a/src/shared/services/contentful.js +++ b/src/shared/services/contentful.js @@ -346,8 +346,8 @@ class Service { query.query = tags.join(' '); } } - if (startDate) query['sys.createdAt[gte]'] = startDate; - if (endDate) query['sys.createdAt[lte]'] = endDate; + if (startDate) query['fields.creationDate[gte]'] = startDate; + if (endDate) query['fields.creationDate[lte]'] = endDate; if (phrase) query.query = phrase; if (title) query['fields.title[match]'] = title; const content = {};