Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable links #84

Merged
merged 8 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
41 changes: 41 additions & 0 deletions src/app/shared-links/Components/ConfirmationDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from '@mui/material';

export const ConfirmationDialog = ({
confirmDeactivate,
confirmDialogOpen,
setConfirmDialogOpen,
}: {
confirmDeactivate: () => void;
confirmDialogOpen: boolean;
setConfirmDialogOpen: (arg: boolean) => void;
}) => {
return (
<Dialog
open={confirmDialogOpen}
onClose={() => setConfirmDialogOpen(false)}
>
<DialogTitle>Confirm Deactivation</DialogTitle>
<DialogContent>
<DialogContentText>
Are you sure you want to deactivate this link? Deactivating will
permanently disable the link, and you will need to create a new one.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setConfirmDialogOpen(false)}>Cancel</Button>
<Button onClick={confirmDeactivate} color="error" variant="contained">
Deactivate
</Button>
</DialogActions>
</Dialog>
);
};

export default ConfirmationDialog;
95 changes: 88 additions & 7 deletions src/app/shared-links/Components/LinksTable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use client';

import CalendarTodayIcon from '@mui/icons-material/CalendarToday';
import LinkOffIcon from '@mui/icons-material/LinkOff';
import {
Button,
Grid,
Expand All @@ -11,6 +13,12 @@ import {
TableHead,
TablePagination,
TableRow,
Tooltip,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from '@mui/material';
import { useEffect, useState } from 'react';
import React from 'react';
Expand All @@ -20,6 +28,7 @@ import { SHLinkMiniDto } from '@/domain/dtos/shlink';

import { AddLinkDialog } from './AddLinkDialog';
import BooleanIcon from './BooleanIcon';
import ConfirmationDialog from './ConfirmationDialog';

interface Column {
id: keyof SHLinkMiniDto;
Expand All @@ -31,6 +40,22 @@ interface Column {
) => string | React.JSX.Element;
}

interface IActionColumn extends Omit<Column, 'id' | 'label'> {
id: 'action';
label: React.JSX.Element;
action: (id: string) => void;
}

const createActionColumn = (
label: React.JSX.Element,
action: (id: string) => void,
): IActionColumn => ({
id: 'action',
label,
minWidth: 50,
action,
});

const columns: readonly Column[] = [
{ id: 'name', label: 'Name', minWidth: 100 },
{
Expand Down Expand Up @@ -60,14 +85,45 @@ export default function LinksTable() {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [addDialog, setAddDialog] = React.useState<boolean>();
const [refetch, setRefetch] = useState(false);

const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
const [selectedLinkId, setSelectedLinkId] = useState<string | null>(null);

const handleChangePage = (_event: unknown, newPage: number) => {
setPage(newPage);
};

const handleDeactivate = async (id: string) => {
setSelectedLinkId(id);
setConfirmDialogOpen(true);
};

const confirmDeactivate = async () => {
if (selectedLinkId) {
try {
await apiSharedLink.deactivateLink(selectedLinkId);
setRefetch(!refetch);
setConfirmDialogOpen(false);
} catch (error) {
console.error('Failed to deactivate link:', error);
}
}
};

const actionColumn: IActionColumn[] = [
createActionColumn(<LinkOffIcon />, handleDeactivate),
// TODO: Other actions will be added
];

const fetchLinks = async () => {
const { data } = await apiSharedLink.findLinks();
setLinks(data);
};

useEffect(() => {
apiSharedLink.findLinks().then(({ data }) => setLinks(data));
}, []);
fetchLinks();
}, [refetch]);

const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement>,
Expand All @@ -80,6 +136,8 @@ export default function LinksTable() {
setAddDialog(true);
};

const combinedCols = [...columns, ...actionColumn];

return (
<Paper sx={{ width: '100%', overflow: 'hidden' }}>
<AddLinkDialog
Expand Down Expand Up @@ -112,20 +170,37 @@ export default function LinksTable() {
{column.label}
</TableCell>
))}
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{links
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => (
<TableRow hover tabIndex={-1} key={row.id}>
{columns.map((column) => {
{combinedCols.map((column) => {
const value = row[column.id];
return (
<TableCell key={column.id} align={column.align}>
{column.format
? column.format(value)
: value?.toString()}
<TableCell
key={column.id + row.active}
align={column.align}
>
{column.id === 'action' ? (
<Tooltip title="Deactivate">
<span>
<Button
disabled={!row.active}
onClick={() => column.action(row.id)}
>
{column.label}
</Button>
</span>
</Tooltip>
) : column.format ? (
column.format(value)
) : (
value?.toString()
)}
</TableCell>
);
})}
Expand All @@ -143,6 +218,12 @@ export default function LinksTable() {
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>

<ConfirmationDialog
confirmDeactivate={confirmDeactivate}
confirmDialogOpen={confirmDialogOpen}
setConfirmDialogOpen={setConfirmDialogOpen}
/>
</Paper>
);
}
4 changes: 4 additions & 0 deletions src/app/utils/api.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export class ApiSHLink extends BaseApi {
return await this.create({ url: `/${EEndpoint.shareLinks}`, data });
}

async deactivateLink(id: string) {
return await this.delete({ url: `/share-links/${id}/deactivate` });
}

async getPatientData(userId: string) {
return await this.find({
url: `/users/${userId}/ips`,
Expand Down
2 changes: 1 addition & 1 deletion src/domain/dtos/shlink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export class SHLinkMiniDto {
passwordRequired?: boolean;
name: string;
url: string;
active: boolean
active: boolean;
}

/**
Expand Down
Loading