Skip to content

Commit

Permalink
Merge pull request #64 from topcoder-platform/develop
Browse files Browse the repository at this point in the history
Group filter and blog feed
  • Loading branch information
ajefts authored Jun 9, 2017
2 parents c6ceef1 + 1099974 commit 44d5746
Show file tree
Hide file tree
Showing 50 changed files with 566 additions and 216 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ We use [https://logentries.com](https://logentries.com) to track the logs. Log E

### Development Notes
- [Challenge Listing - Notes from winning submission](docs/challenge-listing-notes.md)
- [**How to Add a New Topcoder Community?**](docs/how-to-add-a-new-topcoder-community.md)
- [Leaderboard - Notes from the winning submission](docs/leaderboard-notes.md)
- [Why Reducer Factories and How to Use Them?](docs/why-reducer-factories-and-how-to-use-them.md)
- [~~WYSIWYG Page Editor - Notes from the winning submission~~](docs/editor-notes.pdf)
- [**Why Reducer Factories and How to Use Them?**](docs/why-reducer-factories-and-how-to-use-them.md)

### Current Status

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ test('Matches shallow shapshot', () => {
submissionObjects={[{
submissionId: 12345,
}]}
type="DESIGN"
/>
));
expect(renderer.getRenderOutput()).toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ exports[`Snapshot match 2`] = `
>
<img
alt="preview"
className="src-shared-components-SubmissionManagement-Submission-___styles__design-img___1klwr"
className="src-shared-components-SubmissionManagement-Submission-___styles__dev-img___rbFEF"
src="https://studio.topcoder-dev.com?module=DownloadSubmission&sbmid=12345&sbt=tiny"
/>
</td>
Expand All @@ -72,15 +72,6 @@ exports[`Snapshot match 2`] = `
>
Invalid date
</td>
<td
className="src-shared-components-SubmissionManagement-Submission-___styles__status-col___1Byk3"
>
<ScreeningStatus
onShowDetails={[Function]}
screeningObject={Object {}}
submissionId={12345}
/>
</td>
<td>
<div
className="src-shared-components-SubmissionManagement-Submission-___styles__action-col___2M1RY"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ exports[`Matches shallow shapshot 1`] = `
onlineReviewUrl=""
showDetails={Set {}}
submissionObjects={Array []}
type=""
type="Challenge Track"
/>
</div>
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ exports[`Matches shallow shapshot 1`] = `
<th>
Submission Date
</th>
<th
className="src-shared-components-SubmissionManagement-SubmissionsTable-___styles__status___1X1-o"
>
Screening Status
</th>
<th
className="src-shared-components-SubmissionManagement-SubmissionsTable-___styles__actions___16pRz"
>
Expand All @@ -37,7 +42,7 @@ exports[`Matches shallow shapshot 1`] = `
"submissionId": 12345,
}
}
type=""
type="DESIGN"
/>
<tr
className="src-shared-components-SubmissionManagement-SubmissionsTable-___styles__submission-row___1uclT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,56 +157,9 @@ exports[`Snapshot match 1`] = `
title="Compete in Challenges and Win Cash"
/>
</ThemedSection>
<ThemedSection
composeTheme="deeply"
link={null}
mapThemrProps={[Function]}
theme={Object {}}
title="Latest News"
>
<ThemedArticleCard
composeTheme="deeply"
imageSrc="/themes/wipro/home/news-01.jpg"
link={
Object {
"title": "Read More",
"url": ".",
}
}
mapThemrProps={[Function]}
text="There are advances being made in science and technology everyday, and a good example of this is the LCD monitor. LCD monitors have"
theme={Object {}}
title="How Does An IOS 10 LCD Work"
/>
<ThemedArticleCard
composeTheme="deeply"
imageSrc="/themes/wipro/home/news-02.jpg"
link={
Object {
"title": "Read More",
"url": ".",
}
}
mapThemrProps={[Function]}
text="HDMI, or high definition multimedia interface, is a type of audio and video interface that is used for the transmission of uncompressed"
theme={Object {}}
title="Video Games Playing With Imagination "
/>
<ThemedArticleCard
composeTheme="deeply"
imageSrc="/themes/wipro/home/news-03.jpg"
link={
Object {
"title": "Read More",
"url": ".",
}
}
mapThemrProps={[Function]}
text="If you are in the market for a computer, there are a number of factors to consider. Will it be used for your home, your office or"
theme={Object {}}
title="Myspace Layouts The Missing Element"
/>
</ThemedSection>
<NewsSection
news={Array []}
/>
<ThemedNewsletterSignup
buttonText="Sign Up"
composeTheme="deeply"
Expand Down
4 changes: 4 additions & 0 deletions __tests__/shared/containers/tc-communities/Page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const mockState = {
isMobileOpen: false,
failed: false,
},
news: {},
},
auth: {
profile: {
Expand All @@ -51,6 +52,7 @@ const mockState = {
const mockState2 = {
tcCommunities: {
meta: {},
news: {},
},
auth: {
profile: {},
Expand All @@ -64,6 +66,7 @@ const mockState3 = {
communitySelector: COMMUNITY_SELECTOR,
pageId: 'somePageId',
},
news: {},
},
auth: {
profile: {},
Expand All @@ -83,6 +86,7 @@ const mockState4 = {
pageId: 'somePageId',
isMobileOpen: true,
},
news: {},
},
auth: {
profile: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ exports[`Matches shapshot 1`] = `
history={Object {}}
isMobileOpen={false}
loadMetaData={[Function]}
loadNews={[Function]}
loadingNews={false}
location={Object {}}
match={
Object {
Expand Down Expand Up @@ -56,6 +58,7 @@ exports[`Matches shapshot 1`] = `
}
}
mobileToggle={[Function]}
news={null}
openMenu={[Function]}
openMobileMenu={[Function]}
openSearch={[Function]}
Expand Down
2 changes: 2 additions & 0 deletions config/webpack/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ module.exports = {
noParse: [
/* NodeJS library for https://logentries.com. It is server-side only. */
/\/node_modules\/le_node/,

/\/node_modules\/xml2json/,
],
rules: [{
test: /\.(eot|otf|svg|ttf|woff|woff2)$/,
Expand Down
2 changes: 2 additions & 0 deletions config/webpack/production.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module.exports = webpackMerge(defaultConfig, {
/* NodeJS library for https://logentries.com. It is server-side only. */
/\/node_modules\/le_node/,

/\/node_modules\/xml2json/,

/* To avoid bundling of redux-devtools into production bundle. */
/\/src\/shared\/containers\/DevTools/,
],
Expand Down
Binary file removed docs/editor-notes.pdf
Binary file not shown.
95 changes: 95 additions & 0 deletions docs/how-to-add-a-new-topcoder-community.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# How to Add a New Topcoder Community?
*NOTE: Related code is not quite stable yet, be aware that this document might be out of sync with the actual behavior. Current version of this instruction corresponds to the code commit `ec6730c9fc02ee8a4bece061cae5a3eb9d2ce779`*

To add a new community with the name **demo**, we should follow the following protocol:

1. All community-specific assets should be added to the `/src/assets/themes/demo` folder.
2. Community meta-data file should be created under the path `/src/server/tc-communities/demo/metadata.json`:
```json
{
"authorizedGroupIds": [
"12345"
],
"challengeGroupId": "12345",
"challengeFilterTag": "",
"communityId": "demo",
"communitySelector": [{
"label": "Demo Community",
"value": "1"
}, {
"label": "Cognitive Community",
"redirect": "http://cognitive.topcoder.com/",
"value": "2"
}, {
"label": "iOS Community",
"redirect": "https://ios.topcoder.com/",
"value": "3"
}],
"leaderboardApiUrl": "https://api.topcoder.com/v4/looks/0/run/json/",
"logos": [
"/themes/demo/logo_topcoder_with_name.svg"
],
"menuItems": [
{
"title": "Home",
"url": "."
}, {
"title": "Learn",
"url": "learn"
}, {
"title": "Challenges",
"url": "challenges"
}, {
"title": "Leaderboard",
"url": "leaderboard"
}
],
"newsFeed": "http://www.topcoder.com/feed"
}
```
Its fields serve the following purposes:
- `authorizedGroupIds` - *String Array* - Optional. Array of group IDs. If specified, access to the community will be restricted only to authenticated visitors, included into, at least, one of the groups listed in this array. If undefined, community will be accessible to any visitors (including non-authenticated ones).
- `challengeGroupId` - *String* - Optional. ID of the group holding challenges related to this community. If undefined, challenge listing in this community will show all public challenges.
- `challengeFilterTag` - *String* - Optional. If specified, and not an empty string, only challenges having this technology tag will be shown inside the community (it acts as an additional filter after the group-based filtering).
- `communityId` - *String* - Unique ID of this community.
- `communitySelector` - *Object Array* - Specifies data for the community selection dropdown inside the community header. Each object MUST HAVE `label` and `value` string fields, and MAY HAVE `redirect` field. If `redirect` field is specified, a click on that option in the dropdown will redirect user to the specified URL.
- `leaderboardApiUrl` - *String* - Endpoint from where the leaderboard data should be loaded.
- `logo` - *String Array* - Array of image URLs to insert as logos into the left corner of community's header.
- `menuItems` - *Object Array* - Specifies options for the community navigation menu (both in the header and footer). Each object MUST HAVE `title` and `url` fields. For now, `url` field should be a relative link inside the community, within the same path segment.
- `newsFeed` - *String* - Optional. URL of an XML blog feed to be used to render news section at a custom page. To actually render the news section, you should include it into the page code like (also see as example `/src/shared/components/tc-communities/communities/wipro/Home/index.jsx`):
```js
/* This goes inside the import section in the beginning of the file. */
import NewsSection from 'components/tc-communities/NewsSection';

/* This goes into appropriate place of the render function. */
<NewsSection news={props.news} />
```
The `<NewsSection />` component does not render anything, if its `news` property is *null* or an empty array, thus it can be kept inside the page code even when there is no news feed configured for a community.
3. Custom pages of the community (anything beside `Challenges` and `Leaderboard`) should be created inside `/src/shared/components/tc-communities/communities/demo`. At the moment all communities have two custom pages: `Home` and `Learn`, you may just copy these from an existing community, and then customize to your particular needs.
4. Created custom pages should be registered inside `/src/shared/containers/tc-communities/Page/index.jsx`.
- First, import your custom pages into the file as
```js
import DemoHome from 'components/tc-communities/communities/demo/Home';
import DemoLearn from 'components/tc-communities/communities/demo/Learn';
```
- Second, add them into `renderCustomPage()` method. It includes a big `if-else` block, where you should add something similar to:
```js
} else if (communityId === 'demo') {
switch (pageId) {
case 'home': pageContent = <DemoHome />; break;
case 'learn': pageContent = <DemoLearn />; break;
default: break;
}
}
```
here the page IDs inside the switch statement should match the relative URLs you have configured inside `metadata.json` file (the address `.` is internally aliased to `home`, thus `home` pageId should be used to specify the page at the `.` route).

5. At this point **demo** community is ready and accessible at the `/community/demo` route of the App (i.e., if we deploy dev version of the App to `community-west.topcoder-dev.com`, community will be accessible as `community-west.topcoder-dev.com/community/demo`).

To make **demo** community accessible via a dedicated sub-domain, e.g. like `demo.topcoder-dev.com`, you should edit `/src/shared/routes/index.jsx`. In the first `if-else` block inside `Routes()` function add the line
```js
else if (subdomains.indexOf('demo') >= 0) communityId = 'demo';
```
This takes care about proper sub-domain routing from our App's side. Beside it you should:
- Ensure that the web-server where the App is deployed allows access to the subdomain `demo.topcoder-dev`, and redirects incoming requests to the App.
- Ensure that Topcoder `accounts-app` allows to authenticate from the new subdomain address.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@
"tc-accounts": "https://github.com/appirio-tech/accounts-app.git#dev",
"uuid": "^3.0.1",
"webpack": "^2.2.1",
"webpack-merge": "^4.0.0"
"webpack-merge": "^4.0.0",
"xml2json": "^0.11.0"
},
"devDependencies": {
"redux-devtools": "^3.3.2",
Expand Down
Binary file added src/assets/themes/common/NewsSection/news-01.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/themes/common/NewsSection/news-03.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import path from 'path';
import favicon from 'serve-favicon';
import requestIp from 'request-ip';
import stream from 'stream';
import { toJson as xmlToJson } from 'utils/xml2json';

// Temporarily here to test our API service.
// import '../shared/services/api';
Expand Down Expand Up @@ -90,6 +91,14 @@ app.use(express.static(path.resolve(__dirname, '../../build')));
// serve demo api
app.use('/api/tc-communities', tcCommunitiesDemoApi);

/**
* Auxiliary endpoint for xml -> json conversion (the most popular npm library
* for such conversion works only in the node :(
*/
app.use('/api/xml2json', (req, res) => {
xmlToJson(req.body.xml).then(json => res.json(json));
});

app.use(renderer);

/* Catches 404 and forwards it to error handler. */
Expand Down
1 change: 1 addition & 0 deletions src/server/tc-communities/demo-expert/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"challengeGroupId": "1001",
"challengeFilterTag": ".NET",
"communityId": "demo-expert",
"communityName": "Demo Expert Community",
"communitySelector": [{
"label": "Demo Expert Community",
"value": "1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"communityId": "example-theme-default",
"communityName": "Example Community",
"logos": ["http://predix.topcoder.com/wp-content/uploads/sites/7/2016/11/topcoder-hat-logo.png"],
"menuItems": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"communityId": "example-theme-green",
"communityName": "Example Community",
"logos": ["http://predix.topcoder.com/wp-content/uploads/sites/7/2016/11/topcoder-hat-logo.png"],
"menuItems": [
{
Expand Down
1 change: 1 addition & 0 deletions src/server/tc-communities/example-theme-red/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"communityId": "example-theme-red",
"communityName": "Example Community",
"logos": ["http://predix.topcoder.com/wp-content/uploads/sites/7/2016/11/topcoder-hat-logo.png"],
"menuItems": [
{
Expand Down
1 change: 1 addition & 0 deletions src/server/tc-communities/tc-prod-dev/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"challengeGroupId": "20000000",
"challengeFilterTag": "",
"communityId": "tc-prod-dev",
"communityName": "Topcoder Product Development",
"communitySelector": [{
"label": "Topcoder Product Development",
"value": "1"
Expand Down
4 changes: 3 additions & 1 deletion src/server/tc-communities/wipro/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"challengeGroupId": "20000000",
"challengeFilterTag": "",
"communityId": "wipro",
"communityName": "Wipro Hybrid Crowd",
"communitySelector": [{
"label": "Wipro Hybrid Crowd",
"value": "1"
Expand All @@ -17,6 +18,7 @@
"redirect": "https://ios.topcoder.com/",
"value": "3"
}],
"leaderboardApiUrl": "https://api.topcoder.com/v4/looks/0/run/json/",
"logos": [
"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Wipro_Logo_RGB.png/480px-Wipro_Logo_RGB.png",
"/themes/wipro/logo_topcoder_with_name.svg"
Expand All @@ -36,5 +38,5 @@
"url": "leaderboard"
}
],
"leaderboardApiUrl": "https://api.topcoder.com/v4/looks/0/run/json/"
"newsFeed": "http://www.topcoder.com/feed"
}
Loading

0 comments on commit 44d5746

Please sign in to comment.