Skip to content

Commit

Permalink
add top sites to insights and improve token refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
gessfred committed Jan 6, 2024
1 parent dbfc5b3 commit 35b8771
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 42 deletions.
43 changes: 37 additions & 6 deletions web/package-lock.json

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

4 changes: 4 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.2",
"chart.js": "^4.4.0",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
Expand Down Expand Up @@ -37,5 +38,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"tailwindcss": "^3.3.7"
}
}
1 change: 0 additions & 1 deletion web/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import api, { isAuthenticated } from './foundation/api'
function Pages() {
const [flag, setFlag] = useState(false)
const authenticated = isAuthenticated()
console.log('auth', authenticated)
return (
<div className="App">
{!authenticated && <LandingPage onLogin={() => setFlag(p => !p)} />}
Expand Down
56 changes: 29 additions & 27 deletions web/src/foundation/api.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,61 @@
import axios from 'axios';

const url = 'https://keylogg.pub.gessfred.xyz/api'
let failures = 0

const api = axios.create({
baseURL: url,
baseURL: url
})

api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
console.log('token', token)
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
console.log('request', config)
console.log('token', token, 'request', config.url)
return config
},
(error) => Promise.reject(error)
)

const refreshToken = async () => {
const refreshToken = localStorage.getItem('refreshToken')
const response = await axios.post('/api/token', { refreshToken })
const { token } = response.data

localStorage.setItem('token', token)
return token
}

// Add a response interceptor
api.interceptors.response.use(
(response) => response,
/*async (error) => {
console.log('ERROR TOKEN REFRESH', error, error.response.status)
const originalRequest = error.config
console.log('original request', originalRequest)
// If the error status is 401 and there is no originalRequest._retry flag,
// it means the token has expired and we need to refresh it
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
try {
const refreshToken = localStorage.getItem('refreshToken')
const response = await axios.post('/api/token', { refreshToken })
const { token } = response.data
localStorage.setItem('token', token)
// Retry the original request with the new token
(response) => {
++failures
return response
},
async (error) => {
try {
const originalRequest = error.config
console.log("Response error:", error, "original request:", originalRequest)
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
originalRequest._retry_count = originalRequest._retry_count ? originalRequest._retry_count + 1 : 1
const token = await refreshToken()
originalRequest.headers.Authorization = `Bearer ${token}`
return axios(originalRequest)
} catch (error) {
// Handle refresh token error or redirect to login
}
} catch (e) {
console.log("Fatal error during response error resolution. Clearing token cache. Previous")
}
localStorage.removeItem('token')
localStorage.removeItem('refreshToken')
return Promise.reject(error)
}*/
async (error) => {
console.log('ERROR TOKEN REFRESH', error)
}
)

export async function login(username, password) {
console.log('try login for user', username)
let formData = new URLSearchParams({
username: username,
password: password
Expand Down
5 changes: 5 additions & 0 deletions web/src/pages/Insights.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
flex-direction: row;
align-items: center;
justify-content: space-between;
}

#top-site-doughnut {
width: 400px !important;
height: 400px !important;
}
53 changes: 45 additions & 8 deletions web/src/pages/Insights.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ import {
Title,
Tooltip,
Legend,
ArcElement
} from 'chart.js'
import { Line } from 'react-chartjs-2'
import { Line, Pie, Doughnut } from 'react-chartjs-2'

ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
ArcElement,
Title,
Tooltip,
Legend
Expand Down Expand Up @@ -64,6 +66,36 @@ function TypingDashboard({ data, labels, title }) {
);
}

function TopSites({data}) {
// npm install chroma-js
//
const colors = Array.from({ length: data.length }).map((_, i) =>
`hsl(${i * (360 / data.length)}, 100%, 70%)`
)
return (
<Doughnut
id="top-site-doughnut"
width={100}
height={100}
data={{
labels: data.map(({url}, i) => url),
datasets: [
{
id: 1,
label: '???',
data: data.map(({count}) => count),
borderWidth: 2,
backgroundColor: colors
}
],
}}
options={{
responsive: true
}}
/>
)
}

export function Insights({show}) {
const isAuthenticated = false
const [state, setState] = useState({})
Expand All @@ -89,13 +121,18 @@ export function Insights({show}) {
<input type="text" id="insights-lang-request" />
<div id="insights-feed">
<h3>Top sites</h3>
<div>
{topSites.map(({url, count}) => (
<div>
<span>{url}</span>
<span>{count}</span>
</div>
))}
<div id="typing-view">
<table>
<tbody>
{topSites.map(({url, count}) => (
<tr>
<td>{url}</td>
<td>{count}</td>
</tr>
))}
</tbody>
</table>
<TopSites data={topSites} />
</div>
<div id="typing-view">
<TypingDashboard title="Event count" labels={typingData.map((x, i) => i)} data={typingData.map(x => x.event_count).reverse()} />
Expand Down

0 comments on commit 35b8771

Please sign in to comment.