feat(admin): music library admin + fix CRM analytics UTC
Build backend images / build content-svc (push) Failing after 1m7s
Build backend images / build file-svc (push) Failing after 50s
Build backend images / build gateway (push) Failing after 59s
Build backend images / build identity-svc (push) Failing after 56s
Build backend images / build notification-svc (push) Failing after 1m0s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 56s
Build backend images / build content-svc (push) Failing after 1m7s
Build backend images / build file-svc (push) Failing after 50s
Build backend images / build gateway (push) Failing after 59s
Build backend images / build identity-svc (push) Failing after 56s
Build backend images / build notification-svc (push) Failing after 1m0s
Build backend images / build render-svc (push) Failing after 1m0s
Build backend images / build studio-svc (push) Failing after 56s
- /admin/music: list / upload / delete studio audio tracks (content-svc GET/POST/DELETE /v1/music) — fills the legacy music-library gap - fix: CRM analytics coerced query-bound dates to UTC (Npgsql timestamptz rejects Kind=Unspecified) — endpoint was returning 400 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -328,7 +328,8 @@
|
||||
"marketing": "Marketing",
|
||||
"crm": "CRM",
|
||||
"ranking": "Ranking",
|
||||
"stats": "Dashboard"
|
||||
"stats": "Dashboard",
|
||||
"music": "Music"
|
||||
},
|
||||
"appAdminNodesPage": {
|
||||
"title": "Render Nodes",
|
||||
|
||||
+2
-1
@@ -328,7 +328,8 @@
|
||||
"marketing": "بازاریابی",
|
||||
"crm": "مدیریت مشتریان",
|
||||
"ranking": "رتبهبندی",
|
||||
"stats": "داشبورد"
|
||||
"stats": "داشبورد",
|
||||
"music": "موسیقی"
|
||||
},
|
||||
"appAdminNodesPage": {
|
||||
"title": "نودهای رندر",
|
||||
|
||||
@@ -13,8 +13,9 @@ public class AdminService(IdentityDbContext db)
|
||||
|
||||
public async Task<CrmAnalyticsResponse> GetCrmAnalyticsAsync(Guid tenantId, DateTime start, DateTime end)
|
||||
{
|
||||
start = start.Date;
|
||||
end = end.Date.AddDays(1); // inclusive of the end day
|
||||
// Query-bound dates arrive Kind=Unspecified; Npgsql requires UTC for timestamptz.
|
||||
start = DateTime.SpecifyKind(start.Date, DateTimeKind.Utc);
|
||||
end = DateTime.SpecifyKind(end.Date.AddDays(1), DateTimeKind.Utc); // inclusive of the end day
|
||||
if ((end - start).TotalDays > 366) end = start.AddDays(366);
|
||||
|
||||
var signups = await db.Users
|
||||
|
||||
@@ -22,6 +22,7 @@ export default async function AdminLayout({
|
||||
{ href: "/admin/ranking", label: t("ranking") },
|
||||
{ href: "/admin/tags", label: t("tags") },
|
||||
{ href: "/admin/fonts", label: t("fonts") },
|
||||
{ href: "/admin/music", label: t("music") },
|
||||
{ href: "/admin/blogs", label: t("blogs") },
|
||||
{ href: "/admin/slides", label: t("slides") },
|
||||
{ href: "/admin/files", label: t("media") },
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { AdminResource } from "@/components/admin/AdminResource";
|
||||
import { musicConfig } from "@/components/admin/admin-resources";
|
||||
|
||||
export default function Page() {
|
||||
return <AdminResource config={musicConfig} />;
|
||||
}
|
||||
@@ -109,6 +109,34 @@ export const fontsConfig: ResourceConfig = {
|
||||
],
|
||||
};
|
||||
|
||||
export const musicConfig: ResourceConfig = {
|
||||
title: "Music",
|
||||
description: "Audio tracks available in the studio music library.",
|
||||
basePath: "music",
|
||||
listKey: "items",
|
||||
canCreate: true,
|
||||
canEdit: false,
|
||||
canDelete: true,
|
||||
columns: [
|
||||
{ key: "name", label: "Name" },
|
||||
{ key: "genre", label: "Genre" },
|
||||
{ key: "mood", label: "Mood" },
|
||||
{ key: "duration_sec", label: "Duration (s)" },
|
||||
{ key: "is_premium", label: "Premium", render: (r) => badge(!!r.is_premium, "premium", "free") },
|
||||
],
|
||||
fields: [
|
||||
{ key: "name", label: "Name", required: true },
|
||||
{ key: "caption", label: "Caption" },
|
||||
{ key: "keywords", label: "Keywords" },
|
||||
{ key: "url", label: "Audio file", type: "file", required: true },
|
||||
{ key: "duration_sec", label: "Duration (seconds)", type: "number", required: true },
|
||||
{ key: "bpm", label: "BPM", type: "number" },
|
||||
{ key: "genre", label: "Genre" },
|
||||
{ key: "mood", label: "Mood" },
|
||||
{ key: "is_premium", label: "Premium", type: "checkbox" },
|
||||
],
|
||||
};
|
||||
|
||||
export const blogsConfig: ResourceConfig = {
|
||||
title: "Blog Posts",
|
||||
description: "CMS articles (also created by the AI SEO generator).",
|
||||
|
||||
Reference in New Issue
Block a user