import { canManage } from "../lib/access.ts";
import { escapeHtml } from "../lib/html.ts";
import { t } from "../lib/i18n/index.ts";
import type { ProfileInfo } from "../lib/profile.ts";
import { profileUrl, settingsUrl } from "../lib/urls.ts";
import type { MembershipRow } from "../server/db/queries/index.ts";
import { type LayoutOptions, layout } from "./layout.ts";
import { outlineSmallButtonClass, THEME } from "./theme/index.ts";
function renderMemberCard(
m: MembershipRow,
wikiDid: string,
profile: ProfileInfo | undefined,
roleLabel: (role: string) => string,
): string {
const isOwner = m.did === wikiDid;
const role = isOwner ? "owner" : m.role;
const handle = profile?.handle ?? null;
const displayName = profile?.displayName ?? null;
const href = profileUrl(handle ?? m.did);
const avatar = profile?.avatar
? `
`
: `
`;
const nameLine = displayName
? `${escapeHtml(displayName)}`
: "";
const handleLine = handle
? `@${escapeHtml(handle)}`
: `${escapeHtml(m.did.slice(0, 24))}…`;
return `
${avatar}
${nameLine}
${handleLine}
${escapeHtml(roleLabel(role))}
`;
}
export function membersPage(
wikiName: string,
wikiDid: string,
members: MembershipRow[],
profiles: Map,
options: LayoutOptions,
): string {
const locale = options.locale ?? "en";
const msg = t(locale);
const roleLabel = (role: string) =>
({
admin: msg.access.roleAdmin,
contributor: msg.access.roleContributor,
viewer: msg.access.roleViewer,
owner: msg.access.roleOwner,
})[role] ?? role;
// Owner, then admins, then contributors; viewers are excluded upstream.
const rolePriority: Record = {
admin: 1,
contributor: 2,
};
const sorted = [...members].sort((a, b) => {
const aOwner = a.did === wikiDid ? 0 : (rolePriority[a.role] ?? 3);
const bOwner = b.did === wikiDid ? 0 : (rolePriority[b.role] ?? 3);
if (aOwner !== bOwner) return aOwner - bOwner;
return a.created_at.localeCompare(b.created_at);
});
const cards = sorted
.map((m) => renderMemberCard(m, wikiDid, profiles.get(m.did), roleLabel))
.join("\n");
const body =
sorted.length > 0
? `${cards}
`
: `${msg.access.noMembers}
`;
// Admins manage members in wiki settings; this directory links there.
const handle = options.ownerHandle ?? "";
const slug = options.wikiSlug ?? "";
const manageLink =
handle && slug && canManage(options.accessLevel ?? "none")
? `${msg.access.manageMembers}`
: "";
return layout(
`${msg.access.members} — ${wikiName}`,
`
${msg.access.members}
${manageLink}
${body}
`,
options,
);
}