usagestats v0

This commit is contained in:
DirkSchlossmacher 2023-11-14 09:11:08 +01:00
parent f871e2b8bb
commit 595cf6bf46
3 changed files with 187 additions and 0 deletions

View File

@ -0,0 +1,76 @@
// UsageStats.module.scss
.usageStatsContainer {
position: fixed; // Fixed position to overlay on top of the content
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5); // Semi-transparent background to obscure the content
z-index: 1000; // High z-index to ensure it's on top of other elements
}
.usageStatsModal {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 80%;
max-width: 600px; // Maximum width of the modal
z-index: 1001; // Ensure the modal is above the semi-transparent background
}
// ... Add more styles for headings, buttons, tables, etc.
.closeButton {
position: absolute;
top: 10px;
right: 10px;
border: none;
background: transparent;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.dropdown {
margin-bottom: 10px;
}
.button {
padding: 10px 20px;
margin-right: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
background-color: #f0f0f0;
}
}
// ... Add more styles as needed
.table {
width: 100%;
border-collapse: collapse;
th, td {
text-align: left;
padding: 8px;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f8f8f8;
}
}
@media (max-width: 768px) {
.usageStatsModal {
width: 95%;
padding: 10px;
}
}

View File

@ -0,0 +1,79 @@
// UsageStats.tsx
import React, { useState, useEffect } from 'react';
import { getAvailableDateKeys, getSignInCountForPeriod, getDetailsByUser } from './app/utils/cloud/redisRestClient';
import styles from './UsageStats.module.scss'; // Assume you have a separate SCSS module for UsageStats
const UsageStats: React.FC<{ onClose: () => void }> = ({ onClose }) => {
const [dateKeys, setDateKeys] = useState<string[]>([]);
const [selectedDateKey, setSelectedDateKey] = useState<string>('');
const [signInCount, setSignInCount] = useState<number>(0);
const [userDetails, setUserDetails] = useState<Record<string, number>>({});
const [showDrillDown, setShowDrillDown] = useState<boolean>(false);
useEffect(() => {
const fetchData = async () => {
const availableDateKeys = await getAvailableDateKeys();
setDateKeys(availableDateKeys);
};
fetchData();
}, []);
const handleDateChange = async (event: React.ChangeEvent<HTMLSelectElement>) => {
const dateKey = event.target.value;
setSelectedDateKey(dateKey);
const count = await getSignInCountForPeriod(dateKey);
setSignInCount(count);
setShowDrillDown(false);
};
const handleDrillDown = async () => {
const details = await getDetailsByUser(selectedDateKey);
setUserDetails(details);
setShowDrillDown(true);
};
return (
<div className={styles.usageStatsContainer}>
<div className={styles.usageStatsModal}>
<h1>Usage Stats</h1>
<select value={selectedDateKey} onChange={handleDateChange}>
{dateKeys.map(dateKey => (
<option key={dateKey} value={dateKey}>
{dateKey}
</option>
))}
</select>
<p>Number of events: {signInCount}</p>
<button onClick={handleDrillDown}>Drill-down</button>
{showDrillDown && (
{/* ... other UI elements ... */}
<table>
<thead>
<tr>
<th>Email</th>
<th>Count</th>
</tr>
</thead>
<tbody>
{Object.entries(userDetails).map(([email, count]) => (
<tr key={email}>
<td>{email}</td>
<td>{count}</td>
</tr>
))}
</tbody>
</table>
)}
<button className={styles.closeButton} onClick={onClose}>
Close
</button>
</div>
</div>
);
};
export default UsageStats;

View File

@ -60,3 +60,35 @@ export const incrementTokenCounts = async (
console.error('Failed to increment token counts in Redis via Upstash', error); console.error('Failed to increment token counts in Redis via Upstash', error);
} }
}; };
export const getAvailableDateKeys = async (): Promise<string[]> => {
try {
const keys = await redis.keys('signin_count:*');
return keys.map(key => key.split(':')[1]);
} catch (error) {
console.error('Failed to get keys from Redis', error);
return [];
}
};
export const getSignInCountForPeriod = async (dateKey: string): Promise<number> => {
try {
const counts = await redis.hgetall(`signin_count:${dateKey}`);
return Object.values(counts).reduce((total, count) => total + parseInt(count, 10), 0);
} catch (error) {
console.error(`Failed to get sign-in count for period ${dateKey}`, error);
return 0;
}
};
export const getDetailsByUser = async (dateKey: string): Promise<Record<string, number>> => {
try {
const counts = await redis.hgetall(`signin_count:${dateKey}`);
return counts;
} catch (error) {
console.error(`Failed to get details by user for period ${dateKey}`, error);
return {};
}
};