Skip to content

Commit 8571eca

Browse files
committed
2024-11-12 - routes
1 parent b9767f8 commit 8571eca

7 files changed

+234
-155
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { UPDATE_TOAST } from '../context/actionsFeedbackExternalRecipient.js';
2+
import qs from 'qs';
3+
4+
export const BASE_API_URL = import.meta.env.VITE_APP_API_URL
5+
? import.meta.env.VITE_APP_API_URL
6+
: 'http://localhost:8080';
7+
8+
export const getAvatarURL = email =>
9+
BASE_API_URL +
10+
'/services/member-profiles/member-photos/' +
11+
encodeURIComponent(email);
12+
13+
function fetchAbsolute(fetch) {
14+
return baseUrl => (url, otherParams) =>
15+
url.startsWith('/')
16+
? fetch(baseUrl + url, { credentials: 'include', ...otherParams })
17+
: fetch(url, { credentials: 'include', ...otherParams });
18+
}
19+
20+
let myFetch = null;
21+
22+
export const getMyFetch = async () => {
23+
if (!myFetch) {
24+
myFetch = fetchAbsolute(fetch)(BASE_API_URL);
25+
26+
/*
27+
I'm not sure this was working before, but we need to figure out an approach for fetch. I will
28+
open an issue for this.
29+
30+
myAxios.interceptors.response.use(
31+
// Any status code that lie within the range of 2xx cause this function to trigger
32+
(res) => {
33+
return res;
34+
},
35+
// Any status codes that falls outside the range of 2xx cause this function to trigger
36+
(err) => {
37+
if (err.response.status !== 401) {
38+
return Promise.reject(err);
39+
}
40+
41+
// trade in refresh token for access token
42+
return axios.get('/oauth/access_token', {
43+
baseURL: BASE_API_URL,
44+
withCredentials: true,
45+
timeout: 30000
46+
})
47+
.then(() => {
48+
// retry original request
49+
return myAxios(err.config);
50+
})
51+
.catch(() => {
52+
return Promise.reject(err);
53+
})
54+
}
55+
);
56+
*/
57+
}
58+
return myFetch;
59+
};
60+
61+
export const resolve = async payload => {
62+
let { url } = payload;
63+
const { params = null, data = null, ...rest } = payload;
64+
const myFetch = await getMyFetch();
65+
66+
// Convert params to fetch style...
67+
params && (url = `${url}?` + qs.stringify(params, { arrayFormat: 'repeat' }));
68+
69+
// Convert data to body...
70+
data && (rest.body = JSON.stringify(data));
71+
72+
const promise = myFetch(url, rest);
73+
const resolved = {
74+
payload: null,
75+
error: null
76+
};
77+
78+
resolved.payload = await promise;
79+
80+
if (!resolved.payload.ok) {
81+
try {
82+
resolved.error = await resolved.payload.json();
83+
} catch (error) {
84+
resolved.error = resolved.payload.statusText;
85+
console.error(error);
86+
}
87+
88+
if (window.snackDispatch) {
89+
window.snackDispatch({
90+
type: UPDATE_TOAST,
91+
payload: {
92+
severity: 'error',
93+
toast: resolved?.error
94+
}
95+
});
96+
}
97+
} else {
98+
const contentType = resolved.payload.headers.get('Content-Type');
99+
const contentLength = resolved.payload.headers.get('Content-Length');
100+
if (contentType && contentType.indexOf('text/csv') !== -1) {
101+
resolved.payload.data = await resolved.payload.blob();
102+
} else if (contentLength && contentLength > 0) {
103+
if (contentType && contentType.indexOf('application/json') !== -1) {
104+
resolved.payload.data = await resolved.payload.json();
105+
} else {
106+
resolved.payload.data = await resolved.payload.text();
107+
}
108+
} else {
109+
resolved.payload.data = null;
110+
}
111+
}
112+
return resolved;
113+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { resolve } from './apiFeedbackExternalRecipient.js';
2+
3+
const feedbackExternalRecipientsURL = '/services/feedback/requests/external/recipients';
4+
5+
export const getFeedbackRequest = async (cookie, id) => {
6+
return resolve({
7+
url: `${feedbackExternalRecipientsURL}/${id}`,
8+
headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' }
9+
});
10+
};
11+
12+
export const getFeedbackRequestNoCookie = async (id) => {
13+
return resolve({
14+
url: `${feedbackExternalRecipientsURL}/${id}`,
15+
headers: { Accept: 'application/json' }
16+
});
17+
};

web-ui/src/context/AppFeedbackExternalRecipientContext.jsx

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,62 @@
11
import React, { useEffect, useReducer, useMemo } from 'react';
2-
import { reducer, initialState } from './reducer';
2+
import {reducerFeedbackExternalRecipient, initialState} from "./reducerFeedbackExternalRecilpients.js";
3+
import {BASE_API_URL} from "../api/apiFeedbackExternalRecipient.js";
4+
import {SET_CSRF} from "./actionsFeedbackExternalRecipient.js";
35

46
const AppFeedbackExternalRecipientContext = React.createContext();
57

8+
function getSessionCookieValue(name) {
9+
const cookies = document?.cookie?.split(';');
10+
for (let i = 0; i < cookies.length; i++) {
11+
const cookie = cookies[i].trim();
12+
if (cookie.startsWith(name + '=')) {
13+
return decodeURIComponent(cookie.substring(name.length + 1));
14+
}
15+
}
16+
return null;
17+
}
18+
619
const AppFeedbackExternalRecipientContextProvider = props => {
20+
console.log("AppFeedbackExternalRecipientContextProvider props: ", props);
721
const [state, dispatch] = useReducer(
8-
reducer,
22+
reducerFeedbackExternalRecipient,
923
props?.value?.state || initialState
1024
);
1125

26+
const {
27+
csrf,
28+
} = state;
29+
const url = `${BASE_API_URL}/csrf/cookie`;
30+
31+
useEffect(() => {
32+
33+
console.log("AppFeedbackExternalRecipientContextProvider useEffect, csrf");
34+
35+
const getCsrf = async () => {
36+
if (!csrf) {
37+
const payload = getSessionCookieValue('_csrf');
38+
if (payload) {
39+
dispatch({ type: SET_CSRF, payload });
40+
} else {
41+
const res = await fetch(url, {
42+
responseType: 'text',
43+
credentials: 'include'
44+
});
45+
if (res && res.ok) {
46+
dispatch({ type: SET_CSRF, payload: await res.text() });
47+
}
48+
}
49+
}
50+
};
51+
getCsrf();
52+
}, [csrf]);
53+
54+
const value = useMemo(() => {
55+
console.log("AppFeedbackExternalRecipientContextProvider useMemo, state: ", state);
56+
console.log("AppFeedbackExternalRecipientContextProvider useMemo, dispatch: ", dispatch);
57+
return { state, dispatch };
58+
}, [state]);
59+
1260
return (
1361
<AppFeedbackExternalRecipientContext.Provider value={props.value || value}>
1462
{props.children}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const SET_CSRF = '@@check-ins/update_csrf';
2+
export const UPDATE_TOAST = '@@check-ins/update_toast';
3+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {
2+
SET_CSRF,
3+
UPDATE_TOAST,
4+
5+
} from './actionsFeedbackExternalRecipient.js';
6+
7+
export const initialState = {
8+
csrf: undefined,
9+
index: 0,
10+
toast: {
11+
severity: '',
12+
toast: ''
13+
},
14+
};
15+
16+
export const reducerFeedbackExternalRecipient = (state, action) => {
17+
switch (action.type) {
18+
case SET_CSRF:
19+
state.csrf = action.payload;
20+
break;
21+
case UPDATE_TOAST:
22+
state.toast = action.payload;
23+
break;
24+
default:
25+
}
26+
return { ...state };
27+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createSelector } from 'reselect';
2+
3+
export const selectCsrfToken = state => state.csrf;
4+
export const noPermission = 'You do not have permission to view this page.';

0 commit comments

Comments
 (0)