Skip to content

Commit

Permalink
Merge branch 'deployment/naxa' into feat-osm-download
Browse files Browse the repository at this point in the history
  • Loading branch information
varun2948 authored Jan 30, 2024
2 parents 503c3b8 + 2944c11 commit 6e20371
Show file tree
Hide file tree
Showing 19 changed files with 1,064 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
command: |
yarn --version
cd ${CIRCLE_WORKING_DIRECTORY}/frontend
yarn install
yarn install --network-concurrency 1 # lodash which has prepare script fails. Hotfix: https://github.com/yarnpkg/yarn/issues/6312
- save_cache:
key: yarn-deps-{{ checksum "frontend/yarn.lock" }}
paths:
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/build_and_deploy_backend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Build and Deploy Tasking Manager Backend

on:
push:
branches:
- deployment/naxa
paths:
- "backend/**"
workflow_dispatch:

jobs:
deploy:
name: Deploy to Server
runs-on: [ubuntu-latest]
steps:
- name: Clone repository
uses: actions/checkout@v3

- name: Recreate Services
uses: appleboy/ssh-action@master
with:
host: ${{ vars.SERVER_IP }}
username: ${{ vars.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
command_timeout: 20m
script: |
echo '==In Server=='
echo '==Building Backend=='
cd /home/ubuntu/Projects/tasking-manager
git pull naxa deployment/naxa
docker compose build --no-cache backend
docker compose up -d --force-recreate
52 changes: 52 additions & 0 deletions .github/workflows/build_and_deploy_frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Build and Deploy Tasking Manager Frontend

on:
push:
branches:
- deployment/naxa
paths:
- "frontend/**"
workflow_dispatch:

jobs:
deploy:
name: Deploy to Server
runs-on: [ubuntu-latest]
steps:
- name: Clone repository
uses: actions/checkout@v3

- name: SSH Run command
uses: appleboy/ssh-action@master
with:
host: ${{ vars.SERVER_IP }}
username: ${{ vars.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
command_timeout: 20m
script: |
#!/bin/bash -i
echo '==In Server=='
echo '==Building Frontend=='
export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh
cd /tmp
git clone https://github.com/naxa-developers/tasking-manager
cd tasking-manager
git checkout ${{ github.ref }}
cp /home/ubuntu/Projects/tasking-manager/tasking-manager.env .
nvm i 16
nvm use 16
npm i -g yarn
yarn install
npm run build
cp frontend/build/* /home/ubuntu/Projects/tasking-manager/frontend/build/
# cd /home/ubuntu/Projects/tasking-manager
# git pull naxa deployment/naxa
# cd /home/ubuntu/Projects/tasking-manager/frontend
# nvm i 16
# nvm use 16
# npm i -g yarn
# yarn install
# npm run build
4 changes: 4 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ TM_DEFAULT_LOCALE=en
# Sentry.io DSN Config (optional)
# TM_SENTRY_BACKEND_DSN=https://foo.ingest.sentry.io/1234567
# TM_SENTRY_FRONTEND_DSN=https://bar.ingest.sentry.io/8901234
#

# Underpass API URL (for project live monitoring feature)
UNDERPASS_URL=https://underpass.hotosm.org


#EXPORT TOOL Integration with 0(Disable) and 1(Enable) and S3 URL for Export Tool
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
"@formatjs/macro": "^0.2.8",
"@hotosm/id": "^2.21.1",
"@hotosm/iso-countries-languages": "^1.1.2",
"@hotosm/underpass-ui": "https://github.com/hotosm/underpass-ui.git",
"@mapbox/mapbox-gl-draw": "^1.4.1",
"@mapbox/mapbox-gl-geocoder": "^5.0.1",
"@mapbox/mapbox-gl-language": "^0.10.1",
"@placemarkio/geo-viewport": "^1.0.1",
"@rapideditor/rapid": "^2.1.1",
"@sentry/react": "^7.60.1",
"@tmcw/togeojson": "^4.7.0",
"@tanstack/react-query": "^4.29.7",
"@tanstack/react-query-devtools": "^4.29.7",
"@tmcw/togeojson": "^4.7.0",
"@turf/area": "^6.5.0",
"@turf/bbox": "^6.5.0",
"@turf/bbox-polygon": "^6.5.0",
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/api/projects.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import axios from 'axios';
import { subMonths, format } from 'date-fns';
import { useQuery } from '@tanstack/react-query';
import { useSelector } from 'react-redux';

import { remapParamsToAPI } from '../utils/remapParamsToAPI';
import api from './apiClient';
import { UNDERPASS_URL } from '../config';

export const useProjectsQuery = (fullProjectsQuery, action) => {
const token = useSelector((state) => state.auth.token);
Expand Down Expand Up @@ -187,6 +189,18 @@ export const submitValidationTask = (projectId, payload, token, locale) => {
);
};

export const useAvailableCountriesQuery = () => {
const fetchGeojsonData = () => {
return axios.get(`${UNDERPASS_URL}/availability`);
};

return useQuery({
queryKey: ['priority-geojson'],
queryFn: fetchGeojsonData,
select: (res) => res.data,
});
};

const backendToQueryConversion = {
difficulty: 'difficulty',
campaign: 'campaign',
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/components/comments/commentInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export const CommentInputField = ({
values: async (query, cb) => {
try {
if (!query) return cb(contributors.map((username) => ({ username })));

// do not fetch data if the value comes from suggestions popup click
const isValueFromSuggestion = /^\[.*?\]\s$/.test(query);
if (isValueFromSuggestion) return;

const res = await fetchLocalJSONAPI(`users/queries/filter/${query}/`, token);
cb(res.usernames.map((username) => ({ username })));
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/projectDetail/downloadOsmData.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { RoadIcon, HomeIcon, WavesIcon, TaskIcon, DownloadIcon } from '../svgIcons';
import { RoadIcon, HomeIcon, WavesIcon, TaskIcon, DownloadIcon, InfoIcon } from '../svgIcons';
import FileFormatCard from './fileFormatCard';
import Popup from 'reactjs-popup';
import { EXPORT_TOOL_S3_URL } from '../../config';
Expand Down
29 changes: 28 additions & 1 deletion frontend/src/components/projectDetail/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ import { PermissionBox } from './permissionBox';
import { CustomButton } from '../button';
import { ProjectInfoPanel } from './infoPanel';
import { OSMChaButton } from './osmchaButton';
import { LiveViewButton } from './liveViewButton';
import { useSetProjectPageTitleTag } from '../../hooks/UseMetaTags';
import { useProjectContributionsQuery, useProjectTimelineQuery } from '../../api/projects';
import {
useProjectContributionsQuery,
useProjectTimelineQuery,
useAvailableCountriesQuery,
} from '../../api/projects';
import { Alert } from '../alert';

import './styles.scss';
Expand Down Expand Up @@ -153,6 +158,16 @@ export const ProjectDetail = (props) => {
</Link>
);

const { data } = useAvailableCountriesQuery();

// check if the project has live monitoring feature enabled
// based on the country list provided by available.json
const hasLiveMonitoringFeature = !data
? false
: props.project.countryTag.some((country) =>
data.countries.some((item) => country.toLowerCase() === item.toLowerCase()),
);

return (
<div className={`${props.className || 'blue-dark'}`}>
<div className="db flex-l tasks-map-height">
Expand Down Expand Up @@ -346,6 +361,18 @@ export const ProjectDetail = (props) => {
project={props.project}
className="bg-white blue-dark ba b--grey-light pa3"
/>

{/*
show live view button only for published projects &
when the project has live monitoring feature
*/}
{props.project.status === 'PUBLISHED' && hasLiveMonitoringFeature && (
<LiveViewButton
projectId={props.project.projectId}
className="bg-white blue-dark ba b--grey-light pa3"
/>
)}

<DownloadAOIButton
projectId={props.project.projectId}
className="bg-white blue-dark ba b--grey-light pa3"
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/components/projectDetail/liveViewButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';

import messages from './messages';
import { CustomButton } from '../button';

export const LiveViewButton = ({ projectId, className, compact = false }) => (
<Link to={`/projects/${projectId}/live`} className="pr2">
{
<CustomButton className={className}>
{compact ? (
<FormattedMessage {...messages.live} />
) : (
<FormattedMessage {...messages.liveMonitoring} />
)}
</CustomButton>
}
</Link>
);
8 changes: 8 additions & 0 deletions frontend/src/components/projectDetail/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,14 @@ export default defineMessages({
id: 'project.detail.sections.contributions.osmcha',
defaultMessage: 'Changesets in OSMCha',
},
live: {
id: 'project.detail.sections.contributions.live',
defaultMessage: 'Live',
},
liveMonitoring: {
id: 'project.detail.sections.contributions.liveMonitoring',
defaultMessage: 'Live monitoring',
},
changesets: {
id: 'project.detail.sections.contributions.changesets',
defaultMessage: 'Changesets',
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/projectStats/contributorsStats.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Chart as ChartJS, ArcElement, BarElement } from 'chart.js';
import { Chart as ChartJS, ArcElement, BarElement, CategoryScale, LinearScale } from 'chart.js';
import { Doughnut, Bar } from 'react-chartjs-2';
import { FormattedMessage, useIntl } from 'react-intl';

Expand All @@ -10,7 +10,7 @@ import { formatChartData, formatTooltip } from '../../utils/formatChartJSData';
import { useContributorStats } from '../../hooks/UseContributorStats';
import { StatsCardContent } from '../statsCard';

ChartJS.register(ArcElement, BarElement);
ChartJS.register(ArcElement, BarElement, CategoryScale, LinearScale);

export default function ContributorsStats({ contributors }) {
const intl = useIntl();
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/taskSelection/taskList.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { LockIcon, ListIcon, ZoomPlusIcon, CloseIcon, InternalLinkIcon } from '.
import { PaginatorLine, howManyPages } from '../paginator';
import { Dropdown } from '../dropdown';
import { TextField } from '../formInputs';
import useCloseOnDocumentClick from '../../hooks/UseCloseOnDocumentClick';

export function TaskStatus({ status, lockHolder }: Object) {
const isReadyOrLockedForMapping = ['READY', 'LOCKED_FOR_MAPPING'].includes(status);
Expand Down Expand Up @@ -63,6 +64,8 @@ export function TaskItem({
const location = useLocation();
const { value, unit } = selectUnit(new Date(data.actionDate));

const closeOnDocumentClick = useCloseOnDocumentClick();

const handleCopyToClipboard = () =>
navigator.clipboard
.writeText(`${window.location.origin}${location.pathname}?search=${data.taskId}`)
Expand Down Expand Up @@ -117,6 +120,7 @@ export function TaskItem({
<ListIcon width="18px" height="18px" className="pointer hover-blue-grey" />
</div>
}
closeOnDocumentClick={closeOnDocumentClick}
>
{(close) => (
<TaskActivityDetail
Expand Down
1 change: 1 addition & 0 deletions frontend/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const API_URL = process.env.REACT_APP_API_URL
export const OHSOME_STATS_BASE_URL =
process.env.REACT_APP_OHSOME_STATS_BASE_URL || 'https://stats.now.ohsome.org/api';
export const OHSOME_STATS_TOKEN = process.env.REACT_APP_OHSOME_STATS_TOKEN || '';
export const UNDERPASS_URL = process.env.REACT_APP_UNDERPASS_URL || 'https://underpass.hotosm.org';

// APPLICATION SETTINGS
export const DEFAULT_LOCALE = process.env.REACT_APP_DEFAULT_LOCALE || 'en';
Expand Down
50 changes: 50 additions & 0 deletions frontend/src/hooks/UseCloseOnDocumentClick.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// https://github.com/yjose/reactjs-popup/issues/174
import { useEffect, useState } from 'react';

/**
* This hook is a workaround for an issue in reactjs-popup
*
* What this hook does is:
*
* - on mouse down inside the popup, set closeOnDocumentClick to false
* - on mouse up, set closeOnDocumentClick to true
*
* Usage:
*
* const closeOnDocumentClick = useCloseOnDocumentClick()
*
* return (
* <Popup ... closeOnDocumentClick={closeOnDocumentClick} >
* ...
* </Popup>
* )
*/
export default function useCloseOnDocumentClick() {
const [closeOnDocumentClick, setCloseOnDocumentClick] = useState(true);

useEffect(() => {
function insidePopupContents(target: any): boolean {
return target.querySelector('.popup-content') == null;
}

function handleMouseDown(event: MouseEvent) {
if (insidePopupContents(event.target)) {
setCloseOnDocumentClick(false);
}
}

function handleMouseUp() {
setTimeout(() => setCloseOnDocumentClick(true));
}

window.document.addEventListener('mousedown', handleMouseDown);
window.document.addEventListener('mouseup', handleMouseUp);

return () => {
window.document.removeEventListener('mousedown', handleMouseDown);
window.document.removeEventListener('mouseup', handleMouseUp);
};
}, [setCloseOnDocumentClick]);

return closeOnDocumentClick;
}
10 changes: 10 additions & 0 deletions frontend/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ export const router = createBrowserRouter(
}}
ErrorBoundary={FallbackComponent}
/>
<Route
path="projects/:id/live"
lazy={async () => {
const { ProjectLiveMonitoring } = await import(
'./views/projectLiveMonitoring' /* webpackChunkName: "projectLiveMonitoring" */
);
return { Component: ProjectLiveMonitoring };
}}
ErrorBoundary={FallbackComponent}
/>
<Route
path="organisations/:id/stats/"
lazy={async () => {
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/views/projectLiveMonitoring.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@import "@hotosm/underpass-ui/dist/index.css";

.maplibregl-map {
height: 100vh;
}

.top {
position: absolute;
top: 150px;
left: 20px;
z-index: 999;
}

svg.pl2 {
display: inherit;
height: 22px !important;
width: 19px !important;
margin-left: 0px;
}
Loading

0 comments on commit 6e20371

Please sign in to comment.