Skip to content

Commit e8e1768

Browse files
authored
Merge pull request #4923 from topcoder-platform/develop
Release 2020-09-15
2 parents c57652c + 27118ee commit e8e1768

File tree

27 files changed

+171
-71
lines changed

27 files changed

+171
-71
lines changed

.circleci/config.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,15 @@ workflows:
230230
filters:
231231
branches:
232232
only:
233-
- milestone-20200917
233+
- milestone-20200924
234234
- develop
235235
# This is alternate dev env for parallel testing
236236
- "build-test":
237237
context : org-global
238238
filters:
239239
branches:
240240
only:
241+
- hot-fix-ad-code
241242
- feature-contentful
242243
# This is alternate dev env for parallel testing
243244
- "build-qa":

__tests__/shared/__snapshots__/index.jsx.snap

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ exports[`Snapshot match 1`] = `
1919
href="/challenges/manifest.json"
2020
rel="manifest"
2121
/>
22+
<script
23+
async={true}
24+
src="https://43d132d5dbff47c59d9d53ad448f93c2.js.ubembed.com"
25+
/>
2226
</HelmetWrapper>
2327
<withRouter(Connect(Routes)) />
2428
<Connect(ErrorMessageContainer) />
@@ -53,6 +57,10 @@ exports[`Snapshot match 2`] = `
5357
href="/challenges/manifest.json"
5458
rel="manifest"
5559
/>
60+
<script
61+
async={true}
62+
src="https://43d132d5dbff47c59d9d53ad448f93c2.js.ubembed.com"
63+
/>
5664
</HelmetWrapper>
5765
<withRouter(Connect(Routes)) />
5866
<Connect(ErrorMessageContainer) />

__tests__/shared/components/ChallengeTile/__snapshots__/index.jsx.snap

+7-4
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,15 @@ exports[`renders marathon 1`] = `
202202
className="src-shared-components-ChallengeTile-___style__completed-challenge___3w5tT"
203203
>
204204
<header>
205-
<a
205+
<Link
206206
className="src-shared-components-ChallengeTile-___style__name___1jF7j"
207-
href="https://community.topcoder.com/longcontest/stats/?module=ViewOverview&rd=17153"
207+
replace={false}
208+
to="/challenges/15404"
208209
>
209-
2018 TCO Marathon
210-
</a>
210+
<span>
211+
2018 TCO Marathon
212+
</span>
213+
</Link>
211214
<p
212215
className="src-shared-components-ChallengeTile-___style__subtrack-color___2AJaw"
213216
>

__tests__/shared/components/Header/__snapshots__/index.jsx.snap

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ exports[`Default render 1`] = `
118118
},
119119
Object {
120120
"href": "https://www.topcoder-dev.com/blog",
121+
"openNewTab": true,
121122
"title": "Blog",
122123
},
123124
Object {

__tests__/shared/components/ProfilePage/__snapshots__/index.jsx.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ exports[`renders a full Profile correctly 1`] = `
5858
}
5959
onShowBadges={[Function]}
6060
showBadgesButton={true}
61-
wins={3}
61+
wins={0}
6262
/>
6363
</div>
6464
</Sticky>

config/default.js

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ module.exports = {
160160
COMMUNITY_API: 'http://localhost:8000',
161161
COMMUNITY_APP_GITHUB_ISSUES: 'https://github.com/topcoder-platform/community-app/issues',
162162
EMAIL_VERIFY_URL: 'http://www.topcoder-dev.com/settings/account/changeEmail',
163+
ABANDONMENT_EMBED: 'https://43d132d5dbff47c59d9d53ad448f93c2.js.ubembed.com',
163164
},
164165

165166
/* Information about Topcoder user groups can be cached in various places.
@@ -370,6 +371,7 @@ module.exports = {
370371
{
371372
title: 'Blog',
372373
href: 'https://www.topcoder-dev.com/blog',
374+
openNewTab: true,
373375
},
374376
{
375377
title: 'Thrive',

config/production.js

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ module.exports = {
171171
{
172172
title: 'Blog',
173173
href: 'https://www.topcoder.com/blog',
174+
openNewTab: true,
174175
},
175176
{
176177
title: 'Thrive',

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@
137137
"tc-accounts": "git+https://github.com/appirio-tech/accounts-app.git#dev",
138138
"tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3",
139139
"tc-ui": "^1.0.12",
140-
"topcoder-react-lib": "1.0.4",
141-
"topcoder-react-ui-kit": "2.0.0",
140+
"topcoder-react-lib": "1.0.5",
141+
"topcoder-react-ui-kit": "2.0.1",
142142
"topcoder-react-utils": "0.7.8",
143143
"turndown": "^4.0.2",
144144
"url-parse": "^1.4.1",

src/shared/app.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Routes from 'routes';
1111
import ErrorMessage from 'containers/ErrorMessage';
1212
import ErrorIcons from 'containers/ErrorIcons';
1313

14-
import { DevTools, isomorphy } from 'topcoder-react-utils';
14+
import { DevTools, isomorphy, config } from 'topcoder-react-utils';
1515

1616
import ExtendedReduxToastr from 'containers/toastr';
1717

@@ -37,6 +37,7 @@ export default function App() {
3737
<Helmet htmlAttributes={{ lang: 'en' }}>
3838
<meta name="theme-color" content="#FFFFFF" />
3939
<link rel="manifest" href="/challenges/manifest.json" />
40+
<script src={config.URL.ABANDONMENT_EMBED} async />
4041
</Helmet>
4142
<Routes />
4243
<ErrorMessage />

src/shared/components/ChallengeTile/index.jsx

+4-14
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Challenge tile.
33
*/
44
/* eslint-env browser */
5-
import _ from 'lodash';
65
import React from 'react';
76
import PT from 'prop-types';
87
import { Link } from 'react-router-dom';
@@ -83,36 +82,27 @@ class ChallengeTile extends React.Component {
8382
margin: '10px 5px',
8483
};
8584

86-
const isDataScience = track === COMPETITION_TRACKS.DATA_SCIENCE;
8785
const isDevelopment = track === COMPETITION_TRACKS.DEVELOP;
8886
const isDesign = track === COMPETITION_TRACKS.DESIGN;
8987

90-
const roundId = isDataScience ? _.get(challenge, 'rounds.0.id') : 0;
91-
9288
return (
9389
<div styleName="challenge tile" style={extraStyle}>
9490
<div styleName={outStyleName}>
9591
<div styleName="completed-challenge">
9692
<header>
97-
{ !isDataScience && (!challenge.isPrivate
93+
{ !challenge.isPrivate
9894
? (
9995
<Link to={`/challenges/${challenge.id}`} styleName="name">
10096
<span>
10197
{ challenge.name }
10298
</span>
10399
</Link>
104-
) : (
100+
)
101+
: (
105102
<span>
106103
{ challenge.name }
107104
</span>
108-
)) }
109-
110-
{ isDataScience
111-
&& (
112-
<a styleName="name" href={`https://community.topcoder.com/longcontest/stats/?module=ViewOverview&rd=${roundId}`}>
113-
{ challenge.name }
114-
</a>
115-
) }
105+
)}
116106

117107
<p styleName="subtrack-color">
118108
{underscoreReplace(type)}

src/shared/components/Contentful/Article/Article.jsx

+22-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import LoadingIndicator from 'components/LoadingIndicator';
1515
import YouTubeVideo from 'components/YouTubeVideo';
1616
import moment from 'moment';
1717
import localStorage from 'localStorage';
18-
import { config, Link, isomorphy } from 'topcoder-react-utils';
18+
import { Helmet } from 'react-helmet';
19+
import {
20+
config, Link, isomorphy,
21+
} from 'topcoder-react-utils';
1922
import qs from 'qs';
2023
// SVGs and assets
2124
import GestureIcon from 'assets/images/icon-gesture.svg';
@@ -110,9 +113,27 @@ export default class Article extends React.Component {
110113
if (isomorphy.isClientSide()) {
111114
shareUrl = encodeURIComponent(window.location.href);
112115
}
116+
const description = htmlToText.fromString(
117+
ReactDOMServer.renderToString(markdown(fields.content)),
118+
{
119+
ignoreHref: true,
120+
ignoreImage: true,
121+
singleNewLineParagraphs: true,
122+
uppercaseHeadings: false,
123+
},
124+
).substring(0, CONTENT_PREVIEW_LENGTH);
113125

114126
return (
115127
<React.Fragment>
128+
<Helmet>
129+
<title>{fields.title}</title>
130+
<meta name="title" property="og:title" content={fields.title} />
131+
<meta name="description" property="og:description" content={description} />
132+
<meta name="description" property="description" content={description} />
133+
<meta name="twitter:description" content={description} />
134+
<meta name="image" property="og:image" content={fields.featuredImage ? `https:${subData.assets.items[fields.featuredImage.sys.id].fields.file.url}` : null} />
135+
<meta name="twitter:image" content={fields.featuredImage ? `https:${subData.assets.items[fields.featuredImage.sys.id].fields.file.url}` : null} />
136+
</Helmet>
116137
{/* Banner */}
117138
{
118139
fields.featuredImage ? (

src/shared/components/Contentful/SearchBar/SearchBar.jsx

+43-5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class SearchBarInner extends Component {
5656
this.getSuggestionList = this.getSuggestionList.bind(this);
5757
this.handleSearchChange = this.handleSearchChange.bind(this);
5858
this.handleClickOutside = this.handleClickOutside.bind(this);
59+
this.onKeyDown = this.onKeyDown.bind(this);
5960
// using debounce to avoid processing or requesting too much
6061
this.updateSuggestionListWithNewSearch = _.debounce(
6162
this.updateSuggestionListWithNewSearch.bind(this), 400,
@@ -71,6 +72,29 @@ export class SearchBarInner extends Component {
7172
document.removeEventListener('mousedown', this.handleClickOutside);
7273
}
7374

75+
onKeyDown(e) {
76+
const { inputlVal, selectedFilter } = this.state;
77+
if (inputlVal && e.which === 13) {
78+
const searchQuery = {};
79+
if (this.searchFieldRef && this.searchFieldRef.value) {
80+
if (selectedFilter.name === 'Tags') {
81+
searchQuery.tags = [this.searchFieldRef.value];
82+
}
83+
if (selectedFilter.name === 'All') {
84+
searchQuery.phrase = this.searchFieldRef.value;
85+
}
86+
if (selectedFilter.name === 'Title') {
87+
searchQuery.title = this.searchFieldRef.value;
88+
}
89+
}
90+
if (selectedFilter.name !== 'Author') {
91+
window.location.href = `${config.TC_EDU_BASE_PATH}${config.TC_EDU_SEARCH_PATH}?${qs.stringify(searchQuery)}`;
92+
} else {
93+
window.location.href = `${config.TC_EDU_BASE_PATH}${config.TC_EDU_SEARCH_PATH}?author=${inputlVal}`;
94+
}
95+
}
96+
}
97+
7498
/**
7599
* Set the search field ref
76100
*/
@@ -136,6 +160,7 @@ export class SearchBarInner extends Component {
136160
isShowSuggestion,
137161
suggestionList,
138162
selectedFilter,
163+
noResults,
139164
} = this.state;
140165

141166
const searchQuery = {};
@@ -151,7 +176,8 @@ export class SearchBarInner extends Component {
151176
}
152177
}
153178

154-
return (suggestionList && !_.isEmpty(suggestionList) && isShowSuggestion && (
179+
// eslint-disable-next-line no-nested-ternary
180+
return suggestionList && !_.isEmpty(suggestionList) && isShowSuggestion ? (
155181
<div
156182
className={theme['popup-search-result']}
157183
ref={this.setPopupSearchResultRef}
@@ -319,7 +345,14 @@ export class SearchBarInner extends Component {
319345
) : null
320346
}
321347
</div>
322-
));
348+
) : noResults ? (
349+
<div
350+
className={theme['popup-search-result']}
351+
ref={this.setPopupSearchResultRef}
352+
>
353+
<span>No Results</span>
354+
</div>
355+
) : null;
323356
}
324357

325358
handleClickOutside(e) {
@@ -379,23 +412,26 @@ export class SearchBarInner extends Component {
379412
.then((results) => {
380413
// Nothing found?
381414
if (!results.total) {
382-
this.setState({ suggestionList: {} });
415+
this.setState({
416+
suggestionList: {},
417+
noResults: true,
418+
});
383419
return;
384420
}
385421
// Author query?
386422
if (selectedFilter.name === 'Author') {
387423
const suggestionList = {
388424
Author: _.map(results.items, item => ({ ...item.fields })),
389425
};
390-
this.setState({ suggestionList });
426+
this.setState({ suggestionList, noResults: false });
391427
return;
392428
}
393429
// ALL && Tags
394430
const suggestionList = this.groupResults(results);
395431
this.setState({ suggestionList });
396432
});
397433
} else {
398-
this.setState({ suggestionList: {} });
434+
this.setState({ suggestionList: {}, noResults: false });
399435
}
400436
}
401437

@@ -419,6 +455,7 @@ export class SearchBarInner extends Component {
419455
contentAuthor: contentAuthor.fields,
420456
externalArticle: fields.externalArticle,
421457
contentUrl: fields.contentUrl,
458+
slug: fields.slug,
422459
};
423460
}),
424461
'type',
@@ -471,6 +508,7 @@ export class SearchBarInner extends Component {
471508
document.addEventListener('mousedown', this.handleClickOutside);
472509
}}
473510
onChange={this.handleSearchChange}
511+
onKeyDown={this.onKeyDown}
474512
/>
475513
<div className={theme.dropdown}>
476514
<button

src/shared/components/Contentful/SearchBar/themes/default.scss

+4
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ $link-color: #0d61bf;
156156
overflow-y: auto;
157157
box-shadow: 0 25px 50px 0 rgba(0, 0, 0, 0.15);
158158
z-index: 999;
159+
160+
> span {
161+
margin-left: 15px;
162+
}
159163
}
160164

161165
.icon-search {

0 commit comments

Comments
 (0)