124 lines
4.6 KiB
TypeScript
124 lines
4.6 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import { Link } from "react-router";
|
|
import { EntityWithCount } from "~/utils/db/entities/entities.db.server";
|
|
import SimpleBadge from "../ui/badges/SimpleBadge";
|
|
import { Colors } from "~/application/enums/shared/Colors";
|
|
import TableSimple from "../ui/tables/TableSimple";
|
|
import RelationshipHelper from "~/utils/helpers/RelationshipHelper";
|
|
import OrderListButtons from "../ui/sort/OrderListButtons";
|
|
import { useEffect, useState } from "react";
|
|
import { RowHeaderDisplayDto } from "~/application/dtos/data/RowHeaderDisplayDto";
|
|
import { useAppOrAdminData } from "~/utils/data/useAppOrAdminData";
|
|
import { adminPath } from "~/utils/app/CanonicalUrlUtils";
|
|
import { translateEntityTitlePlural, translatePropertyTitle } from "~/utils/i18n/translateLabel";
|
|
|
|
interface Props {
|
|
items: EntityWithCount[];
|
|
selected?: EntityWithCount[];
|
|
onSelected?: (items: EntityWithCount[]) => void;
|
|
}
|
|
|
|
export default function EntitiesTable({ items, selected, onSelected }: Props) {
|
|
const appOrAdminData = useAppOrAdminData();
|
|
const { t, i18n } = useTranslation();
|
|
|
|
const [headers, setHeaders] = useState<RowHeaderDisplayDto<EntityWithCount>[]>([]);
|
|
useEffect(() => {
|
|
const headers: RowHeaderDisplayDto<EntityWithCount>[] = [
|
|
{
|
|
name: "type",
|
|
title: t("models.entity.type"),
|
|
value: (item) => (
|
|
<SimpleBadge
|
|
title={item.type === "all" ? "app-and-admin" : item.type}
|
|
color={item.type === "app" ? Colors.BLUE : item.type === "admin" ? Colors.GRAY : Colors.EMERALD}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: t("shared.order"),
|
|
name: "order",
|
|
value: (item) => item.order,
|
|
formattedValue: (_, idx) => <OrderListButtons index={idx} items={items} />,
|
|
},
|
|
{
|
|
name: "title",
|
|
title: t("models.entity.title"),
|
|
value: (item) => (
|
|
<div className="flex items-center space-x-1">
|
|
<Link to={adminPath("entities/" + item.slug + "/details", { mode: "host-aware" })} className="font-medium hover:underline">
|
|
{translateEntityTitlePlural(t, i18n, item)}
|
|
</Link>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
name: "properties",
|
|
title: t("models.property.plural"),
|
|
className: "w-full text-xs",
|
|
value: (item) => (
|
|
<div className="max-w-xs truncate">
|
|
{item.properties.filter((f) => !f.isDefault).length > 0 ? (
|
|
<Link className="truncate pb-1 hover:underline" to={adminPath("entities/" + item.slug + "/properties", { mode: "host-aware" })}>
|
|
{item.properties
|
|
.filter((f) => !f.isDefault)
|
|
.map((f) => translatePropertyTitle(t, i18n, item.name, f) + (f.isRequired ? "*" : ""))
|
|
.join(", ")}
|
|
</Link>
|
|
) : (
|
|
<Link className="text-muted-foreground truncate pb-1 hover:underline" to={adminPath("entities/" + item.slug + "/properties", { mode: "host-aware" })}>
|
|
{t("shared.setCustomProperties")}
|
|
</Link>
|
|
)}
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
name: "relationships",
|
|
title: t("models.relationship.plural"),
|
|
value: (item) => (
|
|
<Link className="truncate pb-1 hover:underline" to={adminPath("entities/" + item.slug + "/relationships", { mode: "host-aware" })}>
|
|
{[...item.parentEntities, ...item.childEntities]
|
|
.map((relationship) => t(RelationshipHelper.getTitleWithName({ fromEntityId: item.id, relationship })))
|
|
.join(", ")}
|
|
</Link>
|
|
),
|
|
className: "text-xs",
|
|
},
|
|
{
|
|
name: "rows",
|
|
title: t("models.row.plural"),
|
|
value: (item) => (
|
|
<Link to={adminPath("entities/" + item.slug + "/rows", { mode: "host-aware" })} className="hover:underline">
|
|
{item._count.rows}
|
|
</Link>
|
|
),
|
|
},
|
|
];
|
|
|
|
setHeaders(headers);
|
|
}, [appOrAdminData.tenantTypes, items, t]);
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<TableSimple
|
|
selectedRows={selected}
|
|
onSelected={onSelected}
|
|
items={items}
|
|
actions={[
|
|
{
|
|
title: t("models.entity.noCode.menu"),
|
|
onClickRoute: (_, item) => adminPath(`entities/${item.slug}/no-code`, { mode: "host-aware" }),
|
|
disabled: (i) => !i.isAutogenerated,
|
|
},
|
|
{
|
|
title: t("shared.edit"),
|
|
onClickRoute: (_, item) => adminPath(`entities/${item.slug}/details`, { mode: "host-aware" }),
|
|
},
|
|
]}
|
|
headers={headers}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|