feat: patch existing feeds

This commit is contained in:
Corban-Lee Jones 2025-05-01 12:32:32 +01:00
parent 23ca09b4a2
commit 84772852e3
2 changed files with 92 additions and 11 deletions

View File

@ -33,7 +33,7 @@ const emptyTableHtml: string = `
</p>
<div class="mt-5 flex flex-col sm:flex-row gap-2">
<button type="button" class="open-edit-modal-js py-2 px-3 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-hidden focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#TODO">
<button type="button" class="open-edit-modal-js py-2 px-3 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-hidden focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
<svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
Create a feed
</button>
@ -66,8 +66,8 @@ const columnDefs: ConfigColumnDefs[] = [
orderable: true,
searchable: true,
className: "size-px whitespace-nowrap",
render: (data: string) => { return `
<span class="cj-table-link max-w-[250px] truncate">
render: (data: string, _type: string, row: prisma.Feed) => { return `
<span class="cj-table-link open-edit-modal-js max-w-[250px] truncate" data-id="${row.id}">
${data}
</span>
`}
@ -294,12 +294,49 @@ const editModal: HSOverlay = new HSOverlay(
editModalOptions
);
$(document).on("click", ".open-edit-modal-js", async () => {
await openEditModal(-1);
$(document).on("click", ".open-edit-modal-js", async event => {
await openEditModal($(event.target).data("id"));
});
const openEditModal = async (id: number) => {
interface FeedWithChannels extends prisma.Feed {
channels: prisma.Channel[]
}
const clearEditModalData = () => {
$(editModal.el).data("id", undefined);
$("#formName").val("");
$("#formUrl").val("");
$("#formActive").prop("checked", true);
channelSelect.setValue([]);
};
const loadEditModalData = async (id: number) => {
const feed: FeedWithChannels = await ajax({
url: `/guild/${guildId}/feeds/api?id=${id}`,
method: "get"
});
$(editModal.el).data("id", feed.id);
$("#formName").val(feed.name);
$("#formUrl").val(feed.url);
$("#formActive").prop("checked", feed.active);
channelSelect.setValue(feed.channels.map(channel => channel.channel_id));
}
const openEditModal = async (id: number | undefined) => {
// ISSUE:
// The calculation with `channelSelect.setValue([])` assumes components are visible
// when determining the width of the input placeholder 'Select option...'. This
// requires the modal to be opened before running the calculation, which could be
// bad.
editModal.open();
id === undefined
? clearEditModalData()
: loadEditModalData(id);
};
const closeEditModal = () => {
@ -356,11 +393,23 @@ $("#editForm").on("submit", async event => {
if (!form.checkValidity()) return;
let method = "post";
const data = $(event.target).serializeArray();
const id: number | undefined = $(editModal.el).data("id");
if (id !== undefined) {
data.push({
name: "id",
value: `${id}`
})
method = "patch";
}
await $.ajax({
url: `/guild/${guildId}/feeds/api`,
method: "post",
dataType: "json",
data: $(event.target).serializeArray(),
method: method,
data: data,
success: () => {
(table as any).dataTable.draw() // is this okay? dataTable is private, but there is no other method I know of to redraw...
closeEditModal();

View File

@ -34,7 +34,7 @@ export const post = async (request: Request, response: Response) => {
try {
feed = await prisma.feed.create({
data: {
data: {
name: name,
url: url,
guild_id: guildId,
@ -54,7 +54,39 @@ export const post = async (request: Request, response: Response) => {
response.status(201).json(feed);
};
export const patch = async () => {} // TODO ...
export const patch = async (request: Request, response: Response) => {
const guildId = request.params.guildId;
const { id, name, url, active, channels } = request.body;
// channels comes through as either String[] or String
const formattedChannels = Array.isArray(channels)
? channels.map((channelId) => ({ channel_id: channelId }))
: [{ channel_id: channels }]
let feed;
try {
feed = await prisma.feed.update({
where: { id: Number(id) },
data: {
name: name,
url: url,
guild_id: guildId,
active: active === "on",
channels: channels !== undefined ? { create: formattedChannels } : channels
}
});
}
catch (error) {
console.error(error);
if (error instanceof Prisma.PrismaClientKnownRequestError) {
response.status(500).json({ error: error.message });
return;
}
}
response.status(201).json(feed);
}
export const del = async (request: Request, response: Response) => {
const { ids } = request.body;
@ -87,7 +119,7 @@ export const datatable = async (request: Request, response: Response) => {
request,
response,
prisma.feed,
{ id: "asc" },
[{ updated_at: "desc" }, { id: "asc" }],
{ channels: true, filters: true },
{ guild_id: request.params.guildId } // TODO: verify authenticated user can access this guild
);