Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
696d56a
Layout for application created, documentation added.
mroki58 Jun 16, 2025
1a45249
First idea for running test container. Created image with dockerfile…
mroki58 Jun 17, 2025
38f90ed
Session data taken correctly but it rerenders page again which throws…
mroki58 Jun 18, 2025
6b93174
Merge branch 'dev' into feature/TKN/OGUI-1711/implement-overall-layout
mroki58 Aug 20, 2025
6faffd1
- Added eslint configuration with established assumptions
mroki58 Aug 21, 2025
8231106
Merge remote-tracking branch 'origin/dev' into feature/TKN/OGUI-1724/…
mroki58 Aug 22, 2025
3374b5b
- Moved test files for UI to webapp folder
mroki58 Aug 22, 2025
8643941
Merge branch 'feature/TKN/OGUI-1711/implement-overall-layout' into fe…
mroki58 Aug 22, 2025
f0700da
- Proposed session checking logic with context api and hooks.
mroki58 Aug 24, 2025
5311ebf
- Proposed Tokenization project github workflow for UI tests ( eslint…
mroki58 Aug 25, 2025
5232c19
Double import fix
mroki58 Sep 3, 2025
ef7ecfb
Test commit for checking pushing with cuurent tokenization.yml
mroki58 Sep 3, 2025
7ae3345
npm ci => npm i because of some errors in lock file
mroki58 Sep 3, 2025
b75be95
- dependencies for building application taken from dev to normal depe…
mroki58 Sep 3, 2025
8fe9693
Actions for lint-checking in backend (waiting for guys for their chan…
mroki58 Sep 3, 2025
c2f5922
Merge branch 'feature/TKN/OGUI-1724/prepare-testing-env' into feature…
mroki58 Sep 3, 2025
05f7465
Typo correct
mroki58 Sep 3, 2025
7505c32
Updating .dockerignore
mroki58 Sep 3, 2025
d473dcf
Adjust test file
mroki58 Sep 3, 2025
a2a4648
Fixed type error in sidebar.tsx - changed wrong Props type
mroki58 Sep 19, 2025
71129cc
Token panel updated with overwiew and token details pages updated. Re…
mroki58 Oct 3, 2025
8a81548
Merge remote-tracking branch 'origin/dev' into feature/TKN/OGUI-1712/…
mroki58 Nov 13, 2025
7cef0e8
Delete main.test.js
mroki58 Nov 13, 2025
6c6f428
Merge branch 'dev' into feature/TKN/OGUI-1712/token-panel-create
mroki58 Nov 13, 2025
65a6a5f
Commands translated in overview, object destructure in details.tsx
mroki58 Nov 13, 2025
d67d556
Merge remote-tracking branch 'origin/feature/TKN/OGUI-1712/token-pane…
mroki58 Nov 13, 2025
9cc4829
Linting for details and overview
mroki58 Nov 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions Tokenization/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,49 @@ import { HttpServer } from '@aliceo2/web-ui';
const http = new HttpServer({port: 8080, allow: '*'});

const fakeTokens = new Map([
[1, {tokenId: 1, validity: 'good'}],
[2, {tokenId: 2, validity: 'bad'}],
[1, {
tokenId: 1,
last4chars: 'abcd',
serviceFrom: 'Service 1',
serviceTo: 'Service 2',
exp: '2026-01-12T11:31:12',
issuer: 'central-system',
iat: '2025-10-01T10:00:00',
permissions: ['GET', 'POST']
}],
[2, {
tokenId: 2,
last4chars: 'wxyz',
serviceFrom: 'Service 3',
serviceTo: 'Service 4',
exp: '2025-11-15T08:45:30',
issuer: 'admin-portal',
iat: '2025-09-15T14:22:10',
permissions: ['GET']
}],
[3, {
tokenId: 3,
last4chars: 'efgh',
serviceFrom: 'Service 2',
serviceTo: 'Service 1',
exp: '2026-03-20T16:30:00',
issuer: 'central-system',
iat: '2025-10-02T09:15:00',
permissions: ['GET', 'POST', 'PUT', 'DELETE']
}],
[4, {
tokenId: 4,
last4chars: '1234',
serviceFrom: 'Service 1',
serviceTo: 'Service 3',
exp: '2026-02-05T12:00:00',
issuer: 'api-gateway',
iat: '2025-09-25T11:30:45',
permissions: ['GET', 'PUT']
}]
]);


const fakeLogs = new Map([
[1, []],
[2, [
Expand Down
51 changes: 51 additions & 0 deletions Tokenization/webapp/app/components/tokens/action-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @license
* Copyright 2019-2020 CERN and copyright holders of ALICE O2.
* See http://alice-o2.web.cern.ch/copyright for details of the copyright holders.
* All rights not expressly granted are reserved.
*
* This software is distributed under the terms of the GNU General Public
* License v3 (GPL Version 3), copied verbatim in the file "COPYING".
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

import React from 'react';
import { IconDelete } from '~/ui/icon';

interface DeleteDialogState {
isOpen: boolean;
tokenId: string;
}

interface ActionBlockProps {
tokenId: string;
setActionDeleteWindow: React.Dispatch<React.SetStateAction<DeleteDialogState>>;
}

/**
* Action block component that provides token actions such as delete
*/
export default function ActionBlock({ tokenId, setActionDeleteWindow }: ActionBlockProps) {
const handleDelete = () => {
setActionDeleteWindow({
isOpen: true,
tokenId: tokenId,
});
};

return (
<div>
<button
className="bg-danger btn-sm"
onClick={handleDelete}
aria-label={`Delete token ${tokenId}`}
title="Delete token"
>
<IconDelete />
</button>
</div>
);
}
10 changes: 8 additions & 2 deletions Tokenization/webapp/app/components/tokens/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
*/

export interface Token {
tokenId: number;
validity: 'good' | 'bad';
tokenId: string ;
serviceFrom: string;
serviceTo: string;
exp: string;
last4chars: string;
issuer: string;
iat: string;
permissions: string[];
}
21 changes: 19 additions & 2 deletions Tokenization/webapp/app/routes/tokens/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,26 @@ export const clientLoader = async ({ params }: Route.ClientLoaderArgs): Promise<
* @param props.loaderData.logs - Promise that resolves to the logs array
*/
export default function Details({ loaderData: { token, logs } }: Route.ComponentProps) {

const { tokenId, last4chars, issuer, iat, serviceFrom, serviceTo, exp } = token;
const expirationDate = exp.split('T').reverse().join(' - ');

const fields = [
{ label: 'Last 4 token characters', value: last4chars },
{ label: 'Issuer', value: issuer },
{ label: 'Issued at', value: iat },
{ label: 'Subject', value: serviceFrom },
{ label: 'Audience', value: serviceTo },
{ label: 'Expires at', value: expirationDate },
];

return <>
<h1>Token {token.tokenId} details</h1>
<p>The token has a {token.validity} validity.</p>
<h1>Token {tokenId} details</h1>
{fields.map((f) => (
<p key={f.label}>
{f.label}: <strong>{f.value ?? '—'}</strong>
</p>
))}
<h2>Logs</h2>
<Suspense fallback={<Spinner size={2} align={'left'} />}>
<Await resolve={logs} errorElement={<div><em>Failed to load the logs</em></div>}>
Expand Down
99 changes: 84 additions & 15 deletions Tokenization/webapp/app/routes/tokens/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import type { Token } from '../../components/tokens/token';

import { Link } from 'react-router';
import { useState } from 'react';
import { Tab } from '@mui/material';
import { Tab, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button } from '@mui/material';

import ActionBlock from '~/components/tokens/action-block';
import { useSetHeader } from '~/ui/header/headerContext';
import { TabsNavbar } from '~/ui/navbar';
import { useAuth } from '~/hooks/session';

/**
* Client loader that fetches all tokens from the API.
Expand All @@ -34,6 +36,12 @@ export const clientLoader = async (): Promise<Token[]> => {
return response.json();
};

// Interfejs stanu dla okna dialogowego usuwania tokena
interface DeleteDialogState {
isOpen: boolean;
tokenId: string;
}

// Will be changed in next PR
/**
* Table component that displays a list of tokens with their ID and validity.
Expand All @@ -42,20 +50,81 @@ export const clientLoader = async (): Promise<Token[]> => {
* @param tokens - Array of tokens to display
*/
function TokenTable({ tokens }: { tokens: Token[] }) {
return <table className={'table'}>
<thead>
<tr>
<th>ID</th>
<th>validity</th>
</tr>
</thead>
<tbody>
{tokens.map((token: Token) => <tr key={token.tokenId}>
<td><Link to={`/tokens/${token.tokenId}`}>{token.tokenId}</Link></td>
<td className={token.validity === 'bad' ? 'danger' : ''}>{token.validity}</td>
</tr>)}
</tbody>
</table>;
const theaders = ['ID', 'Service From', 'Service To', 'Expires at', 'Actions'];

// State for dialog window
const [deleteDialog, setDeleteDialog] = useState<DeleteDialogState>({
isOpen: false,
tokenId: '',
});

const auth = useAuth('admin');

// Function to handle delete confirmation -> will be updated in next PR
const handleConfirmDelete = async () => {
if (auth) {
// eslint-disable-next-line no-console
console.log('Token Deleted');
}
setDeleteDialog({ isOpen: false, tokenId: '' });
};

const handleCloseDialog = () => {
setDeleteDialog({ isOpen: false, tokenId: '' });
};

return (
<>
<table className={'table'}>
<thead>
<tr>
{theaders.map((content, index) => <th key={index}>{content}</th>)}
</tr>
</thead>
<tbody>
{tokens.map((token: Token) => (
<tr key={token.tokenId}>
<td><Link to={`/tokens/${token.tokenId}`}>{token.tokenId}</Link></td>
<td>{token.serviceFrom}</td>
<td>{token.serviceTo}</td>
<td>{token.exp.split('T').reverse().join(' - ')}</td>
<td>
<ActionBlock
tokenId={token.tokenId}
setActionDeleteWindow={setDeleteDialog}
/>
</td>
</tr>
))}
</tbody>
</table>

<Dialog
open={deleteDialog.isOpen}
onClose={handleCloseDialog}
aria-labelledby="delete-token-dialog-title"
aria-describedby="delete-token-dialog-description"
>
<DialogTitle id="delete-token-dialog-title">
Confirm Token Deletion
</DialogTitle>
<DialogContent>
<DialogContentText id="delete-token-dialog-description">
Are you sure you want to delete token with ID: {deleteDialog.tokenId}?
This action cannot be undone.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleCloseDialog} color="primary">
Cancel
</Button>
<Button onClick={handleConfirmDelete} color="error" variant="contained" autoFocus>
Delete
</Button>
</DialogActions>
</Dialog>
</>
);
}

/**
Expand Down
Loading