Feature/33 api fails when no pilots or logbook entries (#35)
* api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * api no longer fails when no pilots or logbook entries * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * Refactoring * refactoring * refactoring * refactoring * refactoring * adding test environment * adding test environment
This commit was merged in pull request #35.
This commit is contained in:
@@ -1,26 +1,23 @@
|
||||
{
|
||||
"name": "@noahspan/flying-client",
|
||||
"name": "app",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.19",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"serve": "serve -s dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/msal-browser": "^3.17.0",
|
||||
"@azure/msal-react": "^2.0.19",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@azure/msal-browser": "^4.0.1",
|
||||
"@azure/msal-react": "^3.0.1",
|
||||
"@noahspan/noahspan-components": "^0.8.9",
|
||||
"axios": "^1.7.2",
|
||||
"framer-motion": "^11.1.7",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"dotenv": "^16.4.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"react-router-dom": "^6.23.0"
|
||||
},
|
||||
@@ -29,13 +26,13 @@
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
@@ -7,8 +7,14 @@ import { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { useHttpClient } from './hooks/httpClient/UseHttpClient';
|
||||
import { useFeatureFlag } from './hooks/featureFlag/UseFeatureFlag';
|
||||
import SiteNav from './components/siteNav/SiteNav';
|
||||
import { IPublicClientApplication } from '@azure/msal-browser';
|
||||
import { MsalProvider } from '@azure/msal-react';
|
||||
|
||||
const App: React.FC<unknown> = () => {
|
||||
interface AppProps {
|
||||
pca: IPublicClientApplication
|
||||
}
|
||||
|
||||
const App: React.FC<AppProps> = ({ pca }: AppProps) => {
|
||||
const httpClient: AxiosInstance = useHttpClient();
|
||||
const appContext = useAppContext();
|
||||
|
||||
@@ -36,7 +42,7 @@ const App: React.FC<unknown> = () => {
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<MsalProvider instance={pca}>
|
||||
<SiteNav />
|
||||
<Routes>
|
||||
{/* {useFeatureFlag('flying-pilots')?.enabled && ( */}
|
||||
@@ -44,8 +50,8 @@ const App: React.FC<unknown> = () => {
|
||||
{/* )} */}
|
||||
<Route path="/" element={<Logbook />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</MsalProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
70
app/src/auth/msalConfig.ts
Normal file
70
app/src/auth/msalConfig.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
|
||||
import { LogLevel } from '@azure/msal-browser';
|
||||
|
||||
/**
|
||||
* Configuration object to be passed to MSAL instance on creation.
|
||||
* For a full list of MSAL.js configuration parameters, visit:
|
||||
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md
|
||||
*/
|
||||
|
||||
export const msalConfig = {
|
||||
auth: {
|
||||
clientId: import.meta.env.VITE_CLIENT_ID, // This is the ONLY mandatory field that you need to supply.
|
||||
authority: `https://login.microsoftonline.com/${import.meta.env.VITE_TENANT_ID}`, // Replace the placeholder with your tenant subdomain
|
||||
redirectUri: import.meta.env.VITE_REDIRECT_URL, // Points to window.location.origin. You must register this URI on Microsoft Entra admin center/App Registration.
|
||||
postLogoutRedirectUri: '/', // Indicates the page to navigate after logout.
|
||||
navigateToLoginRequestUrl: false, // If "true", will navigate back to the original request location before processing the auth code response.
|
||||
},
|
||||
cache: {
|
||||
cacheLocation: 'sessionStorage', // Configures cache location. "sessionStorage" is more secure, but "localStorage" gives you SSO between tabs.
|
||||
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
|
||||
},
|
||||
system: {
|
||||
loggerOptions: {
|
||||
loggerCallback: (level: any, message: any, containsPii: any) => {
|
||||
if (containsPii) {
|
||||
return;
|
||||
}
|
||||
switch (level) {
|
||||
case LogLevel.Error:
|
||||
console.error(message);
|
||||
return;
|
||||
case LogLevel.Info:
|
||||
console.info(message);
|
||||
return;
|
||||
case LogLevel.Verbose:
|
||||
console.debug(message);
|
||||
return;
|
||||
case LogLevel.Warning:
|
||||
console.warn(message);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Scopes you add here will be prompted for user consent during sign-in.
|
||||
* By default, MSAL.js will add OIDC scopes (openid, profile, email) to any login request.
|
||||
* For more information about OIDC scopes, visit:
|
||||
* https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
|
||||
*/
|
||||
export const loginRequest = {
|
||||
scopes: [`api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`],
|
||||
};
|
||||
|
||||
/**
|
||||
* An optional silentRequest object can be used to achieve silent SSO
|
||||
* between applications by providing a "login_hint" property.
|
||||
*/
|
||||
// export const silentRequest = {
|
||||
// scopes: ["openid", "profile"],
|
||||
// loginHint: "example@domain.net"
|
||||
// };
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FormMode } from '../../enums/formMode';
|
||||
|
||||
export interface ILogbookEntryFormProps {
|
||||
export interface ILogFormProps {
|
||||
entryId?: string;
|
||||
isDrawerOpen: boolean;
|
||||
mode: FormMode;
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface ILogbookEntryFormState {
|
||||
export interface ILogFormState {
|
||||
error: string | undefined;
|
||||
isDisabled: boolean;
|
||||
isLoading: boolean;
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
XmarkIcon
|
||||
} from '@noahspan/noahspan-components';
|
||||
import { useForm, Controller, FormProvider } from 'react-hook-form';
|
||||
import { ILogbookEntryFormProps } from './ILogbookEntryFormProps';
|
||||
import { ILogFormProps } from './ILogFormProps';
|
||||
import { initialState, reducer } from './reducer';
|
||||
import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
|
||||
@@ -26,7 +26,7 @@ import { useIsAuthenticated } from '@azure/msal-react';
|
||||
import { FormMode } from '../../enums/formMode';
|
||||
import { usePilots } from '../../hooks/pilots/UsePilots';
|
||||
|
||||
const LogbookEntryForm: React.FC<ILogbookEntryFormProps> = ({
|
||||
const LogForm: React.FC<ILogFormProps> = ({
|
||||
entryId,
|
||||
isDrawerOpen,
|
||||
mode,
|
||||
@@ -37,8 +37,6 @@ const LogbookEntryForm: React.FC<ILogbookEntryFormProps> = ({
|
||||
const { getAccessToken } = useAccessToken();
|
||||
const isAuthenticated = useIsAuthenticated();
|
||||
const defaultValues = {
|
||||
partitionKey: '',
|
||||
rowKey: '',
|
||||
pilotId: '',
|
||||
pilotName: '',
|
||||
date: null,
|
||||
@@ -80,13 +78,13 @@ const LogbookEntryForm: React.FC<ILogbookEntryFormProps> = ({
|
||||
const accessToken: string = await getAccessToken();
|
||||
|
||||
if (!entryId) {
|
||||
await httpClient.post(`api/logbook`, data, {
|
||||
await httpClient.post(`api/logs`, data, {
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await httpClient.put(`api/logbook/${entryId}`, data, {
|
||||
await httpClient.put(`api/logs/${entryId}`, data, {
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
@@ -120,7 +118,7 @@ const LogbookEntryForm: React.FC<ILogbookEntryFormProps> = ({
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/logbook/${entryId}`,
|
||||
`api/logs/${entryId}`,
|
||||
config
|
||||
);
|
||||
const entry = response.data;
|
||||
@@ -939,4 +937,4 @@ const LogbookEntryForm: React.FC<ILogbookEntryFormProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default LogbookEntryForm;
|
||||
export default LogForm;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ILogbookEntryFormState } from './ILogbookEntryFormState';
|
||||
import { ILogFormState } from './ILogFormState';
|
||||
|
||||
type Action =
|
||||
| { type: 'SET_ERROR'; payload: string | undefined }
|
||||
@@ -7,7 +7,7 @@ type Action =
|
||||
| { type: 'SET_PILOT_OPTIONS'; payload: { label: string; value: string }[] }
|
||||
| { type: 'SET_SELECTED_ENTRY_PILOT_NAME'; payload: string };
|
||||
|
||||
export const initialState: ILogbookEntryFormState = {
|
||||
export const initialState: ILogFormState = {
|
||||
error: undefined,
|
||||
isDisabled: false,
|
||||
isLoading: true,
|
||||
@@ -16,9 +16,9 @@ export const initialState: ILogbookEntryFormState = {
|
||||
};
|
||||
|
||||
export const reducer = (
|
||||
state: ILogbookEntryFormState,
|
||||
state: ILogFormState,
|
||||
action: Action
|
||||
): ILogbookEntryFormState => {
|
||||
): ILogFormState => {
|
||||
switch (action.type) {
|
||||
case 'SET_ERROR': {
|
||||
return {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useReducer, useState } from 'react';
|
||||
import LogbookEntryForm from '../logbookEntryForm/LogbookEntryForm';
|
||||
import { useEffect, useReducer } from 'react';
|
||||
import LogForm from '../logForm/LogForm';
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
@@ -35,11 +35,8 @@ const Logbook: React.FC<unknown> = () => {
|
||||
const config = isAuthenticated
|
||||
? { headers: { Authorization: `${token}` } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/logbook`,
|
||||
config
|
||||
);
|
||||
|
||||
const response: AxiosResponse = await httpClient.get(`api/logs`, config);
|
||||
console.log(response)
|
||||
dispatch({ type: 'SET_ENTRIES', payload: response.data });
|
||||
} catch (error) {
|
||||
const axiosError = error as AxiosError;
|
||||
@@ -98,7 +95,7 @@ const Logbook: React.FC<unknown> = () => {
|
||||
? { headers: { Authorization: `${token}` } }
|
||||
: {};
|
||||
|
||||
await httpClient.delete(`api/logbook/${state.selectedEntryId}`, config);
|
||||
await httpClient.delete(`api/logs/${state.selectedEntryId}`, config);
|
||||
|
||||
dispatch({
|
||||
type: 'SET_DELETE',
|
||||
@@ -418,20 +415,24 @@ const Logbook: React.FC<unknown> = () => {
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<LogbookEntryForm
|
||||
entryId={state.selectedEntryId}
|
||||
isDrawerOpen={state.isFormOpen}
|
||||
mode={state.formMode}
|
||||
onOpenClose={(mode) => onOpenCloseEntryForm(mode)}
|
||||
/>
|
||||
<ConfirmationDialog
|
||||
contentText="Are you sure you want to delete the logbook entry?"
|
||||
isLoading={state.isConfirmDialogLoading}
|
||||
isOpen={state.isConfirmDialogOpen}
|
||||
onCancel={onConfirmationDialogCancel}
|
||||
onConfirm={onConfirmationDialogConfirm}
|
||||
title="Confirm Delete"
|
||||
/>
|
||||
{state.isFormOpen && (
|
||||
<LogForm
|
||||
entryId={state.selectedEntryId}
|
||||
isDrawerOpen={state.isFormOpen}
|
||||
mode={state.formMode}
|
||||
onOpenClose={(mode) => onOpenCloseEntryForm(mode)}
|
||||
/>
|
||||
)}
|
||||
{state.isConfirmDialogOpen && (
|
||||
<ConfirmationDialog
|
||||
contentText="Are you sure you want to delete the logbook entry?"
|
||||
isLoading={state.isConfirmDialogLoading}
|
||||
isOpen={state.isConfirmDialogOpen}
|
||||
onCancel={onConfirmationDialogCancel}
|
||||
onConfirm={onConfirmationDialogConfirm}
|
||||
title="Confirm Delete"
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
XmarkIcon
|
||||
} from '@noahspan/noahspan-components';
|
||||
import { IPilotFormProps } from './IPilotFormProps';
|
||||
import axios, { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
|
||||
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
|
||||
import { useIsAuthenticated } from '@azure/msal-react';
|
||||
@@ -38,8 +38,8 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
const { getAccessToken } = useAccessToken();
|
||||
const isAuthenticated = useIsAuthenticated();
|
||||
const defaultValues = {
|
||||
partitionKey: '',
|
||||
rowKey: '',
|
||||
partitionKey: 'pilot',
|
||||
rowKey: 'noah@noahspannbauer.com',
|
||||
id: '',
|
||||
name: '',
|
||||
address: '',
|
||||
@@ -53,6 +53,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
defaultValues: defaultValues
|
||||
});
|
||||
const [isDisabled, setIsDisabled] = useState<boolean>(false);
|
||||
const [isError, setIsError] = useState<boolean>(false);
|
||||
|
||||
const onPeoplePickerSearch = async (
|
||||
_event: React.SyntheticEvent,
|
||||
@@ -105,24 +106,19 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
||||
setIsLoading(true);
|
||||
|
||||
const accessToken: string = await getAccessToken();
|
||||
const response: AxiosResponse = await httpClient.post(
|
||||
`api/pilots`,
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
|
||||
await httpClient.post(`api/pilots`, data, {
|
||||
headers: {
|
||||
Authorization: accessToken
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (response) console.log(response);
|
||||
onOpenClose(FormMode.CANCEL);
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const errResp = error.response;
|
||||
const axiosError = error as AxiosError;
|
||||
const responseData = axiosError.response?.data as any;
|
||||
|
||||
console.log(errResp?.data.message);
|
||||
} else {
|
||||
}
|
||||
console.log(responseData.message);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,25 @@ const Pilots: React.FC<unknown> = () => {
|
||||
const [pilotFormMode, setPilotFormMode] = useState<FormMode>(FormMode.CANCEL);
|
||||
const [selectedPilotId, setSelectedPilotId] = useState<string | undefined>();
|
||||
const [pilots, setPilots] = useState<Pilot[]>([]);
|
||||
const onOpenClosePilotForm = (mode: FormMode, pilotId?: string) => {
|
||||
|
||||
const getPilots = async (): Promise<Pilot[]> => {
|
||||
try {
|
||||
const config = isAuthenticated
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/pilots`,
|
||||
config
|
||||
);
|
||||
const pilots: Pilot[] = response.data;
|
||||
|
||||
return pilots;
|
||||
} catch (error) {
|
||||
throw new Error('broken');
|
||||
}
|
||||
};
|
||||
|
||||
const onOpenClosePilotForm = async (mode: FormMode, pilotId?: string) => {
|
||||
switch (mode) {
|
||||
case FormMode.ADD:
|
||||
case FormMode.EDIT:
|
||||
@@ -49,6 +67,9 @@ const Pilots: React.FC<unknown> = () => {
|
||||
setIsDrawerOpen(true);
|
||||
break;
|
||||
case FormMode.CANCEL:
|
||||
const pilots = await getPilots();
|
||||
|
||||
setPilots(pilots);
|
||||
setPilotFormMode(mode);
|
||||
setSelectedPilotId(undefined);
|
||||
setIsDrawerOpen(false);
|
||||
@@ -73,6 +94,7 @@ const Pilots: React.FC<unknown> = () => {
|
||||
const onCloseActionMenu = () => {
|
||||
setAnchorElAction(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IconButton onClick={onOpenActionMenu}>
|
||||
@@ -124,23 +146,17 @@ const Pilots: React.FC<unknown> = () => {
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const getPilots = async () => {
|
||||
const loadPilots = async () => {
|
||||
try {
|
||||
const config = isAuthenticated
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
const response: AxiosResponse = await httpClient.get(
|
||||
`api/pilots`,
|
||||
config
|
||||
);
|
||||
console.log(response.data);
|
||||
setPilots(response.data);
|
||||
const pilots = await getPilots();
|
||||
|
||||
setPilots(pilots);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
getPilots();
|
||||
loadPilots();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -43,8 +43,8 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
url: '/pilots'
|
||||
}
|
||||
];
|
||||
const handleSignIn = async () => {
|
||||
await instance.loginRedirect({
|
||||
const handleSignIn = () => {
|
||||
instance.loginRedirect({
|
||||
scopes: [`api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`]
|
||||
});
|
||||
};
|
||||
@@ -52,6 +52,7 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
instance.logoutRedirect();
|
||||
};
|
||||
const getUserProfile = async (accessToken: string): Promise<User> => {
|
||||
console.log(accessToken)
|
||||
try {
|
||||
const response: AxiosResponse = await httpClient.get(`api/userProfile`, {
|
||||
headers: {
|
||||
@@ -66,6 +67,7 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
}
|
||||
};
|
||||
const getUserPhoto = async (accessToken: string): Promise<string> => {
|
||||
console.log(accessToken)
|
||||
try {
|
||||
const response: AxiosResponse = await httpClient.get(`api/userPhoto`, {
|
||||
headers: {
|
||||
@@ -98,40 +100,44 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const callback = instance.addEventCallback(
|
||||
async (message: EventMessage) => {
|
||||
if (message.eventType === EventType.LOGIN_SUCCESS) {
|
||||
try {
|
||||
setLoading(true);
|
||||
// useEffect(() => {
|
||||
// const callback = instance.addEventCallback(
|
||||
// async (message: EventMessage) => {
|
||||
// if (message.eventType === EventType.LOGIN_SUCCESS) {
|
||||
// try {
|
||||
// setLoading(true);
|
||||
|
||||
const eventPayload: EventPayloadExtended =
|
||||
message.payload as EventPayloadExtended;
|
||||
const userProfile: User = await getUserProfile(
|
||||
eventPayload.accessToken
|
||||
);
|
||||
const userPhoto = await getUserPhoto(eventPayload.accessToken);
|
||||
// const eventPayload: EventPayloadExtended =
|
||||
// message.payload as EventPayloadExtended;
|
||||
// const userProfile: User = await getUserProfile(
|
||||
// eventPayload.accessToken
|
||||
// );
|
||||
// const userPhoto = await getUserPhoto(eventPayload.accessToken);
|
||||
|
||||
appContext.dispatch({
|
||||
type: 'SET_USER_PROFILE',
|
||||
payload: userProfile
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
// appContext.dispatch({
|
||||
// type: 'SET_USER_PROFILE',
|
||||
// payload: userProfile
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// } finally {
|
||||
// setLoading(false);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
return () => {
|
||||
if (callback) {
|
||||
instance.removeEventCallback(callback);
|
||||
appContext.dispatch({ type: 'SET_USER_PROFILE', payload: {} });
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
// instance.handleRedirectPromise().then((response) => {
|
||||
// console.log(response)
|
||||
// })
|
||||
|
||||
// return () => {
|
||||
// if (callback) {
|
||||
// instance.removeEventCallback(callback);
|
||||
// appContext.dispatch({ type: 'SET_USER_PROFILE', payload: {} });
|
||||
// }
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
useEffect(() => {
|
||||
const setUserProfile = async () => {
|
||||
@@ -176,4 +182,4 @@ const SiteNav: React.FC<unknown> = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SiteNav;
|
||||
export default SiteNav;
|
||||
@@ -5,6 +5,6 @@ export const useFeatureFlag = (featureFlagKey: string) => {
|
||||
const featureFlag = appContext.state.featureFlags.find(
|
||||
(featureFlag) => featureFlag.key === featureFlagKey
|
||||
);
|
||||
|
||||
console.log(featureFlag)
|
||||
return featureFlag;
|
||||
};
|
||||
|
||||
12
app/src/index.html
Normal file
12
app/src/index.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,27 +5,34 @@ import AppContextProvider from './context/appContext/AppContextProvider.tsx';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import './index.css';
|
||||
import '@noahspan/noahspan-components/noahspan-components.css';
|
||||
import { PublicClientApplication } from '@azure/msal-browser';
|
||||
import { AuthenticationResult, EventMessage, EventType, PublicClientApplication } from '@azure/msal-browser';
|
||||
import { MsalProvider } from '@azure/msal-react';
|
||||
import { msalConfig } from './auth/msalConfig';
|
||||
|
||||
const msalInstance: PublicClientApplication = new PublicClientApplication({
|
||||
auth: {
|
||||
clientId: import.meta.env.VITE_CLIENT_ID,
|
||||
authority: `https://login.microsoftonline.com/${import.meta.env.VITE_TENANT_ID}`,
|
||||
redirectUri: import.meta.env.VITE_REDIRECT_URL
|
||||
}
|
||||
});
|
||||
const msalInstance: PublicClientApplication = new PublicClientApplication(msalConfig);
|
||||
|
||||
msalInstance.initialize().then(() => {
|
||||
const accounts = msalInstance.getAllAccounts();
|
||||
|
||||
if (accounts.length > 0) {
|
||||
msalInstance.setActiveAccount(accounts[0]);
|
||||
}
|
||||
|
||||
msalInstance.addEventCallback((event: EventMessage) => {
|
||||
if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
|
||||
const payload = event.payload as AuthenticationResult;
|
||||
const account = payload.account;
|
||||
msalInstance.setActiveAccount(account);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<MsalProvider instance={msalInstance}>
|
||||
<AppContextProvider>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</AppContextProvider>
|
||||
</MsalProvider>
|
||||
<AppContextProvider>
|
||||
<BrowserRouter>
|
||||
<App pca={msalInstance} />
|
||||
</BrowserRouter>
|
||||
</AppContextProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
});
|
||||
})
|
||||
@@ -1,9 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
darkMode: 'class',
|
||||
plugins: []
|
||||
};
|
||||
@@ -3,5 +3,14 @@ import react from '@vitejs/plugin-react';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()]
|
||||
plugins: [react()],
|
||||
preview: {
|
||||
port: 8080,
|
||||
strictPort: true
|
||||
},
|
||||
server: {
|
||||
port: 8080,
|
||||
strictPort: true,
|
||||
host: '0.0.0.0'
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user