Skip to content

Commit

Permalink
Merge branch 'master' into geo-annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
gino-m authored Nov 27, 2024
2 parents b94ed81 + 125cf86 commit c026666
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 67 deletions.
4 changes: 2 additions & 2 deletions functions/src/export-csv.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ describe('exportCsv()', () => {
[d.taskId]: 'task004',
[d.multipleChoiceResponses]: {
'1': ['aaa', 'bbb'],
'2': 'Other',
'2': 'other',
},
},
{
Expand Down Expand Up @@ -255,7 +255,7 @@ describe('exportCsv()', () => {
'"system:index","geometry","name","area","data:What is the meaning of life?","data:How much?","data:When?","data:Which ones?","data:Where are you now?","data:Take a photo","data:contributor_name","data:contributor_email","data:created_client_timestamp","data:created_server_timestamp"',
'"POINT_001","POINT (125.6 10.1)","Dinagat Islands",3.08,"Submission 1",42,,,,,,,"1970-01-01T00:00:00.000Z","1970-01-01T00:00:00.000Z"',
'"POINT_001","POINT (125.6 10.1)","Dinagat Islands",3.08,"Submission 2",,"2012-03-08T12:17:24.000Z",,,,,,"1970-01-01T00:00:00.000Z","1970-01-01T00:00:00.000Z"',
'"POINT_002","POINT (8.3 47.05)","Luzern",,,,,"AAA,BBB,Other","POINT (45 -123)","http://photo/url",,,"1970-01-01T00:00:00.000Z","1970-01-01T00:00:00.000Z"',
'"POINT_002","POINT (8.3 47.05)","Luzern",,,,,"AAA,BBB,Other: other","POINT (45 -123)","http://photo/url",,,"1970-01-01T00:00:00.000Z","1970-01-01T00:00:00.000Z"',
],
},
];
Expand Down
58 changes: 31 additions & 27 deletions functions/src/export-csv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,38 +237,35 @@ function getValue(
data: Pb.ITaskData[]
): string | number | null {
const result = data.find(d => d.taskId === task.id);
if (!result) {
return null;
}
if (result.textResponse) {
return result.textResponse.text ?? null;
} else if (result.numberResponse) {
return getNumberValue(result.numberResponse);
} else if (result.dateTimeResponse) {
return getDateTimeValue(result.dateTimeResponse);
} else if (result.multipleChoiceResponses) {
return getMultipleChoiceValues(task, result.multipleChoiceResponses);
} else if (result.captureLocationResult) {
if (!result || result.skipped) return null;
const {
textResponse,
numberResponse,
dateTimeResponse,
multipleChoiceResponses,
drawGeometryResult,
captureLocationResult,
takePhotoResult,
} = result;
if (textResponse) return textResponse.text ?? null;
else if (numberResponse) return numberResponse.number ?? null;
else if (dateTimeResponse) return getDateTimeValue(dateTimeResponse);
else if (multipleChoiceResponses)
return getMultipleChoiceValues(task, multipleChoiceResponses);
else if (drawGeometryResult?.geometry) {
// TODO(#1248): Test when implementing other plot annotations feature.
return toWkt(drawGeometryResult.geometry);
} else if (captureLocationResult) {
// TODO(#1916): Include altitude and accuracy in separate columns.
return toWkt(
new Pb.Geometry({
point: new Pb.Point({
coordinates: result.captureLocationResult.coordinates,
coordinates: captureLocationResult.coordinates,
}),
})
);
} else if (result.drawGeometryResult?.geometry) {
// TODO(#1248): Test when implementing other plot annotations feature.
return toWkt(result.drawGeometryResult.geometry);
} else if (result.takePhotoResult) {
return getPhotoUrlValue(result.takePhotoResult);
} else {
return null;
}
}

function getNumberValue(response: Pb.TaskData.INumberResponse): number | null {
return response.number ?? null;
} else if (takePhotoResult) return getPhotoUrlValue(takePhotoResult);
else return null;
}

function getDateTimeValue(
Expand All @@ -293,8 +290,15 @@ function getMultipleChoiceValues(
responses.selectedOptionIds?.map(
id => getMultipleChoiceLabel(task, id) || '#ERR'
) || [];
if (responses.otherText && responses.otherText.trim() !== '')
values.push(responses.otherText);
// Temporary workaround: Ensure at least one value is present: if no values are selected and 'otherText' is empty, add 'Other' as a fallback.
// https://github.com/google/ground-android/issues/2846
if (values.length === 0 && !responses.otherText) values.push('Other');
if (responses.otherText)
values.push(
responses.otherText.trim() !== ''
? `Other: ${responses.otherText}`
: 'Other'
);
return values.join(',');
}

Expand Down
3 changes: 3 additions & 0 deletions proto/src/ground/v1beta1/submission.proto
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ message TaskData {

// The text provided in the "Other (please specify)" field, if present.
string other_text = 2;

// Indicate that the response has Other option selected.
bool other_selected = 3;
}

message DrawGeometryResult {
Expand Down
24 changes: 13 additions & 11 deletions web/src/app/components/header/header.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,21 @@
</ng-container>
</ng-container>

<button mat-icon-button [matMenuTriggerFor]="infoMenu">
<mat-icon fontSet="material-symbols-outlined">info_outline_24px</mat-icon>
</button>
<ng-container *ngIf="authService.getUser$() | async as user">
<button mat-icon-button [matMenuTriggerFor]="infoMenu">
<mat-icon fontSet="material-symbols-outlined">info_outline_24px</mat-icon>
</button>

<mat-menu #infoMenu="matMenu">
<a (click)="onTermsOfServiceClick()">
<button mat-menu-item>Terms of service</button>
</a>
<mat-menu #infoMenu="matMenu">
<a *ngIf="user.isAuthenticated" (click)="onTermsOfServiceClick()">
<button mat-menu-item>Terms of Service</button>
</a>

<a (click)="onAboutClick()">
<button mat-menu-item>About</button>
</a>
</mat-menu>
<a (click)="onAboutClick()">
<button mat-menu-item>About</button>
</a>
</mat-menu>
</ng-container>

<ground-current-user-widget></ground-current-user-widget>
</div>
Expand Down
7 changes: 5 additions & 2 deletions web/src/app/components/header/header.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {ComponentFixture, TestBed} from '@angular/core/testing';
import {MatDialog} from '@angular/material/dialog';
import {MatMenuModule} from '@angular/material/menu';
import {Router} from '@angular/router';
import {of} from 'rxjs';

import {AuthService} from 'app/services/auth/auth.service';
import {DraftSurveyService} from 'app/services/draft-survey/draft-survey.service';
import {SurveyService} from 'app/services/survey/survey.service';

Expand All @@ -33,9 +35,10 @@ describe('HeaderComponent', () => {
imports: [MatMenuModule],
declarations: [HeaderComponent],
providers: [
{provide: Router, useValue: {}},
{provide: DraftSurveyService, useValue: {}},
{provide: MatDialog, useValue: {}},
{provide: AuthService, useValue: {getUser$: () => of()}},
{provide: DraftSurveyService, useValue: {}},
{provide: Router, useValue: {}},
{provide: SurveyService, useValue: {canManageSurvey: () => false}},
],
}).compileComponents();
Expand Down
8 changes: 4 additions & 4 deletions web/src/app/components/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

import {Component} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {Router} from '@angular/router';

import {
DialogData,
DialogType,
JobDialogComponent,
} from 'app/pages/edit-survey/job-dialog/job-dialog.component';
import {AuthService} from 'app/services/auth/auth.service';
import {DraftSurveyService} from 'app/services/draft-survey/draft-survey.service';
import {NavigationService} from 'app/services/navigation/navigation.service';
import {SurveyService} from 'app/services/survey/survey.service';
Expand All @@ -47,10 +47,10 @@ export class HeaderComponent {

constructor(
public dialog: MatDialog,
public authService: AuthService,
public draftSurveyService: DraftSurveyService,
public navigationService: NavigationService,
public surveyService: SurveyService,
private router: Router
public surveyService: SurveyService
) {}

async ngOnInit(): Promise<void> {
Expand All @@ -77,7 +77,7 @@ export class HeaderComponent {
}

onAboutClick() {
this.router.navigate([NavigationService.ABOUT]);
this.navigationService.navigateToAboutPage();
}

onTermsOfServiceClick() {
Expand Down
8 changes: 2 additions & 6 deletions web/src/app/converters/submission-data-converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,8 @@ function taskDataPbToModelValue(
else if (captureLocationResult)
return new Point(
coordinatesPbToModel(captureLocationResult.coordinates!),
captureLocationResult.accuracy === null
? undefined
: captureLocationResult.accuracy,
captureLocationResult.altitude === null
? undefined
: captureLocationResult.altitude
captureLocationResult.accuracy || undefined,
captureLocationResult.altitude || undefined
);
else if (takePhotoResult) return takePhotoResult.photoPath;
else return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
<mat-checkbox disabled="true" checked="true" *ngFor="let optionId of getTaskMultipleChoiceSelections(task).values">
{{getMultipleChoiceOption(task, optionId).label}}
</mat-checkbox>
<mat-checkbox disabled="true" checked="true" *ngIf="getTaskMultipleChoiceSelections(task).otherValue as otherValue">
Other: {{otherValue}}
<mat-checkbox disabled="true" checked="true" *ngIf="getTaskMultipleChoiceOtherValue(task) as otherValue">
{{otherValue}}
</mat-checkbox>
</div>
<!-- Photo task types -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,31 @@ export class SubmissionPanelComponent implements OnInit, OnDestroy {
return this.getTaskSubmissionResult(task)!.value as MultipleSelection;
}

getTaskMultipleChoiceOtherValue(task: Task): string | null {
const multipleSelection = this.getTaskSubmissionResult(task)!
.value as MultipleSelection;
// Temporary workaround: Ensure at least one value is present: if no values are selected and 'otherText' is empty, add 'Other' as a fallback.
// https://github.com/google/ground-android/issues/2846
if (multipleSelection.values.size === 0 && !multipleSelection.otherValue)
return 'Other';
if (multipleSelection.otherValue)
return multipleSelection.otherValue.trim() !== ''
? `Other: ${multipleSelection.otherValue}`
: 'Other';
return null;
}

getCaptureLocationCoord(task: Task): string {
// x represents longitude, y represents latitude
const {coord, accuracy, altitude} = this.getTaskSubmissionResult(task)!
.value as Point;
const {x, y} = coord;
const long = Math.abs(x).toString() + (x > 0 ? '° E' : '° W');
const lng = Math.abs(x).toString() + (x > 0 ? '° E' : '° W');
const lat = Math.abs(y).toString() + (y > 0 ? '° N' : '° S');

let result = lat + ', ' + long;
if (altitude) {
result += '\nAltitude: ' + altitude + 'm';
}
if (accuracy) {
result += '\nAccuracy: ' + accuracy + 'm';
}
return result;
const result = [`${lat}, ${lng}`];
if (altitude) result.push(`Altitude: ${altitude}m`);
if (accuracy) result.push(`Accuracy: ${accuracy}m`);
return result.join('\n');
}

getDate(task: Task): string {
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/pages/terms/terms.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<div class="page">
<ground-header></ground-header>
<div class="page-content">
<h1 class="page-title">Terms Of Service</h1>
<h1 class="page-title">Terms of Service</h1>
<div class="terms-text-container" [innerHTML]="termsOfServiceText"></div>
<div class="action-buttons">
@if(!hasAcceptedTos) {
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/pages/terms/terms.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class TermsComponent implements OnInit {
async ngOnInit() {
const text = await this.dataStore.getTermsOfService();

this.termsOfServiceText = await parse(text.replace(/#NEWLINE#/g, '\n'));
this.termsOfServiceText = await parse(text);
}

onContinueButtonClick() {
Expand Down
1 change: 0 additions & 1 deletion web/src/app/routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ const routes: Routes = [
{
path: NavigationService.ABOUT,
component: AboutComponent,
canActivate: [AuthGuard],
},
{
path: NavigationService.TERMS,
Expand Down
7 changes: 7 additions & 0 deletions web/src/app/services/navigation/navigation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,13 @@ export class NavigationService {
]);
}

/**
* Navigate to the about page
*/
navigateToAboutPage() {
this.router.navigate([NavigationService.ABOUT]);
}

/**
* Navigate to the terms of service page
*/
Expand Down

0 comments on commit c026666

Please sign in to comment.