Skip to content

Commit

Permalink
Merge pull request #888 from mapswipe/master-rc
Browse files Browse the repository at this point in the history
Release Footprint validation Changes
  • Loading branch information
frozenhelium authored Jul 12, 2023
2 parents 4675071 + 4a3b5c1 commit 66b8838
Show file tree
Hide file tree
Showing 103 changed files with 5,624 additions and 1,423 deletions.
4 changes: 4 additions & 0 deletions api/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ server {
listen 80;
server_name api;

gzip on;
gzip_comp_level 2;
gzip_types text/plain text/csv text/css application/json text/javascript;

location / {
alias /usr/share/nginx/html/api/;
autoindex on;
Expand Down
4 changes: 4 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ services:
REACT_APP_SENTRY_DSN: ${MANAGER_DASHBOARD_SENTRY_DSN}
REACT_APP_SENTRY_TRACES_SAMPLE_RATE: ${MANAGER_DASHBOARD_SENTRY_TRACES_SAMPLE_RATE}
REACT_APP_COMMUNITY_DASHBOARD_URL: ${MANAGER_DASHBOARD_COMMUNITY_DASHBOARD_URL}
REACT_APP_IMAGE_BING_API_KEY: ${IMAGE_BING_API_KEY}
REACT_APP_IMAGE_MAPBOX_API_KEY: ${IMAGE_MAPBOX_API_KEY}
REACT_APP_IMAGE_MAXAR_PREMIUM_API_KEY: ${IMAGE_MAXAR_PREMIUM_API_KEY}
REACT_APP_IMAGE_MAXAR_STANDARD_API_KEY: ${IMAGE_MAXAR_STANDARD_API_KEY}
volumes:
- manager-dashboard-static:/code/build/
command: bash -c 'yarn build'
Expand Down
163 changes: 91 additions & 72 deletions firebase/functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ exports.osmAuth.token = functions.https.onRequest((req, res) => {
This function also writes to the `contributions` section in the user profile.
*/
exports.groupUsersCounter = functions.database.ref('/v2/results/{projectId}/{groupId}/{userId}/').onCreate((snapshot, context) => {
exports.groupUsersCounter = functions.database.ref('/v2/results/{projectId}/{groupId}/{userId}/').onCreate(async (snapshot, context) => {
// these references/values will be updated by this function
const groupUsersRef = admin.database().ref('/v2/groupsUsers/' + context.params.projectId + '/' + context.params.groupId);
const userRef = admin.database().ref('/v2/users/' + context.params.userId);
Expand All @@ -53,6 +53,30 @@ exports.groupUsersCounter = functions.database.ref('/v2/results/{projectId}/{gro
}

const result = snapshot.val();


// New versions of app will have the appVersion defined (> 2.2.5)
// appVersion: 2.2.5 (14)-dev
const appVersionString = result.appVersion as string | undefined | null;

// Check if the app is of older version
// (no need to check for specific version since old app won't sent the version info)
if (appVersionString === null || appVersionString === undefined || appVersionString.trim() === '') {
const projectRef = admin.database().ref(`/v2/projects/${context.params.projectId}`);
const dataSnapshot = await projectRef.once('value');

if (dataSnapshot.exists()) {
const project = dataSnapshot.val();
// Check if project type is footprint and also has
// custom options (i.e. these are new type of projects)
if (project.projectType === 2 && project.customOptions) {
// We remove the results submitted from older version of app (< v2.2.6)
console.info(`Result submitted for ${context.params.projectId} was discarded: submitted from older version of app`);
return thisResultRef.remove();
}
}
}

// if result ref does not contain all required attributes we don't updated counters
// e.g. due to some error when uploading from client
if (!Object.prototype.hasOwnProperty.call(result, 'results')) {
Expand Down Expand Up @@ -90,77 +114,72 @@ exports.groupUsersCounter = functions.database.ref('/v2/results/{projectId}/{gro
Update overall taskContributionCount and project taskContributionCount in the user profile
based on the number of results submitted and the existing count values.
*/
return groupUsersRef.child(context.params.userId).once('value')
.then((dataSnapshot) => {
if (dataSnapshot.exists()) {
console.log('group contribution exists already. user: '+context.params.userId+' project: '+context.params.projectId+' group: '+context.params.groupId);
return null;
}
const latestNumberOfTasks = Object.keys(result['results']).length;

return Promise.all([
userContributionRef.child(context.params.groupId).set(true),
groupUsersRef.child(context.params.userId).set(true),
totalTaskContributionCountRef.transaction((currentCount) => {
return currentCount + latestNumberOfTasks;
}),
totalGroupContributionCountRef.transaction((currentCount) => {
return currentCount + 1;
}),
taskContributionCountRef.transaction((currentCount) => {
return currentCount + latestNumberOfTasks;
}),

// Tag userGroups of the user in the result
// eslint-disable-next-line promise/no-nesting
userRef.child('userGroups').once('value').then((userGroupsOfTheUserSnapshot) => {
if (!userGroupsOfTheUserSnapshot.exists()) {
return null;
}

// eslint-disable-next-line promise/no-nesting
return userGroupsRef.once('value').then((allUserGroupsSnapshot) => {
if (!allUserGroupsSnapshot.exists()) {
return null;
}

const userGroupsOfTheUserKeyList = Object.keys(userGroupsOfTheUserSnapshot.val());
if (userGroupsOfTheUserKeyList.length <= 0) {
return null;
}

const allUserGroups = allUserGroupsSnapshot.val();
const nonArchivedUserGroupKeys = userGroupsOfTheUserKeyList.filter((key) => {
const currentUserGroup = allUserGroups[key];

// User might have joined some group that was removed but not cleared from their list
if (!currentUserGroup) {
return false;
}

// Skip groups that have been archived
if (currentUserGroup.archivedAt) {
return false;
}

return true;
});

if (nonArchivedUserGroupKeys.length === 0) {
return null;
}

const nonArchivedUserGroupsOfTheUser = nonArchivedUserGroupKeys.reduce((acc, val) => {
acc[val] = true;
return acc;
}, {} as Record<string, boolean>);

// Include userGroups of the user in the results
return thisResultRef.child('userGroups').set(nonArchivedUserGroupsOfTheUser);
});
}),
]);
});
const dataSnapshot = await groupUsersRef.child(context.params.userId).once('value');
if (dataSnapshot.exists()) {
console.log('group contribution exists already. user: '+context.params.userId+' project: '+context.params.projectId+' group: '+context.params.groupId);
return null;
}

const latestNumberOfTasks = Object.keys(result['results']).length;
await Promise.all([
userContributionRef.child(context.params.groupId).set(true),
groupUsersRef.child(context.params.userId).set(true),
totalTaskContributionCountRef.transaction((currentCount) => {
return currentCount + latestNumberOfTasks;
}),
totalGroupContributionCountRef.transaction((currentCount) => {
return currentCount + 1;
}),
taskContributionCountRef.transaction((currentCount) => {
return currentCount + latestNumberOfTasks;
}),
]);


// Tag userGroups of the user in the result
const userGroupsOfTheUserSnapshot = await userRef.child('userGroups').once('value');
if (!userGroupsOfTheUserSnapshot.exists()) {
return null;
}

const allUserGroupsSnapshot = await userGroupsRef.once('value');
if (!allUserGroupsSnapshot.exists()) {
return null;
}

const userGroupsOfTheUserKeyList = Object.keys(userGroupsOfTheUserSnapshot.val());
if (userGroupsOfTheUserKeyList.length <= 0) {
return null;
}

const allUserGroups = allUserGroupsSnapshot.val();
const nonArchivedUserGroupKeys = userGroupsOfTheUserKeyList.filter((key) => {
const currentUserGroup = allUserGroups[key];

// User might have joined some group that was removed but not cleared from their list
if (!currentUserGroup) {
return false;
}

// Skip groups that have been archived
if (currentUserGroup.archivedAt) {
return false;
}

return true;
});

if (nonArchivedUserGroupKeys.length === 0) {
return null;
}

const nonArchivedUserGroupsOfTheUser = nonArchivedUserGroupKeys.reduce((acc, val) => {
acc[val] = true;
return acc;
}, {} as Record<string, boolean>);

// Include userGroups of the user in the results
return thisResultRef.child('userGroups').set(nonArchivedUserGroupsOfTheUser);
});


Expand Down
6 changes: 6 additions & 0 deletions manager-dashboard/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ REACT_APP_FIREBASE_STORAGE_BUCKET=
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=
REACT_APP_FIREBASE_APP_ID=
REACT_APP_COMMUNITY_DASHBOARD_URL=

REACT_APP_IMAGE_BING_API_KEY=
REACT_APP_IMAGE_MAPBOX_API_KEY=
REACT_APP_IMAGE_MAXAR_PREMIUM_API_KEY=
# -- NOTE: not used and seems to be discontinued
REACT_APP_IMAGE_MAXAR_STANDARD_API_KEY=
6 changes: 3 additions & 3 deletions manager-dashboard/app/Base/components/Navbar/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
box-shadow: 0 3px 5px -2px var(--color-shadow);
background-color: var(--color-primary);
padding: var(--spacing-medium) var(--spacing-large);
color: var(--color-text-on-light);
color: var(--color-text-on-dark);

.container {
display: flex;
Expand Down Expand Up @@ -42,7 +42,7 @@

.link {
opacity: 0.7;
color: var(--color-text-on-light);
color: var(--color-text-on-dark);

&.active {
opacity: 1;
Expand All @@ -58,7 +58,7 @@
gap: var(--spacing-medium);

.logout-button {
color: var(--color-text-on-light);
color: var(--color-text-on-dark);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion manager-dashboard/app/Base/components/SmartLink/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link, LinkProps } from 'react-router-dom';

import {
useButtonFeatures,
Props as ButtonProps,
ButtonProps,
} from '#components/Button';

import useRouteMatching, {
Expand Down
1 change: 1 addition & 0 deletions manager-dashboard/app/Base/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ApolloProvider,
} from '@apollo/client';
import { initializeApp } from 'firebase/app';
import 'react-mde/lib/styles/css/react-mde-all.css';

import Init from '#base/components/Init';
import PreloadMessage from '#base/components/PreloadMessage';
Expand Down
27 changes: 24 additions & 3 deletions manager-dashboard/app/Base/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,26 @@ p {
--color-background-primary-hint: #0d194920;
--color-background-accent-hint: #4746f610;

--color-black: #000000;

--color-scrollbar-foreground: rgba(0, 0, 0, .2);
--color-scrollbar-background: rgba(0, 0, 0, .01);
--color-hover-background: rgba(0, 0, 0, 0.03);
--color-input-background: #4746f605;

--color-primary: #0d1949;
--color-primary-light: #2d5989;
--color-text-on-light: #ffffff;
--color-text-on-dark: #ffffff;
--color-text-watermark: rgba(0, 0, 0, .4);
--color-text: rgba(0, 0, 0, 0.8);
--color-text-dark: rgba(0, 0, 0, 1);
--color-text-light: rgba(0, 0, 0, 0.6);
--color-text-gray: #666666;
--color-accent: #4746f6;
--color-danger: #e04656;
--color-success: #53b391;
--color-banner-alert: #fdf4dc;
--color-banner-text: #5C4813;
--color-separator: rgba(0, 0, 0, 0.1);
--color-shadow: rgba(0, 0, 0, 0.2);

Expand All @@ -83,24 +88,40 @@ p {
--font-size-ultra-large: 4rem;

--font-weight-medium: 400;
--font-weight-semibold: 600;
--font-weight-bold: 700;

--opacity-disabled-element: 0.5;

--width-separator-thin: 1px;
--width-separator-thin: 1pt;
--width-separator-thick: 5pt;
--width-separator-mobile-preview: 8pt;
--width-scrollbar: 0.75rem;
--width-page-content-max: 70rem;
--width-navbar-content-max: 76rem;

--width-mobile-preview: 22rem;
--height-mobile-preview: 40rem;
--height-mobile-preview-builarea-content: 30rem;
--height-mobile-preview-footprint-content: 22rem;
--height-mobile-preview-change-detection-content: 14rem;

--radius-popup-border: 0.25rem;
--radius-scrollbar-border: 0.25rem;
--radius-blur-shadow: 5px;
--radius-modal: 0.25rem;
--radius-button-border: 0.25rem;
--radius-input-border: 0.25rem;
--radius-card-border: 0.25rem;
--radius-card-border: 0.5rem;
--radius-badge-border: 1rem;

--line-height-none: 1;
--line-height-tight: 1.25;
--line-height-snug: 1.375;
--line-height-normal: 1.5;
--line-height-relaxed: 1.625;
--line-height-loose: 2;


--shadow-card: 0 2px 4px -2px var(--color-shadow);

Expand Down
8 changes: 4 additions & 4 deletions manager-dashboard/app/Base/utils/errorTransform.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { internal } from '@togglecorp/toggle-form';
import { nonFieldError } from '@togglecorp/toggle-form';
import { listToMap, isDefined, isNotDefined } from '@togglecorp/fujs';

interface Error {
[internal]?: string | undefined;
[nonFieldError]?: string | undefined;
[key: string]: string | Error | undefined;
}

Expand Down Expand Up @@ -53,7 +53,7 @@ function transformObject(errors: ObjectError[] | undefined): Error | undefined {
);

return {
[internal]: finalNonFieldErrors,
[nonFieldError]: finalNonFieldErrors,
...finalFieldErrors,
};
}
Expand All @@ -68,7 +68,7 @@ function transformArray(errors: (ArrayError | null)[] | undefined): Error | unde
const memberErrors = filteredErrors.filter((error) => error.clientId !== 'nonMemberErrors');

return {
[internal]: topLevelError?.messages,
[nonFieldError]: topLevelError?.messages,
...listToMap(
memberErrors,
(error) => error.clientId,
Expand Down
39 changes: 39 additions & 0 deletions manager-dashboard/app/components/AlertBanner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { IoAlertCircleOutline } from 'react-icons/io5';
import { _cs } from '@togglecorp/fujs';

import Heading from '#components/Heading';

import styles from './styles.css';

interface Props {
className?: string;
title?: React.ReactNode;
children: React.ReactNode;
}

function AlertBanner(props: Props) {
const {
className,
children,
title,
} = props;

return (
<div className={_cs(styles.banner, className)}>
<div className={styles.bannerIcon}>
<IoAlertCircleOutline />
</div>
<div className={styles.container}>
{title && (
<Heading>
{title}
</Heading>
)}
{children}
</div>
</div>
);
}

export default AlertBanner;
Loading

0 comments on commit 66b8838

Please sign in to comment.