This commit is contained in:
parent
0dd928b8f4
commit
d5af04c317
@ -243,7 +243,7 @@
|
|||||||
@apply
|
@apply
|
||||||
z-80
|
z-80
|
||||||
w-full
|
w-full
|
||||||
min-h-[100px]
|
min-h-fit
|
||||||
max-h-72
|
max-h-72
|
||||||
p-1.5
|
p-1.5
|
||||||
space-y-0.5
|
space-y-0.5
|
||||||
|
@ -177,17 +177,23 @@ const columnDefs: ConfigColumnDefs[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
target: 5,
|
target: 5,
|
||||||
data: "message_style",
|
data: null, // "message_style_id"
|
||||||
orderable: false, // both should be true, but message_style doesnt exist yet
|
orderable: false,
|
||||||
searchable: false,
|
searchable: false,
|
||||||
className: "size-px whitespace-nowrap",
|
className: "size-px whitespace-nowrap",
|
||||||
render: (data: string) => { return `
|
render: (_data: unknown, type: string, row: any) => {
|
||||||
<div class="px-6 py-4">
|
if (!row.message_style || type !== "display") return null;
|
||||||
<span class="cj-table-text">
|
|
||||||
${data}
|
const wrapper = $("<div>").addClass("flex px-6 py-4");
|
||||||
</span>
|
const badge = $("<span>").addClass("inline-flex items-center whitespace-nowrap border rounded-md bg-white dark:bg-neutral-800 border-gray-200 dark:border-neutral-700 overflow-hidden");
|
||||||
</div>
|
const colour = $("<span>").addClass("size-6 shrink-0").css("background-color", row.message_style.colour);
|
||||||
`}
|
const label = $("<span>").addClass("py-1 px-2.5 text-xs text-gray-800 dark:text-neutral-200");
|
||||||
|
label.text(row.message_style.name);
|
||||||
|
|
||||||
|
badge.append(colour).append(label);
|
||||||
|
wrapper.append(badge);
|
||||||
|
return wrapper.get(0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
target: 6,
|
target: 6,
|
||||||
@ -381,6 +387,7 @@ const clearEditModalData = () => {
|
|||||||
$("#formActive").prop("checked", true);
|
$("#formActive").prop("checked", true);
|
||||||
channelSelect.setValue([]);
|
channelSelect.setValue([]);
|
||||||
filterSelect.setValue([]);
|
filterSelect.setValue([]);
|
||||||
|
styleSelect.setValue("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadEditModalData = async (id: number) => {
|
const loadEditModalData = async (id: number) => {
|
||||||
@ -397,6 +404,7 @@ const loadEditModalData = async (id: number) => {
|
|||||||
|
|
||||||
channelSelect.setValue(feed.channels.map(channel => channel.channel_id));
|
channelSelect.setValue(feed.channels.map(channel => channel.channel_id));
|
||||||
filterSelect.setValue(feed.filters.map(filter => `${filter.id}`));
|
filterSelect.setValue(feed.filters.map(filter => `${filter.id}`));
|
||||||
|
styleSelect.setValue(`${feed.message_style_id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const openEditModal = async (id: number | undefined) => {
|
const openEditModal = async (id: number | undefined) => {
|
||||||
@ -525,6 +533,45 @@ const filterSelect = new HSSelect(
|
|||||||
filterSelectOptions
|
filterSelectOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const styleSelectOptions: ISelectOptions = {
|
||||||
|
placeholder: "Select option...",
|
||||||
|
|
||||||
|
toggleTag: '<button type="button" aria-expanded="false"><span data-title></span></button>',
|
||||||
|
optionTemplate: `
|
||||||
|
<div class="flex justify-between items-center w-full">
|
||||||
|
<span data-title></span>
|
||||||
|
<span class="hidden hs-selected:block">
|
||||||
|
<svg class="shrink-0 size-3.5 text-blue-600 dark:text-blue-500" xmlns="http:.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"><polyline points="20 6 9 17 4 12"/></svg>
|
||||||
|
</span>
|
||||||
|
</div>`,
|
||||||
|
toggleClasses: "cj-select-toggle select-input",
|
||||||
|
optionClasses: "cj-select-option",
|
||||||
|
dropdownClasses: "cj-select-dropdown",
|
||||||
|
wrapperClasses: "peer",
|
||||||
|
dropdownSpace: 10,
|
||||||
|
dropdownScope: "parent",
|
||||||
|
dropdownPlacement: "top",
|
||||||
|
dropdownVerticalFixedPlacement: null,
|
||||||
|
|
||||||
|
apiUrl: `/guild/${guildId}/styles/api/select`,
|
||||||
|
// apiQuery: "limit=15",
|
||||||
|
apiFieldsMap: {
|
||||||
|
id: "id",
|
||||||
|
val: "id",
|
||||||
|
title: "name",
|
||||||
|
description: "value",
|
||||||
|
name: "title"
|
||||||
|
},
|
||||||
|
apiSearchQueryKey: "search",
|
||||||
|
hasSearch: false,
|
||||||
|
optionAllowEmptyOption: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const styleSelect = new HSSelect(
|
||||||
|
$("#formMessageStyle").get(0),
|
||||||
|
styleSelectOptions
|
||||||
|
);
|
||||||
|
|
||||||
$("#editForm").on("submit", async event => {
|
$("#editForm").on("submit", async event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
<span class="sr-only">Checkbox</span>
|
<span class="sr-only">Checkbox</span>
|
||||||
</label>
|
</label>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="name" class="cj-table-header">
|
<th scope="col" class="cj-table-header">
|
||||||
<div class="cj-table-header-content cursor-pointer">
|
<div class="cj-table-header-content cursor-pointer">
|
||||||
<span>Name</span>
|
<span>Name</span>
|
||||||
<svg 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">
|
<svg 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">
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="url" class="cj-table-header">
|
<th scope="col" class="cj-table-header">
|
||||||
<div class="cj-table-header-content cursor-pointer">
|
<div class="cj-table-header-content cursor-pointer">
|
||||||
<span>URL</span>
|
<span>URL</span>
|
||||||
<svg 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">
|
<svg 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">
|
||||||
@ -67,25 +67,22 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="channels" class="cj-table-header --exclude-from-ordering">
|
<th scope="col" class="cj-table-header --exclude-from-ordering">
|
||||||
<div class="cj-table-header-content">
|
<div class="cj-table-header-content">
|
||||||
<span>Channels</span>
|
<span>Channels</span>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="filters" class="cj-table-header --exclude-from-ordering">
|
<th scope="col" class="cj-table-header --exclude-from-ordering">
|
||||||
<div class="cj-table-header-content">
|
<div class="cj-table-header-content">
|
||||||
<span>Filters</span>
|
<span>Filters</span>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="style" class="cj-table-header">
|
<th scope="col" class="cj-table-header --exclude-from-ordering">
|
||||||
<div class="cj-table-header-content cursor-pointer">
|
<div class="cj-table-header-content cursor-pointer">
|
||||||
<span>Style</span>
|
<span>Style</span>
|
||||||
<svg 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="m7 15 5 5 5-5"></path><path d="m7 9 5-5 5 5"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="created_at" class="cj-table-header">
|
<th scope="col" class="cj-table-header">
|
||||||
<div class="cj-table-header-content cursor-pointer">
|
<div class="cj-table-header-content cursor-pointer">
|
||||||
<span>Created at</span>
|
<span>Created at</span>
|
||||||
<svg 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">
|
<svg 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">
|
||||||
@ -93,7 +90,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" data-dt-column="active" class="cj-table-header">
|
<th scope="col" class="cj-table-header">
|
||||||
<div class="cj-table-header-content cursor-pointer">
|
<div class="cj-table-header-content cursor-pointer">
|
||||||
<span>Status</span>
|
<span>Status</span>
|
||||||
<svg 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">
|
<svg 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">
|
||||||
@ -210,8 +207,18 @@
|
|||||||
Filter out unwanted content from this feed.
|
Filter out unwanted content from this feed.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div></div>
|
<div class="relative">
|
||||||
<div></div>
|
<label for="formMessageStyle" class="text-input-label">Message Style</label>
|
||||||
|
<select name="message_style" id="formMessageStyle" class="--prevent-on-load-init">
|
||||||
|
<option value="">None</option>
|
||||||
|
</select>
|
||||||
|
<p class="text-input-help">
|
||||||
|
placeholder.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
placeholder for publish threshold
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="formActive" class="flex gap-4">
|
<label for="formActive" class="flex gap-4">
|
||||||
<input type="checkbox" id="formActive" name="active" class="form-radio relative w-[3.25rem] h-7 p-px bg-gray-100 border-transparent text-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:ring-blue-600 disabled:opacity-50 disabled:pointer-events-none checked:bg-none checked:text-blue-600 checked:border-blue-600 focus:checked:border-blue-600 dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-600 before:inline-block before:size-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:rounded-full before:shadow-sm before:transform before:ring-0 before:transition before:ease-in-out before:duration-200 dark:before:bg-neutral-400 dark:checked:before:bg-blue-200">
|
<input type="checkbox" id="formActive" name="active" class="form-radio relative w-[3.25rem] h-7 p-px bg-gray-100 border-transparent text-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:ring-blue-600 disabled:opacity-50 disabled:pointer-events-none checked:bg-none checked:text-blue-600 checked:border-blue-600 focus:checked:border-blue-600 dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-600 before:inline-block before:size-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:rounded-full before:shadow-sm before:transform before:ring-0 before:transition before:ease-in-out before:duration-200 dark:before:bg-neutral-400 dark:checked:before:bg-blue-200">
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import prisma, { Prisma } from "@server/prisma";
|
import prisma, { Prisma } from "@server/prisma";
|
||||||
import { datatableRequest } from "@server/controllers/guild/api/dt.module";
|
import { datatableRequest } from "@server/controllers/guild/api/dt.module";
|
||||||
|
import { logger } from "@server/../log";
|
||||||
|
|
||||||
export const get = async (request: Request, response: Response) => {
|
export const get = async (request: Request, response: Response) => {
|
||||||
if (!request.query.id) {
|
if (!request.query.id) {
|
||||||
@ -23,7 +24,9 @@ export const get = async (request: Request, response: Response) => {
|
|||||||
|
|
||||||
export const post = async (request: Request, response: Response) => {
|
export const post = async (request: Request, response: Response) => {
|
||||||
const guildId = request.params.guildId;
|
const guildId = request.params.guildId;
|
||||||
const { name, url, active, channels, filters } = request.body;
|
const { name, url, active, channels, filters, message_style } = request.body;
|
||||||
|
|
||||||
|
logger.debug("Post Feed", request.body);
|
||||||
|
|
||||||
// channels comes through as either String[] or String
|
// channels comes through as either String[] or String
|
||||||
let formattedChannels = undefined;
|
let formattedChannels = undefined;
|
||||||
@ -50,7 +53,8 @@ export const post = async (request: Request, response: Response) => {
|
|||||||
guild_id: guildId,
|
guild_id: guildId,
|
||||||
active: active === "on",
|
active: active === "on",
|
||||||
channels: { create: formattedChannels },
|
channels: { create: formattedChannels },
|
||||||
filters: { connect: formattedFilters }
|
filters: { connect: formattedFilters },
|
||||||
|
message_style_id: message_style === "" ? null : Number(message_style)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -67,7 +71,9 @@ export const post = async (request: Request, response: Response) => {
|
|||||||
|
|
||||||
export const patch = async (request: Request, response: Response) => {
|
export const patch = async (request: Request, response: Response) => {
|
||||||
const guildId = request.params.guildId;
|
const guildId = request.params.guildId;
|
||||||
const { id, name, url, active, channels, filters } = request.body;
|
const { id, name, url, active, channels, filters, message_style } = request.body;
|
||||||
|
|
||||||
|
logger.info("Patch Feed", request.body);
|
||||||
|
|
||||||
// channels comes through as either String[] or String
|
// channels comes through as either String[] or String
|
||||||
let formattedChannels = undefined;
|
let formattedChannels = undefined;
|
||||||
@ -101,7 +107,11 @@ export const patch = async (request: Request, response: Response) => {
|
|||||||
filters: {
|
filters: {
|
||||||
set: [],
|
set: [],
|
||||||
connect: formattedFilters
|
connect: formattedFilters
|
||||||
}
|
},
|
||||||
|
message_style_id:
|
||||||
|
message_style === ""
|
||||||
|
? null
|
||||||
|
: Number(message_style)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -150,7 +160,7 @@ export const datatable = async (request: Request, response: Response) => {
|
|||||||
response,
|
response,
|
||||||
prisma.feed,
|
prisma.feed,
|
||||||
[{ updated_at: "desc" }, { id: "asc" }],
|
[{ updated_at: "desc" }, { id: "asc" }],
|
||||||
{ channels: true, filters: true },
|
{ channels: true, filters: true, message_style: true },
|
||||||
{ guild_id: request.params.guildId } // TODO: verify authenticated user can access this guild
|
{ guild_id: request.params.guildId } // TODO: verify authenticated user can access this guild
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import prisma, { Prisma } from "@server/prisma";
|
import prisma, { Prisma } from "@server/prisma";
|
||||||
import { datatableRequest } from "@server/controllers/guild/api/dt.module";
|
import { datatableRequest } from "@server/controllers/guild/api/dt.module";
|
||||||
|
import { logger } from "@server/../log";
|
||||||
|
|
||||||
export const get = async (request: Request, response: Response) => {
|
export const get = async (request: Request, response: Response) => {
|
||||||
if (!request.query.id) {
|
if (!request.query.id) {
|
||||||
@ -34,6 +35,8 @@ export const post = async (request: Request, response: Response) => {
|
|||||||
description_mutator
|
description_mutator
|
||||||
} = request.body;
|
} = request.body;
|
||||||
|
|
||||||
|
logger.debug("Style Post", request.body);
|
||||||
|
|
||||||
let style;
|
let style;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -147,4 +150,27 @@ export const datatable = async (request: Request, response: Response) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default { get, post, patch, del, datatable };
|
export const select = async (request: Request, response: Response) => {
|
||||||
|
const guildId = request.params.guildId;
|
||||||
|
const { search } = request.query;
|
||||||
|
|
||||||
|
const data = await prisma.messageStyle.findMany({
|
||||||
|
where: {
|
||||||
|
guild_id: guildId,
|
||||||
|
name: { contains: `${search}` }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Preline Bug: https://github.com/htmlstreamofficial/preline/issues/567
|
||||||
|
// The returned data must have a "title" key, otherwise the advanced
|
||||||
|
// select component with 'tags' mode will have no title, regardless of
|
||||||
|
// mapping.
|
||||||
|
const modifiedResults = data.map(filter => ({
|
||||||
|
...filter,
|
||||||
|
title: filter.name
|
||||||
|
}));
|
||||||
|
|
||||||
|
response.json(modifiedResults);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default { get, post, patch, del, datatable, select };
|
@ -40,6 +40,7 @@ router.patch("/:guildId/filters/api", filterApiController.patch);
|
|||||||
router.delete("/:guildId/filters/api", filterApiController.del);
|
router.delete("/:guildId/filters/api", filterApiController.del);
|
||||||
|
|
||||||
router.post("/:guildId/styles/api/datatable", styleApiController.datatable);
|
router.post("/:guildId/styles/api/datatable", styleApiController.datatable);
|
||||||
|
router.get("/:guildId/styles/api/select", styleApiController.select);
|
||||||
router.get("/:guildId/styles/api", styleApiController.get);
|
router.get("/:guildId/styles/api", styleApiController.get);
|
||||||
router.post("/:guildId/styles/api", styleApiController.post);
|
router.post("/:guildId/styles/api", styleApiController.post);
|
||||||
router.patch("/:guildId/styles/api", styleApiController.patch);
|
router.patch("/:guildId/styles/api", styleApiController.patch);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user