Skip to content

Commit

Permalink
Merge branch 'feature/questionnaire' into task/WG-171-fix-location-qu…
Browse files Browse the repository at this point in the history
…estion-map
  • Loading branch information
nathanfranklin authored Dec 18, 2023
2 parents 12b6899 + 1cc7be6 commit ca3e05a
Show file tree
Hide file tree
Showing 30 changed files with 205 additions and 95 deletions.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Related Jira tickets: ##

* [DES-9999](https://jira.tacc.utexas.edu/browse/DES-9999)
* [WG-XYZ](https://tacc-main.atlassian.net/browse/WG-XYZ)

## Summary of Changes: ##

Expand Down
60 changes: 37 additions & 23 deletions angular/src/app/app.interceptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,35 @@ export class JwtInterceptor implements HttpInterceptor {
});
}

/* Disabling custom headers due to https://jira.tacc.utexas.edu/browse/WG-189
// for guest users, add a custom header with a unique id
if (!this.authSvc.isLoggedIn()) {
// Get (or create of needed) the guestUserID in local storage
let guestUuid = localStorage.getItem('guestUuid');
if (!guestUuid) {
guestUuid = uuidv4();
localStorage.setItem('guestUuid', guestUuid);
}
request = request.clone({
setHeaders: {
'X-Guest-UUID': guestUuid,
},
});
}
if (request.url.indexOf(this.envService.apiUrl) > -1) {
// Add information about what app is making the request
request = request.clone({
setHeaders: {
'X-Geoapi-Application': 'hazmapper',
},
});

// Using query params instead of custom headers due to https://tacc-main.atlassian.net/browse/WG-191
let analytics_params = {};

analytics_params = { ...analytics_params, application: 'hazmapper' };

// for guest users, add a unique id
if (!this.authSvc.isLoggedIn()) {
// Get (or create if needed) the guestUserID in local storage
let guestUuid = localStorage.getItem('guestUuid');

if (!guestUuid) {
guestUuid = uuidv4();
localStorage.setItem('guestUuid', guestUuid);
}

analytics_params = { ...analytics_params, guest_uuid: guestUuid };
}
/* Send analytics-related params to projects endpoint only (until we use headers
again in https://tacc-main.atlassian.net/browse/WG-192) */
if (this.isProjectFeaturesRequest(request)) {
// Clone the request and add query parameters
request = request.clone({
setParams: { ...request.params, ...analytics_params },
});
}
}
*/

if (
request.url.indexOf(this.envService.streetviewEnv.mapillary.apiUrl) > -1 &&
Expand Down Expand Up @@ -91,6 +94,17 @@ export class JwtInterceptor implements HttpInterceptor {

return next.handle(request);
}

/**
* Determines whether a given HTTP request targets the features endpoint of a project or public project.
*
* This endpoint is being logged with extra information for analytics purposes.
*/
private isProjectFeaturesRequest(request: HttpRequest<any>): boolean {
// Regular expression to match /projects/{projectId}/features or /public-projects/{projectId}/features
const urlPattern = /\/(projects|public-projects)\/\d+\/features\/?(?:\?.*)?/;
return request.method === 'GET' && urlPattern.test(request.url);
}
}

@Injectable()
Expand Down
4 changes: 2 additions & 2 deletions angular/src/app/components/dock/dock.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</div>
</button>
</div>
<div class="dock-button" [ngClass]="{ active: panelsDisplay.layers }" *ngIf="!isPublicView">
<div class="dock-button" [ngClass]="{ active: panelsDisplay.layers }">
<button (click)="showPanel('layers')" [disabled]="!activeProject">
<div>
<img class="dock-button-icon" src="assets/layers.png" width="32px" />
Expand Down Expand Up @@ -68,7 +68,7 @@
</div>
<div class="cell auto dock-panel">
<app-assets-panel *ngIf="panelsDisplay.assets" [isPublicView]="isPublicView"></app-assets-panel>
<app-layers-panel *ngIf="panelsDisplay.layers"></app-layers-panel>
<app-layers-panel *ngIf="panelsDisplay.layers" [isPublicView]="isPublicView"></app-layers-panel>
<app-filters-panel *ngIf="panelsDisplay.filters"></app-filters-panel>
<app-measure-panel *ngIf="panelsDisplay.measure"></app-measure-panel>
<app-settings-panel *ngIf="panelsDisplay.settings"></app-settings-panel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="dock-panel-content">
<p class="dock-panel-title">Layers</p>
<h6>Tile Layers</h6>
<button class="button expanded hollow tiny success" (click)="openCreateTileServerModal()">
<button class="button expanded hollow tiny success" (click)="openCreateTileServerModal()" *ngIf="!isPublicView">
<i class="fa fa-plus"></i>
</button>
<div #cdkList cdkDropList class="tile-servers-list" (cdkDropListDropped)="drop($event)">
Expand Down Expand Up @@ -35,6 +35,7 @@ <h6>Tile Layers</h6>
(blur)="updateName(activeText.value, ts)"
(keyup.enter)="updateName(activeText.value, ts)"
[value]="ts.name"
[readOnly]="isPublicView"
/>
<div
id="tile-server-name"
Expand All @@ -53,7 +54,7 @@ <h6>Tile Layers</h6>
</div>

<div class="cell small-4 grid-x tile-server-right">
<button class="button secondary clear edit-buttons">
<button class="button secondary clear edit-buttons" *ngIf="!isPublicView">
<i class="fas fa-edit edit-button" (click)="showInput(ts, true)" *ngIf="!ts.uiOptions.showInput"></i>
<i class="fas fa-check edit-button" (click)="showInput(ts, false)" *ngIf="ts.uiOptions.showInput"></i>
</button>
Expand All @@ -63,6 +64,7 @@ <h6>Tile Layers</h6>
<button
class="button secondary clear button-no-margin delete-button"
(click)="openDeleteTileServerModal(deleteTiles)"
*ngIf="!isPublicView"
>
<i class="fa fa-trash"></i>
</button>
Expand Down Expand Up @@ -95,21 +97,21 @@ <h6>Tile Layers</h6>
</div>
</div>

<div *ngIf="dirtyOptions" class="tile-server-dirty-options">
<div *ngIf="dirtyOptions && !isPublicView" class="tile-server-dirty-options">
<i class="tile-server-dirty-options-warning">
Layer options have been changed!
<br />
Save to persist changes.
</i>
</div>

<div class="tile-server-save-button">
<div *ngIf="dirtyOptions && !isPublicView" class="tile-server-save-button">
<button class="button small success" [disabled]="!dirtyOptions" (click)="saveTileOptions()">Save Layer Options</button>
</div>
<hr />

<h6>Overlays</h6>
<button class="button expanded hollow tiny success" (click)="openCreateOverlayModal()">
<button class="button expanded hollow tiny success" (click)="openCreateOverlayModal()" *ngIf="!isPublicView">
<i class="fa fa-plus"></i>
</button>
<div *ngFor="let ov of overlays" class="overlay">
Expand All @@ -121,7 +123,7 @@ <h6>Overlays</h6>
<span class="overlay-label"> {{ ov.label }} </span>
</div>
<div class="cell grid-x auto align-right">
<button class="button hollow tiny alert button-no-margin" (click)="deleteOverlay(ov)">
<button class="button hollow tiny alert button-no-margin" (click)="deleteOverlay(ov)" [disabled]="isPublicView">
<i class="fa fa-trash"></i>
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, ElementRef, ViewChildren, QueryList, TemplateRef, OnDestroy } from '@angular/core';
import { Component, OnInit, ElementRef, ViewChildren, QueryList, TemplateRef, OnDestroy, Input } from '@angular/core';
import { GeoDataService } from '../../services/geo-data.service';
import { Overlay, Project, TileServer } from '../../models/models';
import { BsModalRef, BsModalService } from 'ngx-foundation';
Expand All @@ -17,6 +17,7 @@ import { Subscription } from 'rxjs';
})
export class LayersPanelComponent implements OnInit, OnDestroy {
@ViewChildren('activeText') activeInputs: QueryList<ElementRef>;
@Input() isPublicView = false;

dragHeight: number;
releaseHeight: number;
Expand Down
4 changes: 3 additions & 1 deletion react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"test": "jest",
"lint": "npm run lint:js",
"lint:js": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"prettier:check": "prettier --single-quote --check src",
"prettier:fix": "prettier --single-quote --write src"
},
"eslintConfig": {
"extends": "react-app"
Expand Down
20 changes: 10 additions & 10 deletions react/src/components/AppRouter.tsx → react/src/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {
Navigate,
useLocation,
} from 'react-router-dom';
import * as ROUTES from '../constants/routes';
import MapProject from './MapProject';
import MainMenu from './MainMenu';
import Logout from './Authentication/Logout/Logout';
import Login from './Authentication/Login/Login';
import Callback from './Authentication/Callback/Callback';
import StreetviewCallback from './Authentication/StreetviewCallback/StreetviewCallback';
import { RootState } from '../redux/store';
import { isTokenValid } from '../utils/authUtils';
import * as ROUTES from './constants/routes';
import MapProject from './pages/MapProject';
import MainMenu from './pages/MainMenu';
import Logout from './pages/Logout/Logout';
import Login from './pages/Login/Login';
import Callback from './pages/Callback/Callback';
import StreetviewCallback from './pages/StreetviewCallback/StreetviewCallback';
import { RootState } from './redux/store';
import { isTokenValid } from './utils/authUtils';

interface ProtectedRouteProps {
isAuthenticated: boolean;
Expand All @@ -38,7 +38,7 @@ const ProtectedRoute: React.FC<ProtectedRouteProps> = ({

function AppRouter() {
const isAuthenticated = useSelector((state: RootState) =>
isTokenValid(state.auth)
isTokenValid(state.auth.token)
);

return (
Expand Down
7 changes: 0 additions & 7 deletions react/src/components/MainMenu/MainMenu.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/AppRouter';
import App from './AppRouter';
import './index.css';
import store from './redux/store';
import { Provider } from 'react-redux';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { render } from '@testing-library/react';
import store from '../../../redux/store';
import store from '../../redux/store';
import Callback from './Callback';

test('renders callback', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { loginSuccess, logout } from '../../../redux/authSlice';
import { loginSuccess, logout } from '../../redux/authSlice';

export default function CallbackPage() {
const dispatch = useDispatch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { render, waitFor } from '@testing-library/react';
import Login from './Login';
import { Provider } from 'react-redux';
import store from '../../../redux/store';
import store from '../../redux/store';
import { MemoryRouter } from 'react-router';

test('renders login', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { RootState } from '../../../redux/store';
import { isTokenValid } from '../../../utils/authUtils';
import { RootState } from '../../redux/store';
import { isTokenValid } from '../../utils/authUtils';

function Login() {
const location = useLocation();
const navigate = useNavigate();
const isAuthenticated = useSelector((state: RootState) =>
isTokenValid(state.auth)
isTokenValid(state.auth.token)
);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { render } from '@testing-library/react';
import Logout from './Logout';
import { Provider } from 'react-redux';
import store from '../../../redux/store';
import store from '../../redux/store';
import { BrowserRouter } from 'react-router-dom';

test('renders logout', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { logout } from '../../../redux/authSlice';
import { logout } from '../../redux/authSlice';

function Logout() {
const dispatch = useDispatch();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import React from 'react';
import { render } from '@testing-library/react';
import MainMenu from './MainMenu';
import { Provider } from 'react-redux';
import store from '../../redux/store';

test('renders menu', () => {
const { getByText } = render(<MainMenu />);
const { getByText } = render(
<Provider store={store}>
<MainMenu />
</Provider>
);
expect(getByText(/Main Menu/)).toBeDefined();
});
13 changes: 13 additions & 0 deletions react/src/pages/MainMenu/MainMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import {
useGetGeoapiProjectsQuery,
useGetGeoapiUserInfoQuery,
} from '../../redux/api/geoapi';

function MainMenu() {
useGetGeoapiProjectsQuery();
useGetGeoapiUserInfoQuery();
return <h2>Main Menu</h2>;
}

export default MainMenu;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import Map from '../Map';
import Map from '../../components/Map';
import { tileServerLayers } from '../../__fixtures__/tileServerLayerFixture';
import { featureCollection } from '../../__fixtures__/featuresFixture';
import { useParams } from 'react-router-dom';
Expand Down
File renamed without changes.
29 changes: 22 additions & 7 deletions react/src/redux/api/geoapi.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/dist/query/react';
import store from '../store';
import type { RootState } from '../store';

// TODO: make configurable so can be https://agave.designsafe-ci.org/geo-staging/v2 or https://agave.designsafe-ci.org/geo/v2
const BASE_URL = 'https:localhost:8888';
// See https://tacc-main.atlassian.net/browse/WG-196
const BASE_URL = 'https://agave.designsafe-ci.org/geo/v2';

export const geoapi = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({
baseUrl: BASE_URL,
prepareHeaders: (headers) => {
prepareHeaders: (headers, api) => {
// TODO check if logged in as we don't want to add if public
const token = store.getState().auth.token;
const token = (api.getState() as RootState).auth.token;

if (token) {
headers.set('Authorization', `Bearer ${token}`);
headers.set('Authorization', `Bearer ${token.token}`);
}

headers.set('Content-Type', 'application/json;charset=UTF-8');
headers.set('Authorization', 'anonymous');

// TODO below adding of JWT if localhost and then add JWT
// we put the JWT on the request to our geoapi API because it is not behind ws02 if in local dev
Expand All @@ -25,5 +27,18 @@ export const geoapi = createApi({
},
}),
tagTypes: ['Test'],
endpoints: () => ({}),
endpoints: (builder) => ({
getGeoapiProjects: builder.query<any, void>({

Check warning on line 31 in react/src/redux/api/geoapi.ts

View workflow job for this annotation

GitHub Actions / React-Linting

Unexpected any. Specify a different type
query: () => '/projects/',
}),
// NOTE: Currently fails due to cors on localhost (chrome) works when requesting production backend
getGeoapiUserInfo: builder.query<any, void>({

Check warning on line 35 in react/src/redux/api/geoapi.ts

View workflow job for this annotation

GitHub Actions / React-Linting

Unexpected any. Specify a different type
query: () => ({
url: 'https://agave.designsafe-ci.org/oauth2/userinfo?schema=openid',
method: 'GET',
}),
}),
}),
});

export const { useGetGeoapiProjectsQuery, useGetGeoapiUserInfoQuery } = geoapi;
Loading

0 comments on commit ca3e05a

Please sign in to comment.