feat: tag design for status and channels in feed table

This commit is contained in:
Corban-Lee Jones 2025-04-28 10:33:55 +01:00
parent 336484c13a
commit 1edc1d4016

View File

@ -45,7 +45,7 @@ const columnDefs: ConfigColumnDefs[] = [
target: 0,
orderable: false,
searchable: false,
render(_data: unknown, _type: unknown, row: any) { return `
render: (_data: unknown, _type: unknown, row: any) => { return `
<td class="size-px whitespace-nowrap">
<div class="ps-6 py-4">
<label class="rowSelect${row.id}-js" class="flex">
@ -61,7 +61,7 @@ const columnDefs: ConfigColumnDefs[] = [
data: "name",
orderable: true,
searchable: true,
render(data: string) { return `
render: (data: string) => { return `
<td class="size-px whitespace-nowrap align-top">
<span class="cj-table-link">
${data}
@ -74,7 +74,7 @@ const columnDefs: ConfigColumnDefs[] = [
data: "url",
orderable: true,
searchable: true,
render(data: string) { return `
render: (data: string) => { return `
<td class="size-px whitespace-nowrap align-top">
<span class="cj-table-link">
${data}
@ -87,8 +87,44 @@ const columnDefs: ConfigColumnDefs[] = [
data: "channels",
orderable: false,
searchable: false,
render(data: string) {
return `${data}`
render: (data: Array<any>, type: string, row: any) => {
if (type !== "display") { return data; }
if (!data.length) { return ""; }
const wrapper = $("<div>").addClass("flex flex-nowrap gap-1 px-6 py-4");
const tag = $("<span>").addClass("inline-flex items-center whitespace-nowrap gap-1 py-1 px-2.5 border text-xs rounded-md bg-white dark:bg-neutral-800 border-gray-200 dark:border-neutral-700 text-gray-800 dark:text-neutral-200");
const firstChannelName = data[0].channel_id; // "# " + channels.find(c => c.id === data[0]).name;
wrapper.append(tag.clone().text(firstChannelName));
// No need to run the dropdown code if there's no more to show
if (data.length === 1) {
return wrapper.get(0);
}
else if (data.length <= 2) {
const secondChannelName = data[1].channel_id; // "# " + channels.find(c => c.id === data[1]).name;
wrapper.append(tag.clone().text(secondChannelName));
data.shift();
return wrapper.get(0);
}
// drop the first element to exclude it from the dropdown
data.shift();
const dropdown = $("<div>").addClass("hs-dropdown inline-block");
const dropdownBtn = $("<button>").attr("id", `channelDrop-${row.id}`).attr("type", "button").addClass("cursor-pointer inline-flex items-center gap-1 py-1 px-2.5 border text-xs rounded-md bg-white dark:bg-neutral-800 border-gray-200 dark:border-neutral-700 text-gray-800 dark:text-neutral-200");
const dropdownMenu = $("<div>").addClass("hs-dropdown-menu hidden opacity-0 hs-dropdown-open:opacity-100 transition-[opacity,margin] overflow-hidden z-10 w-fit max-w-64 border p-2 rounded-md bg-gray-200 dark:bg-neutral-700 border-gray-300 dark:border-neutral-600");
dropdown.append(dropdownBtn.text(`+${data.length}`));
data.forEach(channel => {
const channelName = channel.channel_id; // "# " + channels.find(c => c.id === channelId).name;
dropdownMenu.append(tag.clone().text(channelName));
});
dropdown.append(dropdownMenu);
wrapper.append(dropdown);
return wrapper.get(0);
}
},
{
@ -96,7 +132,7 @@ const columnDefs: ConfigColumnDefs[] = [
data: "filters",
orderable: false,
searchable: false,
render(data: string) { return `
render: (data: string) => { return `
<td class="size-px whitespace-nowrap align-top">
<div class="px-6 py-4">
<span class="cj-table-text">
@ -111,7 +147,7 @@ const columnDefs: ConfigColumnDefs[] = [
data: "message_style",
orderable: false, // both should be true, but message_style doesnt exist yet
searchable: false,
render(data: string) { return `
render: (data: string) => { return `
<td class="size-px whitespace-nowrap align-top">
<div class="px-6 py-4">
<span class="cj-table-text">
@ -126,7 +162,7 @@ const columnDefs: ConfigColumnDefs[] = [
data: "created_at",
orderable: true,
searchable: false,
render(data: string) { return `
render: (data: string) => { return `
<td class="size-px whitespace-nowrap align-top">
<div class="px-6 py-4">
<span class="cj-table-text">
@ -141,15 +177,24 @@ const columnDefs: ConfigColumnDefs[] = [
data: "active",
orderable: true,
searchable: false,
render(data: string) { return `
<td class="size-px whitespace-nowrap align-top">
<div class="px-6 py-4">
<span class="cj-table-text">
${data}
</span>
</div>
</td>
`}
render: (data: boolean) => {
const wrapper = $("<div>").addClass("px-6 py-4");
const badge = $("<span>").addClass("py-1 px-1.5 inline-flex items-center gap-x-1 text-xs font-medium rounded-full");
const label = $("<span>");
if (data) {
badge.addClass("bg-teal-100 text-teal-800 dark:bg-teal-500/10 dark:text-teal-500");
badge.append($('<svg class="size-2.5" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/></svg>'))
.append(label.text("Active"));
} else {
badge.addClass("bg-red-100 text-red-800 dark:bg-red-500/10 dark:text-red-500");
badge.append($('<svg class="size-2.5" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z"/></svg>'))
.append(label.text("Inactive"));
}
wrapper.append(badge);
return wrapper.get(0);
}
}
];