Skip to content

Commit

Permalink
resolve merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
royallsilwallz committed Mar 6, 2024
2 parents 18c5950 + 0236f8d commit 72a89f0
Show file tree
Hide file tree
Showing 26 changed files with 774 additions and 44 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
34 changes: 34 additions & 0 deletions .github/workflows/build_frontend_custom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: TM NAXA Custom Branch CICD

on:
push:
tags:
- force-deploy*
workflow_dispatch:

jobs:
build-static-for-branch:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v2

- name: Use Node.js 16
uses: actions/setup-node@v1
with:
node-version: 16.x

- name: Install dependencies
run: cd frontend && yarn install --network-concurrency 1

- name: Generate build
run: cd frontend && GENERATE_SOURCEMAP=false && yarn build

- name: copy file via ssh password
uses: appleboy/[email protected]
with:
host: ${{ vars.SERVER_IP }}
username: ${{ vars.SERVER_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "./frontend/build/"
target: /home/ubuntu/Projects/tasking-manager/frontend/build/
72 changes: 54 additions & 18 deletions backend/services/validator_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from flask import current_app
from sqlalchemy import text
from multiprocessing.dummy import Pool as ThreadPool
import os

from backend import db
from backend.exceptions import NotFound
from backend.models.dtos.mapping_dto import TaskDTOs
from backend.models.dtos.stats_dto import Pagination
Expand Down Expand Up @@ -135,24 +138,16 @@ def _user_can_validate_task(user_id: int, mapped_by: int) -> bool:
return False

@staticmethod
def unlock_tasks_after_validation(
validated_dto: UnlockAfterValidationDTO,
) -> TaskDTOs:
"""
Unlocks supplied tasks after validation
:raises ValidatorServiceError
"""
validated_tasks = validated_dto.validated_tasks
project_id = validated_dto.project_id
user_id = validated_dto.user_id
tasks_to_unlock = ValidatorService.get_tasks_locked_by_user(
project_id, validated_tasks, user_id
)

# Unlock all tasks
dtos = []
message_sent_to = []
for task_to_unlock in tasks_to_unlock:
def _process_tasks(args):
(
app_context,
task_to_unlock,
project_id,
validated_dto,
message_sent_to,
dtos,
) = args
with app_context:
task = task_to_unlock["task"]

if task_to_unlock["comment"]:
Expand Down Expand Up @@ -202,6 +197,47 @@ def unlock_tasks_after_validation(
issues=task_mapping_issues,
)
dtos.append(task.as_dto_with_instructions(validated_dto.preferred_locale))

@staticmethod
def unlock_tasks_after_validation(
validated_dto: UnlockAfterValidationDTO,
) -> TaskDTOs:
"""
Unlocks supplied tasks after validation
:raises ValidatorServiceError
"""
validated_tasks = validated_dto.validated_tasks
project_id = validated_dto.project_id
user_id = validated_dto.user_id
tasks_to_unlock = ValidatorService.get_tasks_locked_by_user(
project_id, validated_tasks, user_id
)

# Unlock all tasks
dtos = []
message_sent_to = []
args_list = []
for task_to_unlock in tasks_to_unlock:
args = (
current_app.app_context(),
task_to_unlock,
project_id,
validated_dto,
message_sent_to,
dtos,
)
args_list.append(args)

# Create a pool and Process the tasks in parallel
pool = ThreadPool(os.cpu_count())
pool.map(ValidatorService._process_tasks, args_list)

# Close the pool and wait for the threads to finish
pool.close()
pool.join()
db.session.commit()

# Send email on project progress
ProjectService.send_email_on_project_progress(validated_dto.project_id)
task_dtos = TaskDTOs()
task_dtos.tasks = dtos
Expand Down
4 changes: 4 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,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
20 changes: 19 additions & 1 deletion frontend/src/api/stats.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useQuery } from '@tanstack/react-query';
import { fetchExternalJSONAPI } from '../network/genericJSONRequest';

import api from './apiClient';
import { OHSOME_STATS_BASE_URL } from '../config';
Expand Down Expand Up @@ -42,7 +43,7 @@ export const useOsmStatsQuery = () => {
queryKey: ['osm-stats'],
queryFn: fetchOsmStats,
useErrorBoundary: true,
select: (data) => data.data.result
select: (data) => data.data.result,
});
};

Expand All @@ -61,3 +62,20 @@ export const useOsmHashtagStatsQuery = (defaultComment) => {
select: (data) => data.data.result,
});
};

export const useUserOsmStatsQuery = (id) => {
const fetchUserOsmStats = () => {
return fetchExternalJSONAPI(
`${OHSOME_STATS_BASE_URL}/topic/poi,highway,building,waterway/user?userId=${id}`,
true,
);
};

return useQuery({
queryKey: ['user-osm-stats'],
queryFn: fetchUserOsmStats,
useErrorBoundary: true,
select: (data) => data.result,
enabled: !!id,
});
};
14 changes: 14 additions & 0 deletions frontend/src/assets/styles/_extra.scss
Original file line number Diff line number Diff line change
Expand Up @@ -621,3 +621,17 @@ a[href="https://www.mapbox.com/map-feedback/"]
.code {
font-family: inherit;
}

// margin auto
.mt-auto {
margin-top: auto;
}
.mb-auto {
margin-bottom: auto;
}
.ml-auto {
margin-left: auto;
}
.ml-auto {
margin-right: auto;
}
1 change: 1 addition & 0 deletions frontend/src/components/footer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export function Footer() {
'projects/:id/tasks',
'projects/:id/map',
'projects/:id/validate',
'projects/:id/live',
'manage/organisations/new/',
'manage/teams/new',
'manage/campaigns/new',
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
2 changes: 2 additions & 0 deletions frontend/src/components/projectStats/contributorsStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { formatChartData, formatTooltip } from '../../utils/formatChartJSData';
import { useContributorStats } from '../../hooks/UseContributorStats';
import { StatsCardContent } from '../statsCard';

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

export default function ContributorsStats({ contributors }) {
ChartJS.register(BarElement, CategoryScale, Legend, LinearScale, Title, Tooltip, ArcElement);
const intl = useIntl();
Expand Down
Loading

0 comments on commit 72a89f0

Please sign in to comment.