Table.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { IconDotsVertical, IconEdit, IconTrash } from "@tabler/icons-react";
  2. import { createColumnHelper, getCoreRowModel, useReactTable } from "@tanstack/react-table";
  3. import { useMemo } from "react";
  4. import type { AccessList } from "src/api/backend";
  5. import { EmptyData, GravatarFormatter, HasPermission, ValueWithDateFormatter } from "src/components";
  6. import { TableLayout } from "src/components/Table/TableLayout";
  7. import { intl, T } from "src/locale";
  8. import { ACCESS_LISTS, MANAGE } from "src/modules/Permissions";
  9. interface Props {
  10. data: AccessList[];
  11. isFiltered?: boolean;
  12. isFetching?: boolean;
  13. onEdit?: (id: number) => void;
  14. onDelete?: (id: number) => void;
  15. onNew?: () => void;
  16. }
  17. export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, onNew }: Props) {
  18. const columnHelper = createColumnHelper<AccessList>();
  19. const columns = useMemo(
  20. () => [
  21. columnHelper.accessor((row: any) => row.owner, {
  22. id: "owner",
  23. cell: (info: any) => {
  24. const value = info.getValue();
  25. return <GravatarFormatter url={value ? value.avatar : ""} name={value ? value.name : ""} />;
  26. },
  27. meta: {
  28. className: "w-1",
  29. },
  30. }),
  31. columnHelper.accessor((row: any) => row, {
  32. id: "name",
  33. header: intl.formatMessage({ id: "column.name" }),
  34. cell: (info: any) => (
  35. <ValueWithDateFormatter value={info.getValue().name} createdOn={info.getValue().createdOn} />
  36. ),
  37. }),
  38. columnHelper.accessor((row: any) => row.items, {
  39. id: "items",
  40. header: intl.formatMessage({ id: "column.authorization" }),
  41. cell: (info: any) => <T id="access-list.auth-count" data={{ count: info.getValue().length }} />,
  42. }),
  43. columnHelper.accessor((row: any) => row.clients, {
  44. id: "clients",
  45. header: intl.formatMessage({ id: "column.access" }),
  46. cell: (info: any) => <T id="access-list.access-count" data={{ count: info.getValue().length }} />,
  47. }),
  48. columnHelper.accessor((row: any) => row.satisfyAny, {
  49. id: "satisfyAny",
  50. header: intl.formatMessage({ id: "column.satisfy" }),
  51. cell: (info: any) => <T id={info.getValue() ? "column.satisfy-any" : "column.satisfy-all"} />,
  52. }),
  53. columnHelper.accessor((row: any) => row.proxyHostCount, {
  54. id: "proxyHostCount",
  55. header: intl.formatMessage({ id: "proxy-hosts" }),
  56. cell: (info: any) => <T id="proxy-hosts.count" data={{ count: info.getValue() }} />,
  57. }),
  58. columnHelper.display({
  59. id: "id",
  60. cell: (info: any) => {
  61. return (
  62. <span className="dropdown">
  63. <button
  64. type="button"
  65. className="btn dropdown-toggle btn-action btn-sm px-1"
  66. data-bs-boundary="viewport"
  67. data-bs-toggle="dropdown"
  68. >
  69. <IconDotsVertical />
  70. </button>
  71. <div className="dropdown-menu dropdown-menu-end">
  72. <span className="dropdown-header">
  73. <T
  74. id="object.actions-title"
  75. tData={{ object: "access-list" }}
  76. data={{ id: info.row.original.id }}
  77. />
  78. </span>
  79. <a
  80. className="dropdown-item"
  81. href="#"
  82. onClick={(e) => {
  83. e.preventDefault();
  84. onEdit?.(info.row.original.id);
  85. }}
  86. >
  87. <IconEdit size={16} />
  88. <T id="action.edit" />
  89. </a>
  90. <HasPermission section={ACCESS_LISTS} permission={MANAGE} hideError>
  91. <div className="dropdown-divider" />
  92. <a
  93. className="dropdown-item"
  94. href="#"
  95. onClick={(e) => {
  96. e.preventDefault();
  97. onDelete?.(info.row.original.id);
  98. }}
  99. >
  100. <IconTrash size={16} />
  101. <T id="action.delete" />
  102. </a>
  103. </HasPermission>
  104. </div>
  105. </span>
  106. );
  107. },
  108. meta: {
  109. className: "text-end w-1",
  110. },
  111. }),
  112. ],
  113. [columnHelper, onEdit, onDelete],
  114. );
  115. const tableInstance = useReactTable<AccessList>({
  116. columns,
  117. data,
  118. getCoreRowModel: getCoreRowModel(),
  119. rowCount: data.length,
  120. meta: {
  121. isFetching,
  122. },
  123. enableSortingRemoval: false,
  124. });
  125. return (
  126. <TableLayout
  127. tableInstance={tableInstance}
  128. emptyState={
  129. <EmptyData
  130. object="access-list"
  131. objects="access-lists"
  132. tableInstance={tableInstance}
  133. onNew={onNew}
  134. isFiltered={isFiltered}
  135. color="cyan"
  136. permissionSection={ACCESS_LISTS}
  137. />
  138. }
  139. />
  140. );
  141. }