Migrate servers table to a tailwind-based Table component

This commit is contained in:
Alejandro Celaya
2025-04-02 09:01:33 +02:00
parent 06fac716d1
commit c9ada8f41d
3 changed files with 34 additions and 36 deletions

View File

@@ -7,5 +7,5 @@ export type NoMenuLayoutProps = PropsWithChildren & {
}; };
export const NoMenuLayout: FC<NoMenuLayoutProps> = ({ children, className }) => ( export const NoMenuLayout: FC<NoMenuLayoutProps> = ({ children, className }) => (
<div className={clsx('no-menu-wrapper container-xl', className)}>{children}</div> <div className={clsx('no-menu-wrapper tw:container tw:mx-auto', className)}>{children}</div>
); );

View File

@@ -1,7 +1,7 @@
import { faFileDownload as exportIcon, faPlus as plusIcon } from '@fortawesome/free-solid-svg-icons'; import { faFileDownload as exportIcon, faPlus as plusIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit'; import type { TimeoutToggle } from '@shlinkio/shlink-frontend-kit';
import { Button, Result, SearchInput, SimpleCard } from '@shlinkio/shlink-frontend-kit/tailwind'; import { Button, Result, SearchInput, SimpleCard, Table } from '@shlinkio/shlink-frontend-kit/tailwind';
import type { FC } from 'react'; import type { FC } from 'react';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { NoMenuLayout } from '../common/NoMenuLayout'; import { NoMenuLayout } from '../common/NoMenuLayout';
@@ -43,40 +43,37 @@ const ManageServers: FCWithDeps<ManageServersProps, ManageServersDeps> = ({ serv
const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME); const [errorImporting, setErrorImporting] = useTimeoutToggle(false, SHOW_IMPORT_MSG_TIME);
return ( return (
<NoMenuLayout className="d-flex flex-column gap-3"> <NoMenuLayout className="tw:flex tw:flex-col tw:gap-y-4">
<SearchInput onChange={setSearchTerm} /> <SearchInput onChange={setSearchTerm} />
<div className="d-flex flex-column flex-md-row gap-2"> <div className="tw:flex tw:flex-col tw:md:flex-row tw:gap-2">
<div className="d-flex gap-2"> <div className="tw:flex tw:gap-2">
<ImportServersBtn className="flex-fill" onImportError={setErrorImporting}>Import servers</ImportServersBtn> <ImportServersBtn className="tw:flex-grow" onImportError={setErrorImporting}>Import servers</ImportServersBtn>
{filteredServers.length > 0 && ( {filteredServers.length > 0 && (
<Button variant="secondary" className="flex-fill" onClick={async () => serversExporter.exportServers()}> <Button variant="secondary" className="tw:flex-grow" onClick={async () => serversExporter.exportServers()}>
<FontAwesomeIcon icon={exportIcon} fixedWidth /> Export servers <FontAwesomeIcon icon={exportIcon} /> Export servers
</Button> </Button>
)} )}
</div> </div>
<Button className="ms-md-auto" to="/server/create"> <Button className="tw:md:ml-auto" to="/server/create">
<FontAwesomeIcon icon={plusIcon} fixedWidth /> Add a server <FontAwesomeIcon icon={plusIcon} /> Add a server
</Button> </Button>
</div> </div>
<SimpleCard> <SimpleCard className="card">
<table className="table table-hover responsive-table mb-0"> <Table header={(
<thead className="responsive-table__header"> <Table.Row>
<tr> {hasAutoConnect && <Table.Cell style={{ width: '50px' }}><span className="sr-only">Auto-connect</span></Table.Cell>}
{hasAutoConnect && <th style={{ width: '50px' }}><span className="sr-only">Auto-connect</span></th>} <Table.Cell>Name</Table.Cell>
<th>Name</th> <Table.Cell>Base URL</Table.Cell>
<th>Base URL</th> <Table.Cell><span className="sr-only">Options</span></Table.Cell>
<th><span className="sr-only">Options</span></th> </Table.Row>
</tr> )}>
</thead> {!filteredServers.length && <Table.Row className="text-center"><Table.Cell colSpan={4}>No servers found.</Table.Cell></Table.Row>}
<tbody>
{!filteredServers.length && <tr className="text-center"><td colSpan={4}>No servers found.</td></tr>}
{filteredServers.map((server) => ( {filteredServers.map((server) => (
<ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} /> <ManageServersRow key={server.id} server={server} hasAutoConnect={hasAutoConnect} />
))} ))}
</tbody> </Table>
</table>
</SimpleCard> </SimpleCard>
{errorImporting && ( {errorImporting && (

View File

@@ -1,5 +1,6 @@
import { faCheck as checkIcon } from '@fortawesome/free-solid-svg-icons'; import { faCheck as checkIcon } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Table } from '@shlinkio/shlink-frontend-kit/tailwind';
import type { FC } from 'react'; import type { FC } from 'react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import { UncontrolledTooltip } from 'reactstrap'; import { UncontrolledTooltip } from 'reactstrap';
@@ -21,9 +22,9 @@ const ManageServersRow: FCWithDeps<ManageServersRowProps, ManageServersRowDeps>
const { ManageServersRowDropdown } = useDependencies(ManageServersRow); const { ManageServersRowDropdown } = useDependencies(ManageServersRow);
return ( return (
<tr className="responsive-table__row"> <Table.Row className="tw:relative">
{hasAutoConnect && ( {hasAutoConnect && (
<td className="responsive-table__cell" data-th="Auto-connect"> <Table.Cell columnName="Auto-connect">
{server.autoConnect && ( {server.autoConnect && (
<> <>
<FontAwesomeIcon icon={checkIcon} className="text-primary" id="autoConnectIcon" /> <FontAwesomeIcon icon={checkIcon} className="text-primary" id="autoConnectIcon" />
@@ -32,16 +33,16 @@ const ManageServersRow: FCWithDeps<ManageServersRowProps, ManageServersRowDeps>
</UncontrolledTooltip> </UncontrolledTooltip>
</> </>
)} )}
</td> </Table.Cell>
)} )}
<th className="responsive-table__cell" data-th="Name"> <Table.Cell className="tw:font-bold" columnName="Name">
<Link to={`/server/${server.id}`}>{server.name}</Link> <Link to={`/server/${server.id}`}>{server.name}</Link>
</th> </Table.Cell>
<td className="responsive-table__cell" data-th="Base URL">{server.url}</td> <Table.Cell columnName="Base URL" className="tw:max-lg:border-b-0">{server.url}</Table.Cell>
<td className="responsive-table__cell text-end"> <Table.Cell className="tw:text-right tw:max-lg:absolute tw:right-0 tw:-top-1 tw:mx-lg:pt-0">
<ManageServersRowDropdown server={server} /> <ManageServersRowDropdown server={server} />
</td> </Table.Cell>
</tr> </Table.Row>
); );
}; };