diff --git a/.circleci/config.yml b/.circleci/config.yml index ed03863f..89b6efa1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -77,6 +77,7 @@ workflows: branches: only: - dev + - dev-1_5 # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/config/index.js b/config/index.js index 0de81581..4cbf464b 100644 --- a/config/index.js +++ b/config/index.js @@ -3,6 +3,8 @@ module.exports = (() => { const env = process.env.APPENV || "dev"; + console.info(`APPENV: "${env}"`); + // for security reason don't let to require any arbitrary file defined in process.env if (["prod", "dev"].indexOf(env) < 0) { return require("./dev"); diff --git a/package.json b/package.json index 3a16e2cc..eccf8c3b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "start": "node server.js", "dev": "webpack-dev-server --port 8501 --host 0.0.0.0", "dev-https": "webpack-dev-server --https --port 8501 --host 0.0.0.0", - "build": "webpack --mode=${APPMODE:-development} --env.config=${APPENV:-dev}", + "build": "webpack --mode=${APPMODE:-production} --env.config=${APPENV:-prod}", "analyze": "webpack --mode=production --env.analyze=true", "lint": "eslint src --ext js", "format": "prettier --write \"./**\"", diff --git a/src/components/LayoutContainer/index.jsx b/src/components/LayoutContainer/index.jsx deleted file mode 100644 index 6f7046af..00000000 --- a/src/components/LayoutContainer/index.jsx +++ /dev/null @@ -1,18 +0,0 @@ -/** - * LayoutContainer - * - * Common container for pages. - */ -import React from "react"; -import PT from "prop-types"; -import "./styles.module.scss"; - -const LayoutContainer = ({ children }) => { - return <div styleName="container">{children}</div>; -}; - -LayoutContainer.propTypes = { - children: PT.node, -}; - -export default LayoutContainer; diff --git a/src/components/Page/index.jsx b/src/components/Page/index.jsx new file mode 100644 index 00000000..3b06b3aa --- /dev/null +++ b/src/components/Page/index.jsx @@ -0,0 +1,33 @@ +/** + * Page + * + * Handles common stuff for pages. + * Should wrap each page. + */ +import React, { useEffect } from "react"; +import PT from "prop-types"; +import "./styles.module.scss"; +import { formatPageTitle } from "utils/format"; + +const Page = ({ children, title }) => { + // set page title and triggering analytics + useEffect(() => { + // we set title manually like this instead of using `react-helmet` because of the issue: + // https://github.com/nfl/react-helmet/issues/189 + document.title = formatPageTitle(title); + + // call analytics if the parent Frame app initialized it + if (window.analytics && typeof window.analytics.page === "function") { + window.analytics.page(); + } + }, [title]); + + return <div styleName="page">{children}</div>; +}; + +Page.propTypes = { + children: PT.node, + title: PT.string, +}; + +export default Page; diff --git a/src/components/LayoutContainer/styles.module.scss b/src/components/Page/styles.module.scss similarity index 66% rename from src/components/LayoutContainer/styles.module.scss rename to src/components/Page/styles.module.scss index 671a3abd..88860a5b 100644 --- a/src/components/LayoutContainer/styles.module.scss +++ b/src/components/Page/styles.module.scss @@ -1,3 +1,3 @@ -.container { +.page { padding: 0 35px 32px; } diff --git a/src/routes/MyTeamsDetails/index.jsx b/src/routes/MyTeamsDetails/index.jsx index 2d48b65e..712b7c5c 100644 --- a/src/routes/MyTeamsDetails/index.jsx +++ b/src/routes/MyTeamsDetails/index.jsx @@ -6,7 +6,7 @@ */ import React from "react"; import PT from "prop-types"; -import LayoutContainer from "components/LayoutContainer"; +import Page from "components/Page"; import PageHeader from "components/PageHeader"; import { useData } from "hooks/useData"; import { getTeamById } from "services/teams"; @@ -20,7 +20,7 @@ const MyTeamsDetails = ({ teamId }) => { const [team, loadingError] = useData(getTeamById, teamId); return ( - <LayoutContainer> + <Page title="Team Details"> {!team ? ( <LoadingIndicator error={loadingError} /> ) : ( @@ -31,7 +31,7 @@ const MyTeamsDetails = ({ teamId }) => { <TeamPositions positions={team.jobs || []} teamId={teamId} /> </> )} - </LayoutContainer> + </Page> ); }; diff --git a/src/routes/MyTeamsList/index.jsx b/src/routes/MyTeamsList/index.jsx index afc92e73..cb35ab06 100644 --- a/src/routes/MyTeamsList/index.jsx +++ b/src/routes/MyTeamsList/index.jsx @@ -5,7 +5,7 @@ */ import React, { useCallback, useState, useEffect } from "react"; import _ from "lodash"; -import LayoutContainer from "components/LayoutContainer"; +import Page from "components/Page"; import PageHeader from "components/PageHeader"; import Input from "components/Input"; import Pagination from "components/Pagination"; @@ -60,7 +60,7 @@ const MyTeamsList = () => { ); return ( - <LayoutContainer> + <Page title="My Teams"> <PageHeader title="My Teams" aside={ @@ -95,7 +95,7 @@ const MyTeamsList = () => { )} </> )} - </LayoutContainer> + </Page> ); }; diff --git a/src/routes/PositionDetails/index.jsx b/src/routes/PositionDetails/index.jsx index cb9d3ae6..cd916f24 100644 --- a/src/routes/PositionDetails/index.jsx +++ b/src/routes/PositionDetails/index.jsx @@ -5,7 +5,7 @@ */ import React, { useCallback, useState } from "react"; import PT from "prop-types"; -import LayoutContainer from "components/LayoutContainer"; +import Page from "components/Page"; import LoadingIndicator from "components/LoadingIndicator"; import PageHeader from "components/PageHeader"; import { CANDIDATE_STATUS } from "constants"; @@ -30,7 +30,7 @@ const PositionDetails = ({ teamId, positionId }) => { ); return ( - <LayoutContainer> + <Page title="Job Details"> {!position ? ( <LoadingIndicator error={error} /> ) : ( @@ -53,7 +53,7 @@ const PositionDetails = ({ teamId, positionId }) => { /> </> )} - </LayoutContainer> + </Page> ); }; diff --git a/src/utils/format.js b/src/utils/format.js index 47435e12..274cb23e 100644 --- a/src/utils/format.js +++ b/src/utils/format.js @@ -167,3 +167,17 @@ export const formatDateRange = (startDate, endDate) => { return `${startDateStr} - ${endDateStr}`; }; + +/** + * Format page title to show in the browser header. + * + * @param {string} pageTitle page title + */ +export const formatPageTitle = (pageTitle) => { + let formattedPageTitle = "TaaS | Topcoder"; + if (pageTitle) { + formattedPageTitle = pageTitle + " | " + formattedPageTitle; + } + + return formattedPageTitle; +}; diff --git a/webpack.config.js b/webpack.config.js index 64dbbbfe..222fa8a4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -6,7 +6,7 @@ const path = require("path"); const autoprefixer = require("autoprefixer"); -const cssLocalIdent = process.env.APPMODE === "production" +const cssLocalIdent = process.env.APPMODE === "production" ? "[hash:base64:6]" : "teams_[path][name]___[local]___[hash:base64:6]"; @@ -18,6 +18,10 @@ module.exports = (webpackConfigEnv) => { }); return webpackMerge.smart(defaultConfig, { + output: { + // path: path.resolve(__dirname, 'dist'), + publicPath: 'taas-app', + }, // modify the webpack config however you'd like to by adding to this object module: { rules: [