Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Map view starting point and position #369

Merged
merged 9 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
-p AWS_ACCESS_KEY_SECRET='${{ secrets.AWS_ACCESS_KEY_SECRET }}'
-p ORACLE_DB_USER=${{ secrets.DB_USER }}
-p ORACLE_DB_PASSWORD='${{ secrets.DB_PASSWORD }}'
-p FORESTCLIENTAPI_KEY='${{ secrets.FORESTCLIENTAPI_KEY }}'
-p ZONE=test

deploys-test:
Expand Down Expand Up @@ -99,6 +100,7 @@ jobs:
-p AWS_ACCESS_KEY_SECRET='${{ secrets.AWS_ACCESS_KEY_SECRET }}'
-p ORACLE_DB_USER=${{ secrets.DB_USER }}
-p ORACLE_DB_PASSWORD='${{ secrets.DB_PASSWORD }}'
-p FORESTCLIENTAPI_KEY='${{ secrets.FORESTCLIENTAPI_KEY }}'
-p ZONE=prod

image-promotions:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pr-open.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
-p AWS_ACCESS_KEY_SECRET='${{ secrets.AWS_ACCESS_KEY_SECRET }}'
-p ORACLE_DB_USER=${{ secrets.DB_USER }}
-p ORACLE_DB_PASSWORD='${{ secrets.DB_PASSWORD }}'
-p FORESTCLIENTAPI_KEY='${{ secrets.FORESTCLIENTAPI_KEY }}'
triggers: ('common/' 'backend/' 'frontend/')

builds:
Expand Down
5 changes: 5 additions & 0 deletions backend/openshift.deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ objects:
value: ${ALLOWED_ORIGINS}
- name: WMS_LAYERS_WHITELIST_USERS
value: ${WMS_LAYERS_WHITELIST_USERS}
- name: FORESTCLIENTAPI_KEY
valueFrom:
secretKeyRef:
name: ${NAME}-${ZONE}-${COMPONENT}
key: forest-client-api-key
- name: DATABASE_USER
valueFrom:
secretKeyRef:
Expand Down
4 changes: 4 additions & 0 deletions common/openshift.init.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ parameters:
description: Password for the PostgreSQL connection user.
from: "[a-zA-Z0-9]{16}"
generate: expression
- name: FORESTCLIENTAPI_KEY
description:
required: true
objects:
- apiVersion: v1
kind: Secret
Expand All @@ -53,6 +56,7 @@ objects:
stringData:
oracle-user: ${ORACLE_DB_USER}
oracle-password: ${ORACLE_DB_PASSWORD}
forest-client-api-key: ${FORESTCLIENTAPI_KEY}
- apiVersion: v1
kind: Secret
metadata:
Expand Down
7 changes: 0 additions & 7 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"vite": "^5.0.0",
"vite-plugin-svgr": "^4.0.0",
"vite-tsconfig-paths": "^5.0.0",
"web-vitals": "^4.0.0",
"yaml": "^2.3.2"
},
"scripts": {
Expand Down
59 changes: 56 additions & 3 deletions frontend/src/components/OpeningsMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ import axios from 'axios';
import { getAuthIdToken } from '../../services/AuthService';
import { env } from '../../env';
import { shiftBcGwLngLat2LatLng } from '../../map-services/BcGwLatLongUtils';
import { LayersControl, MapContainer, Polygon, Popup, TileLayer, useMap, WMSTileLayer } from 'react-leaflet';
import {
LayersControl,
MapContainer,
Polygon,
Popup,
TileLayer,
useMap,
useMapEvents,
WMSTileLayer
} from 'react-leaflet';
import { LatLngExpression } from 'leaflet';

const backendUrl = env.VITE_BACKEND_URL;
Expand All @@ -28,6 +37,7 @@ const OpeningsMap: React.FC<MapProps> = ({
const [layers, setLayers] = useState<MapLayer[]>([]);
const [baseMaps, setBaseMaps] = useState<BaseMapLayer[]>([]);
const authToken = getAuthIdToken();
const [zoomLevel, setZoomLevel] = useState<number>(13);

const resultsStyle = {
color: 'black'
Expand Down Expand Up @@ -99,24 +109,67 @@ const OpeningsMap: React.FC<MapProps> = ({
setLayers(filtered);
}

const getUserLocation = () => {
if (navigator.geolocation) {
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};

navigator.geolocation.getCurrentPosition((position: GeolocationPosition) => {
setPosition({
lat: position.coords.latitude,
lng: position.coords.longitude,
});
setZoomLevel(8);
}, (error: GeolocationPositionError) => {
console.error(`${error.code}: ${error.message}`);
// Set the province location, if user denied
// north east - lat = 54.76267040025495, lng = -103.46923828125
// south east - lat = 47.91634204016118, lng = -139.35058593750003
setPosition({
lat: 51.339506220208065,
lng: -121.40991210937501
});
setZoomLevel(6);
}, options);
}
}

setBaseMaps(allBaseMaps);
getUserLocation();
}, [openingId]);

useEffect(() => {}, [openings, reloadMap]);

const RecenterAutomatically = ({latLong}: {latLong: LatLngExpression}) => {
const map = useMap();
const zoom = 13;
const zoom = zoomLevel;
useEffect(() => {
map.setView(latLong, zoom);
}, [latLong]);
return null;
};

// Use this function to investigate/play with map click
// Just add <LocationMarker /> inside <MapContainer /> below
/*
function LocationMarker() {
const map = useMapEvents({
click() {
console.log('click, bounds:', map.getBounds());
console.log('click, zoom:', map.getZoom());
}
});
return null;
}
*/

return (
<MapContainer
center={position}
zoom={13}
zoom={zoomLevel}
style={{ height: "400px", width: "100%" }}
>
<TileLayer
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/contexts/PaginationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface PaginationContextData {
handlePageChange(page: number): void;
handleItemsPerPageChange(page: number, pageSize: number): void;
itemsPerPage: number;
setPageData(data: any[]): void;
setPageData(data: object[]): void;
setInitialItemsPerPage(items: number): void;
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/env.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
declare global {
// eslint-disable-next-line no-unused-vars
interface Window {
config: any
config: object
}
}

// eslint-disable-next-line import/prefer-default-export
export const env: Record<string, any> = { ...import.meta.env, ...window.config }
export const env: Record<string, string> = { ...import.meta.env, ...window.config }
16 changes: 0 additions & 16 deletions frontend/src/reportWebVitals.ts

This file was deleted.

17 changes: 6 additions & 11 deletions frontend/src/services/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { env } from '../env';
import { CognitoUserSession } from 'amazon-cognito-identity-js';
import { formatRolesArray } from '../utils/famUtils';
import { UserClientRolesType } from '../types/UserRoleType';

// Define a global variable to store the ID token
let authIdToken: string | null = null;
Expand Down Expand Up @@ -91,7 +92,7 @@ async function refreshToken (): Promise<FamLoginUser | undefined> {
// Set the authIdToken variable
setAuthIdToken(tokens?.idToken?.toString() || null);

const famLoginUser = parseToken(tokens?.idToken, tokens?.accessToken);
const famLoginUser = parseToken(tokens?.idToken);
await storeFamUser(famLoginUser);
return famLoginUser;

Expand All @@ -115,9 +116,9 @@ async function refreshToken (): Promise<FamLoginUser | undefined> {
/**
* Function to parse roles and extract client IDs
*/
function parseToken(idToken: JWT | undefined, accessToken: JWT | undefined): FamLoginUser {
function parseToken(idToken: JWT | undefined): FamLoginUser {
const decodedIdToken = idToken?.payload;
const decodedAccessToken = accessToken?.payload;

// Extract the first name and last name from the displayName and remove unwanted part
let displayName: string = '';
if (decodedIdToken && 'custom:idp_display_name' in decodedIdToken) {
Expand Down Expand Up @@ -154,14 +155,8 @@ function parseToken(idToken: JWT | undefined, accessToken: JWT | undefined): Fam
}
}

let roles: string[] = [];
if (decodedAccessToken && 'cognito:groups' in decodedAccessToken) {
roles = decodedAccessToken['cognito:groups'] as Array<string>;
}


//get the user roles from the FAM token
const rolesArray = formatRolesArray(decodedIdToken);
// Get user roles from FAM token
const rolesArray: UserClientRolesType[] = formatRolesArray(decodedIdToken);

const famLoginUser = {
userName,
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/store.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createStore, combineReducers, applyMiddleware } from 'redux'
import { thunk } from 'redux-thunk'
import { composeWithDevTools } from '@redux-devtools/extension'
import type { CognitoUserSession } from 'amazon-cognito-identity-js'
import { userDetailsReducer } from './reducers/userReducer'
import { UserClientRolesType } from './types/UserRoleType'
import { selectedClientRolesReducer } from './reducers/selectedClientRolesReducer'
Expand All @@ -25,7 +24,7 @@ const selectedClientRolesFromStorage = JSON.parse(localStorage.getItem('selected
| null;

// set the initial state
const initialState: any = {
const initialState: object = {
userDetails: {
user: {
...userInfoFromStorage,
Expand Down
57 changes: 33 additions & 24 deletions frontend/src/utils/famUtils.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import { UserClientRolesType } from "../types/UserRoleType";
import { UserClientRolesType } from '../types/UserRoleType';

export function formatRolesArray(decodedIdToken: any): UserClientRolesType[] {
if (!decodedIdToken || !decodedIdToken['cognito:groups']) {
/**
* Decode user roles from token and format for the UserClientRolesType type.
*
* @param {object | undefined} decodedIdToken Decoded token with payload.
* @returns {UserClientRolesType} Array of UserClientRolesType containing user roles.
*/
export function formatRolesArray(decodedIdToken: object | undefined): UserClientRolesType[] {
if (!decodedIdToken) {
return [];
}

const cognitoGroups: string[] = decodedIdToken['cognito:groups'];
const rolesMap: { [key: string]: string[] } = {};

cognitoGroups.forEach((group: string) => {
if (group.indexOf('_') > 0) {
const [role, clientId] = group.split('_');
if (!rolesMap[clientId]) {
rolesMap[clientId] = [];

if ('cognito:groups' in decodedIdToken) {
const cognitoGroups: string[] = decodedIdToken['cognito:groups'] as string[];
const rolesMap: { [key: string]: string[] } = {};

cognitoGroups.forEach((group: string) => {
if (group.indexOf('_') > 0) {
const [role, clientId] = group.split('_');
if (!rolesMap[clientId]) {
rolesMap[clientId] = [];
}
rolesMap[clientId].push(role);
}
rolesMap[clientId].push(role);
}
});

const rolesArray: UserClientRolesType[] = Object.keys(rolesMap).map(clientId => ({
clientId,
roles: rolesMap[clientId],
clientName: `Client Number ${clientId}` // Placeholder for client name, modify as needed
}));
console.log(rolesArray)
return rolesArray;
});

const rolesArray: UserClientRolesType[] = Object.keys(rolesMap).map(clientId => ({
clientId,
roles: rolesMap[clientId],
clientName: `Client Number ${clientId}` // Placeholder for client name, modify as needed
}));

return rolesArray;
}

return [];
}

Loading