Skip to content

Commit f211c34

Browse files
committed
Refactor SPA code
1 parent 3e9be59 commit f211c34

File tree

3 files changed

+164
-152
lines changed

3 files changed

+164
-152
lines changed

client/src/App.js

+6-152
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,15 @@
1-
import React, { useState, useEffect } from 'react';
2-
import { PublicClientApplication } from '@azure/msal-browser';
1+
import React from 'react';
32
import { Buffer } from 'buffer';
3+
import { AuthProvider } from './components/AuthProvider';
4+
import CsvUploader from './components/CsvUploader';
45

56
window.Buffer = Buffer;
67

7-
// MSAL Configuration
8-
const msalConfig = {
9-
auth: {
10-
clientId: process.env.REACT_APP_STATIC_WEB_APP_CLIENT_ID,
11-
authority: `https://login.microsoftonline.com/${process.env.REACT_APP_AZURE_TENANT_ID}`,
12-
redirectUri: window.location.origin,
13-
},
14-
};
15-
16-
const msalInstance = new PublicClientApplication(msalConfig);
17-
188
const App = () => {
19-
const [file, setFile] = useState(null);
20-
const [error, setError] = useState('');
21-
const [modalVisible, setModalVisible] = useState(false);
22-
const [user, setUser] = useState(null);
23-
const [isInitialized, setIsInitialized] = useState(false);
24-
25-
const handleFileChange = (e) => {
26-
setError('');
27-
setFile(e.target.files[0]);
28-
};
29-
30-
const uploadFile = async (file) => {
31-
if (!file) {
32-
setError('Please select a file to upload');
33-
return;
34-
}
35-
36-
try {
37-
console.log('Authenticating and uploading file...');
38-
39-
// Acquire access token
40-
const account = msalInstance.getAllAccounts()[0];
41-
if (!account) {
42-
throw new Error('User is not signed in');
43-
}
44-
45-
const tokenResponse = await msalInstance.acquireTokenSilent({
46-
scopes: ['api://hvalfangst-function-app/Csv.Writer'],
47-
account
48-
});
49-
50-
console.log('Token response:', tokenResponse);
51-
52-
const token = tokenResponse.accessToken;
53-
54-
const endpoint = 'https://hvalfangstlinuxfunctionapp.azurewebsites.net/api/upload_csv';
55-
56-
// Read the file as a text string
57-
const fileContent = await file.text();
58-
59-
const response = await fetch(endpoint, {
60-
method: 'POST',
61-
headers: {
62-
'Content-Type': 'text/csv', // Set content type to CSV
63-
Authorization: `Bearer ${token}`, // Include OAuth token
64-
},
65-
body: fileContent, // Send the file content as the body
66-
});
67-
68-
if (!response.ok) {
69-
const errorMessage = await response.text();
70-
throw new Error(`Failed to upload: ${errorMessage}`);
71-
}
72-
73-
console.log('Response:', response)
74-
75-
console.log('File uploaded successfully');
76-
setModalVisible(true); // Show success modal
77-
} catch (error) {
78-
console.error('Error uploading file:', error);
79-
setError(`Error uploading file: ${error.message}`);
80-
}
81-
};
82-
83-
const handleFileUpload = () => {
84-
if (file) {
85-
uploadFile(file);
86-
} else {
87-
setError('Please select a file to upload');
88-
}
89-
};
90-
91-
const closeModal = () => {
92-
setModalVisible(false);
93-
};
94-
95-
const handleSignIn = async () => {
96-
try {
97-
await msalInstance.initialize();
98-
setIsInitialized(true);
99-
const response = await msalInstance.loginPopup({
100-
scopes: ['openid'],
101-
});
102-
console.log('Sign in response:', response);
103-
console.log('User signed in successfully');
104-
setUser(response.account);
105-
} catch (error) {
106-
console.error('Error signing in:', error);
107-
setError(`Error signing in: ${error.message}`);
108-
}
109-
};
110-
111-
const handleSignOut = async () => {
112-
if (!isInitialized) {
113-
console.error('MSAL instance is not initialized.');
114-
return;
115-
}
116-
await msalInstance.logoutPopup();
117-
setUser(null);
118-
};
119-
120-
useEffect(() => {
121-
const initializeMsal = async () => {
122-
await msalInstance.initialize();
123-
setIsInitialized(true);
124-
const accounts = msalInstance.getAllAccounts();
125-
if (accounts.length > 0) {
126-
setUser(accounts[0]);
127-
}
128-
};
129-
130-
initializeMsal();
131-
}, []);
132-
1339
return (
134-
<div className="csv-uploader">
135-
<h1>CSV Uploader</h1>
136-
{user ? (
137-
<div>
138-
<p>Welcome, {user.name}</p>
139-
<button onClick={handleSignOut}>Sign Out</button>
140-
</div>
141-
) : (
142-
<button onClick={handleSignIn}>Sign In</button>
143-
)}
144-
145-
<input type="file" accept=".csv" onChange={handleFileChange} />
146-
<button onClick={handleFileUpload}>Upload</button>
147-
{error && <p className="error">{error}</p>}
148-
149-
{modalVisible && (
150-
<div className="modal">
151-
<div className="modal-content">
152-
<h2>Upload Successful!</h2>
153-
<p>Your file has been uploaded to Azure Blob Storage via Azure Function.</p>
154-
<button onClick={closeModal}>Close</button>
155-
</div>
156-
</div>
157-
)}
158-
</div>
10+
<AuthProvider>
11+
<CsvUploader />
12+
</AuthProvider>
15913
);
16014
};
16115

client/src/components/AuthProvider.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React, { createContext, useContext, useState, useEffect } from 'react';
2+
import { PublicClientApplication } from '@azure/msal-browser';
3+
4+
const AuthContext = createContext();
5+
6+
const msalConfig = {
7+
auth: {
8+
clientId: process.env.REACT_APP_STATIC_WEB_APP_CLIENT_ID,
9+
authority: `https://login.microsoftonline.com/${process.env.REACT_APP_AZURE_TENANT_ID}`,
10+
redirectUri: window.location.origin,
11+
},
12+
};
13+
14+
const msalInstance = new PublicClientApplication(msalConfig);
15+
16+
export const AuthProvider = ({ children }) => {
17+
const [user, setUser] = useState(null);
18+
const [isInitialized, setIsInitialized] = useState(false);
19+
20+
const getCurrentAccount = () => {
21+
const accounts = msalInstance.getAllAccounts();
22+
return accounts.length > 0 ? accounts[0] : null;
23+
};
24+
25+
const acquireToken = async (scopes) => {
26+
const account = getCurrentAccount();
27+
if (!account) {
28+
throw new Error('No account found');
29+
}
30+
return await msalInstance.acquireTokenSilent({
31+
scopes,
32+
account,
33+
});
34+
};
35+
36+
const handleSignIn = async () => {
37+
try {
38+
await msalInstance.initialize();
39+
setIsInitialized(true);
40+
const response = await msalInstance.loginPopup({
41+
scopes: ['openid'],
42+
});
43+
setUser(response.account);
44+
} catch (error) {
45+
console.error('Error signing in:', error);
46+
}
47+
};
48+
49+
const handleSignOut = async () => {
50+
if (!isInitialized) {
51+
console.error('MSAL instance is not initialized.');
52+
return;
53+
}
54+
await msalInstance.logoutPopup();
55+
setUser(null);
56+
};
57+
58+
return (
59+
<AuthContext.Provider value={{ user, handleSignIn, handleSignOut, acquireToken }}>
60+
{children}
61+
</AuthContext.Provider>
62+
);
63+
};
64+
65+
export const useAuth = () => useContext(AuthContext);

client/src/components/CsvUploader.js

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React, {useState} from 'react';
2+
import {useAuth} from './AuthProvider';
3+
4+
5+
const CsvUploader = () => {
6+
const {user, handleSignIn, handleSignOut, acquireToken} = useAuth();
7+
const [file, setFile] = useState(null);
8+
const [error, setError] = useState('');
9+
const [modalVisible, setModalVisible] = useState(false);
10+
11+
const handleFileChange = (e) => {
12+
setError('');
13+
setFile(e.target.files[0]);
14+
};
15+
16+
const uploadFile = async (file) => {
17+
if (!file) {
18+
setError('Please select a file to upload');
19+
return;
20+
}
21+
22+
try {
23+
console.log('Authenticating and uploading file...');
24+
const tokenResponse = acquireToken(['api://hvalfangst-function-app/Csv.Writer']);
25+
const accessToken = tokenResponse.accessToken;
26+
const endpoint = 'https://hvalfangstlinuxfunctionapp.azurewebsites.net/api/upload_csv';
27+
const fileContent = await file.text();
28+
29+
const response = await fetch(endpoint, {
30+
method: 'POST',
31+
headers: {
32+
'Content-Type': 'text/csv',
33+
Authorization: `Bearer ${accessToken}`,
34+
},
35+
body: fileContent,
36+
});
37+
38+
if (!response.ok) {
39+
const errorMessage = await response.text();
40+
throw new Error(`Failed to upload: ${errorMessage}`);
41+
}
42+
43+
setModalVisible(true);
44+
} catch (error) {
45+
console.error('Error uploading file:', error);
46+
setError(`Error uploading file: ${error.message}`);
47+
}
48+
};
49+
50+
const handleFileUpload = async () => {
51+
if (file) {
52+
await uploadFile(file);
53+
} else {
54+
setError('Please select a file to upload');
55+
}
56+
};
57+
58+
const closeModal = () => {
59+
setModalVisible(false);
60+
};
61+
62+
return (
63+
<div className="csv-uploader">
64+
<div>
65+
<h1>CSV Uploader</h1>
66+
{user ? (
67+
<div>
68+
<p>Welcome, {user.name}</p>
69+
<button onClick={handleSignOut}>Sign Out</button>
70+
</div>
71+
) : (
72+
<button onClick={handleSignIn}>Sign In</button>
73+
)}
74+
</div>
75+
<div>
76+
<input type="file" accept=".csv" onChange={handleFileChange}/>
77+
<button onClick={handleFileUpload}>Upload</button>
78+
{error && <p className="error">{error}</p>}
79+
</div>
80+
{modalVisible && (
81+
<div className="modal">
82+
<div className="modal-content">
83+
<h2>Upload Successful!</h2>
84+
<p>Your file has been uploaded to Azure Blob Storage via Azure Function.</p>
85+
<button onClick={closeModal}>Close</button>
86+
</div>
87+
</div>
88+
)}
89+
</div>
90+
);
91+
};
92+
93+
export default CsvUploader;

0 commit comments

Comments
 (0)