diff --git a/server.js b/server.js
index 9b7653a5..7aa29253 100644
--- a/server.js
+++ b/server.js
@@ -16,6 +16,16 @@ function check () {
return true
}
app.use(healthCheck.middleware([check]))
+app.use((req, res, next) => {
+ res.header('Referrer-Policy', 'strict-origin-when-cross-origin');
+ res.header('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
+ res.header('X-Content-Type-Options', 'nosniff');
+ res.header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
+ res.header('Cache-control', 'public, max-age=0');
+ res.header('Pragma', 'no-cache');
+
+ next();
+});
// app.use(requireHTTPS) // removed because app servers don't handle https
// app.use(express.static(__dirname))
app.use(express.static(path.join(__dirname, 'build')))
diff --git a/src/components/ChallengesComponent/ChallengeList/ChallengeList.module.scss b/src/components/ChallengesComponent/ChallengeList/ChallengeList.module.scss
index f891e5fa..428e1229 100644
--- a/src/components/ChallengesComponent/ChallengeList/ChallengeList.module.scss
+++ b/src/components/ChallengesComponent/ChallengeList/ChallengeList.module.scss
@@ -20,6 +20,20 @@
padding-bottom: 10px;
}
}
+
+ .title {
+ font-weight: bold;
+ }
+ .error {
+ font-weight: bold;
+ color: #BE405E;
+ }
+ .active {
+ color: #008000;
+ }
+ .inactive {
+ color: #BE405E;
+ }
}
.header {
diff --git a/src/components/ChallengesComponent/ChallengeList/index.js b/src/components/ChallengesComponent/ChallengeList/index.js
index 88634a4a..65329c5e 100644
--- a/src/components/ChallengesComponent/ChallengeList/index.js
+++ b/src/components/ChallengesComponent/ChallengeList/index.js
@@ -125,6 +125,10 @@ class ChallengeList extends Component {
partiallyUpdateChallengeDetails,
deleteChallenge,
isBillingAccountExpired,
+ billingStartDate,
+ billingEndDate,
+ isBillingAccountLoadingFailed,
+ isBillingAccountLoading,
selfService
} = this.props
if (warnMessage) {
@@ -172,14 +176,29 @@ class ChallengeList extends Component {
return (
-
this.updateSearchParam(e.target.value, status)}
- value={searchText}
- />
+ {!isBillingAccountLoading && !isBillingAccountLoadingFailed && !isBillingAccountExpired && (
+
+ Billing Account: {status} Start Date: {billingStartDate} End Date: {billingEndDate}
+
+ )}
+ {!isBillingAccountLoading && !isBillingAccountLoadingFailed && isBillingAccountExpired && (
+
+ Billing Account: INACTIVE Start Date: {billingStartDate} End Date: {billingEndDate}
+
+ )}
+ {!isBillingAccountLoading && isBillingAccountLoadingFailed && (
+ Billing Account failed to load
+ )}
+
+ this.updateSearchParam(e.target.value, status)}
+ value={searchText}
+ />
+
{activeProject && (
{
@@ -78,6 +82,10 @@ const ChallengesComponent = ({
partiallyUpdateChallengeDetails={partiallyUpdateChallengeDetails}
deleteChallenge={deleteChallenge}
isBillingAccountExpired={isBillingAccountExpired}
+ billingStartDate={billingStartDate}
+ billingEndDate={billingEndDate}
+ isBillingAccountLoadingFailed={isBillingAccountLoadingFailed}
+ isBillingAccountLoading={isBillingAccountLoading}
selfService={selfService}
auth={auth}
/>
@@ -106,6 +114,10 @@ ChallengesComponent.propTypes = {
partiallyUpdateChallengeDetails: PropTypes.func.isRequired,
deleteChallenge: PropTypes.func.isRequired,
isBillingAccountExpired: PropTypes.bool,
+ billingStartDate: PropTypes.string,
+ billingEndDate: PropTypes.string,
+ isBillingAccountLoadingFailed: PropTypes.bool,
+ isBillingAccountLoading: PropTypes.bool,
selfService: PropTypes.bool,
auth: PropTypes.object.isRequired
}
diff --git a/src/containers/Challenges/index.js b/src/containers/Challenges/index.js
index 60046ab1..6a12f204 100644
--- a/src/containers/Challenges/index.js
+++ b/src/containers/Challenges/index.js
@@ -34,6 +34,7 @@ class Challenges extends Component {
resetSidebarActiveParams()
} else if (projectId || selfService) {
if (projectId) {
+ window.localStorage.setItem('projectLoading', 'true')
this.props.loadProject(projectId)
}
this.reloadChallenges(this.props)
@@ -51,9 +52,12 @@ class Challenges extends Component {
if (activeProjectId !== challengeProjectId || selfService) {
const isAdmin = checkAdmin(this.props.auth.token)
this.props.loadChallengesByPage(1, projectId ? parseInt(projectId) : -1, CHALLENGE_STATUS.ACTIVE, '', selfService, isAdmin ? null : this.props.auth.user.handle)
- if (!selfService && (!reduxProjectInfo || `${reduxProjectInfo.id}` !== projectId)
+ const projectLoading = window.localStorage.getItem('projectLoading') !== null
+ if (!selfService && (!reduxProjectInfo || `${reduxProjectInfo.id}` !== projectId) && !projectLoading
) {
loadProject(projectId)
+ } else {
+ window.localStorage.removeItem('projectLoading')
}
}
}
@@ -87,6 +91,10 @@ class Challenges extends Component {
partiallyUpdateChallengeDetails,
deleteChallenge,
isBillingAccountExpired,
+ billingStartDate,
+ billingEndDate,
+ isBillingAccountLoadingFailed,
+ isBillingAccountLoading,
selfService,
auth
} = this.props
@@ -155,6 +163,10 @@ class Challenges extends Component {
partiallyUpdateChallengeDetails={partiallyUpdateChallengeDetails}
deleteChallenge={deleteChallenge}
isBillingAccountExpired={isBillingAccountExpired}
+ billingStartDate={billingStartDate}
+ billingEndDate={billingEndDate}
+ isBillingAccountLoadingFailed={isBillingAccountLoadingFailed}
+ isBillingAccountLoading={isBillingAccountLoading}
selfService={selfService}
auth={auth}
/>
@@ -186,6 +198,10 @@ Challenges.propTypes = {
partiallyUpdateChallengeDetails: PropTypes.func.isRequired,
deleteChallenge: PropTypes.func.isRequired,
isBillingAccountExpired: PropTypes.bool,
+ billingStartDate: PropTypes.string,
+ billingEndDate: PropTypes.string,
+ isBillingAccountLoadingFailed: PropTypes.bool,
+ isBillingAccountLoading: PropTypes.bool,
selfService: PropTypes.bool,
auth: PropTypes.object.isRequired
}
@@ -197,6 +213,10 @@ const mapStateToProps = ({ challenges, sidebar, projects, auth }) => ({
projects: sidebar.projects,
projectDetail: projects.projectDetail,
isBillingAccountExpired: projects.isBillingAccountExpired,
+ billingStartDate: projects.billingStartDate,
+ billingEndDate: projects.billingEndDate,
+ isBillingAccountLoadingFailed: projects.isBillingAccountLoadingFailed,
+ isBillingAccountLoading: projects.isBillingAccountLoading,
auth: auth
})
diff --git a/src/reducers/projects.js b/src/reducers/projects.js
index 464ef784..bc3d04e5 100644
--- a/src/reducers/projects.js
+++ b/src/reducers/projects.js
@@ -13,12 +13,33 @@ import {
LOAD_PROJECT_PHASES_PENDING,
LOAD_PROJECT_PHASES_SUCCESS
} from '../config/constants'
+import moment from 'moment-timezone'
+
+/**
+ * checks if billing is expired or not
+ * @param {boolean} active if billing account is active or not
+ * @param {string} endDate the end date
+ * @returns if billing expired or not
+ */
+const checkBillingExpired = (active, endDate) => {
+ if (active) {
+ if (moment().isBefore(endDate)) {
+ return false
+ }
+ return true
+ }
+ return true
+}
+const dateFormat = 'MMM DD, YYYY'
const initialState = {
isLoading: false,
projectDetail: {},
isBillingAccountExpired: false,
isBillingAccountLoading: false,
+ isBillingAccountLoadingFailed: false,
+ billingStartDate: null,
+ billingEndDate: null,
isPhasesLoading: false,
phases: []
}
@@ -42,19 +63,27 @@ export default function (state = initialState, action) {
return {
...state,
isBillingAccountLoading: true,
- isBillingAccountExpired: false
+ isBillingAccountExpired: false,
+ billingStartDate: '',
+ billingEndDate: ''
}
case LOAD_PROJECT_BILLING_ACCOUNT_SUCCESS:
return {
...state,
isBillingAccountLoading: false,
- isBillingAccountExpired: !action.payload.active
+ isBillingAccountExpired: checkBillingExpired(action.payload.active, action.payload.endDate),
+ billingStartDate: moment(action.payload.startDate).format(dateFormat),
+ billingEndDate: moment(action.payload.endDate).format(dateFormat),
+ isBillingAccountLoadingFailed: false
}
case LOAD_PROJECT_BILLING_ACCOUNT_FAILURE:
return {
...state,
isBillingAccountLoading: false,
- isBillingAccountExpired: false
+ isBillingAccountExpired: false,
+ billingStartDate: '',
+ billingEndDate: '',
+ isBillingAccountLoadingFailed: true
}
case LOAD_PROJECT_PHASES_PENDING:
return {