From 48f4aa7fdb50019c46f93a85df632128a67df1d3 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Mon, 4 Oct 2021 22:42:28 +0300 Subject: [PATCH 1/6] init tracking codebase --- src/server/routes/growsurf.js | 11 +++- src/server/services/growsurf.js | 46 ++++++++++++---- src/shared/actions/growSurf.js | 5 +- .../components/Gigs/GigDetails/index.jsx | 5 +- .../components/Gigs/ReferralModal/index.jsx | 8 ++- .../components/Gigs/ReferralModal/modal.scss | 14 +++++ .../containers/Gigs/RecruitCRMJobDetails.jsx | 54 +++++++++++++++++-- src/shared/containers/GigsPages.jsx | 11 ++-- 8 files changed, 131 insertions(+), 23 deletions(-) diff --git a/src/server/routes/growsurf.js b/src/server/routes/growsurf.js index 7e7fa2c1a8..298464e44e 100644 --- a/src/server/routes/growsurf.js +++ b/src/server/routes/growsurf.js @@ -2,11 +2,16 @@ * The routes related to Growsurf integration */ +import _ from 'lodash'; import express from 'express'; +import { middleware } from 'tc-core-library-js'; +import config from 'config'; import GrowsurfService from '../services/growsurf'; const cors = require('cors'); +const authenticator = middleware.jwtAuthenticator; +const authenticatorOptions = _.pick(config.SECRET.JWT_AUTH, ['AUTH_SECRET', 'VALID_ISSUERS']); const routes = express.Router(); // Enables CORS on those routes according config above @@ -14,7 +19,9 @@ const routes = express.Router(); routes.use(cors()); routes.options('*', cors()); -routes.get('/participants', (req, res) => new GrowsurfService().getParticipant(req, res).then(res.send.bind(res))); -routes.post('/participants', (req, res) => new GrowsurfService().getOrCreateParticipant(req, res).then(res.send.bind(res))); +routes.get('/participant/:emailOrId', (req, res) => new GrowsurfService().getParticipantController(req, res).then(res.send.bind(res))); +routes.get('/participants', (req, res) => new GrowsurfService().getParticipantsController(req, res).then(res.send.bind(res))); +routes.post('/participants', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), (req, res) => new GrowsurfService().getOrCreateParticipantController(req, res).then(res.send.bind(res))); +routes.patch('/participant/:emailOrId', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), (req, res) => new GrowsurfService().updateParticipantController(req, res).then(res.send.bind(res))); export default routes; diff --git a/src/server/services/growsurf.js b/src/server/services/growsurf.js index 1ede169b40..b9850e002c 100644 --- a/src/server/services/growsurf.js +++ b/src/server/services/growsurf.js @@ -21,7 +21,7 @@ export default class GrowsurfService { } /** - * Gets get participant. + * Gets participant by email or id * @return {Promise} * @param {String} idOrEmail growsurf id or email */ @@ -45,14 +45,28 @@ export default class GrowsurfService { } /** - * Gets get participant by email or id. + * Controller - Gets get participant by email or id * @return {Promise} * @param {Object} req the request. * @param {Object} res the response. */ - async getParticipant(req, res) { - const { participantId } = req.query; - const response = await fetch(`${this.private.baseUrl}/campaign/${config.GROWSURF_CAMPAIGN_ID}/participant/${participantId}`, { + async getParticipantController(req, res) { + const { emailOrId } = req.params; + const growSurfData = await this.getParticipantByIdOREmail(emailOrId); + if (growSurfData.error) { + res.status(growSurfData.code); + } + return growSurfData; + } + + /** + * Controller - Gets get participants in the campaign + * @return {Promise} + * @param {Object} req the request. + * @param {Object} res the response. + */ + async getParticipantsController(req, res) { + const response = await fetch(`${this.private.baseUrl}/campaign/${config.GROWSURF_CAMPAIGN_ID}/participants`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -64,7 +78,7 @@ export default class GrowsurfService { return { error: await response.json(), code: response.status, - url: `${this.private.baseUrl}/campaign/${config.GROWSURF_CAMPAIGN_ID}/participant/${participantId}`, + url: `${this.private.baseUrl}/campaign/${config.GROWSURF_CAMPAIGN_ID}/participants`, }; } const data = await response.json(); @@ -98,13 +112,13 @@ export default class GrowsurfService { } /** - * Gets get participant by email or id + * Controller - Gets get participant by email or id * if not exxists create it * @return {Promise} * @param {Object} req the request. * @param {Object} res the response. */ - async getOrCreateParticipant(req, res) { + async getOrCreateParticipantController(req, res) { const { body } = req; const result = await this.addParticipant(JSON.stringify({ email: body.email, @@ -133,7 +147,7 @@ export default class GrowsurfService { 'Content-Type': 'application/json', Authorization: this.private.authorization, }, - body, + body: JSON.stringify(body), }); if (response.status >= 300) { return { @@ -146,4 +160,18 @@ export default class GrowsurfService { const data = await response.json(); return data; } + + /** + * Controller - update participant in the system + * @param {Object} req request + * @param {Object} res respons + */ + async updateParticipantController(req, res) { + const { emailOrId } = req.params; + const updateGrowRes = await this.updateParticipant(emailOrId, req.body); + if (updateGrowRes.error) { + res.status(updateGrowRes.code); + } + return updateGrowRes; + } } diff --git a/src/shared/actions/growSurf.js b/src/shared/actions/growSurf.js index b3cbf3571d..38f7920de7 100644 --- a/src/shared/actions/growSurf.js +++ b/src/shared/actions/growSurf.js @@ -18,8 +18,10 @@ function getReferralIdInit() { /** * Get referral id for the logged user * if this member does not exist in growsurf it creates it in the system + * @param {Object} profile the member auth profile + * @param {String} token the auth token */ -async function getReferralIdDone(profile) { +async function getReferralIdDone(profile, tokenV3) { if (profile.email) { const res = await fetch(`${PROXY_ENDPOINT}/growsurf/participants?participantId=${profile.email}`, { method: 'POST', @@ -31,6 +33,7 @@ async function getReferralIdDone(profile) { }), headers: { 'Content-Type': 'application/json', + Authorization: `Bearer ${tokenV3}`, }, }); if (res.status >= 300) { diff --git a/src/shared/components/Gigs/GigDetails/index.jsx b/src/shared/components/Gigs/GigDetails/index.jsx index 074cd79ab0..4ebbbef24c 100644 --- a/src/shared/components/Gigs/GigDetails/index.jsx +++ b/src/shared/components/Gigs/GigDetails/index.jsx @@ -262,7 +262,10 @@ function GigDetails(props) { && ( setModalOpen(false)} + onCloseButton={() => { + onReferralDone(); + setModalOpen(false); + }} isReferrSucess={isReferrSucess} isReferrError={isReferrError} referralId={growSurf && growSurf.data ? growSurf.data.id : null} diff --git a/src/shared/components/Gigs/ReferralModal/index.jsx b/src/shared/components/Gigs/ReferralModal/index.jsx index 4c9e8f39f4..6131810b38 100644 --- a/src/shared/components/Gigs/ReferralModal/index.jsx +++ b/src/shared/components/Gigs/ReferralModal/index.jsx @@ -73,7 +73,13 @@ function ReferralModal({

OOPS!

{isReferrError.message}

-

Looks like there is a problem on our end. Please try again.
If this persists please contact support@topcoder.com.

+ { + isReferrError.isReferred ? ( +

If you think this is an error please contact support@topcoder.com.

+ ) : ( +

Looks like there is a problem on our end. Please try again.
If this persists please contact support@topcoder.com.

+ ) + }
button { + margin: 0 0 20px !important; + } + } + } } } diff --git a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx index 5594841ec9..59380097f9 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx @@ -53,8 +53,25 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, * Send gig referral invite */ async onSendClick(email) { - const { profile, growSurf } = this.props; + const { + profile, growSurf, tokenV3, + } = this.props; const { formData } = this.state; + // check if email is already referred? + const growCheck = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${email}`); + if (growCheck.status === 200) { + const growCheckData = await growCheck.json(); + if (growCheckData.referrer) { + this.setState({ + isReferrError: { + message: `${email} has already been referred.`, + isReferred: true, + }, + }); + // exit no email sending + return; + } + } // email the invite const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { method: 'POST', @@ -79,11 +96,34 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, this.setState({ isReferrError: await res.json(), }); - } else { - this.setState({ - isReferrSucess: true, - }); + // exit no email tracking due to the error + return; } + // put tracking in growsurf + // let { emailInvitesLog } = growSurf.data.metadata; + // if (!emailInvitesLog) emailInvitesLog = []; + // else emailInvitesLog = JSON.parse(JSON.parse(emailInvitesLog)); + // const updateGrowProfile = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${growSurf.data}`, { + // method: 'PATCH', + // headers: { + // 'Content-Type': 'application/json', + // Authorization: `Bearer ${tokenV3}`, + // }, + // body: JSON.stringify({ + // ...growSurf.data, + // metadata: { + // ...growSurf.data.metadata, + // emailInvitesSent: Number(growSurf.data.metadata.emailInvitesSent || 0) + 1, + // emailInvitesLog: JSON.stringify(JSON.stringify(emailInvitesLog.concat({ + // e: email, d: new Date().toISOString(), + // }))), + // }, + // }), + // }); + // finally do: + this.setState({ + isReferrSucess: true, + }); } /** @@ -94,6 +134,7 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, delete formData.email; this.setState({ isReferrSucess: false, + isReferrError: false, formData, }); } @@ -143,6 +184,7 @@ RecruitCRMJobDetailsContainer.defaultProps = { application: null, profile: {}, growSurf: {}, + tokenV3: null, }; RecruitCRMJobDetailsContainer.propTypes = { @@ -154,6 +196,7 @@ RecruitCRMJobDetailsContainer.propTypes = { application: PT.shape(), profile: PT.shape(), growSurf: PT.shape(), + tokenV3: PT.string, }; function mapStateToProps(state, ownProps) { @@ -166,6 +209,7 @@ function mapStateToProps(state, ownProps) { application: data ? data.application : null, profile, growSurf, + tokenV3: state.auth ? state.auth.tokenV3 : null, }; } diff --git a/src/shared/containers/GigsPages.jsx b/src/shared/containers/GigsPages.jsx index ac159c7d81..3418d7ed7a 100644 --- a/src/shared/containers/GigsPages.jsx +++ b/src/shared/containers/GigsPages.jsx @@ -25,7 +25,7 @@ const cookies = require('browser-cookies'); function GigsPagesContainer(props) { const { - match, profile, growSurf, getReferralId, + match, profile, growSurf, getReferralId, tokenV3, } = props; const optProfile = { attributes: {}, @@ -38,7 +38,7 @@ function GigsPagesContainer(props) { // trigger referral id fetching when profile is loaded if (isomorphy.isClientSide()) { if (_.isEmpty(growSurf) || (!growSurf.loading && !growSurf.data && !growSurf.error)) { - getReferralId(profile); + getReferralId(profile, tokenV3); } } } else if (isomorphy.isClientSide()) { @@ -124,6 +124,7 @@ window._chatlio = window._chatlio||[]; GigsPagesContainer.defaultProps = { profile: null, growSurf: null, + tokenV3: null, }; GigsPagesContainer.propTypes = { @@ -131,6 +132,7 @@ GigsPagesContainer.propTypes = { profile: PT.shape(), growSurf: PT.shape(), getReferralId: PT.func.isRequired, + tokenV3: PT.string, }; function mapStateToProps(state) { @@ -139,15 +141,16 @@ function mapStateToProps(state) { return { profile, growSurf, + tokenV3: state.auth ? state.auth.tokenV3 : null, }; } function mapDispatchToActions(dispatch) { const a = actions.growsurf; return { - getReferralId: (profile) => { + getReferralId: (profile, tokenV3) => { dispatch(a.getReferralidInit()); - dispatch(a.getReferralidDone(profile)); + dispatch(a.getReferralidDone(profile, tokenV3)); }, }; } From 83a8559500dd9444ba8bd7b800a6902968d48152 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 5 Oct 2021 13:01:46 +0300 Subject: [PATCH 2/6] store to grow as json --- .../components/Gigs/GigDetails/index.jsx | 2 +- .../components/Gigs/ReferralModal/index.jsx | 2 +- .../containers/Gigs/RecruitCRMJobDetails.jsx | 125 ++++++++++++------ 3 files changed, 86 insertions(+), 43 deletions(-) diff --git a/src/shared/components/Gigs/GigDetails/index.jsx b/src/shared/components/Gigs/GigDetails/index.jsx index 4ebbbef24c..cffab15131 100644 --- a/src/shared/components/Gigs/GigDetails/index.jsx +++ b/src/shared/components/Gigs/GigDetails/index.jsx @@ -270,7 +270,7 @@ function GigDetails(props) { isReferrError={isReferrError} referralId={growSurf && growSurf.data ? growSurf.data.id : null} onReferralDone={() => { - onReferralDone(); + onReferralDone(true); setModalOpen(false); }} /> diff --git a/src/shared/components/Gigs/ReferralModal/index.jsx b/src/shared/components/Gigs/ReferralModal/index.jsx index 6131810b38..f4af505232 100644 --- a/src/shared/components/Gigs/ReferralModal/index.jsx +++ b/src/shared/components/Gigs/ReferralModal/index.jsx @@ -74,7 +74,7 @@ function ReferralModal({

OOPS!

{isReferrError.message}

{ - isReferrError.isReferred ? ( + isReferrError.userError ? (

If you think this is an error please contact support@topcoder.com.

) : (

Looks like there is a problem on our end. Please try again.
If this persists please contact support@topcoder.com.

diff --git a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx index 59380097f9..727a50f84e 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx @@ -3,7 +3,7 @@ * driven by recruitCRM */ -import { isEmpty } from 'lodash'; +import { isEmpty, find } from 'lodash'; import actions from 'actions/recruitCRM'; import LoadingIndicator from 'components/LoadingIndicator'; import GigDetails from 'components/Gigs/GigDetails'; @@ -12,6 +12,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { config } from 'topcoder-react-utils'; import fetch from 'isomorphic-fetch'; +import moment from 'moment'; import RecruitCRMJobApply from './RecruitCRMJobApply'; const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api`; @@ -57,6 +58,41 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, profile, growSurf, tokenV3, } = this.props; const { formData } = this.state; + // should not be able to send emails to themselves + if (profile.email === email) { + this.setState({ + isReferrError: { + message: 'We not allow sending to yourself.', + userError: true, + }, + }); + // exit no email sending + return; + } + // process sent log + let { emailInvitesLog } = growSurf.data.metadata; + if (!emailInvitesLog) emailInvitesLog = []; + // check if email is in sent log alredy? + const foundInLog = find(emailInvitesLog, ['e', email]); + if (foundInLog) { + this.setState({ + isReferrError: { + message: `${email} was already invited on ${foundInLog.d}.`, + userError: true, + }, + }); + // exit no email sending + return; + } + // prepare new log payload + emailInvitesLog.unshift({ + e: email, d: moment().format('MM-DD-YY'), + }); + let newEmailInvitesLog = `${JSON.stringify(emailInvitesLog)}`; + if (newEmailInvitesLog.length >= 500) { + emailInvitesLog.pop(); + newEmailInvitesLog = `${JSON.stringify(emailInvitesLog)}`; + } // check if email is already referred? const growCheck = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${email}`); if (growCheck.status === 200) { @@ -65,7 +101,7 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, this.setState({ isReferrError: { message: `${email} has already been referred.`, - isReferred: true, + userError: true, }, }); // exit no email sending @@ -73,53 +109,56 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, } } // email the invite - const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { - method: 'POST', - body: JSON.stringify({ - personalizations: [ - { - to: [{ email }], - subject: `${profile.firstName} ${profile.lastName} Thinks This Topcoder Gig Is For You!`, - }, - ], - from: { email: 'noreply@topcoder.com', name: `${profile.firstName} ${profile.lastName} via Topcoder Gigwork` }, - content: [{ - type: 'text/plain', value: `${formData.body}?referralId=${growSurf.data.id}`, - }], - }), + // const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { + // method: 'POST', + // body: JSON.stringify({ + // personalizations: [ + // { + // to: [{ email }], + // subject: `${profile.firstName} ${profile.lastName} Thinks This Topcoder Gig Is For You!`, + // }, + // ], + // from: { email: 'noreply@topcoder.com', name: `${profile.firstName} ${profile.lastName} via Topcoder Gigwork` }, + // content: [{ + // type: 'text/plain', value: `${formData.body}?referralId=${growSurf.data.id}`, + // }], + // }), + // headers: { + // 'Content-Type': 'application/json', + // }, + // redirect: 'follow', + // }); + // if (res.status >= 300) { + // this.setState({ + // isReferrError: await res.json(), + // }); + // // exit no email tracking due to the error + // return; + // } + // put tracking in growsurf + const updateRed = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${growSurf.data.id}`, { + method: 'PATCH', headers: { 'Content-Type': 'application/json', + Authorization: `Bearer ${tokenV3}`, }, - redirect: 'follow', + body: JSON.stringify({ + ...growSurf.data, + metadata: { + ...growSurf.data.metadata, + emailInvitesSent: Number(growSurf.data.metadata.emailInvitesSent || 0) + 1, + emailInvitesLog: newEmailInvitesLog, + }, + }), }); - if (res.status >= 300) { + if (updateRed.status >= 300) { this.setState({ - isReferrError: await res.json(), + isReferrError: await updateRed.json(), }); // exit no email tracking due to the error + // just notify the user about it return; } - // put tracking in growsurf - // let { emailInvitesLog } = growSurf.data.metadata; - // if (!emailInvitesLog) emailInvitesLog = []; - // else emailInvitesLog = JSON.parse(JSON.parse(emailInvitesLog)); - // const updateGrowProfile = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${growSurf.data}`, { - // method: 'PATCH', - // headers: { - // 'Content-Type': 'application/json', - // Authorization: `Bearer ${tokenV3}`, - // }, - // body: JSON.stringify({ - // ...growSurf.data, - // metadata: { - // ...growSurf.data.metadata, - // emailInvitesSent: Number(growSurf.data.metadata.emailInvitesSent || 0) + 1, - // emailInvitesLog: JSON.stringify(JSON.stringify(emailInvitesLog.concat({ - // e: email, d: new Date().toISOString(), - // }))), - // }, - // }), - // }); // finally do: this.setState({ isReferrSucess: true, @@ -129,7 +168,11 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, /** * Reset the form when referral done */ - onReferralDone() { + onReferralDone(refresh = false) { + if (refresh) { + window.location.reload(false); + return; + } const { formData } = this.state; delete formData.email; this.setState({ From f34620a35322171e7083ed51197a34c4abe97bbd Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 5 Oct 2021 18:36:25 +0300 Subject: [PATCH 3/6] fixes for lint and css --- .../components/Gigs/ReferralModal/modal.scss | 1 + .../MemberPath/PathSelector/index.jsx | 2 +- .../containers/Gigs/RecruitCRMJobDetails.jsx | 52 +++++++++---------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/shared/components/Gigs/ReferralModal/modal.scss b/src/shared/components/Gigs/ReferralModal/modal.scss index 23e5f735a4..ec36a10e32 100644 --- a/src/shared/components/Gigs/ReferralModal/modal.scss +++ b/src/shared/components/Gigs/ReferralModal/modal.scss @@ -1,3 +1,4 @@ +/* stylelint-disable no-descending-specificity */ @import "~styles/mixins"; @import "~components/Contentful/default"; diff --git a/src/shared/components/MemberPath/PathSelector/index.jsx b/src/shared/components/MemberPath/PathSelector/index.jsx index ae16a7c202..4afafe7a62 100644 --- a/src/shared/components/MemberPath/PathSelector/index.jsx +++ b/src/shared/components/MemberPath/PathSelector/index.jsx @@ -101,7 +101,7 @@ export default function PathSelector({
diff --git a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx index 727a50f84e..ce5f8998b0 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx @@ -109,32 +109,32 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, } } // email the invite - // const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { - // method: 'POST', - // body: JSON.stringify({ - // personalizations: [ - // { - // to: [{ email }], - // subject: `${profile.firstName} ${profile.lastName} Thinks This Topcoder Gig Is For You!`, - // }, - // ], - // from: { email: 'noreply@topcoder.com', name: `${profile.firstName} ${profile.lastName} via Topcoder Gigwork` }, - // content: [{ - // type: 'text/plain', value: `${formData.body}?referralId=${growSurf.data.id}`, - // }], - // }), - // headers: { - // 'Content-Type': 'application/json', - // }, - // redirect: 'follow', - // }); - // if (res.status >= 300) { - // this.setState({ - // isReferrError: await res.json(), - // }); - // // exit no email tracking due to the error - // return; - // } + const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { + method: 'POST', + body: JSON.stringify({ + personalizations: [ + { + to: [{ email }], + subject: `${profile.firstName} ${profile.lastName} Thinks This Topcoder Gig Is For You!`, + }, + ], + from: { email: 'noreply@topcoder.com', name: `${profile.firstName} ${profile.lastName} via Topcoder Gigwork` }, + content: [{ + type: 'text/plain', value: `${formData.body}?referralId=${growSurf.data.id}`, + }], + }), + headers: { + 'Content-Type': 'application/json', + }, + redirect: 'follow', + }); + if (res.status >= 300) { + this.setState({ + isReferrError: await res.json(), + }); + // exit no email tracking due to the error + return; + } // put tracking in growsurf const updateRed = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${growSurf.data.id}`, { method: 'PATCH', From 2586469563ea5b6e9f600428adfb852fdf9ed87e Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 5 Oct 2021 18:36:59 +0300 Subject: [PATCH 4/6] ci:on test --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ab8fcc9a87..778ca4859f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -349,7 +349,7 @@ workflows: filters: branches: only: - - gig-apply-new-options-dropdown + - ref-email-tracking # This is alternate dev env for parallel testing - "build-qa": context : org-global From 7faa2d695089d99b01cc7d4d7f3e9136165cc879 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 5 Oct 2021 22:52:37 +0300 Subject: [PATCH 5/6] ci: free test and put on qa --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 778ca4859f..69b61f02d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -349,14 +349,14 @@ workflows: filters: branches: only: - - ref-email-tracking + - free # This is alternate dev env for parallel testing - "build-qa": context : org-global filters: branches: only: - - member-path-component + - ref-email-tracking # This is beta env for production soft releases - "build-prod-beta": context : org-global From c1c0dc039eecb82b1a88d317c553522b785b60d7 Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Wed, 6 Oct 2021 14:20:54 +0300 Subject: [PATCH 6/6] store log as comma string --- .../containers/Gigs/RecruitCRMJobDetails.jsx | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx index ce5f8998b0..ba5aea8091 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobDetails.jsx @@ -3,7 +3,7 @@ * driven by recruitCRM */ -import { isEmpty, find } from 'lodash'; +import { isEmpty } from 'lodash'; import actions from 'actions/recruitCRM'; import LoadingIndicator from 'components/LoadingIndicator'; import GigDetails from 'components/Gigs/GigDetails'; @@ -12,7 +12,6 @@ import React from 'react'; import { connect } from 'react-redux'; import { config } from 'topcoder-react-utils'; import fetch from 'isomorphic-fetch'; -import moment from 'moment'; import RecruitCRMJobApply from './RecruitCRMJobApply'; const PROXY_ENDPOINT = `${config.URL.COMMUNITY_APP}/api`; @@ -62,7 +61,7 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, if (profile.email === email) { this.setState({ isReferrError: { - message: 'We not allow sending to yourself.', + message: 'You are not allowed to send to yourself.', userError: true, }, }); @@ -70,29 +69,20 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, return; } // process sent log - let { emailInvitesLog } = growSurf.data.metadata; - if (!emailInvitesLog) emailInvitesLog = []; + let { emailInvitesLog, emailInvitesStatus } = growSurf.data.metadata; + if (!emailInvitesLog) emailInvitesLog = ''; // check if email is in sent log alredy? - const foundInLog = find(emailInvitesLog, ['e', email]); - if (foundInLog) { + const foundInLog = emailInvitesLog.indexOf(email); + if (foundInLog !== -1) { this.setState({ isReferrError: { - message: `${email} was already invited on ${foundInLog.d}.`, + message: `${email} was already invited.`, userError: true, }, }); // exit no email sending return; } - // prepare new log payload - emailInvitesLog.unshift({ - e: email, d: moment().format('MM-DD-YY'), - }); - let newEmailInvitesLog = `${JSON.stringify(emailInvitesLog)}`; - if (newEmailInvitesLog.length >= 500) { - emailInvitesLog.pop(); - newEmailInvitesLog = `${JSON.stringify(emailInvitesLog)}`; - } // check if email is already referred? const growCheck = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${email}`); if (growCheck.status === 200) { @@ -108,7 +98,7 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, return; } } - // email the invite + // // email the invite const res = await fetch(`${PROXY_ENDPOINT}/mailchimp/email`, { method: 'POST', body: JSON.stringify({ @@ -135,7 +125,20 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, // exit no email tracking due to the error return; } - // put tracking in growsurf + // parse the log to array of emails + if (emailInvitesLog.length) { + emailInvitesLog = emailInvitesLog.split(','); + } else emailInvitesLog = []; + // prepare growSurf update payload + // we keep only 10 emails in the log to justify program rules + if (emailInvitesLog.length < 10) { + emailInvitesLog.push(email); + } + // Auto change status when 10 emails sent + if (emailInvitesLog.length === 10 && emailInvitesStatus !== 'Paid' && emailInvitesStatus !== 'Payment Pending') { + emailInvitesStatus = 'Payment Pending'; + } + // put the tracking update in growsurf const updateRed = await fetch(`${PROXY_ENDPOINT}/growsurf/participant/${growSurf.data.id}`, { method: 'PATCH', headers: { @@ -147,7 +150,8 @@ ${config.URL.BASE}${config.GIGS_PAGES_PATH}/${props.id}`, metadata: { ...growSurf.data.metadata, emailInvitesSent: Number(growSurf.data.metadata.emailInvitesSent || 0) + 1, - emailInvitesLog: newEmailInvitesLog, + emailInvitesLog: emailInvitesLog.join(), + emailInvitesStatus, }, }), });