@oktis-works/admin 0.1.4 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/bin/admin.js +14 -0
  2. package/bin/listen-log.d.ts +8 -0
  3. package/bin/listen-log.js +66 -0
  4. package/dist/client/_astro/{BaseLayout.COf3Eran.css → BaseLayout.BPkaFsmK.css} +1 -1
  5. package/dist/client/_astro/{ContentEditor.COyD6bGV.js → ContentEditor.DOcUnkMP.js} +1 -1
  6. package/dist/client/_astro/ContentList.KzxsMMxH.js +1 -0
  7. package/dist/client/_astro/DashboardHome.DFRZ_yyM.js +1 -0
  8. package/dist/client/_astro/DashboardLayout.astro_astro_type_script_index_0_lang.B663y3aY.js +1 -0
  9. package/dist/client/_astro/GeneralSettings.gbcKHf_p.js +1 -0
  10. package/dist/client/_astro/MediaLibrary.BtCjwNlR.js +1 -0
  11. package/dist/client/_astro/{PostTypesManager.APvO7Cs9.js → PostTypesManager.DsxV-sF3.js} +1 -1
  12. package/dist/client/_astro/{TaxonomiesManager.CVFdfaUR.js → TaxonomiesManager.DqnwUCtt.js} +1 -1
  13. package/dist/client/_astro/UserCreateForm.BLaiQTzI.js +1 -0
  14. package/dist/client/_astro/UsersManager.BPRG8tjn.js +1 -0
  15. package/dist/client/_astro/api.BegLcOlq.js +1 -0
  16. package/dist/client/_astro/{login.astro_astro_type_script_index_0_lang.BLhqPWk8.js → login.astro_astro_type_script_index_0_lang.ozrnjgkA.js} +1 -1
  17. package/dist/server/chunks/{BaseLayout_Mvr1_6Ng.mjs → BaseLayout_C41_wW4F.mjs} +19 -2
  18. package/dist/server/chunks/{edit_D14rRl_p.mjs → ContentEditor_DwBpNq-K.mjs} +21 -30
  19. package/dist/server/chunks/DashboardLayout_DO66tdeZ.mjs +43 -0
  20. package/dist/server/chunks/MediaLibrary_DEi9k6ms.mjs +179 -0
  21. package/dist/server/chunks/api_BWOj0bUJ.mjs +274 -0
  22. package/dist/server/chunks/edit_DNavSwFw.mjs +30 -0
  23. package/dist/server/chunks/general_r50g45qE.mjs +173 -0
  24. package/dist/server/chunks/index_6G7rXrus.mjs +133 -0
  25. package/dist/server/chunks/index_B50u2M3P.mjs +23 -0
  26. package/dist/server/chunks/index_DUzUgyr4.mjs +155 -0
  27. package/dist/server/chunks/index_qxSk7_hO.mjs +30 -0
  28. package/dist/server/chunks/index_yiAU3Mfy.mjs +204 -0
  29. package/dist/server/chunks/{login_B7vbWIed.mjs → login_BH67N4b1.mjs} +2 -19
  30. package/dist/server/chunks/new_BWcSqoqV.mjs +86 -0
  31. package/dist/server/chunks/new_h8TItZZ9.mjs +30 -0
  32. package/dist/server/chunks/{post-types_BtNyF2Iv.mjs → post-types_BSobAovm.mjs} +2 -2
  33. package/dist/server/chunks/{taxonomies_DSgstawN.mjs → taxonomies_Ij7CReDF.mjs} +2 -2
  34. package/dist/server/chunks/upload_16xg6koU.mjs +31 -0
  35. package/dist/server/entry.mjs +259 -13
  36. package/package.json +5 -5
  37. package/dist/client/_astro/api.DSP61PKM.js +0 -1
  38. package/dist/server/chunks/DashboardLayout_CP5ag-_P.mjs +0 -17
  39. package/dist/server/chunks/api_Cy8sbUHf.mjs +0 -153
  40. package/dist/server/chunks/index_BgbHlcwr.mjs +0 -23
  41. package/dist/server/chunks/index_c3b5hMDp.mjs +0 -22
@@ -1,8 +1,5 @@
1
- import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
2
- import { d as maybeRenderHead, i as renderComponent, u as renderTemplate } from "./server_CnzC2Y0K.mjs";
3
- import { t as createComponent$1 } from "./compiler_CYjwXhLT.mjs";
4
- import { t as $$DashboardLayout } from "./DashboardLayout_CP5ag-_P.mjs";
5
- import { t as apiClient } from "./api_Cy8sbUHf.mjs";
1
+ import "./rolldown-runtime_BMI-E3GI.mjs";
2
+ import { t as apiClient } from "./api_BWOj0bUJ.mjs";
6
3
  import { t as require_semver } from "./semver_WbqCUY_o.mjs";
7
4
  import { createComponent, escape, memo, ssr, ssrAttribute, ssrHydrationKey } from "solid-js/web";
8
5
  import { For, For as For$1, Show, Show as Show$1, createMemo, createMemo as createMemo$1, createSignal, createSignal as createSignal$1, onMount } from "solid-js";
@@ -710,6 +707,24 @@ function ContentEditor() {
710
707
  } catch (err) {
711
708
  setErrors([err instanceof Error ? err.message : String(err)]);
712
709
  }
710
+ const editId = new URLSearchParams(window.location.search).get("id");
711
+ if (editId) try {
712
+ const existing = await apiClient.getContentById(editId);
713
+ const rawRow = existing;
714
+ setDraft({
715
+ id: existing.id,
716
+ type: existing.type,
717
+ title: existing.title,
718
+ slug: existing.slug,
719
+ excerpt: existing.excerpt,
720
+ featuredImageId: rawRow["featuredImageId"] ?? rawRow["featured_image_id"],
721
+ status: existing.status,
722
+ layout: existing.layout
723
+ });
724
+ setData(existing.body ?? {});
725
+ } catch (err) {
726
+ setErrors([err instanceof Error ? err.message : String(err)]);
727
+ }
713
728
  await loadGroups(draft().type);
714
729
  });
715
730
  const availableLayouts = () => {
@@ -818,28 +833,4 @@ function ContentEditor() {
818
833
  })), ssrAttribute("disabled", saving(), true));
819
834
  }
820
835
  //#endregion
821
- //#region src/pages/content/edit.astro
822
- var edit_exports = /* @__PURE__ */ __exportAll({
823
- default: () => $$Edit,
824
- file: () => $$file,
825
- url: () => $$url
826
- });
827
- var $$Edit = createComponent$1(($$result, $$props, $$slots) => {
828
- return renderTemplate`${renderComponent($$result, "DashboardLayout", $$DashboardLayout, {
829
- "title": "Editor de Conteúdo",
830
- "data-astro-cid-4zhgedtj": true
831
- }, { "default": ($$result) => renderTemplate`${maybeRenderHead($$result)}<div class="editor-page" data-astro-cid-4zhgedtj>${renderComponent($$result, "ContentEditor", ContentEditor, {
832
- "client:load": true,
833
- "data-astro-cid-4zhgedtj": true,
834
- "client:component-hydration": "load",
835
- "client:component-path": "/home/runner/work/cms/cms/apps/admin/src/components/content/ContentEditor.tsx",
836
- "client:component-export": "ContentEditor"
837
- })}</div>` })}`;
838
- }, "/home/runner/work/cms/cms/apps/admin/src/pages/content/edit.astro", void 0);
839
- var $$file = "/home/runner/work/cms/cms/apps/admin/src/pages/content/edit.astro";
840
- var $$url = "/content/edit";
841
- //#endregion
842
- //#region \0virtual:astro:page:src/pages/content/edit@_@astro
843
- var page = () => edit_exports;
844
- //#endregion
845
- export { page };
836
+ export { ContentEditor as t };
@@ -0,0 +1,43 @@
1
+ import { S as createAstro, d as maybeRenderHead, i as renderComponent, p as addAttribute, s as renderSlot, u as renderTemplate } from "./server_CnzC2Y0K.mjs";
2
+ import { t as createComponent } from "./compiler_CYjwXhLT.mjs";
3
+ import { n as renderScript, t as $$BaseLayout } from "./BaseLayout_C41_wW4F.mjs";
4
+ //#region src/layouts/DashboardLayout.astro
5
+ createAstro("https://astro.build");
6
+ var $$DashboardLayout = createComponent(($$result, $$props, $$slots) => {
7
+ const Astro = $$result.createAstro($$props, $$slots);
8
+ Astro.self = $$DashboardLayout;
9
+ const { title, description } = Astro.props;
10
+ const pathname = Astro.url.pathname;
11
+ const isActive = (href) => href === "/" ? pathname === "/" : pathname === href || pathname.startsWith(`${href}/`);
12
+ const navActive = {
13
+ dashboard: isActive("/"),
14
+ content: isActive("/content"),
15
+ media: isActive("/media"),
16
+ users: isActive("/users"),
17
+ settings: isActive("/settings")
18
+ };
19
+ const settingsChildren = [
20
+ {
21
+ href: "/settings/general",
22
+ label: "General",
23
+ active: isActive("/settings/general")
24
+ },
25
+ {
26
+ href: "/settings/post-types",
27
+ label: "Content Types",
28
+ active: isActive("/settings/post-types")
29
+ },
30
+ {
31
+ href: "/settings/taxonomies",
32
+ label: "Taxonomies",
33
+ active: isActive("/settings/taxonomies")
34
+ }
35
+ ];
36
+ return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, {
37
+ "title": title,
38
+ "description": description,
39
+ "data-astro-cid-ynf3rr4n": true
40
+ }, { "default": ($$result) => renderTemplate`${maybeRenderHead($$result)}<div class="layout" data-astro-cid-ynf3rr4n><aside class="sidebar" data-astro-cid-ynf3rr4n><div class="sidebar-header" data-astro-cid-ynf3rr4n><h2 class="text-lg font-bold" data-astro-cid-ynf3rr4n>OkCMS</h2><span class="badge badge-secondary" data-astro-cid-ynf3rr4n>Admin</span></div><nav class="sidebar-nav" data-astro-cid-ynf3rr4n><a href="/"${addAttribute(["nav-item", { active: navActive.dashboard }], "class:list")} data-astro-cid-ynf3rr4n><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-ynf3rr4n><rect x="3" y="3" width="7" height="7" data-astro-cid-ynf3rr4n></rect><rect x="14" y="3" width="7" height="7" data-astro-cid-ynf3rr4n></rect><rect x="14" y="14" width="7" height="7" data-astro-cid-ynf3rr4n></rect><rect x="3" y="14" width="7" height="7" data-astro-cid-ynf3rr4n></rect></svg>Dashboard</a><a href="/content"${addAttribute(["nav-item", { active: navActive.content }], "class:list")} data-astro-cid-ynf3rr4n><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-ynf3rr4n><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" data-astro-cid-ynf3rr4n></path><polyline points="14 2 14 8 20 8" data-astro-cid-ynf3rr4n></polyline><line x1="16" y1="13" x2="8" y2="13" data-astro-cid-ynf3rr4n></line><line x1="16" y1="17" x2="8" y2="17" data-astro-cid-ynf3rr4n></line><polyline points="10 9 9 9 8 9" data-astro-cid-ynf3rr4n></polyline></svg>Content</a><a href="/media"${addAttribute(["nav-item", { active: navActive.media }], "class:list")} data-astro-cid-ynf3rr4n><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-ynf3rr4n><rect x="3" y="3" width="18" height="18" rx="2" ry="2" data-astro-cid-ynf3rr4n></rect><circle cx="8.5" cy="8.5" r="1.5" data-astro-cid-ynf3rr4n></circle><polyline points="21 15 16 10 5 21" data-astro-cid-ynf3rr4n></polyline></svg>Media</a><a href="/users"${addAttribute(["nav-item", { active: navActive.users }], "class:list")} data-astro-cid-ynf3rr4n><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-ynf3rr4n><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" data-astro-cid-ynf3rr4n></path><circle cx="9" cy="7" r="4" data-astro-cid-ynf3rr4n></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87" data-astro-cid-ynf3rr4n></path><path d="M16 3.13a4 4 0 0 1 0 7.75" data-astro-cid-ynf3rr4n></path></svg>Users</a><a href="/settings"${addAttribute(["nav-item", { active: navActive.settings }], "class:list")} data-astro-cid-ynf3rr4n><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-ynf3rr4n><circle cx="12" cy="12" r="3" data-astro-cid-ynf3rr4n></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" data-astro-cid-ynf3rr4n></path></svg>Settings</a><div class="nav-submenu" data-astro-cid-ynf3rr4n>${settingsChildren.map((child) => renderTemplate`<a${addAttribute(child.href, "href")}${addAttribute(["nav-subitem", { active: child.active }], "class:list")} data-astro-cid-ynf3rr4n>${child.label}</a>`)}</div></nav></aside><main class="main-content" data-astro-cid-ynf3rr4n><header class="main-header" data-astro-cid-ynf3rr4n><h1 class="text-lg font-bold" data-astro-cid-ynf3rr4n>${title}</h1><div class="header-actions" data-astro-cid-ynf3rr4n><button class="btn btn-secondary btn-sm" id="logout-btn" data-astro-cid-ynf3rr4n>Logout</button></div></header><div class="content" data-astro-cid-ynf3rr4n>${renderSlot($$result, $$slots["default"])}</div></main></div>` })}${renderScript($$result, "/home/runner/work/cms/cms/apps/admin/src/layouts/DashboardLayout.astro?astro&type=script&index=0&lang.ts")}`;
41
+ }, "/home/runner/work/cms/cms/apps/admin/src/layouts/DashboardLayout.astro", void 0);
42
+ //#endregion
43
+ export { $$DashboardLayout as t };
@@ -0,0 +1,179 @@
1
+ import { t as apiClient } from "./api_BWOj0bUJ.mjs";
2
+ import { createComponent, escape, ssr, ssrAttribute, ssrHydrationKey, ssrStyleProperty } from "solid-js/web";
3
+ import { For, Show, createSignal, onMount } from "solid-js";
4
+ //#region src/components/media/MediaLibrary.tsx
5
+ var _tmpl$ = [
6
+ "<div",
7
+ " class=\"notice notice--error\">",
8
+ "</div>"
9
+ ];
10
+ var _tmpl$2 = [
11
+ "<div",
12
+ " class=\"notice\">",
13
+ "</div>"
14
+ ];
15
+ var _tmpl$3 = [
16
+ "<div",
17
+ " class=\"media-grid\">",
18
+ "</div>"
19
+ ];
20
+ var _tmpl$4 = [
21
+ "<div",
22
+ " class=\"pagination\"><button class=\"btn btn-secondary btn-sm\" type=\"button\"",
23
+ ">← Anterior</button><span class=\"muted\">Página <!--$-->",
24
+ "<!--/--> de <!--$-->",
25
+ "<!--/--></span><button class=\"btn btn-secondary btn-sm\" type=\"button\"",
26
+ ">Próxima →</button></div>"
27
+ ];
28
+ var _tmpl$5 = [
29
+ "<div",
30
+ " class=\"media-library\"><!--$-->",
31
+ "<!--/--><!--$-->",
32
+ "<!--/--><div class=\"",
33
+ "\"><p><strong>Arraste arquivos aqui</strong> ou</p><label class=\"btn btn-primary\" style=\"",
34
+ "\"><!--$-->",
35
+ "<!--/--><input type=\"file\" multiple style=\"",
36
+ "\"",
37
+ "></label><p class=\"muted\">Imagens, vídeos, áudios e documentos · até 25MB por arquivo</p></div><div class=\"toolbar\"><input class=\"input\" placeholder=\"Buscar por nome ou alt…\"",
38
+ "><select class=\"input\"",
39
+ "><option value>Todos os tipos</option><option value=\"image/png\">PNG</option><option value=\"image/jpeg\">JPEG</option><option value=\"image/gif\">GIF</option><option value=\"image/webp\">WebP</option><option value=\"image/svg+xml\">SVG</option><option value=\"application/pdf\">PDF</option><option value=\"video/mp4\">MP4</option><option value=\"audio/mpeg\">MP3</option></select><button class=\"btn btn-secondary\" type=\"button\">Buscar</button></div><!--$-->",
40
+ "<!--/--><!--$-->",
41
+ "<!--/--><!--$-->",
42
+ "<!--/--></div>"
43
+ ];
44
+ var _tmpl$6 = ["<p", " class=\"muted\">Nenhum arquivo ainda. Envie o primeiro!</p>"];
45
+ var _tmpl$7 = ["<img", " loading=\"lazy\">"];
46
+ var _tmpl$8 = [
47
+ "<button",
48
+ " type=\"button\" class=\"",
49
+ "\"><div class=\"media-card__preview\">",
50
+ "</div><div class=\"media-card__meta\"><span class=\"media-card__name\"",
51
+ ">",
52
+ "</span><span class=\"muted\">",
53
+ "</span></div></button>"
54
+ ];
55
+ var _tmpl$9 = [
56
+ "<span",
57
+ " class=\"media-card__ext\">",
58
+ "</span>"
59
+ ];
60
+ var _tmpl$0 = ["<img", ">"];
61
+ var _tmpl$1 = [
62
+ "<div",
63
+ " class=\"card media-details\"><h3>Detalhes</h3><div class=\"media-details__preview\">",
64
+ "</div><dl class=\"media-details__list\"><dt>Arquivo</dt><dd>",
65
+ "</dd><dt>Tipo</dt><dd>",
66
+ "</dd><dt>Tamanho</dt><dd>",
67
+ "</dd><dt>URL</dt><dd class=\"media-details__url\"><code>",
68
+ "</code><button class=\"btn btn-secondary btn-sm\" type=\"button\">Copiar</button></dd></dl><label>Texto alternativo (alt)<input class=\"input\"",
69
+ "></label><label>Legenda<input class=\"input\"",
70
+ "></label><div class=\"media-details__actions\"><button class=\"btn btn-primary\" type=\"button\"",
71
+ ">",
72
+ "</button><button class=\"btn btn-danger\" type=\"button\">Excluir</button><button class=\"btn btn-secondary\" type=\"button\">Fechar</button></div></div>"
73
+ ];
74
+ var _tmpl$10 = [
75
+ "<p",
76
+ " class=\"muted\">",
77
+ "</p>"
78
+ ];
79
+ function formatSize(bytes) {
80
+ if (!Number.isFinite(bytes)) return "—";
81
+ if (bytes < 1024) return `${bytes} B`;
82
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
83
+ return `${(bytes / 1048576).toFixed(1)} MB`;
84
+ }
85
+ var isImage = (media) => media.mime_type.startsWith("image/");
86
+ function MediaLibrary(props) {
87
+ const [items, setItems] = createSignal([]);
88
+ const [total, setTotal] = createSignal(0);
89
+ const [page, setPage] = createSignal(1);
90
+ const [search, setSearch] = createSignal("");
91
+ const [mimeType, setMimeType] = createSignal("");
92
+ const [error, setError] = createSignal("");
93
+ const [info, setInfo] = createSignal("");
94
+ const [uploading, setUploading] = createSignal(false);
95
+ const [selected, setSelected] = createSignal(null);
96
+ const [dragOver, setDragOver] = createSignal(false);
97
+ const [savingDetails, setSavingDetails] = createSignal(false);
98
+ const limit = 24;
99
+ const load = async () => {
100
+ try {
101
+ const result = await apiClient.listMedia({
102
+ page: page(),
103
+ limit,
104
+ search: search() || void 0,
105
+ mimeType: mimeType() || void 0
106
+ });
107
+ setItems(result.data ?? []);
108
+ setTotal(result.total ?? 0);
109
+ } catch (err) {
110
+ setError(err instanceof Error ? err.message : String(err));
111
+ }
112
+ };
113
+ onMount(load);
114
+ const totalPages = () => Math.max(1, Math.ceil(total() / limit));
115
+ return ssr(_tmpl$5, ssrHydrationKey(), escape(createComponent(Show, {
116
+ get when() {
117
+ return error();
118
+ },
119
+ get children() {
120
+ return ssr(_tmpl$, ssrHydrationKey(), escape(error()));
121
+ }
122
+ })), escape(createComponent(Show, {
123
+ get when() {
124
+ return info();
125
+ },
126
+ get children() {
127
+ return ssr(_tmpl$2, ssrHydrationKey(), escape(info()));
128
+ }
129
+ })), `upload-zone ${dragOver() || props.focusUpload ? "upload-zone--active" : ""}`, ssrStyleProperty("cursor:", "pointer"), uploading() ? "Enviando…" : "Selecionar arquivos", ssrStyleProperty("display:", "none"), ssrAttribute("disabled", uploading(), true), ssrAttribute("value", escape(search(), true), false), ssrAttribute("value", escape(mimeType(), true), false), escape(createComponent(Show, {
130
+ get when() {
131
+ return items().length > 0;
132
+ },
133
+ get fallback() {
134
+ return ssr(_tmpl$6, ssrHydrationKey());
135
+ },
136
+ get children() {
137
+ return ssr(_tmpl$3, ssrHydrationKey(), escape(createComponent(For, {
138
+ get each() {
139
+ return items();
140
+ },
141
+ children: (media) => ssr(_tmpl$8, ssrHydrationKey(), `media-card ${selected()?.id === media.id ? "media-card--selected" : ""}`, escape(createComponent(Show, {
142
+ get when() {
143
+ return isImage(media);
144
+ },
145
+ get fallback() {
146
+ return ssr(_tmpl$9, ssrHydrationKey(), escape(media.mime_type.split("/")[1]?.toUpperCase() ?? "FILE"));
147
+ },
148
+ get children() {
149
+ return ssr(_tmpl$7, ssrHydrationKey() + ssrAttribute("src", escape(media.url, true), false) + ssrAttribute("alt", escape(media.alt ?? media.filename, true), false));
150
+ }
151
+ })), ssrAttribute("title", escape(media.filename, true), false), escape(media.filename), escape(formatSize(media.size)))
152
+ })));
153
+ }
154
+ })), escape(createComponent(Show, {
155
+ get when() {
156
+ return totalPages() > 1;
157
+ },
158
+ get children() {
159
+ return ssr(_tmpl$4, ssrHydrationKey(), ssrAttribute("disabled", page() <= 1, true), escape(page()), escape(totalPages()), ssrAttribute("disabled", page() >= totalPages(), true));
160
+ }
161
+ })), escape(createComponent(Show, {
162
+ get when() {
163
+ return selected();
164
+ },
165
+ children: (media) => ssr(_tmpl$1, ssrHydrationKey(), escape(createComponent(Show, {
166
+ get when() {
167
+ return isImage(media());
168
+ },
169
+ get fallback() {
170
+ return ssr(_tmpl$10, ssrHydrationKey(), escape(media().mime_type));
171
+ },
172
+ get children() {
173
+ return ssr(_tmpl$0, ssrHydrationKey() + ssrAttribute("src", escape(media().url, true), false) + ssrAttribute("alt", escape(media().alt ?? "", true), false));
174
+ }
175
+ })), escape(media().filename), escape(media().mime_type), escape(formatSize(media().size)), escape(media().url), ssrAttribute("value", escape(media().alt ?? "", true), false), ssrAttribute("value", escape(media().caption ?? "", true), false), ssrAttribute("disabled", savingDetails(), true), savingDetails() ? "Salvando…" : "Salvar detalhes")
176
+ })));
177
+ }
178
+ //#endregion
179
+ export { MediaLibrary as t };
@@ -0,0 +1,274 @@
1
+ //#region src/lib/api.ts
2
+ var API_BASE = Object.assign({
3
+ "ASSETS_PREFIX": void 0,
4
+ "BASE_URL": "/",
5
+ "DEV": false,
6
+ "MODE": "production",
7
+ "PROD": true,
8
+ "SITE": void 0,
9
+ "SSR": true
10
+ }, { _: "/home/runner/work/cms/cms/apps/admin/node_modules/.bin/astro" })["PUBLIC_API_URL"] ?? "http://localhost:3000";
11
+ var ApiClient = class {
12
+ baseUrl;
13
+ csrfToken = null;
14
+ isRefreshing = false;
15
+ constructor(baseUrl = API_BASE) {
16
+ this.baseUrl = baseUrl;
17
+ }
18
+ /** Inicializa lendo CSRF do cookie (chamado no boot da app) */
19
+ async init() {
20
+ try {
21
+ await fetch(`${this.baseUrl}/api/v1/auth/me`, { credentials: "include" });
22
+ } catch {}
23
+ }
24
+ /** Sessão válida — verifica via /me (usa cookies HttpOnly automaticamente) */
25
+ async isLoggedIn() {
26
+ try {
27
+ return (await fetch(`${this.baseUrl}/api/v1/auth/me`, { credentials: "include" })).ok;
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
32
+ /** Obtém tenantId do backend via /me */
33
+ async getTenantId() {
34
+ try {
35
+ const res = await fetch(`${this.baseUrl}/api/v1/auth/me`, { credentials: "include" });
36
+ if (!res.ok) return null;
37
+ return (await res.json()).tenantId ?? null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ }
42
+ /** Login — o backend seta cookies HttpOnly e CSRF; retorna user + tenantId */
43
+ async login(input) {
44
+ return await this.request("POST", "/api/v1/auth/login", input);
45
+ }
46
+ /** Logout — limpa cookies no backend */
47
+ async logout() {
48
+ await this.request("POST", "/api/v1/auth/logout", {});
49
+ this.csrfToken = null;
50
+ }
51
+ /** Refresh de access token via cookie refresh_token */
52
+ async refreshTokens() {
53
+ if (this.isRefreshing) return;
54
+ this.isRefreshing = true;
55
+ try {
56
+ await this.request("POST", "/api/v1/auth/refresh", {});
57
+ } finally {
58
+ this.isRefreshing = false;
59
+ }
60
+ }
61
+ /** Requisição genérica com:
62
+ * - credentials: 'include' (envia cookies HttpOnly)
63
+ * - auto-refresh em 401
64
+ * - CSRF header para mutações
65
+ */
66
+ async request(method, path, body, headers) {
67
+ const url = `${this.baseUrl}${path}`;
68
+ const requestHeaders = {
69
+ "Content-Type": "application/json",
70
+ ...headers
71
+ };
72
+ if (![
73
+ "GET",
74
+ "HEAD",
75
+ "OPTIONS"
76
+ ].includes(method.toUpperCase())) {
77
+ const csrf = this.getCsrfToken();
78
+ if (csrf) requestHeaders["x-csrf-token"] = csrf;
79
+ }
80
+ let response = await fetch(url, {
81
+ method,
82
+ headers: requestHeaders,
83
+ credentials: "include",
84
+ body: body ? JSON.stringify(body) : void 0
85
+ });
86
+ if (response.status === 401 && !path.includes("/auth/refresh") && !path.includes("/auth/logout")) {
87
+ await this.refreshTokens();
88
+ response = await fetch(url, {
89
+ method,
90
+ headers: requestHeaders,
91
+ credentials: "include",
92
+ body: body ? JSON.stringify(body) : void 0
93
+ });
94
+ }
95
+ if (!response.ok) {
96
+ const error = await response.json().catch(() => ({ error: "Request failed" }));
97
+ throw new Error(error.error ?? `Request failed: ${response.status}`);
98
+ }
99
+ const setCookie = response.headers.get("set-cookie");
100
+ if (setCookie) {
101
+ const csrfMatch = setCookie.match(/csrf_token=([^;]+)/);
102
+ if (csrfMatch?.[1]) this.csrfToken = csrfMatch[1];
103
+ }
104
+ return response.json();
105
+ }
106
+ /** Lê CSRF token do cookie (document.cookie) */
107
+ getCsrfToken() {
108
+ if (this.csrfToken) return this.csrfToken;
109
+ if (typeof document !== "undefined") {
110
+ const match = document.cookie.match(/(?:^|;\s*)csrf_token=([^;]+)/);
111
+ if (match?.[1]) return match[1];
112
+ }
113
+ return null;
114
+ }
115
+ async getContent(options) {
116
+ const params = new URLSearchParams();
117
+ if (options?.page) params.set("page", String(options.page));
118
+ if (options?.limit) params.set("limit", String(options.limit));
119
+ if (options?.type) params.set("type", options.type);
120
+ if (options?.status) params.set("status", options.status);
121
+ if (options?.search) params.set("search", options.search);
122
+ return this.request("GET", `/api/v1/content?${params.toString()}`);
123
+ }
124
+ async getContentById(id) {
125
+ return this.request("GET", `/api/v1/content/${id}`);
126
+ }
127
+ async createContent(data) {
128
+ return this.request("POST", `/api/v1/content`, data);
129
+ }
130
+ async updateContent(id, data) {
131
+ return this.request("PUT", `/api/v1/content/${id}`, data);
132
+ }
133
+ async deleteContent(id) {
134
+ await this.request("DELETE", `/api/v1/content/${id}`);
135
+ }
136
+ async getContentTypes() {
137
+ return this.request("GET", "/api/v1/content-types");
138
+ }
139
+ async createContentType(data) {
140
+ return this.request("POST", "/api/v1/content-types", data);
141
+ }
142
+ async updateContentType(slug, data) {
143
+ return this.request("PUT", `/api/v1/content-types/${slug}`, data);
144
+ }
145
+ async deleteContentType(slug) {
146
+ await this.request("DELETE", `/api/v1/content-types/${slug}`);
147
+ }
148
+ async getTaxonomies() {
149
+ return this.request("GET", "/api/v1/taxonomies");
150
+ }
151
+ async createTaxonomy(data) {
152
+ return this.request("POST", "/api/v1/taxonomies", data);
153
+ }
154
+ async attachTaxonomy(slug, contentType) {
155
+ await this.request("POST", `/api/v1/taxonomies/${slug}/attach`, { contentType });
156
+ }
157
+ async detachTaxonomy(slug, contentType) {
158
+ await this.request("POST", `/api/v1/taxonomies/${slug}/detach`, { contentType });
159
+ }
160
+ async deleteTaxonomy(slug) {
161
+ await this.request("DELETE", `/api/v1/taxonomies/${slug}`);
162
+ }
163
+ async getFieldGroups(context) {
164
+ if (context?.type) {
165
+ const qs = new URLSearchParams({ type: context.type });
166
+ for (const [key, value] of Object.entries(context)) if (key !== "type" && value) qs.set(key, value);
167
+ return this.request("GET", `/api/v1/field-groups?${qs.toString()}`);
168
+ }
169
+ return this.request("GET", "/api/v1/field-groups");
170
+ }
171
+ async getFieldGroup(id) {
172
+ return this.request("GET", `/api/v1/field-groups/${id}`);
173
+ }
174
+ async createFieldGroup(data) {
175
+ return this.request("POST", "/api/v1/field-groups", data);
176
+ }
177
+ async getFieldTypes(category) {
178
+ const query = category ? `?category=${encodeURIComponent(category)}` : "";
179
+ return this.request("GET", `/api/v1/field-types${query}`);
180
+ }
181
+ async listMedia(options) {
182
+ const params = new URLSearchParams();
183
+ if (options?.page) params.set("page", String(options.page));
184
+ if (options?.limit) params.set("limit", String(options.limit));
185
+ if (options?.mimeType) params.set("mimeType", options.mimeType);
186
+ if (options?.search) params.set("search", options.search);
187
+ return this.request("GET", `/api/v1/media?${params.toString()}`);
188
+ }
189
+ async getMedia(id) {
190
+ return this.request("GET", `/api/v1/media/${id}`);
191
+ }
192
+ /** Upload multipart — NÃO seta Content-Type (o fetch precisa do boundary). */
193
+ async uploadMedia(file, options) {
194
+ const formData = new FormData();
195
+ formData.append("file", file);
196
+ if (options?.alt) formData.append("alt", options.alt);
197
+ if (options?.caption) formData.append("caption", options.caption);
198
+ const url = `${this.baseUrl}/api/v1/media/upload`;
199
+ const requestHeaders = {};
200
+ const csrf = this.getCsrfToken();
201
+ if (csrf) requestHeaders["x-csrf-token"] = csrf;
202
+ const response = await fetch(url, {
203
+ method: "POST",
204
+ headers: requestHeaders,
205
+ credentials: "include",
206
+ body: formData
207
+ });
208
+ if (!response.ok) {
209
+ const error = await response.json().catch(() => ({ error: `Upload failed: ${response.status}` }));
210
+ throw new Error(error.error ?? `Upload failed: ${response.status}`);
211
+ }
212
+ return response.json();
213
+ }
214
+ async updateMedia(id, data) {
215
+ return this.request("PUT", `/api/v1/media/${id}`, data);
216
+ }
217
+ async deleteMedia(id) {
218
+ await this.request("DELETE", `/api/v1/media/${id}`);
219
+ }
220
+ async listUsers(options) {
221
+ const params = new URLSearchParams();
222
+ if (options?.page) params.set("page", String(options.page));
223
+ if (options?.limit) params.set("limit", String(options.limit));
224
+ if (options?.search) params.set("search", options.search);
225
+ if (options?.status) params.set("status", options.status);
226
+ return this.request("GET", `/api/v1/users?${params.toString()}`);
227
+ }
228
+ async getUser(id) {
229
+ return this.request("GET", `/api/v1/users/${id}`);
230
+ }
231
+ async createUser(data) {
232
+ return this.request("POST", "/api/v1/users", data);
233
+ }
234
+ async updateUser(id, data) {
235
+ return this.request("PUT", `/api/v1/users/${id}`, data);
236
+ }
237
+ async deleteUser(id) {
238
+ await this.request("DELETE", `/api/v1/users/${id}`);
239
+ }
240
+ async setUserPassword(id, password) {
241
+ await this.request("PUT", `/api/v1/users/${id}/password`, { password });
242
+ }
243
+ async assignRole(userId, roleId) {
244
+ return this.request("POST", `/api/v1/users/${userId}/roles`, { roleId });
245
+ }
246
+ async removeRole(userId, roleId) {
247
+ return this.request("DELETE", `/api/v1/users/${userId}/roles/${roleId}`);
248
+ }
249
+ async listRoles() {
250
+ return this.request("GET", "/api/v1/roles");
251
+ }
252
+ async getSettings(group) {
253
+ const query = group ? `?group=${encodeURIComponent(group)}` : "";
254
+ return this.request("GET", `/api/v1/settings${query}`);
255
+ }
256
+ async updateSettings(items) {
257
+ await this.request("PUT", "/api/v1/settings", items);
258
+ }
259
+ async healthCheck() {
260
+ return this.request("GET", "/health");
261
+ }
262
+ async getThemes() {
263
+ return (await this.request("GET", "/api/v1/themes")).map((theme) => ({
264
+ id: String(theme["id"] ?? ""),
265
+ name: String(theme["name"] ?? ""),
266
+ version: theme["version"] ? String(theme["version"]) : void 0,
267
+ status: String(theme["status"] ?? "INSTALLED"),
268
+ manifest: theme["manifest"] ?? null
269
+ }));
270
+ }
271
+ };
272
+ var apiClient = new ApiClient();
273
+ //#endregion
274
+ export { apiClient as t };
@@ -0,0 +1,30 @@
1
+ import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
2
+ import { d as maybeRenderHead, i as renderComponent, u as renderTemplate } from "./server_CnzC2Y0K.mjs";
3
+ import { t as createComponent } from "./compiler_CYjwXhLT.mjs";
4
+ import { t as $$DashboardLayout } from "./DashboardLayout_DO66tdeZ.mjs";
5
+ import { t as ContentEditor } from "./ContentEditor_DwBpNq-K.mjs";
6
+ //#region src/pages/content/edit.astro
7
+ var edit_exports = /* @__PURE__ */ __exportAll({
8
+ default: () => $$Edit,
9
+ file: () => $$file,
10
+ url: () => $$url
11
+ });
12
+ var $$Edit = createComponent(($$result, $$props, $$slots) => {
13
+ return renderTemplate`${renderComponent($$result, "DashboardLayout", $$DashboardLayout, {
14
+ "title": "Editor de Conteúdo",
15
+ "data-astro-cid-4zhgedtj": true
16
+ }, { "default": ($$result) => renderTemplate`${maybeRenderHead($$result)}<div class="editor-page" data-astro-cid-4zhgedtj>${renderComponent($$result, "ContentEditor", ContentEditor, {
17
+ "client:load": true,
18
+ "data-astro-cid-4zhgedtj": true,
19
+ "client:component-hydration": "load",
20
+ "client:component-path": "/home/runner/work/cms/cms/apps/admin/src/components/content/ContentEditor.tsx",
21
+ "client:component-export": "ContentEditor"
22
+ })}</div>` })}`;
23
+ }, "/home/runner/work/cms/cms/apps/admin/src/pages/content/edit.astro", void 0);
24
+ var $$file = "/home/runner/work/cms/cms/apps/admin/src/pages/content/edit.astro";
25
+ var $$url = "/content/edit";
26
+ //#endregion
27
+ //#region \0virtual:astro:page:src/pages/content/edit@_@astro
28
+ var page = () => edit_exports;
29
+ //#endregion
30
+ export { page };