Skip to content

Commit

Permalink
Merge pull request #1441 from GSA/combined-dev-staging
Browse files Browse the repository at this point in the history
Merge Dev & Staging
  • Loading branch information
kkrug authored Oct 7, 2024
2 parents 72c4fd2 + f2606a2 commit 6e9e2dd
Show file tree
Hide file tree
Showing 33 changed files with 786 additions and 884 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
elixir 1.16.3
erlang 26.2.5
nodejs 20.14.0
yarn 1.22.5
yarn 1.22.19
7 changes: 5 additions & 2 deletions assets/client/src/components/ChallengeAnnouncement.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React from 'react';
import moment from 'moment';
import {formatDate, daysInMinutes, formatDateTime} from "../helpers/phaseHelpers"

export const ChallengeAnnouncement = ({challenge}) => {
const checkAnnouncementDate = ({announcement_datetime}) => {
return moment().diff(announcement_datetime, 'minutes') <= daysInMinutes(14)

let now = new Date();
let announcementDate = new Date(announcement_datetime);
let diffInMinutes = (now - announcementDate) / (1000 * 60);
return diffInMinutes <= daysInMinutes(14)
}

const renderAnnouncement = ({header, body}) => {
Expand Down
47 changes: 37 additions & 10 deletions assets/client/src/components/ChallengeDetails.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useContext, useEffect, useState } from 'react'
import moment from "moment"
import { stripHtml } from "string-strip-html";
import { Tooltip } from 'reactstrap';
import NumberFormat from 'react-number-format';
Expand Down Expand Up @@ -30,22 +29,50 @@ export const ChallengeDetails = ({challenge, challengePhases, preview, print, ta
const toggleShareTooltip = () => setShareTooltipOpen(!shareTooltipOpen)

const renderEndDate = (date) => {
const fiveDaysFromNow = moment().add(5,'d').utc().format()
const withinFiveDays = moment(date).diff(fiveDaysFromNow) <= 0

if (date > moment().utc().format()) {
let localTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

let formatLocalDateTime = (date) => {
let dateObj = new Date(date);
let dateOptions = { year: 'numeric', month: '2-digit', day: '2-digit', timeZone: localTimeZone };
let timeOptions = { hour: '2-digit', minute: '2-digit', hour12: true, timeZone: localTimeZone };
let formattedDate = dateObj.toLocaleDateString('en-US', dateOptions);
let formattedTime = dateObj.toLocaleTimeString('en-US', timeOptions);
return `${formattedDate} ${formattedTime}`;
}

const fiveDaysFromNow = () => {
let now = new Date();
now.setDate(now.getDate() + 5);
let utcDate = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds()));
return utcDate.toDateString();
}

const withinFiveDays = (date) => {
let givenDate = new Date(date);
let now = new Date();
let futureDate = new Date(fiveDaysFromNow());
return givenDate <= futureDate;
}

let getUTCNow = () => {
let now = new Date();
return now.toISOString();
}

if (date > getUTCNow()) {
return (
<div className="item">
<p className="info-title">Open until:</p>
<p>{moment(date).local().format('L LT')}</p>
{ withinFiveDays && <p className="date-qualifier">Closing soon</p> }
<p>{formatLocalDateTime(date)}</p>
{ withinFiveDays() && <p className="date-qualifier">Closing soon</p> }
</div>
)
} else {
return (
<div className="item">
<p className="info-title">Closed on:</p>
<p>{moment(date).local().format('L LT')}</p>
<p>{formatLocalDateTime(date)}</p>
</div>
)
}
Expand Down Expand Up @@ -94,7 +121,7 @@ export const ChallengeDetails = ({challenge, challengePhases, preview, print, ta
<div className="follow-tooltip__section">
<h4>Follow challenge as guest</h4>
<p>Receive challenge updates to your email. No sign-in required</p>
<a href={preview ? null : challenge.gov_delivery_topic_subscribe_link}>
<a href={preview ? "#" : `${encodeURIComponent(challenge.gov_delivery_topic_subscribe_link)}`}>
<button className="follow-tooltip__button">Follow challenge</button>
</a>
</div>
Expand Down Expand Up @@ -323,7 +350,7 @@ export const ChallengeDetails = ({challenge, challengePhases, preview, print, ta
<div className="logos">
<img
className="agency-logo"
src={imageBase + challenge.agency_logo}
src={`${imageBase}${encodeURIComponent(challenge.agency_logo)}`}
alt={`Agency logo for ${challenge.agency_name}`}
/>

Expand Down Expand Up @@ -377,7 +404,7 @@ export const ChallengeDetails = ({challenge, challengePhases, preview, print, ta
</div>
}
{!print &&
<a className="follow__btn" href={apiUrl + `/public/previews/challenges?challenge=${challenge.uuid}&print=true`} target="_blank">
<a className="follow__btn" href={`${apiUrl}/public/previews/challenges?challenge=${encodeURIComponent(challenge.uuid)}&print=true`} target="_blank" rel="noopener noreferrer">
<span className="details__btn">
<svg className="usa-icon" aria-hidden="true" focusable="false" role="img"
style={{fill: "#FA9441", height: "21px", width: "21px", position: "relative", top: "5px", right: "5px"}}>
Expand Down
28 changes: 17 additions & 11 deletions assets/client/src/components/ChallengeTile.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React, {useContext} from 'react'
import { Link } from "react-router-dom";
import moment from "moment"
import {getCurrentPhase, getNextPhase, phaseNumber, formatDateTime, formatTime, isSinglePhase, isPhaseless, daysInMinutes} from "../helpers/phaseHelpers"
import {truncateString} from '../helpers/stringHelpers'
import { ApiUrlContext } from '../ApiUrlContext'

export const ChallengeTile = ({challenge, preview}) => {
const { publicUrl, imageBase } = useContext(ApiUrlContext)

let diffMinutes = (d) =>{
let now = new Date();
let date = new Date(d);
return (now - date) / (1000 * 60)
}

const renderTags = ({is_archived, start_date, end_date, announcement_datetime}) => {
const startDateDiff = moment().diff(start_date, 'minutes')
const endDateDiff = moment().diff(end_date, 'minutes')
const announcementDateDiff = moment().diff(announcement_datetime, 'minutes')

const startDateDiff = diffMinutes(start_date);
const endDateDiff = diffMinutes(end_date);
const announcementDateDiff = diffMinutes(announcement_datetime);

let tags = []

Expand Down Expand Up @@ -40,8 +46,8 @@ export const ChallengeTile = ({challenge, preview}) => {

const renderDate = (challenge) => {
const {start_date, end_date, phases} = challenge
const startDateDiff = moment().diff(start_date, 'minutes')
const endDateDiff = moment().diff(end_date, 'minutes')
const startDateDiff = diffMinutes(start_date)
const endDateDiff = diffMinutes(end_date)

if (isPhaseless(challenge)) {
return handlePhaselessChallengeDate(challenge)
Expand Down Expand Up @@ -73,8 +79,8 @@ export const ChallengeTile = ({challenge, preview}) => {

// TODO: This is potentially temporary until the importer handles adding phases to imported challenges
const handlePhaselessChallengeDate = ({start_date, end_date}) => {
const startDateDiff = moment().diff(start_date, 'minutes')
const endDateDiff = moment().diff(end_date, 'minutes')
const startDateDiff = diffMinutes(start_date)
const endDateDiff = diffMinutes(end_date)

if (startDateDiff < 0) {
return `Opens on ${formatDateTime(start_date)}`
Expand Down Expand Up @@ -109,7 +115,7 @@ export const ChallengeTile = ({challenge, preview}) => {
<div className="agency_image_wrapper">
<img
className="agency-logo"
src={imageBase + challenge.agency_logo}
src={`${imageBase}${encodeURIComponent(challenge.agency_logo)}`}
alt={truncateString(`Agency Logo: ${challenge.agency_name}`, 90)}
/>
</div>
Expand All @@ -128,7 +134,7 @@ export const ChallengeTile = ({challenge, preview}) => {
<div className="image_wrapper">
<img
className="agency-logo"
src={imageBase + challenge.agency_logo}
src={`${imageBase}${encodeURIComponent(challenge.agency_logo)}`}
alt={truncateString(`Agency Logo: ${challenge.agency_name}`, 90)}
/>
</div>
Expand All @@ -138,7 +144,7 @@ export const ChallengeTile = ({challenge, preview}) => {
return (
challenge ? (
<div key={challenge.id} className="challenge-tile card">
<a href={challengeTileUrl(challenge, preview)} target={challenge.external_url ? "_blank" : ""} aria-label="">
<a href={encodeURI(challengeTileUrl(challenge, preview))} target={challenge.external_url ? "_blank" : ""} aria-label="">
{renderTileLogo()}
<div className="challenge-tile__text-wrapper">
<h2 className="challenge-tile__title test" aria-label="" style={{ textAlign: 'left', paddingLeft: '20px', paddingTop: '20px', lineHeight: '30px' }}>{truncateString(challenge.title, 90)}</h2>
Expand Down
52 changes: 36 additions & 16 deletions assets/client/src/components/ChallengeTiles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react';
import moment from 'moment';
import { ChallengeTile } from './ChallengeTile';

const dateAddedOptions = [
Expand Down Expand Up @@ -75,6 +74,15 @@ export const ChallengeTiles = ({ data, loading, isArchived, selectedYear, handle
const [keyword, setKeyword] = useState('');
const [filteredChallenges, setFilteredChallenges] = useState([]);

const isBetween = (date, startDate, endDate) => {

let dateObj = new Date(date);
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
return dateObj >= startDateObj && dateObj < endDateObj;

}

useEffect(() => {
try {
if (data && data.collection) {
Expand All @@ -88,26 +96,32 @@ export const ChallengeTiles = ({ data, loading, isArchived, selectedYear, handle
}

if (dateAdded) {
const now = moment();
let fromDate = now.clone().subtract(1, "years");

const now = new Date();
let fromDate = new Date(now);
fromDate.setFullYear(fromDate.getFullYear() -1);


switch (dateAdded) {
case "Past Week":
fromDate = now.clone().subtract(7, "days");
fromDate = new Date(now);
fromDate.setDate(fromDate.getDate() -7);
break;
case "Past Month":
fromDate = now.clone().subtract(1, "months");
fromDate = new Date(now);
fromDate.setMonth(fromDate.getMonth() -1);
break;
case "Past 90 Days":
fromDate = now.clone().subtract(90, "days");
fromDate = new Date(now);
fromDate.setDate(fromDate.getDate() -90);
break;
default:
break;
}

filtered = filtered.filter((challenge) => {
const challengeDate = moment(challenge.inserted_at);
return challengeDate.isBetween(fromDate, now, null, "[)");
const challengeDate = new Date(challenge.inserted_at);
return isBetween(challengeDate, fromDate, now);
});
}

Expand All @@ -116,30 +130,35 @@ export const ChallengeTiles = ({ data, loading, isArchived, selectedYear, handle
}

if (lastDay) {
const now = moment();
const now = new Date();
let toDate;

switch (lastDay) {
case "Next Week":
toDate = now.clone().add(7, "days");
toDate = new Date(now);
toDate.setDate(toDate.getDate() +7);
break;
case "Next Month":
toDate = now.clone().add(1, "months");
toDate = new Date(now);
toDate.setMonth(toDate.getMonth()+1);
break;
case "Next 90 days":
toDate = new Date(now);
toDate = now.clone().add(90, "days");
break;
case "Within Year":
toDate = now.clone().add(1, "years");
toDate = new Date(now);
toDate.setFullYear(toDate.getFullYear()+1);
break;
default:
toDate = now.clone().add(1, "years");
toDate = new Date(now);
toDate.setFullYear(toDate.getFullYear()+1);
break;
}

filtered = filtered.filter((challenge) => {
const challengeEnd = moment(challenge.end_date);
return challengeEnd.isBetween(now, toDate, null, "[)");
const challengeEnd = new Date(challenge.end_date);
return isBetween(challengeEnd, now, toDate);
});
}

Expand Down Expand Up @@ -296,7 +315,8 @@ export const ChallengeTiles = ({ data, loading, isArchived, selectedYear, handle

const renderYearFilter = () => {
const startYear = 2010;
const currentYear = moment().year();
let year = new Date();
const currentYear = year.getFullYear();
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + (i * step));
const years = range(currentYear, startYear, -1);

Expand Down
25 changes: 20 additions & 5 deletions assets/client/src/components/PreviewBanner.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import React, { useContext } from 'react'
import moment from 'moment'
import { ApiUrlContext } from '../ApiUrlContext'

export const PreviewBanner = ({challenge}) => {
const location = window.location.href.split('?')[0]
const { apiUrl } = useContext(ApiUrlContext)

const formatDateToLLLL = () => {

let now = new Date()
const options = {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true
};

return new Intl.DateTimeFormat('en-US', options).format(now);
}

return (
challenge ? (
Expand All @@ -20,11 +35,11 @@ export const PreviewBanner = ({challenge}) => {
</div>
<br/>
<div>
<span className="me-3">Preview generated on {moment().format("llll")}</span>
<span className="me-3">Preview generated on {formatDateToLLLL()}</span>
<a className="me-3" href={window.location.href}>Refresh page</a>
{!challenge.external_url &&
<a href={apiUrl + `/public/previews/challenges?challenge=${challenge.uuid}&print=true`} target="_blank">Print</a>
}
{!challenge.external_url && (
<a href={`${apiUrl}/public/previews/challenges?challenge=${encodeURIComponent(challenge.uuid)}&print=true`} target="_blank">Print</a>
)}
</div>
<br/>
<div>Link to share for internal agency review:</div>
Expand Down
4 changes: 2 additions & 2 deletions assets/client/src/components/challenge_tabs/Winners.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Winners = ({challenge, challengePhases, print}) => {
if (phaseWinner.overview_image_path) {
return (
<img
src={imageBase + phaseWinner.overview_image_path}
src={`${imageBase}${encodeURIComponent(phaseWinner.overview_image_path)}`}
alt="Phase Winner image"
title="Phase Winner image"
className="phase-winner-image mt-3"
Expand All @@ -23,7 +23,7 @@ export const Winners = ({challenge, challengePhases, print}) => {
const {id, image_path, name, place_title} = winner
return (
<div key={id} className="d-flex flex-row align-items-center usa-tbm-1rem">
{image_path && <img src={imageBase + winner.image_path} alt="winner image" title="winner image" className="phase-winner-image me-3" />}
{image_path && (<img src={`${imageBase}${encodeURIComponent(winner.image_path)}`} alt="winner image" title="winner image" className="phase-winner-image me-3" />)}
{name && <p>{name}</p>}
{place_title && <p>{` - ${place_title}`}</p>}
</div>
Expand Down
Loading

0 comments on commit 6e9e2dd

Please sign in to comment.