Skip to content

Commit d7ec24c

Browse files
committed
fix: Session tracking and UI improvements
- Fix lastActive not being updated (middleware now passes token to touch()) - Add id alias for documentId (frontend compatibility) - Redesign table action buttons with styled IconButtons - Redesign SessionDetailModal with styled buttons and status badge - Add IconButtonWarning for terminate action - Fix empty state text display (now shows on separate lines) - Add session-required policy for session validation
1 parent 04116f3 commit d7ec24c

12 files changed

Lines changed: 527 additions & 104 deletions

File tree

admin/src/components/SessionDetailModal.jsx

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
Box,
77
Flex,
88
Typography,
9-
Button,
109
Badge,
1110
Divider,
1211
} from '@strapi/design-system';
@@ -27,6 +26,12 @@ import parseUserAgent from '../utils/parseUserAgent';
2726
import pluginId from '../pluginId';
2827
import { useLicense } from '../hooks/useLicense';
2928
import { getTranslation } from '../utils/getTranslation';
29+
import {
30+
TertiaryButton,
31+
DangerButton,
32+
GradientButton,
33+
ShowHideButton,
34+
} from './StyledButtons';
3035

3136
const TwoColumnGrid = styled.div`
3237
display: grid;
@@ -54,6 +59,79 @@ const Section = styled(Box)`
5459
margin-bottom: 24px;
5560
`;
5661

62+
// Status Badge - pill-shaped with gradient
63+
const ModalStatusBadge = styled.span`
64+
display: inline-flex;
65+
align-items: center;
66+
gap: 8px;
67+
padding: 10px 24px;
68+
border-radius: 24px;
69+
font-size: 14px;
70+
font-weight: 700;
71+
letter-spacing: 0.5px;
72+
text-transform: uppercase;
73+
74+
${props => props.$online && `
75+
background: linear-gradient(135deg, #DCFCE7 0%, #BBF7D0 100%);
76+
color: #166534;
77+
border: 2px solid #86EFAC;
78+
box-shadow: 0 4px 12px rgba(34, 197, 94, 0.2);
79+
`}
80+
81+
${props => !props.$online && `
82+
background: linear-gradient(135deg, #F3F4F6 0%, #E5E7EB 100%);
83+
color: #4B5563;
84+
border: 2px solid #D1D5DB;
85+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
86+
`}
87+
`;
88+
89+
const StatusDot = styled.span`
90+
width: 10px;
91+
height: 10px;
92+
border-radius: 50%;
93+
94+
${props => props.$online && `
95+
background: #22C55E;
96+
box-shadow: 0 0 8px rgba(34, 197, 94, 0.6);
97+
animation: pulse-green 2s ease-in-out infinite;
98+
`}
99+
100+
${props => !props.$online && `
101+
background: #9CA3AF;
102+
`}
103+
104+
@keyframes pulse-green {
105+
0%, 100% { opacity: 1; transform: scale(1); }
106+
50% { opacity: 0.7; transform: scale(1.15); }
107+
}
108+
`;
109+
110+
// Premium Upgrade Button
111+
const PremiumButton = styled.button`
112+
background: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
113+
color: white;
114+
border: none;
115+
padding: 12px 24px;
116+
border-radius: 10px;
117+
font-weight: 700;
118+
font-size: 14px;
119+
cursor: pointer;
120+
transition: all 0.2s ease;
121+
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
122+
margin-top: 8px;
123+
124+
&:hover {
125+
background: linear-gradient(135deg, #D97706 0%, #B45309 100%);
126+
transform: translateY(-2px);
127+
box-shadow: 0 6px 16px rgba(245, 158, 11, 0.4);
128+
}
129+
130+
&:active {
131+
transform: translateY(0);
132+
}
133+
`;
134+
57135
const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
58136
const { formatMessage } = useIntl();
59137
const { get, post } = useFetchClient();
@@ -205,14 +283,10 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
205283
<Box padding={6}>
206284
{/* Status Badge */}
207285
<Flex justifyContent="center" style={{ marginBottom: '24px' }}>
208-
<Badge
209-
backgroundColor={isOnline ? 'success600' : 'neutral600'}
210-
textColor="neutral0"
211-
size="M"
212-
style={{ fontSize: '14px', padding: '8px 20px', fontWeight: '600' }}
213-
>
286+
<ModalStatusBadge $online={isOnline}>
287+
<StatusDot $online={isOnline} />
214288
{isOnline ? t('modal.status.online', 'ONLINE') : t('modal.status.offline', 'OFFLINE')}
215-
</Badge>
289+
</ModalStatusBadge>
216290
</Flex>
217291

218292
<Divider style={{ marginBottom: '24px' }} />
@@ -364,21 +438,11 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
364438
<Typography variant="omega" style={{ color: '#78350f', fontSize: '14px', lineHeight: '1.6' }}>
365439
{t('modal.premium.description', 'Unlock premium features to get IP geolocation, security scoring, and VPN/Proxy detection for every session')}
366440
</Typography>
367-
<Button
368-
variant="secondary"
369-
size="M"
441+
<PremiumButton
370442
onClick={() => window.open('https://magicapi.fitlex.me', '_blank')}
371-
style={{
372-
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
373-
color: 'white',
374-
border: 'none',
375-
fontWeight: '600',
376-
marginTop: '8px',
377-
boxShadow: '0 4px 12px rgba(245, 158, 11, 0.3)',
378-
}}
379443
>
380444
{t('modal.premium.upgrade', 'Upgrade to Premium')}
381-
</Button>
445+
</PremiumButton>
382446
</Flex>
383447
</Box>
384448
</Section>
@@ -390,14 +454,12 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
390454
<SectionTitle style={{ marginBottom: 0, paddingBottom: 0, border: 'none' }}>
391455
{t('modal.section.technical', 'Technical Details')}
392456
</SectionTitle>
393-
<Button
394-
variant="tertiary"
457+
<ShowHideButton
395458
size="S"
396459
onClick={() => setShowUserAgent(!showUserAgent)}
397-
style={{ fontSize: '12px' }}
398460
>
399-
{showUserAgent ? `▲ ${t('modal.technical.hide', 'Hide Details')}` : `▼ ${t('modal.technical.show', 'Show Details')}`}
400-
</Button>
461+
{showUserAgent ? t('modal.technical.hide', 'Hide Details') : t('modal.technical.show', 'Show Details')}
462+
</ShowHideButton>
401463
</Flex>
402464

403465
{showUserAgent && (
@@ -426,18 +488,17 @@ const SessionDetailModal = ({ session, onClose, onSessionTerminated }) => {
426488

427489
<Modal.Footer>
428490
<Flex justifyContent="space-between" style={{ width: '100%' }}>
429-
<Button onClick={onClose} variant="tertiary">
491+
<TertiaryButton onClick={onClose}>
430492
{t('modal.actions.close', 'Close')}
431-
</Button>
432-
<Button
493+
</TertiaryButton>
494+
<DangerButton
433495
onClick={handleTerminate}
434-
variant="danger"
435496
disabled={!session.isActive || terminating}
436497
loading={terminating}
437498
startIcon={<Cross />}
438499
>
439500
{t('modal.actions.terminate', 'Terminate Session')}
440-
</Button>
501+
</DangerButton>
441502
</Flex>
442503
</Modal.Footer>
443504
</Modal.Content>

admin/src/components/SessionInfoPanel.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,10 @@ const SessionInfoPanel = ({ documentId, model, document }) => {
385385
<EmptyIcon>
386386
<User width="24px" height="24px" />
387387
</EmptyIcon>
388-
<Typography variant="omega" fontWeight="semiBold" textColor="neutral700">
388+
<Typography variant="omega" fontWeight="semiBold" textColor="neutral700" style={{ display: 'block' }}>
389389
{t('panel.empty.title', 'No active sessions')}
390390
</Typography>
391-
<Typography variant="pi" textColor="neutral500" style={{ marginTop: '4px' }}>
391+
<Typography variant="pi" textColor="neutral500" style={{ display: 'block', marginTop: '4px' }}>
392392
{t('panel.empty.description', 'User has not logged in yet')}
393393
</Typography>
394394
</EmptyState>

admin/src/components/StyledButtons.jsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,47 @@ export const IconButtonSuccess = styled(Button)`
290290
}
291291
`;
292292

293+
// ================ ICON BUTTON WARNING (for terminate/logout) ================
294+
export const IconButtonWarning = styled(Button)`
295+
&& {
296+
background: linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%);
297+
color: #D97706;
298+
border: 1px solid #FDE68A;
299+
padding: 8px;
300+
min-width: 38px;
301+
min-height: 38px;
302+
width: 38px;
303+
height: 38px;
304+
border-radius: 10px;
305+
display: flex;
306+
align-items: center;
307+
justify-content: center;
308+
transition: all 0.2s ease;
309+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
310+
311+
svg {
312+
width: 18px;
313+
height: 18px;
314+
}
315+
316+
&:hover:not(:disabled) {
317+
background: linear-gradient(135deg, #F59E0B 0%, #D97706 100%);
318+
border-color: #F59E0B;
319+
color: white;
320+
transform: translateY(-1px);
321+
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
322+
}
323+
324+
&:disabled {
325+
opacity: 0.5;
326+
cursor: not-allowed;
327+
background: #F3F4F6;
328+
border-color: #E5E7EB;
329+
color: #9CA3AF;
330+
}
331+
}
332+
`;
333+
293334
// ================ LARGE CTA BUTTON ================
294335
export const CTAButton = styled(Button)`
295336
&& {

0 commit comments

Comments
 (0)