Skip to content

Release v1.17.3 #6380

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1d3c7c7
fix social share for Contentful routes
kkartunov May 24, 2022
fc9782f
ci: on beta
kkartunov May 24, 2022
b068d13
domain fix for social thumb
kkartunov May 25, 2022
807f6fa
add csp header for tco
eisbilir May 25, 2022
d46f467
combine tco headers with veterans
eisbilir May 26, 2022
d8c750a
Merge pull request #6358 from eisbilir/fix-security-headers
luizrrodrigues May 26, 2022
9270256
ci: deploy fix-security-headers to Stag env
luizrrodrigues May 26, 2022
0cda9c0
ci: deploy develop branch to QA env
luizrrodrigues Jun 6, 2022
4af7415
Add error and res for logging more details
kkartunov Jun 8, 2022
9697367
Merge pull request #6378 from topcoder-platform/debug-CMS-error
luizrrodrigues Jun 9, 2022
09f481a
add more infos for debug
kkartunov Jun 9, 2022
373ebbe
Merge pull request #6379 from topcoder-platform/debug-CMS-error
kkartunov Jun 9, 2022
87ba361
enhance mm dashboard
nursoltan-chemantics Jun 9, 2022
4387367
add opacity
nursoltan-chemantics Jun 12, 2022
2bd8e34
fix test fail
nursoltan-chemantics Jun 12, 2022
951be91
Merge pull request #6381 from nursoltan-s/enhance-mm-dashboard
rakibansary Jun 13, 2022
73ddb5f
dump action for inspection
kkartunov Jun 13, 2022
38c0dc8
ci: on test
kkartunov Jun 13, 2022
e03855e
JSON.stringify CMS errors
kkartunov Jun 13, 2022
081bfa6
JSON.stringify all objects for error dump
kkartunov Jun 13, 2022
342a01f
Fix CMS-related error for NotFound entries
kkartunov Jun 13, 2022
9c93b21
catch unhandled exceptions
kkartunov Jun 13, 2022
25c9c6f
Merge pull request #6383 from topcoder-platform/debug-CMS-error
kkartunov Jun 13, 2022
7b43f2e
Merge branch 'develop' into social-share-thumb
kkartunov Jun 13, 2022
39c8f92
Merge pull request #6377 from topcoder-platform/social-share-thumb
kkartunov Jun 13, 2022
474e96e
Merge pull request #6363 from topcoder-platform/fix-security-headers
luizrrodrigues Jun 14, 2022
f36f059
ci: deploy develop branch on Dev env
luizrrodrigues Jun 14, 2022
785ebfb
fix indexOf on null image
kkartunov Jun 14, 2022
a4123f9
Merge pull request #6385 from topcoder-platform/social-share-thumb
luizrrodrigues Jun 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -349,14 +349,14 @@ workflows:
filters:
branches:
only:
- reskin
- develop
# This is alternate dev env for parallel testing
- "build-test":
context : org-global
filters:
branches:
only:
- circleci-fix
- debug-CMS-error
# This is alternate dev env for parallel testing
- "build-qa":
context : org-global
Expand All @@ -370,7 +370,6 @@ workflows:
filters:
branches:
only:
- footer-update
- reskin
# This is stage env for production QA releases
- "build-prod-staging":
Expand All @@ -379,7 +378,7 @@ workflows:
branches:
only:
- develop
- stat_marathon_match_link
- fix-security-headers
# Production builds are exectuted
# when PR is merged to the master
# Don't change anything in this configuration
Expand Down
11 changes: 9 additions & 2 deletions src/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ ts = moment(ts.timestamp).valueOf();
const sw = `sw.js${process.env.NODE_ENV === 'production' ? '' : '?debug'}`;
const swScope = '/challenges'; // we are currently only interested in improving challenges pages

const tcoPattern = new RegExp(/^tco\d{2}\.topcoder(?:-dev)?\.com$/i);

const EXTRA_SCRIPTS = [
`<script type="application/javascript">
if('serviceWorker' in navigator){
Expand Down Expand Up @@ -135,13 +137,14 @@ async function onExpressJsSetup(server) {
res.header('Referrer-Policy', 'strict-origin-when-cross-origin');
res.header('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');

if (req.url.startsWith('/__community__/veterans') || req.hostname === 'veterans.topcoder.com') {
if (req.url.startsWith('/__community__/veterans') || req.hostname === 'veterans.topcoder.com' || req.url.startsWith('/__community__/tco') || tcoPattern.test(req.hostname)) {
res.header(
'Content-Security-Policy',
"default-src 'self';"
+ " script-src 'report-sample' 'self' 'unsafe-inline' 'unsafe-eval'"
+ ` ${config.CDN.PUBLIC}`
+ ' http://www.google-analytics.com'
+ ' https://www.google-analytics.com'
+ ' https://43d132d5dbff47c59d9d53ad448f93c2.js.ubembed.com'
+ ' https://assets.ubembed.com'
+ ' https://assets.zendesk.com'
Expand Down Expand Up @@ -187,6 +190,7 @@ async function onExpressJsSetup(server) {
+ ` ${config.URL.AUTH}`
+ ' https://www.youtube.com;'
+ " img-src 'self'"
+ ' data:'
+ ` ${config.CDN.PUBLIC}`
+ ' https://cdn.segment.com'
+ ' https://d1of0acg2orgco.cloudfront.net'
Expand All @@ -196,11 +200,14 @@ async function onExpressJsSetup(server) {
+ ' https://heapanalytics.com'
+ ' https://q.quora.com'
+ ' https://topcoder-prod-media.s3.amazonaws.com'
+ ' https://topcoder-dev-media.s3.amazonaws.com'
+ ' https://www.facebook.com'
+ ' https://www.google-analytics.com'
+ ' https://www.google.com'
+ ' https://www.googletagmanager.com'
+ ' https://i.ytimg.com;'
+ ' https://i.ytimg.com'
+ ' https://images.contentful.com'
+ ' https://d0.awsstatic.com/logos/;'
+ " manifest-src 'self';"
+ " media-src 'self';"
+ ' report-uri https://623d4c23f90d055298b24042.endpoint.csper.io/?v=0;'
Expand Down
46 changes: 27 additions & 19 deletions src/shared/actions/contentful.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getService } from 'services/contentful';
import { config, redux } from 'topcoder-react-utils';
import { removeTrailingSlash } from 'utils/url';
import { menuItemBuilder, target as urlTarget } from 'utils/contentful';
import { services } from 'topcoder-react-lib';
import { services, logger } from 'topcoder-react-lib';

const ERRMSG_UNKNOWN_TARGET = 'Unknown action target';

Expand Down Expand Up @@ -91,15 +91,19 @@ async function getContentDone(operationId, contentId, target, preview, spaceName
environment,
});
let content;
switch (target) {
case TARGETS.ASSETS:
content = await service.getAsset(contentId);
break;
case TARGETS.ENTRIES:
content = await service.getEntry(contentId);
break;
default:
throw new Error(ERRMSG_UNKNOWN_TARGET);
try {
switch (target) {
case TARGETS.ASSETS:
content = await service.getAsset(contentId);
break;
case TARGETS.ENTRIES:
content = await service.getEntry(contentId);
break;
default:
throw new Error(ERRMSG_UNKNOWN_TARGET);
}
} catch (e) {
logger.error('getContentDone error', e);
}

return {
Expand Down Expand Up @@ -141,15 +145,19 @@ async function queryContentDone(operationId, queryId, target,
environment,
});
let data;
switch (target) {
case TARGETS.ASSETS:
data = await service.queryAssets(query);
break;
case TARGETS.ENTRIES:
data = await service.queryEntries(query);
break;
default:
throw new Error(ERRMSG_UNKNOWN_TARGET);
try {
switch (target) {
case TARGETS.ASSETS:
data = await service.queryAssets(query);
break;
case TARGETS.ENTRIES:
data = await service.queryEntries(query);
break;
default:
throw new Error(ERRMSG_UNKNOWN_TARGET);
}
} catch (e) {
logger.error('queryContentDone error', e);
}

return {
Expand Down
2 changes: 1 addition & 1 deletion src/shared/components/Contentful/Route.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function ChildRoutesLoader(props) {
<React.Fragment>
<MetaTags
description={fields.description}
image={fields.thumbnail}
image={fields.socialThumbnail}
siteName={fields.socialSiteName}
socialDescription={fields.socialDescription}
socialTitle={fields.socialTitle}
Expand Down
5 changes: 4 additions & 1 deletion src/shared/components/MetaTags.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ function MetaTags({
feed,
feedTitle,
}) {
const img = `${domain}${image}`;
let img = `${domain}${image}`;
if (image && (image.indexOf('http://') === 0 || image.indexOf('https://') === 0)) {
img = `${image}`;
}
const socTitle = socialTitle || title;
const socDesc = socialDescription || description;
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
/* eslint-disable react/no-this-in-sfc */
import React from 'react';
import React, { useState } from 'react';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import PT from 'prop-types';
import moment from 'moment';
import { getRatingColor } from 'utils/tc';
import { getHighlightedColor, getRatingColor, getUnSelectedColors } from 'utils/tc';
import DefaultUserImage from 'assets/images/ico-user-default.png';

import './styles.scss';
import _ from 'lodash';
import styles from './styles.scss';

export default function Graph({ statisticsData, baseline, awardLine }) {
const [point, setPoint] = useState(null);

const flatData = [];
const dates = [];
_.each(statisticsData, (entry) => {
Expand All @@ -24,28 +26,71 @@ export default function Graph({ statisticsData, baseline, awardLine }) {
});
});

const pointDatas = _.map(flatData, (data) => {
let color;
let isSelected = false;
if (point) {
isSelected = point.customData.handle === data.handle;
if (isSelected) {
color = getHighlightedColor(data.rating || 0);
} else {
color = getUnSelectedColors(data.rating || 0);
}
} else {
color = data.ratingColor || getRatingColor(data.rating || 0);
}
return {
x: moment(data.created).valueOf(),
y: _.max([0, data.score ? (parseFloat(data.score)) : 0]),
name: data.handle,
color,
customData: data,
marker: {
enabled: true,
width: 'circle',
radius: isSelected ? 6 : 4,
},
className: !isSelected && point ? styles.selectedPoint : '',
};
});

const options = {
plotOptions: {
line: {
events: {
click() {
this.group.toFront();
},
},
},
},
chart: {
type: 'scatter',
backgroundColor: '#fff',
events: {
click: () => {
setPoint(null);
},
},
},
title: {
text: '',
},
series: [
{
data: _.map(flatData, data => ({
x: moment(data.created).valueOf(),
y: _.max([0, data.score ? (parseFloat(data.score)) : 0]),
name: data.handle,
color: data.ratingColor
|| getRatingColor(data.rating
|| 0),
customData: data,
})),
data: pointDatas,
pointStart: moment(_.min(dates)).valueOf(),
pointInterval: 24 * 3600 * 1000,
backgroundColor: 'rgb(51,51,51)',
point: {
events: {
click: (e) => {
if (e && e.point) {
setPoint(e.point);
}
},
},
},
},
],
legend: {
Expand Down Expand Up @@ -106,23 +151,27 @@ export default function Graph({ statisticsData, baseline, awardLine }) {
},
tooltip: {
formatter() {
const str = `
<div style="border-radius:4px; padding-top: 15px; padding-left: 10px;">
<img height="30" width="30" src="${this.point.customData.photoUrl || DefaultUserImage}" style="position: absolute; border-radius: 50%;" />
<p style="margin-left: 50px">${this.point.customData.handle}</p>
<br />
<p style="margin-left: 50px;">${this.point.customData.submissionCount} submissions</p>
<p style="margin-left: 50px;">Score: ${this.y}</p>
<p style="margin-left: 50px;">Submitted: ${moment(this.point.customData.created).format('MM/DD/YYYY')} </p>
</div>
`;
return str;
const currentPointer = this.point || point;
if (currentPointer) {
const str = `
<div style="border-radius:4px; padding-top: 15px; padding-left: 10px;">
<img height="30" width="30" src="${currentPointer.customData.photoUrl || DefaultUserImage}" style="position: absolute; border-radius: 50%;" />
<p style="margin-left: 50px">${currentPointer.customData.handle}</p>
<br />
<p style="margin-left: 50px;">${currentPointer.customData.submissionCount} submissions</p>
<p style="margin-left: 50px;">Score: ${this.y}</p>
<p style="margin-left: 50px;">Submitted: ${moment(currentPointer.customData.created).format('MM/DD/YYYY')} </p>
</div>
`;
return str;
}
return false;
},
useHTML: true,
style: {
color: '#fff',
},
backgroundColor: 'rgb(51,51,51)',
backgroundColor: point ? '#2e2e2e' : 'rgb(51,51,51)',
shared: true,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@
padding-right: 16px;
}
}

.selectedPoint {
z-index: 1000 !important;
opacity: 0.9;
}
4 changes: 2 additions & 2 deletions src/shared/reducers/contentful/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ function create(init) {
const spaceName = _.get(payload, 'spaceName') || config.CONTENTFUL.DEFAULT_SPACE_NAME;
const environment = _.get(payload, 'environment') || config.CONTENTFUL.DEFAULT_ENVIRONMENT;
const res = _.get(newState, `${spaceName}.${environment}`);
if (error || !res) {
logger.log('CMS-related error');
if ((error && payload && payload.sys && payload.sys.id !== 'NotFound') || !res) {
logger.log('CMS-related error', JSON.stringify(action), config.CONTENTFUL.DEFAULT_SPACE_NAME, config.CONTENTFUL.DEFAULT_ENVIRONMENT, JSON.stringify(res), JSON.stringify(newState));
return state;
}
const st = state[spaceName][environment];
Expand Down
45 changes: 45 additions & 0 deletions src/shared/utils/tc.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,57 @@ export const RATING_COLORS = [{
color: '#EF3A3A' /* Red */,
limit: Infinity,
}];

export function getRatingColor(rating) {
let i = 0; const r = Number(rating);
while (RATING_COLORS[i].limit <= r) i += 1;
return RATING_COLORS[i].color || 'black';
}

export const HIGHLIGHTED_RATING_COLORS = [{
color: '#464646' /* Grey */,
limit: 900,
}, {
color: '#00ab00' /* Green */,
limit: 1200,
}, {
color: '#3748ff' /* Blue */,
limit: 1500,
}, {
color: '#ffe879' /* Yellow */,
limit: 2200,
}, {
color: '#ff2a2a' /* Red */,
limit: Infinity,
}];
export function getHighlightedColor(rating) {
let i = 0; const r = Number(rating);
while (HIGHLIGHTED_RATING_COLORS[i].limit <= r) i += 1;
return HIGHLIGHTED_RATING_COLORS[i].color || 'black';
}

export const UNSELECTED_RATING_COLORS = [{
color: '#f3f3f3' /* Grey */,
limit: 900,
}, {
color: '#e6f6e6' /* Green */,
limit: 1200,
}, {
color: '#c5c8ef' /* Blue */,
limit: 1500,
}, {
color: '#fff5c4' /* Yellow */,
limit: 2200,
}, {
color: '#f47d7d' /* Red */,
limit: Infinity,
}];
export function getUnSelectedColors(rating) {
let i = 0; const r = Number(rating);
while (UNSELECTED_RATING_COLORS[i].limit <= r) i += 1;
return UNSELECTED_RATING_COLORS[i].color || 'black';
}

/**
* Given ExpressJS HTTP request it extracts Topcoder auth tokens from cookies,
* if they are present there and are not expired.
Expand Down