Skip to content

Commit

Permalink
Merge pull request #6675 from hotosm/develop
Browse files Browse the repository at this point in the history
Mapswipe changes on staging
  • Loading branch information
ramyaragupathy authored Jan 7, 2025
2 parents 1a3e872 + 70ce6df commit 6446849
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 41 deletions.
5 changes: 2 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ jobs:
- env
- run:
name: Run yarn test
no_output_timeout: 20m
command: |
cd ${CIRCLE_WORKING_DIRECTORY}/frontend/
CI=true yarn test -w 3 --silent
CI=true yarn test -w 1 --silent
CI=true GENERATE_SOURCEMAP=false yarn build
backend-code-check-PEP8:
Expand Down Expand Up @@ -133,7 +134,6 @@ jobs:
--output text)
- run:
name: Make Database Backup
no_output_timeout: 15m
command: |
aws rds wait db-instance-available \
--db-instance-identifier ${RDS_ID}
Expand Down Expand Up @@ -211,7 +211,6 @@ jobs:
/tmp/tasking-manager.cfn.json > "$tmpfile" && mv "$tmpfile" $CIRCLE_WORKING_DIRECTORY/cfn-config-<< parameters.stack_name >>.json
- run:
name: Deploy to << parameters.stack_name >>
no_output_timeout: 15m
command: |
export NODE_PATH=/usr/local/share/.config/yarn/global/node_modules/
validate-template $CIRCLE_WORKING_DIRECTORY/scripts/aws/cloudformation/tasking-manager.template.js
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/assets/styles/_extra.scss
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ a[href="https://www.mapbox.com/map-feedback/"]
color: rgba($blue-dark, 0.9);
}

.gap-0\.625 {
gap: 0.75rem;
.gap-0\.5 {
gap: 0.5rem;
}

.gap-0\.75 {
Expand Down
29 changes: 11 additions & 18 deletions frontend/src/components/partnerMapswipeStats/contributionsGrid.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import CalendarHeatmap from 'react-calendar-heatmap';
import { Tooltip } from 'react-tooltip';
import { FormattedMessage, useIntl } from 'react-intl';
import { format } from 'date-fns';
import PropTypes from 'prop-types';

import messages from './messages';

const LEGEND_INDEXES = [30, 50, 70, 100];

const Legend = () => {
const legendFontStyle = 'ph2 f7 blue-grey ttc';

Expand All @@ -25,27 +27,13 @@ const Legend = () => {
);
};

export const ContributionsGrid = ({ contributionsByDate = [] }) => {
export const ContributionsGrid = ({ contributionsByDate = [], startDate, endDate }) => {
const gridData = contributionsByDate.map((contribution) => ({
date: contribution.taskDate,
count: contribution.totalcontributions,
}));
const intl = useIntl();

const getDate = (isEndDate = false) => {
const today = new Date();
const currentYear = today.getFullYear();

const formatDate = (date) => {
const offset = date.getTimezoneOffset();
return new Date(date.getTime() - offset * 60 * 1000);
};

return !isEndDate
? formatDate(new Date(currentYear - 1, 11, 31))
: formatDate(new Date(currentYear, 11, 31));
};

const countValues = gridData.map((contribution) => contribution.count);
const maxValue = Math.max(...countValues);

Expand All @@ -69,16 +57,19 @@ export const ContributionsGrid = ({ contributionsByDate = [] }) => {
}
};

const endDateYear = endDate.split('-')[0];
const formattedEndDate = format(new Date(endDateYear, 11, 31), 'yyyy-MM-dd');

return (
<div>
<h3 className="f2 fw6 ttu barlow-condensed blue-dark mt0 pt2 mb4">
<h3 className="f2 fw6 ttu barlow-condensed blue-dark mt0 mb4">
<FormattedMessage {...messages.contributions} />
</h3>

<div className="bg-white pv4 pr4 shadow-6" style={{ fontSize: '1rem' }}>
<CalendarHeatmap
startDate={getDate()}
endDate={getDate(true)}
startDate={startDate}
endDate={formattedEndDate}
values={gridData}
classForValue={(value) => {
if (!value) return 'fill-tan';
Expand Down Expand Up @@ -114,4 +105,6 @@ ContributionsGrid.propTypes = {
totalcontributions: PropTypes.number,
}),
),
startDate: PropTypes.instanceOf(Date),
endDate: PropTypes.instanceOf(Date),
};
91 changes: 91 additions & 0 deletions frontend/src/components/partnerMapswipeStats/dateFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { format, parse } from 'date-fns';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

import { CalendarIcon } from '../svgIcons';
import messages from './messages';

const today = new Date();
const currentYear = today.getFullYear();
const dateFormat = 'yyyy-MM-dd';

const initialState = {
fromDate: format(new Date(currentYear, 0, 1), dateFormat),
toDate: format(today, dateFormat),
};

export const DateFilter = ({ isLoading, filters, setFilters }) => {
// set initial date filter state
useEffect(() => {
setFilters((prev) => ({
...prev,
...initialState,
}));
}, [setFilters]);

const handleDateSelect = (key, selectedDate) => {
let { fromDate, toDate } = filters;
const selectedDateValue = new Date(selectedDate).valueOf();
const toDateValue = new Date(toDate).valueOf();
const fromDateValue = new Date(fromDate).valueOf();
// adjust from and to date based on greater/lesser value
if (key === 'fromDate' && selectedDateValue > toDateValue) {
fromDate = toDate;
toDate = selectedDate;
} else if (key === 'toDate' && selectedDateValue < fromDateValue) {
toDate = fromDate;
fromDate = selectedDate;
} else if (key === 'toDate') {
toDate = selectedDate;
} else {
fromDate = selectedDate;
}
// set filters state
setFilters((prev) => ({
...prev,
fromDate,
toDate,
}));
};

if (isLoading) return <></>;

return (
<div className="w-100 mt4 flex justify-end">
<div className="flex flex-column items-end gap-0.5">
<div className="flex items-center">
<CalendarIcon className="blue-grey dib w1 pr2 v-mid" />
<DatePicker
selected={filters.fromDate ? parse(filters.fromDate, dateFormat, new Date()) : null}
onChange={(date) => {
handleDateSelect('fromDate', format(date, dateFormat));
}}
dateFormat={dateFormat}
className="w4 pv2 ph1 ba b--grey-light"
showYearDropdown
scrollableYearDropdown
/>

<span className="ph3">to</span>

<CalendarIcon className="blue-grey dib w1 pr2 v-mid" />
<DatePicker
selected={filters.toDate ? parse(filters.toDate, dateFormat, new Date()) : null}
onChange={(date) => {
handleDateSelect('toDate', format(date, dateFormat));
}}
dateFormat={dateFormat}
className="w4 pv2 ph1 ba b--grey-light"
showYearDropdown
scrollableYearDropdown
/>
</div>
<span className="blue-grey f6">
<FormattedMessage {...messages.dateFilterSubText} />
</span>
</div>
</div>
);
};
8 changes: 8 additions & 0 deletions frontend/src/components/partnerMapswipeStats/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ export default defineMessages({
id: 'management.partners.stats.mapswipe.groupMembers.error',
defaultMessage: 'Something went wrong!',
},
groupStatsboard: {
id: 'management.partners.stats.mapswipe.groupStatsboard',
defaultMessage: 'Group Statsboard',
},
dateFilterSubText: {
id: 'management.partners.stats.mapswipe.dateFilterSubText',
defaultMessage: 'All dates are calculated in UTC',
},
contributions: {
id: 'management.partners.stats.mapswipe.contributions',
defaultMessage: 'Contributions',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/partnerMapswipeStats/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const getShortNumber = (value) => {
<span>
<FormattedNumber value={Number(shortNumberValue.substr(0, shortNumberValue.length - 1))} />
&nbsp;
<span className="fw1">{shortNumberValue.substr(-1)}</span>
<span>{shortNumberValue.substr(-1)}</span>
</span>
);
};
Expand Down
34 changes: 19 additions & 15 deletions frontend/src/views/partnersMapswipeStats.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router-dom';
import ReactPlaceholder from 'react-placeholder';
Expand All @@ -9,6 +10,7 @@ import {
getShortNumber,
formatSecondsToTwoUnits,
} from '../components/partnerMapswipeStats/overview';
import { DateFilter } from '../components/partnerMapswipeStats/dateFilter';
import { GroupMembers } from '../components/partnerMapswipeStats/groupMembers';
import { ContributionsGrid } from '../components/partnerMapswipeStats/contributionsGrid';
import { ContributionsHeatmap } from '../components/partnerMapswipeStats/contributionsHeatmap';
Expand All @@ -19,6 +21,7 @@ import { SwipesByProjectType } from '../components/partnerMapswipeStats/swipesBy
import { SwipesByOrganization } from '../components/partnerMapswipeStats/swipesByOrganization';
import messages from './messages';
import { fetchLocalJSONAPI } from '../network/genericJSONRequest';

import './partnersMapswipeStats.scss';

const PagePlaceholder = () => (
Expand Down Expand Up @@ -57,23 +60,18 @@ const InfoBanner = () => {

export const PartnersMapswipeStats = () => {
const { id: partnerPermalink } = useParams();
const [filters, setFilters] = useState({}); // state for date filter
const { isLoading, isError, data, isRefetching } = useQuery({
queryKey: ['partners-mapswipe-filtered-statistics', partnerPermalink],
queryKey: [
'partners-mapswipe-filtered-statistics',
partnerPermalink,
filters.fromDate,
filters.toDate,
],
queryFn: async () => {
const today = new Date();
const currentYear = today.getFullYear();

const formatDate = (date) => {
const offset = date.getTimezoneOffset();
const adjustedDate = new Date(date.getTime() - offset * 60 * 1000);
return adjustedDate.toISOString().split('T')[0];
};

const fromDate = formatDate(new Date(currentYear, 0, 1));
const endDate = formatDate(today);

const { fromDate, toDate } = filters;
const response = await fetchLocalJSONAPI(
`partners/${partnerPermalink}/filtered-statistics/?fromDate=${fromDate}&toDate=${endDate}`,
`partners/${partnerPermalink}/filtered-statistics/?fromDate=${fromDate}&toDate=${toDate}`,
);
return response;
},
Expand Down Expand Up @@ -105,6 +103,8 @@ export const PartnersMapswipeStats = () => {
<InfoBanner />
<Overview />

<DateFilter isLoading={isLoading} filters={filters} setFilters={setFilters} />

<ReactPlaceholder customPlaceholder={<PagePlaceholder />} ready={!isLoading && !isRefetching}>
{!isLoading && isError ? (
<div className="pa3 pl0 bg-tan">
Expand All @@ -118,7 +118,11 @@ export const PartnersMapswipeStats = () => {
) : (
<>
<div className="mt3">
<ContributionsGrid contributionsByDate={data?.contributionsByDate} />
<ContributionsGrid
startDate={filters?.fromDate}
endDate={filters?.toDate}
contributionsByDate={data?.contributionsByDate}
/>
</div>

<div className="mt3">
Expand Down
16 changes: 14 additions & 2 deletions frontend/src/views/teams.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Link, useNavigate, useParams, useLocation } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { Form } from 'react-final-form';
import {
Expand Down Expand Up @@ -421,18 +421,30 @@ export function EditTeam(props) {
export function TeamDetail() {
const { id } = useParams();
useSetTitleTag(`Team #${id}`);
const location = useLocation();
const navigate = useNavigate();
const userDetails = useSelector((state) => state.auth.userDetails);
const token = useSelector((state) => state.auth.token);
const [error, loading, team] = useFetch(`teams/${id}/`);
// eslint-disable-next-line
const [projectsError, projectsLoading, projects] = useFetch(
`projects/?teamId=${id}&omitMapResults=true&projectStatuses=PUBLISHED,DRAFT,ARCHIVED`,
`projects/?teamId=${id}&omitMapResults=true&projectStatuses=PUBLISHED`,
id,
);
const [isMember, setIsMember] = useState(false);
const [managers, setManagers] = useState([]);
const [members, setMembers] = useState([]);

useEffect(() => {
if (!token) {
navigate('/login', {
state: {
from: location.pathname,
},
});
}
}, [location.pathname, navigate, token]);

useEffect(() => {
if (team && team.members) {
setManagers(filterActiveManagers(team.members));
Expand Down

0 comments on commit 6446849

Please sign in to comment.