@webx-ui/module-blog 0.7.3 → 0.8.1

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.
package/dist/index.js CHANGED
@@ -1,3037 +1,27 @@
1
- import { useAdmin as ue, useTranslate as Y, useDates as xt, useErrorText as be, useEditing as kt, WxScreenHead as rt, WxEditingAlerts as $t, WxScreen as ut, WxSaveState as ct, WxDate as He, WxDrafts as Tt, rowMenuWidth as dt, WxListScreen as je, WxRowMenu as Ie, WxAddressNote as At, WxFilterChips as St, useBodyKeys as Wt, categoryRoutes as Ct } from "@webx-ui/module-admin";
2
- import { provide as Vt, inject as qt, defineComponent as ie, useModel as Ze, computed as f, openBlock as y, createElementBlock as G, createVNode as r, unref as e, createBlock as U, withCtx as n, createTextVNode as N, toDisplayString as S, createCommentVNode as J, mergeModels as Qe, ref as V, watch as he, onMounted as ze, onBeforeUnmount as Pe, Fragment as _e, createElementVNode as F, renderList as Ue, normalizeClass as qe, normalizeProps as Nt, guardReactiveProps as zt, useTemplateRef as Be, nextTick as Xe, isRef as Ee, withKeys as De, createSlots as Pt, useId as Ut, withModifiers as nt } from "vue";
3
- import { RouterLink as Mt, useRoute as Me, useRouter as Oe, onBeforeRouteLeave as vt, onBeforeRouteUpdate as Rt } from "vue-router";
4
- import { WxSelect as $e, useLocales as Ye, localizedValue as pt, confirm as pe, WxSkeleton as Ne, WxCard as et, WxBadge as re, WxBreadcrumb as It, WxBreadcrumbItem as it, WxActionBar as tt, WxButton as le, toast as O, WxEmpty as Je, WxText as ve, WxSortableList as Dt, WxAction as Bt, WxInput as We, WxAlert as Ge, WxFormItem as me, useModal as Le, WxDialog as Fe, WxSpace as Ke, useElementWidth as Et, createModal as Re, WxTable as ht, WxEntityCard as Ot, WxIcon as ke, WxTooltip as gt, WxListDetail as Lt, WxAvatar as Ft, WxCheckbox as Kt } from "@webx-ui/core";
5
- import { provideBlocksPreview as Ht } from "@webx-ui/module-blocks";
6
- const ft = /* @__PURE__ */ Symbol("wx-article-editor");
7
- function Jt(w) {
8
- Vt(ft, w);
9
- }
10
- function Ce() {
11
- return qt(ft, null);
12
- }
13
- const Gt = {
14
- module: {
15
- group: "Blog",
16
- articles: "Articles",
17
- rubrics: "Rubrics",
18
- tags: "Tags",
19
- authors: "Authors",
20
- author: "Author"
21
- },
22
- panel: {
23
- new: "New article",
24
- search: "Search by title or address",
25
- empty: "No articles yet.",
26
- "empty-search": "Nothing matches that.",
27
- "empty-bin": "The bin is empty.",
28
- "column-title": "Title",
29
- "column-rubrics": "Rubrics",
30
- "column-author": "Author",
31
- "column-date": "Date",
32
- "column-status": "Status",
33
- "column-deleted": "Deleted",
34
- "status-draft": "Draft",
35
- "status-scheduled": "Scheduled",
36
- "status-published": "Live",
37
- "status-modified": "Live",
38
- "status-unpublished": "Off the site",
39
- edits: "edits",
40
- pinned: "Pinned to the top",
41
- "no-address": "The address appears when it is published",
42
- "no-author": "Nobody",
43
- "view-all": "All",
44
- "view-published": "Live",
45
- "view-scheduled": "Scheduled",
46
- "view-draft": "Drafts",
47
- "view-unpublished": "Off the site",
48
- bin: "Bin",
49
- "filter-rubric": "Rubric",
50
- "filter-tag": "Tag",
51
- "filter-author": "Author",
52
- "any-rubric": "Any rubric",
53
- "any-tag": "Any tag",
54
- "any-author": "Any author",
55
- open: "Open",
56
- "open-on-site": "Open on the site",
57
- "copy-address": "Copy the address",
58
- pin: "Pin to the top",
59
- unpin: "Unpin",
60
- publish: "Publish",
61
- unpublish: "Take off the site",
62
- delete: "Delete",
63
- restore: "Restore",
64
- cancel: "Cancel",
65
- "delete-title": "Delete “:title”?",
66
- "delete-text": "It goes to the bin and comes off the site, and its address is free again.",
67
- deleted: "The article is in the bin.",
68
- restored: "The article is back.",
69
- published: "The article is on the site.",
70
- "unpublished-done": "The article is off the site.",
71
- "pinned-done": "Pinned to the top.",
72
- unpinned: "No longer pinned.",
73
- "address-copied": "The address is on the clipboard.",
74
- "new-title": "New article",
75
- "field-title": "Title",
76
- create: "Create"
77
- },
78
- article: {
79
- trail: "Where this article sits",
80
- untitled: "Untitled",
81
- save: "Save",
82
- "save-failed": "The article was not saved.",
83
- schedule: "Schedule",
84
- scheduled: "The article is scheduled.",
85
- "publish-title": "Put “:title” on the site?",
86
- "publish-text": "It answers at :address from the moment you do, for everyone.",
87
- "publish-later": "It goes on the site on :date and not before. Until then nothing changes.",
88
- "publish-nowhere": "It has no address in this language yet, so nothing will answer.",
89
- "publish-now": "now",
90
- preview: "Preview",
91
- more: "More",
92
- discard: "Discard changes",
93
- discarded: "The article is back to what is published.",
94
- "conflict-title": "The article changed while you were editing",
95
- "conflict-mine": "Keep mine",
96
- "conflict-theirs": "Take the newer version",
97
- "conflict-theirs-title": "Give up what you wrote?",
98
- "conflict-theirs-text": "The article is read again as it now is, and what you have typed since goes.",
99
- leave: "Leave",
100
- "leave-title": "Leave without saving?",
101
- "leave-text": "The article could not be saved, and what you wrote is not on the server.",
102
- "live-scheduled": "Goes out :date",
103
- "live-since": "On the site since :date",
104
- "unpublish-title": "Take “:title” off the site?",
105
- "unpublish-text": "It stops answering at its address. The draft, the history and the rubrics stay — publishing puts it back.",
106
- "unpublish-waiting": "It has not gone out yet. The day it was set for will pass without it.",
107
- "unpublish-help": "Takes the article off the site without deleting it.",
108
- "address-moving": "The address is changing. The old one keeps working and leads to the new one.",
109
- author: "Author",
110
- "no-author": "Nobody",
111
- rubrics: "Rubrics",
112
- "rubrics-empty": "In no rubric yet.",
113
- "rubric-main": "Main",
114
- "rubric-add": "Add a rubric",
115
- "rubric-remove": "Take out of this rubric",
116
- "rubric-none-left": "Every rubric is already on this article.",
117
- "tags-empty": "No tags yet.",
118
- "tag-add": "Find or make a tag",
119
- "tag-remove": "Take this tag off",
120
- "tag-option": ":title · :count",
121
- "tag-nothing": "No tag is spelled that way.",
122
- "tag-create": "Make “:title”",
123
- related: "Related",
124
- "related-empty": "Nothing pinned by hand.",
125
- "related-add": "Find an article",
126
- "related-remove": "Unpin",
127
- "related-nothing": "Nothing matches that.",
128
- "history-empty": "This article has never been published.",
129
- version: "#:number",
130
- "version-live": "On the site",
131
- "source-panel": "From the panel",
132
- "source-mcp": "By an agent",
133
- "source-import": "Imported",
134
- "restore-title": "Restore version :number?",
135
- "restore-text": "It becomes the draft. The site keeps showing what is published until you publish this.",
136
- "restore-version": "Restore",
137
- "restored-version": "Version :number is now the draft."
138
- },
139
- rubric: {
140
- new: "New rubric",
141
- empty: "No rubrics yet.",
142
- "empty-help": "A rubric is a section of the blog. An article can be in several of them.",
143
- order: "The order here is the order on the site",
144
- hidden: "Hidden from the site",
145
- "no-address": "No address in this language",
146
- articles: ":count articles",
147
- "show-articles": "Show its articles",
148
- edit: "Edit",
149
- "tab-content": "Content",
150
- "tab-seo": "SEO",
151
- "field-title": "Name",
152
- "field-slug": "Address",
153
- visible: "Show on the site",
154
- "visible-help": "Hidden, it drops out of the menu and answers 404. Its articles go on answering at their own addresses.",
155
- "field-lead": "Introduction",
156
- "lead-help": "Printed above the list of articles.",
157
- "cover-help": "Shown wherever the site lists the sections.",
158
- "address-moving": "The address is changing. The old one keeps working and leads to the new one.",
159
- "seo-help": "Left empty, the title and the description of this page come from the SEO rules.",
160
- delete: "Delete",
161
- "delete-blocked": "While it holds articles it cannot go — move them first.",
162
- "delete-title": "Delete “:name”?",
163
- "delete-text": "It goes to the bin and comes off the site, and its address is free again.",
164
- deleted: "The rubric is in the bin.",
165
- cancel: "Cancel",
166
- save: "Save",
167
- saved: "The rubric is saved.",
168
- created: "The rubric is made.",
169
- "reorder-failed": "The new order was not saved."
170
- },
171
- author: {
172
- "tab-profile": "Profile",
173
- "field-name": "Name on the site",
174
- "field-name-help": "What readers see under the articles and on the page. Required in the main language.",
175
- "field-role": "Role",
176
- "field-bio": "About",
177
- "field-bio-help": "A few lines for the author's page.",
178
- "card-page": "On the site",
179
- "field-photo": "Photo",
180
- "field-public": "Page on the site",
181
- "field-public-help": "With it, the name under the articles links to a page with all of the author's articles. Without it, the name is plain text.",
182
- "field-slug": "Address",
183
- "field-slug-help": "The last part of the page's address, after …/author/.",
184
- "account-missing": "Choose the account this profile is for.",
185
- "account-taken": "This account already has a profile.",
186
- "name-required": "Write the name in the main language.",
187
- new: "New author",
188
- search: "Search by name",
189
- empty: "No authors yet.",
190
- "empty-help": "A profile gives an administrator who writes a name for readers, a photo and, if they want it, a page with their articles.",
191
- "empty-search": "Nothing matches that.",
192
- choose: "Choose an author",
193
- "choose-help": "Or add a new one: pick the account and write the name.",
194
- account: "Account",
195
- "account-help": "Whose articles these are. Chosen once.",
196
- "no-accounts": "Every account already has a profile.",
197
- articles: "Articles: :count",
198
- "page-open": "Page on the site",
199
- "page-closed": "No page",
200
- "open-page": "Open the page",
201
- save: "Save",
202
- saved: "Saved",
203
- "save-failed": "Check the highlighted fields",
204
- delete: "Delete",
205
- "delete-title": "Delete the profile of :name?",
206
- "delete-text": "The articles stay; under them the account's name is shown instead.",
207
- deleted: "Profile deleted",
208
- cancel: "Cancel",
209
- back: "Authors",
210
- "leave-title": "Leave without saving?",
211
- "leave-text": "The changes to this profile will be lost.",
212
- leave: "Leave",
213
- untitled: "Without a name",
214
- profile: "Author profile",
215
- "make-profile": "Make a profile",
216
- "field-socials": "Networks",
217
- "field-socials-help": "Shown on the author's page, and named to search engines as the same person.",
218
- "socials-add": "Add a network",
219
- "socials-empty": "No networks yet.",
220
- "social-network": "Network",
221
- "social-url": "Address",
222
- "social-network-missing": "Choose the network.",
223
- "social-url-invalid": "An address that starts with https://."
224
- },
225
- tag: {
226
- new: "New tag",
227
- "new-title": "New tag",
228
- "field-title": "Name",
229
- "field-slug": "Address",
230
- "field-slug-help": "Left empty, it is made out of the name.",
231
- create: "Create",
232
- cancel: "Cancel",
233
- search: "Search by word or address",
234
- empty: "No tags yet.",
235
- "no-address": "No address in this language",
236
- "column-title": "Name",
237
- "column-address": "Address",
238
- "column-articles": "Articles",
239
- "column-indexing": "Indexing",
240
- "view-all": "All",
241
- "view-empty": "Nothing filed",
242
- "view-noindex": "Not indexed",
243
- "sort-articles": "Most used",
244
- "sort-name": "A to Z",
245
- "indexing-open": "indexed",
246
- "indexing-rule": "indexed — SEO rule",
247
- "indexing-noindex": "noindex",
248
- "indexing-rule-help": "A rule in the SEO section covers this address, so the page is in the index however this tag is set.",
249
- rename: "Rename",
250
- renamed: "The tag is renamed.",
251
- index: "Index",
252
- noindex: "Keep out of the index",
253
- indexed: "The tag page is in the index.",
254
- "kept-out": "The tag page is out of the index.",
255
- "indexed-many": ":count tag pages are in the index.",
256
- "kept-out-many": ":count tag pages are out of the index.",
257
- "open-on-site": "Open on the site",
258
- "show-articles": "Show its articles",
259
- delete: "Delete",
260
- "delete-title": "Delete “:title”?",
261
- "delete-text": "A tag has no bin: it is gone for good.",
262
- "delete-text-used": "It is on :count articles and comes off all of them. A tag has no bin: it is gone for good.",
263
- deleted: "The tag is gone.",
264
- "delete-many-title": "Delete :count tags?",
265
- "delete-many-text": "A tag has no bin: they are gone for good.",
266
- "delete-many-text-used": "They are on :count articles between them and come off all of them. A tag has no bin.",
267
- "deleted-many": ":count tags are gone.",
268
- selected: ":count selected",
269
- clear: "Clear the selection",
270
- merge: "Merge into one",
271
- merged: ":count articles now carry “:tag”.",
272
- "merge-title": "Merge tags",
273
- "merge-keep": "Which tag to keep",
274
- "merge-redirect": "Redirect the old addresses",
275
- "merge-redirect-help": ":addresses will answer 301.",
276
- "merge-redirect-none": "These tags have no address in this language, so there is nothing to redirect.",
277
- "merge-warning": ":count articles will carry “:tag” instead. :merged tags will be deleted, and there is no undoing it.",
278
- "merge-confirm": "Merge"
279
- }
280
- }, st = /* @__PURE__ */ new WeakSet();
281
- function se() {
282
- try {
283
- const { i18n: w } = ue();
284
- st.has(w) || (w.defaults("webx-blog", Gt), st.add(w));
285
- } catch {
286
- }
287
- }
288
- const jt = { class: "wx-article-author" }, Zt = /* @__PURE__ */ ie({
289
- name: "WxArticleAuthor",
290
- __name: "ArticleAuthor",
291
- props: /* @__PURE__ */ Qe({
292
- disabled: { type: Boolean, default: !1 }
293
- }, {
294
- modelValue: { default: null },
295
- modelModifiers: {}
296
- }),
297
- emits: ["update:modelValue"],
298
- setup(w) {
299
- const d = w, c = Ze(w, "modelValue"), o = Ce();
300
- se();
301
- const a = Y("webx-blog"), i = ue(), t = f(() => d.disabled || o?.disabled.value === !0), v = f(
302
- () => (o?.options.value.authors ?? []).map((p) => ({
303
- label: p.title,
304
- value: p.id
305
- }))
306
- ), l = f(() => {
307
- if (!i.state.manifest?.modules.some((u) => u.id === "authors") || !i.can("blog.authors.manage") || c.value === null) return null;
308
- const h = o?.base ?? "/blog", k = o?.options.value.authors.find((u) => u.id === c.value)?.profile;
309
- return k ? {
310
- to: { path: `${h}/authors`, query: { author: String(k) } },
311
- label: a("author.profile")
312
- } : {
313
- to: { path: `${h}/authors`, query: { author: "new", account: String(c.value) } },
314
- label: a("author.make-profile")
315
- };
316
- }), m = f({
317
- get: () => c.value,
318
- set: (p) => {
319
- c.value = typeof p == "number" ? p : null;
320
- }
321
- });
322
- return (p, h) => (y(), G("div", jt, [
323
- r(e($e), {
324
- modelValue: m.value,
325
- "onUpdate:modelValue": h[0] || (h[0] = (k) => m.value = k),
326
- options: v.value,
327
- placeholder: e(a)("article.no-author"),
328
- disabled: t.value,
329
- clearable: "",
330
- filterable: "",
331
- teleport: "",
332
- "aria-label": e(a)("article.author")
333
- }, null, 8, ["modelValue", "options", "placeholder", "disabled", "aria-label"]),
334
- l.value ? (y(), U(e(Mt), {
335
- key: 0,
336
- class: "wx-article-author__profile",
337
- to: l.value.to
338
- }, {
339
- default: n(() => [
340
- N(S(l.value.label), 1)
341
- ]),
342
- _: 1
343
- }, 8, ["to"])) : J("", !0)
344
- ]));
345
- }
346
- }), de = (w, d) => {
347
- const c = w.__vccOpts || w;
348
- for (const [o, a] of d)
349
- c[o] = a;
350
- return c;
351
- }, Qt = /* @__PURE__ */ de(Zt, [["__scopeId", "data-v-4b275a4c"]]);
352
- function ye(w) {
353
- const d = `${w.apiPath}/blog/articles`, c = `${w.apiPath}/blog/tags`, o = (a) => a.data;
354
- return {
355
- articles: (a = {}) => {
356
- const i = new URLSearchParams();
357
- a.q && i.set("q", a.q), a.rubric != null && i.set("rubric", String(a.rubric)), a.tag != null && i.set("tag", String(a.tag)), a.author != null && i.set("author", String(a.author)), a.status && i.set("status", a.status), a.sort && i.set("sort", a.sort), a.trashed && i.set("trashed", "1"), a.page && a.page > 1 && i.set("page", String(a.page)), a.per_page && i.set("per_page", String(a.per_page));
358
- const t = i.size > 0 ? `?${i}` : "";
359
- return w.http.get(`${d}${t}`).then((v) => ({ ...v.meta, data: v.data, filters: v.filters }));
360
- },
361
- get: (a) => w.http.get(`${d}/${a}`).then(o),
362
- create: (a) => w.http.post(d, a).then(o),
363
- save: (a, i) => w.http.put(`${d}/${a}`, i).then(o),
364
- discard: (a) => w.http.post(`${d}/${a}/discard`, {}).then(o),
365
- versions: (a) => w.http.get(`${d}/${a}/versions`).then(o),
366
- restoreVersion: (a, i) => w.http.post(`${d}/${a}/versions/${i}/restore`, {}).then(o),
367
- tags: (a = "") => {
368
- const i = a.trim() === "" ? "" : `?q=${encodeURIComponent(a.trim())}`;
369
- return w.http.get(`${c}${i}`).then(o);
370
- },
371
- createTag: (a) => w.http.post(c, a).then(o),
372
- publish: (a, i, t) => w.http.post(`${d}/${a}/publish`, {
373
- ...i == null ? {} : { at: i },
374
- ...t ? { revision: t } : {}
375
- }).then(o),
376
- unpublish: (a) => w.http.post(`${d}/${a}/unpublish`, {}).then(o),
377
- remove: (a) => w.http.delete(`${d}/${a}`).then(() => {
378
- }),
379
- restore: (a) => w.http.post(`${d}/${a}/restore`, {}).then(o),
380
- tagsPage: (a = {}) => {
381
- const i = new URLSearchParams();
382
- a.q && i.set("q", a.q), a.empty && i.set("empty", "1"), a.noindex && i.set("noindex", "1"), a.sort && i.set("sort", a.sort), a.page && a.page > 1 && i.set("page", String(a.page)), a.per_page && i.set("per_page", String(a.per_page));
383
- const t = i.size > 0 ? `?${i}` : "";
384
- return w.http.get(`${c}${t}`).then((v) => ({ ...v.meta, data: v.data, filters: v.filters }));
385
- },
386
- saveTag: (a, i) => w.http.put(`${c}/${a}`, i).then(o),
387
- removeTag: (a) => w.http.delete(`${c}/${a}`).then(() => {
388
- }),
389
- massTags: (a, i) => w.http.post(`${c}/mass`, { ids: a, action: i }).then((t) => t.data.affected),
390
- mergeTags: (a, i, t) => w.http.post(`${c}/merge`, { ids: a, keep: i, redirect: t }).then(o)
391
- };
392
- }
393
- const Xt = { class: "wx-article-editor__screen" }, Yt = 1200, ea = /* @__PURE__ */ ie({
394
- __name: "ArticleEditorPage",
395
- props: {
396
- base: { default: "/blog" }
397
- },
398
- setup(w) {
399
- const d = w, c = ue(), o = ye(c), a = Me(), i = Oe(), t = Ye(), v = xt();
400
- se();
401
- const l = Y("webx-blog"), m = Y("webx-admin"), p = be(), h = f(() => Number(a.params.id)), k = f(() => `${d.base}/articles`), u = V(null), T = V({}), W = V(""), E = V(""), B = V(null), _ = V({ rubrics: [], authors: [] }), q = V([]), M = V(!0), $ = V(!1), g = V(!1), z = V({}), L = V(""), Q = V(0), te = f(() => c.can("blog.articles.manage")), K = kt({
402
- entity: "articles",
403
- id: () => u.value?.id,
404
- values: T,
405
- revision: W,
406
- read: async () => {
407
- const A = await o.get(h.value);
408
- return { values: A.values, revision: A.revision };
409
- },
410
- adopt: (A) => {
411
- L.value = JSON.stringify(A.values), Q.value += 1;
412
- },
413
- // Published or restored by somebody else: the badge and the address follow, and the form
414
- // stays as it is.
415
- refresh: () => Ve(),
416
- restore: async () => {
417
- u.value && await o.restore(u.value.id);
418
- },
419
- canWrite: () => te.value,
420
- busy: () => $.value || ee !== void 0,
421
- screen: "blog.article-form"
422
- }), ce = K.conflict, oe = f(() => !te.value || g.value), ne = f(() => JSON.stringify(T.value)), X = f(() => L.value !== "" && ne.value !== L.value), we = f(() => $.value ? "saving" : X.value ? "unsaved" : "saved"), C = f(() => {
423
- const A = T.value.title;
424
- return pt(A, t.active.value, u.value?.title ?? "");
425
- }), I = f(() => {
426
- const A = T.value.published_at;
427
- return typeof A == "string" && A !== "" ? A : null;
428
- }), j = f(() => {
429
- if (I.value === null) return !1;
430
- const A = new Date(I.value.replace(" ", "T"));
431
- return !Number.isNaN(A.valueOf()) && A.valueOf() > Date.now();
432
- }), ge = f(() => {
433
- const A = u.value;
434
- if (!A) return "";
435
- const H = v.short(A.published_at);
436
- return {
437
- scheduled: l("article.live-scheduled", { date: H }),
438
- published: l("article.live-since", { date: H }),
439
- modified: l("article.live-since", { date: H })
440
- }[A.status] ?? "";
441
- });
442
- Ht({ url: f(() => B.value), reload: Q }), Jt({
443
- article: u,
444
- values: T,
445
- options: _,
446
- related: q,
447
- prefix: E,
448
- base: d.base,
449
- canManage: te.value,
450
- disabled: oe,
451
- reload: () => ae(!0),
452
- save: () => s()
453
- });
454
- function xe(A) {
455
- u.value = A.article, T.value = A.values, W.value = A.revision, E.value = A.prefix, B.value = A.preview_url, _.value = A.options, q.value = A.related, L.value = JSON.stringify(A.values), K.opened(A.values), ce.value = null;
456
- }
457
- async function ae(A = !1) {
458
- A || (M.value = !0);
459
- try {
460
- xe(await o.get(h.value));
461
- } catch (H) {
462
- O.danger(p(H)), i.push(k.value);
463
- } finally {
464
- M.value = !1;
465
- }
466
- }
467
- async function Ve() {
468
- try {
469
- const A = await o.get(h.value);
470
- u.value = A.article, E.value = A.prefix, B.value = A.preview_url;
471
- } catch {
472
- }
473
- }
474
- let b;
475
- function D() {
476
- !te.value || ce.value || !X.value || K.stopped.value || (clearTimeout(b), b = setTimeout(() => {
477
- s();
478
- }, Yt));
479
- }
480
- function P() {
481
- !te.value || ce.value || !X.value || $.value || K.stopped.value || (clearTimeout(b), s());
482
- }
483
- let ee;
484
- async function s() {
485
- for (; ee; ) {
486
- const { carried: Z, done: fe } = ee;
487
- if (await fe, !X.value || ce.value || ne.value === Z) return;
488
- }
489
- const A = ne.value, H = R();
490
- ee = { carried: A, done: H };
491
- try {
492
- await H;
493
- } finally {
494
- ee?.done === H && (ee = void 0);
495
- }
496
- }
497
- async function R() {
498
- if (!u.value || !te.value) return;
499
- clearTimeout(b);
500
- const A = ne.value, H = T.value;
501
- $.value = !0, z.value = {};
502
- try {
503
- const Z = await o.save(u.value.id, { values: H, revision: W.value });
504
- u.value = Z.article, W.value = Z.revision, E.value = Z.prefix, B.value = Z.preview_url, _.value = Z.options, q.value = Z.related, ce.value = null, ne.value === A && (L.value = A), K.opened(H), Q.value += 1;
505
- } catch (Z) {
506
- const fe = Z;
507
- if (fe.status === 409 && fe.body?.data) {
508
- const Se = fe.body.data;
509
- K.refused({
510
- values: Se.values,
511
- revision: Se.revision,
512
- changed: fe.body.changed
513
- }) && (u.value = Se.article, s());
514
- } else fe.body?.errors ? (z.value = fe.body.errors, O.danger(l("article.save-failed"))) : await K.failed(Z) || O.danger(p(Z));
515
- } finally {
516
- $.value = !1;
517
- }
518
- }
519
- async function x() {
520
- await ae(!0);
521
- }
522
- async function Te() {
523
- if (!(!u.value || !await pe({
524
- title: m("editor.discard-title"),
525
- message: m("editor.discard-text"),
526
- confirmText: l("article.discard"),
527
- // Not «Cancel»: beside «Discard changes» the two read as the same word.
528
- cancelText: m("editor.keep-changes"),
529
- tone: "danger"
530
- }))) {
531
- g.value = !0;
532
- try {
533
- xe(await o.discard(u.value.id)), O.success(l("article.discarded"));
534
- } catch (H) {
535
- O.danger(p(H));
536
- } finally {
537
- g.value = !1;
538
- }
539
- }
540
- }
541
- async function Ae() {
542
- if (X.value && await s(), ce.value || X.value || !u.value) return;
543
- const A = await K.beforePublish();
544
- if (!A) return;
545
- const H = u.value, Z = H.next_path ?? H.path, fe = H.next_path != null && H.path !== null ? ` ${m("editor.publish-moves", { old: `/${H.path}` })}` : "", Se = Z === null ? null : `/${Z}`, _t = I.value === null ? l("article.publish-now") : v.short(I.value);
546
- if (A.asked || await pe({
547
- title: l("article.publish-title", { title: H.title }),
548
- message: j.value ? l("article.publish-later", { date: _t }) : Se === null ? l("article.publish-nowhere") : l("article.publish-text", { address: Se }) + fe,
549
- confirmText: j.value ? l("article.schedule") : l("panel.publish"),
550
- cancelText: l("panel.cancel")
551
- })) {
552
- g.value = !0;
553
- try {
554
- await o.publish(H.id, I.value, A.revision), await ae(!0), O.success(j.value ? l("article.scheduled") : l("panel.published"));
555
- } catch (lt) {
556
- await K.failed(lt) || O.danger(p(lt));
557
- } finally {
558
- g.value = !1;
559
- }
560
- }
561
- }
562
- async function bt() {
563
- const A = u.value;
564
- if (!(!A || !await pe({
565
- title: m("editor.unpublish-title"),
566
- message: m("editor.unpublish-text"),
567
- confirmText: m("editor.unpublish"),
568
- cancelText: m("editor.keep-published")
569
- }))) {
570
- g.value = !0;
571
- try {
572
- await o.unpublish(A.id), await ae(!0), O.success(m("editor.unpublished"));
573
- } catch (Z) {
574
- O.danger(p(Z));
575
- } finally {
576
- g.value = !1;
577
- }
578
- }
579
- }
580
- function yt() {
581
- const A = u.value?.status;
582
- return A === "published" ? "success" : A === "modified" ? "warning" : A === "scheduled" ? "primary" : "default";
583
- }
584
- function at(A) {
585
- X.value && A.preventDefault();
586
- }
587
- he(ne, D), he(h, () => {
588
- ae();
589
- }), ze(() => {
590
- ae(), window.addEventListener("beforeunload", at);
591
- }), Pe(() => {
592
- clearTimeout(b), window.removeEventListener("beforeunload", at);
593
- }), vt(async () => !X.value || !te.value || (await s(), !X.value) ? !0 : await pe({
594
- title: l("article.leave-title"),
595
- message: l("article.leave-text"),
596
- confirmText: l("article.leave"),
597
- cancelText: l("panel.cancel"),
598
- tone: "danger"
599
- }));
600
- const wt = f(() => {
601
- const A = [];
602
- return B.value && A.push({ key: "preview", label: l("article.preview"), icon: "eye", href: B.value }), u.value?.url && u.value.status !== "draft" && A.push({
603
- key: "site",
604
- label: l("panel.open-on-site"),
605
- icon: "link",
606
- href: u.value.url
607
- }), te.value && (u.value?.status === "published" || u.value?.status === "modified") && A.push({
608
- key: "unpublish",
609
- label: m("editor.unpublish"),
610
- icon: "eye-off",
611
- run: () => {
612
- bt();
613
- }
614
- }), u.value?.status === "modified" && A.push({
615
- key: "discard",
616
- label: l("article.discard"),
617
- icon: "refresh",
618
- danger: !0,
619
- menu: !0,
620
- run: () => {
621
- Te();
622
- }
623
- }), A;
624
- });
625
- return (A, H) => (y(), G("div", {
626
- class: "wx-article-editor",
627
- onFocusout: P
628
- }, [
629
- M.value || !u.value ? (y(), G(_e, { key: 0 }, [
630
- r(e(Ne), {
631
- class: "wx-article-editor__ghost",
632
- title: "",
633
- rows: 1
634
- }),
635
- r(e(et), null, {
636
- default: n(() => [
637
- r(e(Ne), { rows: 8 })
638
- ]),
639
- _: 1
640
- })
641
- ], 64)) : (y(), G(_e, { key: 1 }, [
642
- r(e(rt), {
643
- divider: "",
644
- back: k.value,
645
- "back-label": e(l)("module.articles"),
646
- title: C.value || e(l)("article.untitled"),
647
- subtitle: ge.value,
648
- actions: wt.value
649
- }, {
650
- trail: n(() => [
651
- r(e(It), {
652
- size: "sm",
653
- label: e(l)("article.trail")
654
- }, {
655
- default: n(() => [
656
- r(e(it), {
657
- as: "router-link",
658
- to: k.value
659
- }, {
660
- default: n(() => [
661
- N(S(e(l)("module.articles")), 1)
662
- ]),
663
- _: 1
664
- }, 8, ["to"]),
665
- r(e(it), { current: "" }, {
666
- default: n(() => [
667
- N(S(C.value || e(l)("article.untitled")), 1)
668
- ]),
669
- _: 1
670
- })
671
- ]),
672
- _: 1
673
- }, 8, ["label"])
674
- ]),
675
- "title-after": n(() => [
676
- r(e(re), {
677
- type: yt(),
678
- dot: ""
679
- }, {
680
- default: n(() => [
681
- N(S(e(l)(`panel.status-${u.value.status}`)), 1)
682
- ]),
683
- _: 1
684
- }, 8, ["type"]),
685
- u.value.status === "modified" ? (y(), U(e(re), {
686
- key: 0,
687
- type: "primary",
688
- round: ""
689
- }, {
690
- default: n(() => [
691
- N(S(e(l)("panel.edits")), 1)
692
- ]),
693
- _: 1
694
- })) : J("", !0)
695
- ]),
696
- _: 1
697
- }, 8, ["back", "back-label", "title", "subtitle", "actions"]),
698
- r(e($t), {
699
- editing: e(K),
700
- onSave: s,
701
- onTheirs: x
702
- }, null, 8, ["editing"]),
703
- F("div", Xt, [
704
- r(e(ut), {
705
- modelValue: T.value,
706
- "onUpdate:modelValue": H[0] || (H[0] = (Z) => T.value = Z),
707
- name: "blog.article-form",
708
- errors: z.value,
709
- disabled: oe.value
710
- }, null, 8, ["modelValue", "errors", "disabled"])
711
- ]),
712
- te.value ? (y(), U(e(tt), { key: 0 }, {
713
- state: n(() => [
714
- e(K).stopped.value ? J("", !0) : (y(), U(e(ct), {
715
- key: 0,
716
- state: we.value
717
- }, null, 8, ["state"]))
718
- ]),
719
- default: n(() => [
720
- r(e(le), {
721
- variant: "outline",
722
- loading: $.value,
723
- disabled: !X.value || e(K).stopped.value,
724
- title: e(K).blocked.value,
725
- onClick: s
726
- }, {
727
- default: n(() => [
728
- N(S(e(l)("article.save")), 1)
729
- ]),
730
- _: 1
731
- }, 8, ["loading", "disabled", "title"]),
732
- r(e(le), {
733
- type: "primary",
734
- loading: g.value,
735
- disabled: e(K).stopped.value || u.value.status === "published" && !X.value,
736
- title: e(K).blocked.value,
737
- onClick: Ae
738
- }, {
739
- default: n(() => [
740
- N(S(j.value ? e(l)("article.schedule") : e(l)("panel.publish")), 1)
741
- ]),
742
- _: 1
743
- }, 8, ["loading", "disabled", "title"])
744
- ]),
745
- _: 1
746
- })) : J("", !0)
747
- ], 64))
748
- ], 32));
749
- }
750
- }), ta = /* @__PURE__ */ de(ea, [["__scopeId", "data-v-49f5a61d"]]), aa = { class: "wx-article-history-tab" }, la = { class: "wx-article-history" }, na = { class: "wx-article-history__number" }, ia = { class: "wx-article-history__who" }, sa = /* @__PURE__ */ ie({
751
- name: "WxArticleHistory",
752
- __name: "ArticleHistory",
753
- setup(w) {
754
- const d = ue(), c = ye(d), o = Ce();
755
- se();
756
- const a = Y("webx-blog"), i = be(), t = V(null), v = V(!1), l = f(() => o?.article.value ?? null), m = f(() => d.can("blog.articles.manage")), p = f(
757
- () => l.value?.status === "published" || l.value?.status === "modified" ? t.value?.[0]?.number ?? null : null
758
- );
759
- async function h() {
760
- const u = l.value;
761
- if (u)
762
- try {
763
- t.value = await c.versions(u.id);
764
- } catch (T) {
765
- t.value = [], O.danger(i(T));
766
- }
767
- }
768
- async function k(u) {
769
- const T = l.value;
770
- if (!(!T || !await pe({
771
- title: a("article.restore-title", { number: u.number }),
772
- message: a("article.restore-text"),
773
- confirmText: a("article.restore-version"),
774
- cancelText: a("panel.cancel")
775
- }))) {
776
- v.value = !0;
777
- try {
778
- await c.restoreVersion(T.id, u.number), await o?.reload(), O.success(a("article.restored-version", { number: u.number }));
779
- } catch (E) {
780
- O.danger(i(E));
781
- } finally {
782
- v.value = !1;
783
- }
784
- }
785
- }
786
- return he(
787
- () => [l.value?.id, l.value?.published_at, l.value?.updated_at],
788
- () => {
789
- h();
790
- },
791
- { immediate: !0 }
792
- ), (u, T) => (y(), G("div", aa, [
793
- F("div", la, [
794
- t.value === null ? (y(), U(e(Ne), {
795
- key: 0,
796
- class: "wx-article-history__ghost",
797
- rows: 3
798
- })) : t.value.length === 0 ? (y(), U(e(Je), {
799
- key: 1,
800
- description: e(a)("article.history-empty")
801
- }, null, 8, ["description"])) : (y(!0), G(_e, { key: 2 }, Ue(t.value, (W) => (y(), G("div", {
802
- key: W.number,
803
- class: qe(["wx-article-history__row", { "is-live": W.number === p.value }])
804
- }, [
805
- F("code", na, S(e(a)("article.version", { number: W.number })), 1),
806
- F("div", ia, [
807
- W.created_at ? (y(), U(e(He), {
808
- key: 0,
809
- value: W.created_at,
810
- size: "md",
811
- tone: "default"
812
- }, null, 8, ["value"])) : J("", !0),
813
- r(e(ve), {
814
- size: "sm",
815
- tone: "muted"
816
- }, {
817
- default: n(() => [
818
- N(S(W.author ?? e(a)(`article.source-${W.source}`)) + " ", 1),
819
- W.comment ? (y(), G(_e, { key: 0 }, [
820
- N(" · " + S(W.comment), 1)
821
- ], 64)) : J("", !0)
822
- ]),
823
- _: 2
824
- }, 1024)
825
- ]),
826
- W.number === p.value ? (y(), U(e(re), {
827
- key: 0,
828
- type: "success",
829
- dot: ""
830
- }, {
831
- default: n(() => [
832
- N(S(e(a)("article.version-live")), 1)
833
- ]),
834
- _: 1
835
- })) : J("", !0),
836
- m.value && W.number !== p.value ? (y(), U(e(le), {
837
- key: 1,
838
- size: "sm",
839
- variant: "outline",
840
- loading: v.value,
841
- onClick: (E) => k(W)
842
- }, {
843
- default: n(() => [
844
- N(S(e(a)("article.restore-version")), 1)
845
- ]),
846
- _: 1
847
- }, 8, ["loading", "onClick"])) : J("", !0)
848
- ], 2))), 128))
849
- ]),
850
- r(e(Tt), {
851
- id: l.value?.id,
852
- entity: "articles",
853
- screen: "blog.article-form",
854
- "can-restore": m.value,
855
- stamp: [l.value?.published_at, l.value?.updated_at],
856
- onRestored: T[0] || (T[0] = (W) => e(o)?.reload())
857
- }, null, 8, ["id", "can-restore", "stamp"])
858
- ]));
859
- }
860
- }), oa = /* @__PURE__ */ de(sa, [["__scopeId", "data-v-0052c4f9"]]), ra = { class: "wx-article-related" }, ua = { class: "wx-article-related__name" }, ca = 250, da = 10, va = /* @__PURE__ */ ie({
861
- name: "WxArticleRelated",
862
- __name: "ArticleRelated",
863
- props: /* @__PURE__ */ Qe({
864
- disabled: { type: Boolean, default: !1 }
865
- }, {
866
- modelValue: { default: () => [] },
867
- modelModifiers: {}
868
- }),
869
- emits: ["update:modelValue"],
870
- setup(w) {
871
- const d = w, c = Ze(w, "modelValue"), o = ue(), a = ye(o), i = Ce();
872
- se();
873
- const t = Y("webx-blog"), v = be(), l = f(() => d.disabled || i?.disabled.value === !0), m = V(/* @__PURE__ */ new Map()), p = V([]);
874
- let h;
875
- he(
876
- () => i?.related.value,
877
- (_) => {
878
- const q = new Map(m.value);
879
- for (const M of _ ?? []) q.set(M.id, M.title);
880
- m.value = q;
881
- },
882
- { immediate: !0, deep: !0 }
883
- );
884
- const k = f({
885
- get: () => c.value.map((_) => ({ id: _, title: m.value.get(_) ?? `#${_}` })),
886
- set: (_) => {
887
- c.value = _.map((q) => q.id);
888
- }
889
- }), u = f(
890
- () => p.value.filter((_) => !c.value.includes(_.id)).map((_) => ({ label: _.title, value: _.id }))
891
- );
892
- async function T(_) {
893
- const q = i?.article.value?.id;
894
- try {
895
- const M = await a.articles({ q: _, per_page: da });
896
- p.value = M.data.filter((g) => g.id !== q).map((g) => ({ id: g.id, title: g.title }));
897
- const $ = new Map(m.value);
898
- for (const g of p.value) $.set(g.id, g.title);
899
- m.value = $;
900
- } catch (M) {
901
- O.danger(v(M));
902
- }
903
- }
904
- function W(_) {
905
- clearTimeout(h), h = setTimeout(() => {
906
- T(_);
907
- }, ca);
908
- }
909
- function E(_) {
910
- typeof _ != "number" || c.value.includes(_) || (c.value = [...c.value, _]);
911
- }
912
- function B(_) {
913
- c.value = c.value.filter((q) => q !== _);
914
- }
915
- return he(
916
- () => i?.article.value?.id,
917
- () => {
918
- T("");
919
- },
920
- { immediate: !0 }
921
- ), Pe(() => clearTimeout(h)), (_, q) => (y(), G("div", ra, [
922
- r(e(Dt), {
923
- modelValue: k.value,
924
- "onUpdate:modelValue": q[0] || (q[0] = (M) => k.value = M),
925
- plain: "",
926
- size: "sm",
927
- "item-key": "id",
928
- "item-label": "title",
929
- disabled: l.value,
930
- "empty-text": e(t)("article.related-empty"),
931
- "aria-label": e(t)("article.related")
932
- }, {
933
- default: n(({ item: M }) => [
934
- F("span", ua, S(M.title), 1)
935
- ]),
936
- actions: n(({ item: M }) => [
937
- r(e(Bt), {
938
- type: "remove",
939
- size: "sm",
940
- disabled: l.value,
941
- title: e(t)("article.related-remove"),
942
- onClick: ($) => B(M.id)
943
- }, null, 8, ["disabled", "title", "onClick"])
944
- ]),
945
- _: 1
946
- }, 8, ["modelValue", "disabled", "empty-text", "aria-label"]),
947
- r(e($e), {
948
- "model-value": null,
949
- options: u.value,
950
- placeholder: e(t)("article.related-add"),
951
- "empty-text": e(t)("article.related-nothing"),
952
- disabled: l.value,
953
- filterable: "",
954
- teleport: "",
955
- "aria-label": e(t)("article.related-add"),
956
- onSearch: W,
957
- "onUpdate:modelValue": E
958
- }, null, 8, ["options", "placeholder", "empty-text", "disabled", "aria-label"])
959
- ]));
960
- }
961
- }), pa = /* @__PURE__ */ de(va, [["__scopeId", "data-v-164e86fe"]]), ha = { class: "wx-article-slug" }, ga = { class: "wx-article-slug__prefix" }, fa = /* @__PURE__ */ ie({
962
- name: "WxArticleSlug",
963
- inheritAttrs: !1,
964
- __name: "ArticleSlug",
965
- setup(w) {
966
- const d = Ce(), c = Ye();
967
- se();
968
- const o = Y("webx-blog"), a = f(() => {
969
- const v = d?.prefix.value ?? "";
970
- return v === "" ? "/" : `/${v}/`;
971
- }), i = f(() => {
972
- const v = d?.values.value.slug;
973
- return typeof v == "string" ? v : v?.[c.active.value] ?? "";
974
- }), t = f(() => {
975
- const v = d?.article.value?.path;
976
- return typeof v == "string" && i.value !== "" && `${a.value}${i.value}` != `/${v}`;
977
- });
978
- return (v, l) => (y(), G("div", ha, [
979
- r(e(We), Nt(zt(v.$attrs)), {
980
- prefix: n(() => [
981
- F("span", ga, S(a.value), 1)
982
- ]),
983
- _: 1
984
- }, 16),
985
- t.value ? (y(), U(e(Ge), {
986
- key: 0,
987
- type: "info",
988
- variant: "soft",
989
- description: e(o)("article.address-moving")
990
- }, null, 8, ["description"])) : J("", !0)
991
- ]));
992
- }
993
- }), ma = /* @__PURE__ */ de(fa, [["__scopeId", "data-v-5da20e5e"]]), ba = { class: "wx-article-tags" }, ya = {
994
- key: 0,
995
- class: "wx-article-tags__chips"
996
- }, wa = { class: "wx-article-tags__pick" }, _a = 250, xa = /* @__PURE__ */ ie({
997
- name: "WxArticleTags",
998
- __name: "ArticleTags",
999
- props: /* @__PURE__ */ Qe({
1000
- disabled: { type: Boolean, default: !1 }
1001
- }, {
1002
- modelValue: { default: () => [] },
1003
- modelModifiers: {}
1004
- }),
1005
- emits: ["update:modelValue"],
1006
- setup(w) {
1007
- const d = w, c = Ze(w, "modelValue"), o = ue(), a = ye(o), i = Ce();
1008
- se();
1009
- const t = Y("webx-blog"), v = be(), l = f(() => d.disabled || i?.disabled.value === !0), m = V(/* @__PURE__ */ new Map()), p = V([]), h = V(""), k = V(!1);
1010
- let u;
1011
- he(
1012
- () => i?.article.value?.tags,
1013
- (g) => {
1014
- const z = new Map(m.value);
1015
- for (const L of g ?? []) z.set(L.id, L.title);
1016
- m.value = z;
1017
- },
1018
- { immediate: !0, deep: !0 }
1019
- );
1020
- const T = f(
1021
- () => c.value.map((g) => ({ id: g, title: m.value.get(g) ?? `#${g}` }))
1022
- ), W = f(
1023
- () => p.value.filter((g) => !c.value.includes(g.id)).map((g) => ({
1024
- // The count is part of the label rather than a column: a select draws a line of text, and
1025
- // the number is what the reader is choosing between two near-identical words on.
1026
- label: t("article.tag-option", { title: g.title, count: g.articles_count }),
1027
- value: g.id
1028
- }))
1029
- ), E = f(() => {
1030
- const g = h.value.trim();
1031
- if (g === "") return null;
1032
- const z = (L) => L.toLowerCase() === g.toLowerCase();
1033
- return p.value.some((L) => z(L.title)) ? null : g;
1034
- });
1035
- async function B() {
1036
- try {
1037
- p.value = await a.tags(h.value);
1038
- const g = new Map(m.value);
1039
- for (const z of p.value) g.set(z.id, z.title);
1040
- m.value = g;
1041
- } catch (g) {
1042
- O.danger(v(g));
1043
- }
1044
- }
1045
- function _(g) {
1046
- h.value = g, clearTimeout(u), u = setTimeout(() => {
1047
- B();
1048
- }, _a);
1049
- }
1050
- function q(g) {
1051
- typeof g != "number" || c.value.includes(g) || (c.value = [...c.value, g], h.value = "");
1052
- }
1053
- function M(g) {
1054
- c.value = c.value.filter((z) => z !== g);
1055
- }
1056
- async function $() {
1057
- const g = E.value;
1058
- if (!(g === null || k.value)) {
1059
- k.value = !0;
1060
- try {
1061
- const z = await a.createTag({ title: g });
1062
- m.value = new Map(m.value).set(z.id, z.title), p.value = [z, ...p.value], q(z.id);
1063
- } catch (z) {
1064
- O.danger(v(z));
1065
- } finally {
1066
- k.value = !1;
1067
- }
1068
- }
1069
- }
1070
- return he(
1071
- () => i?.article.value?.id,
1072
- () => {
1073
- B();
1074
- },
1075
- { immediate: !0 }
1076
- ), Pe(() => clearTimeout(u)), (g, z) => (y(), G("div", ba, [
1077
- T.value.length > 0 ? (y(), G("div", ya, [
1078
- (y(!0), G(_e, null, Ue(T.value, (L) => (y(), U(e(re), {
1079
- key: L.id,
1080
- type: "default",
1081
- closable: !l.value,
1082
- "close-label": e(t)("article.tag-remove"),
1083
- onClose: (Q) => M(L.id)
1084
- }, {
1085
- default: n(() => [
1086
- N(S(L.title), 1)
1087
- ]),
1088
- _: 2
1089
- }, 1032, ["closable", "close-label", "onClose"]))), 128))
1090
- ])) : (y(), U(e(ve), {
1091
- key: 1,
1092
- size: "sm",
1093
- tone: "muted"
1094
- }, {
1095
- default: n(() => [
1096
- N(S(e(t)("article.tags-empty")), 1)
1097
- ]),
1098
- _: 1
1099
- })),
1100
- F("div", wa, [
1101
- r(e($e), {
1102
- "model-value": null,
1103
- options: W.value,
1104
- placeholder: e(t)("article.tag-add"),
1105
- "empty-text": e(t)("article.tag-nothing"),
1106
- disabled: l.value,
1107
- filterable: "",
1108
- teleport: "",
1109
- "aria-label": e(t)("article.tag-add"),
1110
- onSearch: _,
1111
- "onUpdate:modelValue": q
1112
- }, null, 8, ["options", "placeholder", "empty-text", "disabled", "aria-label"]),
1113
- E.value ? (y(), U(e(le), {
1114
- key: 0,
1115
- variant: "outline",
1116
- icon: "plus",
1117
- loading: k.value,
1118
- disabled: l.value,
1119
- onClick: $
1120
- }, {
1121
- default: n(() => [
1122
- N(S(e(t)("article.tag-create", { title: E.value })), 1)
1123
- ]),
1124
- _: 1
1125
- }, 8, ["loading", "disabled"])) : J("", !0)
1126
- ])
1127
- ]));
1128
- }
1129
- }), ka = /* @__PURE__ */ de(xa, [["__scopeId", "data-v-faf5adec"]]), $a = /* @__PURE__ */ ie({
1130
- name: "WxArticleUnpublish",
1131
- __name: "ArticleUnpublish",
1132
- setup(w) {
1133
- const d = ue(), c = ye(d), o = Ce();
1134
- se();
1135
- const a = Y("webx-blog"), i = be(), t = V(!1), v = f(() => {
1136
- const p = o?.article.value?.status;
1137
- return p === "published" || p === "modified" || p === "scheduled";
1138
- }), l = f(() => o?.disabled.value === !0 || t.value);
1139
- async function m() {
1140
- const p = o?.article.value;
1141
- if (!(!p || !await pe({
1142
- title: a("article.unpublish-title", { title: p.title }),
1143
- message: p.status === "scheduled" ? a("article.unpublish-waiting") : a("article.unpublish-text"),
1144
- confirmText: a("panel.unpublish"),
1145
- cancelText: a("panel.cancel"),
1146
- tone: "danger"
1147
- }))) {
1148
- t.value = !0;
1149
- try {
1150
- await c.unpublish(p.id), await o?.reload(), O.success(a("panel.unpublished-done"));
1151
- } catch (k) {
1152
- O.danger(i(k));
1153
- } finally {
1154
- t.value = !1;
1155
- }
1156
- }
1157
- }
1158
- return (p, h) => v.value && e(o)?.canManage ? (y(), U(e(me), {
1159
- key: 0,
1160
- class: "wx-article-unpublish",
1161
- help: e(a)("article.unpublish-help")
1162
- }, {
1163
- default: n(() => [
1164
- r(e(le), {
1165
- variant: "outline",
1166
- type: "danger",
1167
- icon: "eye-off",
1168
- loading: t.value,
1169
- disabled: l.value,
1170
- onClick: m
1171
- }, {
1172
- default: n(() => [
1173
- N(S(e(a)("panel.unpublish")), 1)
1174
- ]),
1175
- _: 1
1176
- }, 8, ["loading", "disabled"])
1177
- ]),
1178
- _: 1
1179
- }, 8, ["help"])) : J("", !0);
1180
- }
1181
- }), Ta = /* @__PURE__ */ de($a, [["__scopeId", "data-v-c311cff2"]]), Aa = /* @__PURE__ */ ie({
1182
- __name: "ArticleCreateDialog",
1183
- setup(w) {
1184
- const { open: d, resolve: c, dismiss: o } = Le(), a = ue(), i = ye(a);
1185
- se();
1186
- const t = Y("webx-blog"), v = V(""), l = V(!1), m = V({}), p = Be("field");
1187
- ze(async () => {
1188
- await Xe(), p.value?.querySelector("input")?.focus();
1189
- });
1190
- async function h() {
1191
- if (!(v.value.trim() === "" || l.value)) {
1192
- l.value = !0, m.value = {};
1193
- try {
1194
- c(await i.create({ title: v.value.trim() }));
1195
- } catch (k) {
1196
- m.value = k.body?.errors ?? {};
1197
- } finally {
1198
- l.value = !1;
1199
- }
1200
- }
1201
- }
1202
- return (k, u) => (y(), U(e(Fe), {
1203
- open: e(d),
1204
- "onUpdate:open": u[2] || (u[2] = (T) => Ee(d) ? d.value = T : null),
1205
- title: e(t)("panel.new-title"),
1206
- width: 440
1207
- }, {
1208
- footer: n(() => [
1209
- r(e(Ke), { size: "sm" }, {
1210
- default: n(() => [
1211
- r(e(le), {
1212
- variant: "outline",
1213
- onClick: u[1] || (u[1] = (T) => e(o)())
1214
- }, {
1215
- default: n(() => [
1216
- N(S(e(t)("panel.cancel")), 1)
1217
- ]),
1218
- _: 1
1219
- }),
1220
- r(e(le), {
1221
- type: "primary",
1222
- loading: l.value,
1223
- disabled: v.value.trim() === "",
1224
- onClick: h
1225
- }, {
1226
- default: n(() => [
1227
- N(S(e(t)("panel.create")), 1)
1228
- ]),
1229
- _: 1
1230
- }, 8, ["loading", "disabled"])
1231
- ]),
1232
- _: 1
1233
- })
1234
- ]),
1235
- default: n(() => [
1236
- r(e(me), {
1237
- label: e(t)("panel.field-title"),
1238
- error: m.value.title?.[0] ?? m.value.slug?.[0],
1239
- required: ""
1240
- }, {
1241
- default: n(() => [
1242
- F("div", {
1243
- ref_key: "field",
1244
- ref: p
1245
- }, [
1246
- r(e(We), {
1247
- modelValue: v.value,
1248
- "onUpdate:modelValue": u[0] || (u[0] = (T) => v.value = T),
1249
- "aria-label": e(t)("panel.field-title"),
1250
- onKeyup: De(h, ["enter"])
1251
- }, null, 8, ["modelValue", "aria-label"])
1252
- ], 512)
1253
- ]),
1254
- _: 1
1255
- }, 8, ["label", "error"])
1256
- ]),
1257
- _: 1
1258
- }, 8, ["open", "title"]));
1259
- }
1260
- }), Sa = ["src"], Wa = { class: "wx-articles__name" }, Ca = { class: "wx-articles__name-text" }, Va = { class: "wx-articles__title" }, qa = { class: "wx-articles__address" }, Na = { class: "wx-articles__chips" }, za = { class: "wx-articles__state" }, ot = 640, Pa = /* @__PURE__ */ ie({
1261
- __name: "ArticlesPage",
1262
- props: {
1263
- base: { default: "/blog" }
1264
- },
1265
- setup(w) {
1266
- const d = w, c = ue(), o = ye(c), a = Me(), i = Oe();
1267
- se();
1268
- const t = Y("webx-blog"), v = Y("webx-admin"), l = be(), m = Be("root"), p = Et(m), h = V(null), k = V(!0), u = Re(Aa), T = f(() => c.can("blog.articles.manage")), W = f(
1269
- () => c.state.manifest?.modules.find((s) => s.id === "articles")?.title ?? t("module.articles")
1270
- ), E = f({
1271
- get: () => typeof a.query.view == "string" ? a.query.view : "",
1272
- set: (s) => {
1273
- i.replace({
1274
- query: { ...a.query, view: s === "" ? void 0 : String(s), page: void 0 }
1275
- });
1276
- }
1277
- }), B = f(() => E.value === "trashed"), _ = f(() => ({
1278
- q: typeof a.query.q == "string" ? a.query.q : "",
1279
- rubric: q(a.query.rubric),
1280
- tag: q(a.query.tag),
1281
- author: q(a.query.author),
1282
- sort: typeof a.query.sort == "string" ? a.query.sort : null,
1283
- page: Number(a.query.page ?? 1) || 1
1284
- }));
1285
- function q(s) {
1286
- return typeof s == "string" && s !== "" && Number(s) || null;
1287
- }
1288
- const M = f(() => [
1289
- { value: "", label: t("panel.view-all") },
1290
- { value: "published", label: t("panel.view-published") },
1291
- { value: "scheduled", label: t("panel.view-scheduled") },
1292
- { value: "draft", label: t("panel.view-draft") },
1293
- { value: "unpublished", label: t("panel.view-unpublished") },
1294
- { value: "trashed", label: t("panel.bin"), icon: "trash" }
1295
- ]), $ = f(() => h.value?.filters ?? { rubrics: [], tags: [], authors: [] }), g = f(() => p.value > 0 && p.value < ot), z = f(() => g.value ? [{ key: "card", label: "" }] : [
1296
- { key: "cover", label: "", width: 68 },
1297
- /* The one that takes what the others leave, and the only one without a number. */
1298
- { key: "title", label: t("panel.column-title"), minWidth: 220 },
1299
- { key: "rubrics", label: t("panel.column-rubrics"), width: 190, hideBelow: 1e3 },
1300
- { key: "author", label: t("panel.column-author"), width: 160, hideBelow: 1200 },
1301
- {
1302
- key: "date",
1303
- label: B.value ? t("panel.column-deleted") : t("panel.column-date"),
1304
- width: 120,
1305
- hideBelow: 700,
1306
- // "today at 16:22" is three words the table will break over two lines given half a
1307
- // chance, and a date read down a column has to be one line to be read at all.
1308
- cellClass: "wx-articles__when"
1309
- },
1310
- { key: "status", label: t("panel.column-status"), width: 170 },
1311
- { key: "actions", label: "", width: dt, align: "right" }
1312
- ]), L = f(() => _.value.q !== "" ? t("panel.empty-search") : B.value ? t("panel.empty-bin") : t("panel.empty")), Q = f(() => {
1313
- const s = [], R = $.value.rubrics.find((Ae) => Ae.id === _.value.rubric);
1314
- R && s.push({
1315
- key: "rubric",
1316
- label: `${t("panel.filter-rubric")}: ${R.title}`,
1317
- clear: () => oe("rubric", void 0)
1318
- });
1319
- const x = $.value.tags.find((Ae) => Ae.id === _.value.tag);
1320
- x && s.push({
1321
- key: "tag",
1322
- label: `${t("panel.filter-tag")}: ${x.title}`,
1323
- clear: () => oe("tag", void 0)
1324
- });
1325
- const Te = $.value.authors.find((Ae) => Ae.id === _.value.author);
1326
- return Te && s.push({
1327
- key: "author",
1328
- label: `${t("panel.filter-author")}: ${Te.title}`,
1329
- clear: () => oe("author", void 0)
1330
- }), s;
1331
- });
1332
- function te() {
1333
- i.replace({
1334
- query: {
1335
- ...a.query,
1336
- rubric: void 0,
1337
- tag: void 0,
1338
- author: void 0,
1339
- page: void 0
1340
- }
1341
- });
1342
- }
1343
- async function K(s) {
1344
- k.value = !0;
1345
- try {
1346
- h.value = await o.articles({
1347
- q: s?.search ?? _.value.q,
1348
- status: B.value ? "" : E.value,
1349
- trashed: B.value,
1350
- rubric: _.value.rubric,
1351
- tag: _.value.tag,
1352
- author: _.value.author,
1353
- sort: s?.sort ? `${s.sort.order === "desc" ? "-" : ""}${s.sort.key}` : null,
1354
- page: s?.page ?? _.value.page,
1355
- per_page: s?.perPage
1356
- });
1357
- } catch (R) {
1358
- O.danger(l(R));
1359
- } finally {
1360
- k.value = !1;
1361
- }
1362
- }
1363
- function ce(s) {
1364
- const R = {
1365
- ...a.query,
1366
- q: s.search === "" ? void 0 : s.search,
1367
- sort: s.sort === null ? void 0 : `${s.sort.order === "desc" ? "-" : ""}${s.sort.key}`,
1368
- page: s.page === 1 ? void 0 : String(s.page)
1369
- };
1370
- i.replace({ query: R }), K(s);
1371
- }
1372
- function oe(s, R) {
1373
- i.replace({
1374
- query: {
1375
- ...a.query,
1376
- [s]: typeof R == "number" ? String(R) : void 0,
1377
- page: void 0
1378
- }
1379
- });
1380
- }
1381
- he(
1382
- [E, () => _.value.rubric, () => _.value.tag, () => _.value.author],
1383
- () => {
1384
- K();
1385
- }
1386
- ), K();
1387
- function ne(s) {
1388
- const R = `${d.base}/articles/${s.id}`;
1389
- i.resolve(R).matched.length > 0 && i.push({ path: R, query: { ...a.query } });
1390
- }
1391
- async function X() {
1392
- const s = await u({});
1393
- s && (await K(), ne(s));
1394
- }
1395
- function we(s) {
1396
- if (!T.value) return [];
1397
- if (B.value)
1398
- return [
1399
- {
1400
- key: "restore",
1401
- icon: "refresh",
1402
- label: t("panel.restore"),
1403
- run: () => {
1404
- xe(s);
1405
- }
1406
- }
1407
- ];
1408
- const R = [
1409
- { key: "open", icon: "edit", label: t("panel.open"), run: () => ne(s) }
1410
- ];
1411
- return s.url && s.status !== "draft" && R.push({
1412
- key: "site",
1413
- icon: "external-link",
1414
- label: t("panel.open-on-site"),
1415
- href: s.url
1416
- }), s.path !== null && R.push({
1417
- key: "copy",
1418
- icon: "copy",
1419
- label: t("panel.copy-address"),
1420
- run: () => {
1421
- Ve(s);
1422
- }
1423
- }), R.push({
1424
- key: "pin",
1425
- icon: "star",
1426
- label: s.pinned ? t("panel.unpin") : t("panel.pin"),
1427
- run: () => {
1428
- j(s, !s.pinned);
1429
- }
1430
- }), R.push(
1431
- s.status === "published" || s.status === "modified" || s.status === "scheduled" ? {
1432
- key: "unpublish",
1433
- icon: "eye-off",
1434
- label: t("panel.unpublish"),
1435
- run: () => {
1436
- I(s);
1437
- }
1438
- } : {
1439
- key: "publish",
1440
- icon: "upload",
1441
- label: t("panel.publish"),
1442
- run: () => {
1443
- C(s);
1444
- }
1445
- }
1446
- ), R.push({
1447
- key: "delete",
1448
- icon: "trash",
1449
- label: t("panel.delete"),
1450
- danger: !0,
1451
- run: () => {
1452
- ge(s);
1453
- }
1454
- }), R;
1455
- }
1456
- async function C(s) {
1457
- await ae(() => o.publish(s.id), t("panel.published"));
1458
- }
1459
- async function I(s) {
1460
- await ae(() => o.unpublish(s.id), t("panel.unpublished-done"));
1461
- }
1462
- async function j(s, R) {
1463
- await ae(
1464
- () => o.save(s.id, { values: { pinned: R }, revision: s.revision }),
1465
- t(R ? "panel.pinned-done" : "panel.unpinned")
1466
- );
1467
- }
1468
- async function ge(s) {
1469
- await pe({
1470
- title: t("panel.delete-title", { title: s.title }),
1471
- message: t("panel.delete-text"),
1472
- confirmText: t("panel.delete"),
1473
- cancelText: t("panel.cancel"),
1474
- tone: "danger"
1475
- }) && await ae(() => o.remove(s.id), t("panel.deleted"));
1476
- }
1477
- async function xe(s) {
1478
- await ae(() => o.restore(s.id), t("panel.restored"));
1479
- }
1480
- async function ae(s, R) {
1481
- try {
1482
- await s(), O.success(R);
1483
- } catch (x) {
1484
- O.danger(l(x));
1485
- } finally {
1486
- await K();
1487
- }
1488
- }
1489
- async function Ve(s) {
1490
- if (s.url)
1491
- try {
1492
- await navigator.clipboard.writeText(s.url), O.success(t("panel.address-copied"));
1493
- } catch {
1494
- }
1495
- }
1496
- function b(s) {
1497
- return s === "published" || s === "modified" ? "success" : s === "scheduled" ? "warning" : "default";
1498
- }
1499
- function D(s) {
1500
- return B.value ? "—" : s.path === null ? t("panel.no-address") : `/${s.path}`;
1501
- }
1502
- function P(s) {
1503
- return B.value ? s.deleted_at : s.published_at;
1504
- }
1505
- const ee = f(
1506
- () => T.value ? [{ key: "new", label: t("panel.new"), icon: "plus", primary: !0, run: () => {
1507
- X();
1508
- } }] : []
1509
- );
1510
- return (s, R) => (y(), G("div", {
1511
- ref_key: "root",
1512
- ref: m,
1513
- class: "wx-articles"
1514
- }, [
1515
- r(e(je), {
1516
- view: E.value,
1517
- "onUpdate:view": R[3] || (R[3] = (x) => E.value = x),
1518
- title: W.value,
1519
- views: M.value,
1520
- actions: ee.value
1521
- }, {
1522
- default: n(() => [
1523
- r(e(ht), {
1524
- data: h.value,
1525
- columns: z.value,
1526
- "row-key": "id",
1527
- searchable: "",
1528
- clickable: !B.value,
1529
- hover: !B.value,
1530
- flush: "",
1531
- loading: k.value,
1532
- layout: "fixed",
1533
- "cards-below": ot,
1534
- "filters-count": Q.value.length,
1535
- "filters-label": e(v)("filters.title"),
1536
- "search-placeholder": e(t)("panel.search"),
1537
- "empty-text": L.value,
1538
- "aria-label": W.value,
1539
- onRowClick: ne,
1540
- onStateChange: ce
1541
- }, {
1542
- filters: n(() => [
1543
- r(e(me), {
1544
- label: e(t)("panel.filter-rubric")
1545
- }, {
1546
- default: n(() => [
1547
- r(e($e), {
1548
- "model-value": _.value.rubric,
1549
- options: $.value.rubrics.map((x) => ({ value: x.id, label: x.title })),
1550
- placeholder: e(t)("panel.any-rubric"),
1551
- clearable: "",
1552
- size: "sm",
1553
- "onUpdate:modelValue": R[0] || (R[0] = (x) => oe("rubric", x))
1554
- }, null, 8, ["model-value", "options", "placeholder"])
1555
- ]),
1556
- _: 1
1557
- }, 8, ["label"]),
1558
- r(e(me), {
1559
- label: e(t)("panel.filter-tag")
1560
- }, {
1561
- default: n(() => [
1562
- r(e($e), {
1563
- "model-value": _.value.tag,
1564
- options: $.value.tags.map((x) => ({ value: x.id, label: x.title })),
1565
- placeholder: e(t)("panel.any-tag"),
1566
- clearable: "",
1567
- filterable: "",
1568
- size: "sm",
1569
- "onUpdate:modelValue": R[1] || (R[1] = (x) => oe("tag", x))
1570
- }, null, 8, ["model-value", "options", "placeholder"])
1571
- ]),
1572
- _: 1
1573
- }, 8, ["label"]),
1574
- r(e(me), {
1575
- label: e(t)("panel.filter-author")
1576
- }, {
1577
- default: n(() => [
1578
- r(e($e), {
1579
- "model-value": _.value.author,
1580
- options: $.value.authors.map((x) => ({ value: x.id, label: x.title })),
1581
- placeholder: e(t)("panel.any-author"),
1582
- clearable: "",
1583
- size: "sm",
1584
- "onUpdate:modelValue": R[2] || (R[2] = (x) => oe("author", x))
1585
- }, null, 8, ["model-value", "options", "placeholder"])
1586
- ]),
1587
- _: 1
1588
- }, 8, ["label"]),
1589
- Q.value.length > 0 ? (y(), U(e(le), {
1590
- key: 0,
1591
- variant: "text",
1592
- size: "sm",
1593
- block: "",
1594
- onClick: te
1595
- }, {
1596
- icon: n(() => [
1597
- r(e(ke), { name: "close" })
1598
- ]),
1599
- default: n(() => [
1600
- N(" " + S(e(v)("filters.reset")), 1)
1601
- ]),
1602
- _: 1
1603
- })) : J("", !0)
1604
- ]),
1605
- applied: n(() => [
1606
- r(e(St), { filters: Q.value }, null, 8, ["filters"])
1607
- ]),
1608
- "cell-cover": n(({ row: x }) => [
1609
- F("span", {
1610
- class: qe(["wx-articles__cover", { "is-empty": !x.cover }])
1611
- }, [
1612
- x.cover?.thumb ? (y(), G("img", {
1613
- key: 0,
1614
- src: x.cover.thumb,
1615
- alt: "",
1616
- loading: "lazy"
1617
- }, null, 8, Sa)) : (y(), U(e(ke), {
1618
- key: 1,
1619
- name: "image",
1620
- size: "sm"
1621
- }))
1622
- ], 2)
1623
- ]),
1624
- "cell-title": n(({ row: x }) => [
1625
- F("div", Wa, [
1626
- x.pinned ? (y(), U(e(gt), {
1627
- key: 0,
1628
- content: e(t)("panel.pinned")
1629
- }, {
1630
- default: n(() => [
1631
- r(e(ke), {
1632
- class: "wx-articles__pin",
1633
- name: "star",
1634
- size: "sm"
1635
- })
1636
- ]),
1637
- _: 1
1638
- }, 8, ["content"])) : J("", !0),
1639
- F("div", Ca, [
1640
- F("span", Va, S(x.title), 1),
1641
- F("span", qa, [
1642
- N(S(D(x)) + " ", 1),
1643
- B.value ? J("", !0) : (y(), U(e(At), {
1644
- key: 0,
1645
- locale: x.address_locale
1646
- }, null, 8, ["locale"]))
1647
- ])
1648
- ])
1649
- ])
1650
- ]),
1651
- "cell-rubrics": n(({ row: x }) => [
1652
- F("span", Na, [
1653
- (y(!0), G(_e, null, Ue(x.rubrics, (Te) => (y(), U(e(re), {
1654
- key: Te.id,
1655
- size: "sm",
1656
- round: ""
1657
- }, {
1658
- default: n(() => [
1659
- N(S(Te.title), 1)
1660
- ]),
1661
- _: 2
1662
- }, 1024))), 128))
1663
- ])
1664
- ]),
1665
- "cell-author": n(({ row: x }) => [
1666
- r(e(ve), {
1667
- size: "sm",
1668
- tone: "muted",
1669
- truncate: ""
1670
- }, {
1671
- default: n(() => [
1672
- N(S(x.author ? x.author.name : "—"), 1)
1673
- ]),
1674
- _: 2
1675
- }, 1024)
1676
- ]),
1677
- "cell-date": n(({ row: x }) => [
1678
- P(x) ? (y(), U(e(He), {
1679
- key: 0,
1680
- value: P(x),
1681
- compact: ""
1682
- }, null, 8, ["value"])) : (y(), U(e(ve), {
1683
- key: 1,
1684
- size: "sm",
1685
- tone: "muted"
1686
- }, {
1687
- default: n(() => [...R[4] || (R[4] = [
1688
- N("—", -1)
1689
- ])]),
1690
- _: 1
1691
- }))
1692
- ]),
1693
- "cell-status": n(({ row: x }) => [
1694
- F("span", za, [
1695
- r(e(re), {
1696
- type: b(x.status),
1697
- dot: "",
1698
- size: "sm"
1699
- }, {
1700
- default: n(() => [
1701
- N(S(e(t)(`panel.status-${x.status}`)), 1)
1702
- ]),
1703
- _: 2
1704
- }, 1032, ["type"]),
1705
- x.status === "modified" ? (y(), U(e(re), {
1706
- key: 0,
1707
- type: "primary",
1708
- size: "sm",
1709
- round: ""
1710
- }, {
1711
- default: n(() => [
1712
- N(S(e(t)("panel.edits")), 1)
1713
- ]),
1714
- _: 1
1715
- })) : J("", !0)
1716
- ])
1717
- ]),
1718
- "cell-card": n(({ row: x }) => [
1719
- r(e(Ot), {
1720
- class: "wx-articles__entity",
1721
- variant: "plain",
1722
- title: x.title,
1723
- image: x.cover?.thumb ?? void 0,
1724
- "image-size": "56px",
1725
- "title-lines": 2,
1726
- subtitle: D(x)
1727
- }, {
1728
- title: n(() => [
1729
- x.pinned ? (y(), U(e(ke), {
1730
- key: 0,
1731
- class: "wx-articles__pin",
1732
- name: "star",
1733
- size: "sm"
1734
- })) : J("", !0),
1735
- N(" " + S(x.title), 1)
1736
- ]),
1737
- meta: n(() => [
1738
- x.rubrics[0] ? (y(), U(e(re), {
1739
- key: 0,
1740
- size: "sm",
1741
- round: ""
1742
- }, {
1743
- default: n(() => [
1744
- N(S(x.rubrics[0].title), 1)
1745
- ]),
1746
- _: 2
1747
- }, 1024)) : J("", !0),
1748
- r(e(re), {
1749
- type: b(x.status),
1750
- dot: "",
1751
- size: "sm"
1752
- }, {
1753
- default: n(() => [
1754
- N(S(e(t)(`panel.status-${x.status}`)), 1)
1755
- ]),
1756
- _: 2
1757
- }, 1032, ["type"]),
1758
- P(x) ? (y(), U(e(He), {
1759
- key: 1,
1760
- value: P(x)
1761
- }, null, 8, ["value"])) : J("", !0)
1762
- ]),
1763
- _: 2
1764
- }, 1032, ["title", "image", "subtitle"])
1765
- ]),
1766
- "card-actions": n(({ row: x }) => [
1767
- r(e(Ie), {
1768
- actions: we(x),
1769
- label: x.title
1770
- }, null, 8, ["actions", "label"])
1771
- ]),
1772
- "cell-actions": n(({ row: x }) => [
1773
- r(e(Ie), {
1774
- actions: we(x),
1775
- label: x.title
1776
- }, null, 8, ["actions", "label"])
1777
- ]),
1778
- _: 1
1779
- }, 8, ["data", "columns", "clickable", "hover", "loading", "filters-count", "filters-label", "search-placeholder", "empty-text", "aria-label"])
1780
- ]),
1781
- _: 1
1782
- }, 8, ["view", "title", "views", "actions"])
1783
- ], 512));
1784
- }
1785
- }), Ua = /* @__PURE__ */ de(Pa, [["__scopeId", "data-v-5dfe798a"]]);
1786
- function mt(w) {
1787
- const d = `${w.apiPath}/blog/authors`, c = (o) => o.data;
1788
- return {
1789
- list: (o = "") => {
1790
- const a = o.trim() === "" ? "" : `?q=${encodeURIComponent(o.trim())}`;
1791
- return w.http.get(`${d}${a}`).then(c);
1792
- },
1793
- accounts: () => w.http.get(`${d}/accounts`).then(c),
1794
- get: (o) => w.http.get(`${d}/${o}`).then(c),
1795
- create: (o, a) => w.http.post(d, { user_id: o, values: a }).then(c),
1796
- save: (o, a) => w.http.put(`${d}/${o}`, { values: a }).then(c),
1797
- remove: (o) => w.http.delete(`${d}/${o}`).then(() => {
1798
- })
1799
- };
1800
- }
1801
- const Ma = {
1802
- key: 1,
1803
- class: "wx-author__account"
1804
- }, Ra = /* @__PURE__ */ ie({
1805
- name: "WxAuthorPane",
1806
- __name: "AuthorPane",
1807
- props: {
1808
- id: {},
1809
- inline: { type: Boolean, default: !0 }
1810
- },
1811
- emits: ["back", "saved", "created", "removed"],
1812
- setup(w, { emit: d }) {
1813
- const c = w, o = d, a = ue(), i = mt(a), t = Me(), v = Ye();
1814
- se();
1815
- const l = Y("webx-blog"), m = be(), p = V(null), h = V({}), k = V(""), u = V([]), T = V(null), W = V(!0), E = V(!1), B = V({}), _ = f(() => a.can("blog.authors.manage")), q = f(() => JSON.stringify(h.value)), M = f(
1816
- () => k.value !== "" && (q.value !== k.value || T.value !== null)
1817
- ), $ = f(() => E.value ? "saving" : M.value || c.id === null ? "unsaved" : "saved"), g = f(() => {
1818
- const C = h.value.title, I = c.id === null ? l("author.new") : p.value?.name ?? "";
1819
- return pt(C, v.active.value, I) || l("author.untitled");
1820
- }), z = f(
1821
- () => u.value.map((C) => ({
1822
- label: C.articles_count > 0 ? `${C.name} · ${l("author.articles", { count: C.articles_count })}` : C.name,
1823
- value: C.id
1824
- }))
1825
- ), L = f({
1826
- get: () => T.value,
1827
- set: (C) => {
1828
- T.value = typeof C == "number" ? C : null;
1829
- const I = u.value.find((xe) => xe.id === T.value), j = h.value.title, ge = v.list.value[0]?.code;
1830
- I && ge && !(j?.[ge] ?? "").trim() && (h.value = { ...h.value, title: { ...j ?? {}, [ge]: I.name } });
1831
- }
1832
- });
1833
- function Q(C) {
1834
- p.value = C.author, h.value = C.values, k.value = JSON.stringify(C.values), T.value = null;
1835
- }
1836
- async function te() {
1837
- W.value = !0;
1838
- try {
1839
- if (c.id === null) {
1840
- const C = {
1841
- title: {},
1842
- slug: {},
1843
- role: {},
1844
- bio: {},
1845
- photo: null,
1846
- socials: [],
1847
- is_public: !1
1848
- };
1849
- h.value = C, k.value = JSON.stringify(C), u.value = await i.accounts();
1850
- const I = Number(t.query.account);
1851
- u.value.some((j) => j.id === I) && (L.value = I);
1852
- } else
1853
- Q(await i.get(c.id));
1854
- } catch (C) {
1855
- O.danger(m(C)), o("back");
1856
- } finally {
1857
- W.value = !1;
1858
- }
1859
- }
1860
- async function K() {
1861
- if (!(E.value || !_.value)) {
1862
- E.value = !0, B.value = {};
1863
- try {
1864
- const C = c.id === null;
1865
- if (C && T.value === null) {
1866
- B.value = { user_id: [l("author.account-missing")] }, O.danger(l("author.save-failed"));
1867
- return;
1868
- }
1869
- const I = C ? await i.create(T.value, h.value) : await i.save(c.id, h.value);
1870
- Q(I), O.success(l("author.saved")), o(C ? "created" : "saved", I.author);
1871
- } catch (C) {
1872
- const I = C.body;
1873
- I?.errors ? (B.value = I.errors, O.danger(l("author.save-failed"))) : O.danger(m(C));
1874
- } finally {
1875
- E.value = !1;
1876
- }
1877
- }
1878
- }
1879
- async function ce() {
1880
- const C = p.value;
1881
- if (!(!C || !await pe({
1882
- title: l("author.delete-title", { name: C.name }),
1883
- message: l("author.delete-text"),
1884
- confirmText: l("author.delete"),
1885
- cancelText: l("author.cancel"),
1886
- tone: "danger"
1887
- })))
1888
- try {
1889
- await i.remove(C.id), O.success(l("author.deleted")), k.value = q.value, T.value = null, o("removed", C.id);
1890
- } catch (j) {
1891
- O.danger(m(j));
1892
- }
1893
- }
1894
- function oe(C) {
1895
- M.value && C.preventDefault();
1896
- }
1897
- function ne(C) {
1898
- (C.ctrlKey || C.metaKey) && C.key.toLowerCase() === "s" && (C.preventDefault(), (M.value || c.id === null) && K());
1899
- }
1900
- Wt(ne), ze(() => {
1901
- te(), window.addEventListener("beforeunload", oe);
1902
- }), Pe(() => {
1903
- window.removeEventListener("beforeunload", oe);
1904
- });
1905
- async function X() {
1906
- return !M.value || !_.value ? !0 : await pe({
1907
- title: l("author.leave-title"),
1908
- message: l("author.leave-text"),
1909
- confirmText: l("author.leave"),
1910
- cancelText: l("author.cancel"),
1911
- tone: "danger"
1912
- });
1913
- }
1914
- Rt(
1915
- async (C, I) => C.query.author === I.query.author ? !0 : await X()
1916
- ), vt(X);
1917
- const we = f(() => {
1918
- const C = [], I = p.value;
1919
- return I?.open && I.url && C.push({
1920
- key: "open",
1921
- label: l("author.open-page"),
1922
- icon: "external-link",
1923
- run: () => {
1924
- window.open(I.url, "_blank", "noopener");
1925
- }
1926
- }), _.value && I !== null && C.push({
1927
- key: "delete",
1928
- label: l("author.delete"),
1929
- icon: "trash",
1930
- danger: !0,
1931
- menu: !0,
1932
- run: () => {
1933
- ce();
1934
- }
1935
- }), C;
1936
- });
1937
- return (C, I) => (y(), G("div", {
1938
- class: "wx-author",
1939
- onKeydown: ne
1940
- }, [
1941
- W.value ? (y(), U(e(Ne), {
1942
- key: 0,
1943
- class: "wx-author__ghost",
1944
- title: "",
1945
- rows: 6
1946
- })) : (y(), G(_e, { key: 1 }, [
1947
- r(e(rt), {
1948
- level: 3,
1949
- back: !c.inline,
1950
- "back-label": e(l)("author.back"),
1951
- title: g.value,
1952
- actions: we.value,
1953
- "collapse-below": 480,
1954
- onBack: I[0] || (I[0] = (j) => o("back"))
1955
- }, Pt({ _: 2 }, [
1956
- p.value && !p.value.open ? {
1957
- name: "title-after",
1958
- fn: n(() => [
1959
- r(e(re), { dot: "" }, {
1960
- default: n(() => [
1961
- N(S(e(l)("author.page-closed")), 1)
1962
- ]),
1963
- _: 1
1964
- })
1965
- ]),
1966
- key: "0"
1967
- } : void 0
1968
- ]), 1032, ["back", "back-label", "title", "actions"]),
1969
- c.id === null ? (y(), U(e(et), { key: 0 }, {
1970
- default: n(() => [
1971
- r(e(me), {
1972
- label: e(l)("author.account"),
1973
- help: u.value.length === 0 ? e(l)("author.no-accounts") : e(l)("author.account-help"),
1974
- error: B.value.user_id?.[0],
1975
- required: ""
1976
- }, {
1977
- default: n(() => [
1978
- r(e($e), {
1979
- modelValue: L.value,
1980
- "onUpdate:modelValue": I[1] || (I[1] = (j) => L.value = j),
1981
- options: z.value,
1982
- disabled: !_.value || E.value || u.value.length === 0,
1983
- filterable: "",
1984
- teleport: "",
1985
- "aria-label": e(l)("author.account")
1986
- }, null, 8, ["modelValue", "options", "disabled", "aria-label"])
1987
- ]),
1988
- _: 1
1989
- }, 8, ["label", "help", "error"])
1990
- ]),
1991
- _: 1
1992
- })) : p.value?.user ? (y(), G("p", Ma, S(e(l)("author.account")) + ": " + S(p.value.user.name), 1)) : J("", !0),
1993
- r(e(ut), {
1994
- modelValue: h.value,
1995
- "onUpdate:modelValue": I[2] || (I[2] = (j) => h.value = j),
1996
- name: "blog.author-form",
1997
- errors: B.value,
1998
- disabled: !_.value || E.value
1999
- }, null, 8, ["modelValue", "errors", "disabled"]),
2000
- _.value ? (y(), U(e(tt), { key: 2 }, {
2001
- state: n(() => [
2002
- r(e(ct), { state: $.value }, null, 8, ["state"])
2003
- ]),
2004
- default: n(() => [
2005
- r(e(le), {
2006
- type: "primary",
2007
- loading: E.value,
2008
- disabled: !M.value && c.id !== null,
2009
- onClick: K
2010
- }, {
2011
- default: n(() => [
2012
- N(S(e(l)("author.save")), 1)
2013
- ]),
2014
- _: 1
2015
- }, 8, ["loading", "disabled"])
2016
- ]),
2017
- _: 1
2018
- })) : J("", !0)
2019
- ], 64))
2020
- ], 32));
2021
- }
2022
- }), Ia = /* @__PURE__ */ de(Ra, [["__scopeId", "data-v-60f7aa2e"]]), Da = { class: "wx-authors__bar" }, Ba = ["onClick"], Ea = { class: "wx-author-row__body" }, Oa = { class: "wx-author-row__name" }, La = { class: "wx-author-row__meta" }, Fa = { key: 0 }, Ka = { class: "wx-author-row__facts" }, Ha = /* @__PURE__ */ ie({
2023
- __name: "AuthorsPage",
2024
- props: {
2025
- base: { default: "/blog" }
2026
- },
2027
- setup(w) {
2028
- const d = ue(), c = mt(d), o = Me(), a = Oe();
2029
- se();
2030
- const i = Y("webx-blog"), t = be(), v = V([]), l = V(!0), m = f(() => d.can("blog.authors.manage")), p = f(
2031
- () => d.state.manifest?.modules.find(($) => $.id === "authors")?.title ?? i("module.authors")
2032
- ), h = f(() => typeof o.query.q == "string" ? o.query.q : ""), k = V(h.value), u = f(() => {
2033
- const $ = o.query.author;
2034
- return $ === "new" ? m.value ? "new" : null : typeof $ == "string" && $ !== "" && Number($) || null;
2035
- }), T = f({
2036
- get: () => u.value !== null,
2037
- set: ($) => {
2038
- $ || _();
2039
- }
2040
- });
2041
- async function W() {
2042
- l.value = !0;
2043
- try {
2044
- v.value = await c.list(h.value);
2045
- } catch ($) {
2046
- O.danger(t($));
2047
- } finally {
2048
- l.value = !1;
2049
- }
2050
- }
2051
- he(h, () => {
2052
- W();
2053
- }), W();
2054
- let E;
2055
- he(k, ($) => {
2056
- clearTimeout(E), E = setTimeout(() => {
2057
- a.replace({ query: { ...o.query, q: $.trim() === "" ? void 0 : $ } });
2058
- }, 300);
2059
- }), Pe(() => clearTimeout(E));
2060
- function B($) {
2061
- const g = { ...o.query, author: String($) };
2062
- $ !== "new" && delete g.account, a.replace({ query: g });
2063
- }
2064
- function _() {
2065
- const $ = { ...o.query };
2066
- delete $.author, delete $.account, a.replace({ query: $ });
2067
- }
2068
- function q($) {
2069
- B($.id), W();
2070
- }
2071
- function M($) {
2072
- u.value === $ && _(), W();
2073
- }
2074
- return ($, g) => (y(), U(e(je), {
2075
- title: p.value,
2076
- card: !1
2077
- }, {
2078
- default: n(() => [
2079
- r(e(et), {
2080
- class: "wx-authors",
2081
- padding: "none"
2082
- }, {
2083
- default: n(() => [
2084
- r(e(Lt), {
2085
- open: T.value,
2086
- "onUpdate:open": g[2] || (g[2] = (z) => T.value = z),
2087
- class: "wx-authors__panes",
2088
- "list-width": 360,
2089
- "detail-min": 460,
2090
- "detail-label": e(i)("module.authors")
2091
- }, {
2092
- list: n(() => [
2093
- F("div", Da, [
2094
- r(e(We), {
2095
- modelValue: k.value,
2096
- "onUpdate:modelValue": g[0] || (g[0] = (z) => k.value = z),
2097
- class: "wx-authors__search",
2098
- size: "sm",
2099
- clearable: "",
2100
- placeholder: e(i)("author.search"),
2101
- "aria-label": e(i)("author.search")
2102
- }, {
2103
- prefix: n(() => [
2104
- r(e(ke), {
2105
- name: "search",
2106
- size: "sm"
2107
- })
2108
- ]),
2109
- _: 1
2110
- }, 8, ["modelValue", "placeholder", "aria-label"])
2111
- ]),
2112
- m.value ? (y(), G("button", {
2113
- key: 0,
2114
- type: "button",
2115
- class: qe(["wx-authors__new", { "is-current": u.value === "new" }]),
2116
- onClick: g[1] || (g[1] = (z) => B("new"))
2117
- }, [
2118
- r(e(ke), {
2119
- name: "plus",
2120
- size: "sm"
2121
- }),
2122
- N(" " + S(e(i)("author.new")), 1)
2123
- ], 2)) : J("", !0),
2124
- l.value && v.value.length === 0 ? (y(), U(e(Ne), {
2125
- key: 1,
2126
- class: "wx-authors__loading",
2127
- rows: 4
2128
- })) : v.value.length === 0 ? (y(), U(e(Je), {
2129
- key: 2,
2130
- title: h.value === "" ? e(i)("author.empty") : e(i)("author.empty-search"),
2131
- description: h.value === "" ? e(i)("author.empty-help") : void 0
2132
- }, null, 8, ["title", "description"])) : (y(), G("ul", {
2133
- key: 3,
2134
- class: qe(["wx-authors__list", { "is-loading": l.value }])
2135
- }, [
2136
- (y(!0), G(_e, null, Ue(v.value, (z) => (y(), G("li", {
2137
- key: z.id
2138
- }, [
2139
- F("button", {
2140
- type: "button",
2141
- class: qe(["wx-author-row", { "is-current": u.value === z.id }]),
2142
- onClick: (L) => B(z.id)
2143
- }, [
2144
- r(e(Ft), {
2145
- class: "wx-author-row__photo",
2146
- src: z.photo ?? void 0,
2147
- name: z.name,
2148
- size: "md"
2149
- }, null, 8, ["src", "name"]),
2150
- F("span", Ea, [
2151
- F("span", Oa, S(z.name), 1),
2152
- F("span", La, [
2153
- z.user ? (y(), G("span", Fa, S(z.user.name), 1)) : J("", !0),
2154
- F("span", null, S(e(i)("author.articles", { count: z.articles_count })), 1)
2155
- ]),
2156
- F("span", Ka, [
2157
- z.open ? (y(), U(e(re), {
2158
- key: 0,
2159
- dot: "",
2160
- size: "sm",
2161
- type: "success"
2162
- }, {
2163
- default: n(() => [
2164
- N(S(e(i)("author.page-open")), 1)
2165
- ]),
2166
- _: 1
2167
- })) : (y(), U(e(re), {
2168
- key: 1,
2169
- dot: "",
2170
- size: "sm"
2171
- }, {
2172
- default: n(() => [
2173
- N(S(e(i)("author.page-closed")), 1)
2174
- ]),
2175
- _: 1
2176
- }))
2177
- ])
2178
- ])
2179
- ], 10, Ba)
2180
- ]))), 128))
2181
- ], 2))
2182
- ]),
2183
- detail: n(({ inline: z, back: L }) => [
2184
- u.value !== null ? (y(), U(Ia, {
2185
- id: u.value === "new" ? null : u.value,
2186
- key: String(u.value),
2187
- inline: z,
2188
- onBack: L,
2189
- onSaved: W,
2190
- onCreated: q,
2191
- onRemoved: M
2192
- }, null, 8, ["id", "inline", "onBack"])) : J("", !0)
2193
- ]),
2194
- empty: n(() => [
2195
- r(e(Je), {
2196
- title: e(i)("author.choose"),
2197
- description: m.value ? e(i)("author.choose-help") : void 0
2198
- }, null, 8, ["title", "description"])
2199
- ]),
2200
- _: 1
2201
- }, 8, ["open", "detail-label"])
2202
- ]),
2203
- _: 1
2204
- })
2205
- ]),
2206
- _: 1
2207
- }, 8, ["title"]));
2208
- }
2209
- }), Ja = /* @__PURE__ */ de(Ha, [["__scopeId", "data-v-b0022a2f"]]), Ga = /* @__PURE__ */ ie({
2210
- __name: "TagCreateDialog",
2211
- setup(w) {
2212
- const { open: d, resolve: c, dismiss: o } = Le(), a = ue(), i = ye(a);
2213
- se();
2214
- const t = Y("webx-blog"), v = V(""), l = V(""), m = V(!1), p = V({}), h = Be("field");
2215
- ze(async () => {
2216
- await Xe(), h.value?.querySelector("input")?.focus();
2217
- });
2218
- async function k() {
2219
- if (!(v.value.trim() === "" || m.value)) {
2220
- m.value = !0, p.value = {};
2221
- try {
2222
- c(
2223
- await i.createTag({
2224
- title: v.value.trim(),
2225
- ...l.value.trim() === "" ? {} : { slug: l.value.trim() }
2226
- })
2227
- );
2228
- } catch (u) {
2229
- p.value = u.body?.errors ?? {};
2230
- } finally {
2231
- m.value = !1;
2232
- }
2233
- }
2234
- }
2235
- return (u, T) => (y(), U(e(Fe), {
2236
- open: e(d),
2237
- "onUpdate:open": T[3] || (T[3] = (W) => Ee(d) ? d.value = W : null),
2238
- title: e(t)("tag.new-title"),
2239
- width: 440
2240
- }, {
2241
- footer: n(() => [
2242
- r(e(Ke), { size: "sm" }, {
2243
- default: n(() => [
2244
- r(e(le), {
2245
- variant: "outline",
2246
- onClick: T[2] || (T[2] = (W) => e(o)())
2247
- }, {
2248
- default: n(() => [
2249
- N(S(e(t)("tag.cancel")), 1)
2250
- ]),
2251
- _: 1
2252
- }),
2253
- r(e(le), {
2254
- type: "primary",
2255
- loading: m.value,
2256
- disabled: v.value.trim() === "",
2257
- onClick: k
2258
- }, {
2259
- default: n(() => [
2260
- N(S(e(t)("tag.create")), 1)
2261
- ]),
2262
- _: 1
2263
- }, 8, ["loading", "disabled"])
2264
- ]),
2265
- _: 1
2266
- })
2267
- ]),
2268
- default: n(() => [
2269
- r(e(me), {
2270
- label: e(t)("tag.field-title"),
2271
- error: p.value.title?.[0],
2272
- required: ""
2273
- }, {
2274
- default: n(() => [
2275
- F("div", {
2276
- ref_key: "field",
2277
- ref: h
2278
- }, [
2279
- r(e(We), {
2280
- modelValue: v.value,
2281
- "onUpdate:modelValue": T[0] || (T[0] = (W) => v.value = W),
2282
- "aria-label": e(t)("tag.field-title"),
2283
- onKeyup: De(k, ["enter"])
2284
- }, null, 8, ["modelValue", "aria-label"])
2285
- ], 512)
2286
- ]),
2287
- _: 1
2288
- }, 8, ["label", "error"]),
2289
- r(e(me), {
2290
- label: e(t)("tag.field-slug"),
2291
- error: p.value.slug?.[0],
2292
- help: e(t)("tag.field-slug-help")
2293
- }, {
2294
- default: n(() => [
2295
- r(e(We), {
2296
- modelValue: l.value,
2297
- "onUpdate:modelValue": T[1] || (T[1] = (W) => l.value = W),
2298
- "aria-label": e(t)("tag.field-slug"),
2299
- onKeyup: De(k, ["enter"])
2300
- }, null, 8, ["modelValue", "aria-label"])
2301
- ]),
2302
- _: 1
2303
- }, 8, ["label", "error", "help"])
2304
- ]),
2305
- _: 1
2306
- }, 8, ["open", "title"]));
2307
- }
2308
- }), ja = ["id"], Za = /* @__PURE__ */ ie({
2309
- __name: "TagRenameDialog",
2310
- props: {
2311
- name: {}
2312
- },
2313
- setup(w) {
2314
- const d = w, { open: c, resolve: o, dismiss: a } = Le();
2315
- se();
2316
- const i = Y("webx-blog"), t = Y("webx-admin"), v = Ut(), l = V(d.name), m = Be("field");
2317
- ze(async () => {
2318
- await Xe();
2319
- const h = m.value?.querySelector("input");
2320
- h?.focus(), h?.select();
2321
- });
2322
- function p() {
2323
- const h = l.value.trim();
2324
- if (h === "" || h === d.name) {
2325
- a();
2326
- return;
2327
- }
2328
- o(h);
2329
- }
2330
- return (h, k) => (y(), U(e(Fe), {
2331
- open: e(c),
2332
- "onUpdate:open": k[2] || (k[2] = (u) => Ee(c) ? c.value = u : null),
2333
- title: e(i)("tag.rename"),
2334
- width: 420
2335
- }, {
2336
- footer: n(() => [
2337
- r(e(Ke), { size: "sm" }, {
2338
- default: n(() => [
2339
- r(e(le), {
2340
- variant: "outline",
2341
- onClick: k[1] || (k[1] = (u) => e(a)())
2342
- }, {
2343
- default: n(() => [
2344
- N(S(e(i)("tag.cancel")), 1)
2345
- ]),
2346
- _: 1
2347
- }),
2348
- r(e(le), {
2349
- type: "primary",
2350
- "native-type": "submit",
2351
- form: e(v),
2352
- disabled: l.value.trim() === ""
2353
- }, {
2354
- default: n(() => [
2355
- N(S(e(t)("editor.save")), 1)
2356
- ]),
2357
- _: 1
2358
- }, 8, ["form", "disabled"])
2359
- ]),
2360
- _: 1
2361
- })
2362
- ]),
2363
- default: n(() => [
2364
- F("form", {
2365
- id: e(v),
2366
- ref_key: "field",
2367
- ref: m,
2368
- onSubmit: nt(p, ["prevent"])
2369
- }, [
2370
- r(e(me), {
2371
- label: e(i)("tag.field-title"),
2372
- required: ""
2373
- }, {
2374
- default: n(() => [
2375
- r(e(We), {
2376
- modelValue: l.value,
2377
- "onUpdate:modelValue": k[0] || (k[0] = (u) => l.value = u),
2378
- "aria-label": e(i)("tag.field-title"),
2379
- onKeydown: De(nt(p, ["prevent"]), ["enter"])
2380
- }, null, 8, ["modelValue", "aria-label", "onKeydown"])
2381
- ]),
2382
- _: 1
2383
- }, 8, ["label"])
2384
- ], 40, ja)
2385
- ]),
2386
- _: 1
2387
- }, 8, ["open", "title"]));
2388
- }
2389
- }), Qa = { class: "wx-tag-merge" }, Xa = { class: "wx-tag-merge__chips" }, Ya = { class: "wx-tag-merge__redirect" }, el = /* @__PURE__ */ ie({
2390
- __name: "TagMergeDialog",
2391
- props: {
2392
- tags: {}
2393
- },
2394
- setup(w) {
2395
- const d = w, { open: c, resolve: o, dismiss: a } = Le(), i = ue(), t = ye(i);
2396
- se();
2397
- const v = Y("webx-blog"), l = be(), m = V(
2398
- [...d.tags].sort((q, M) => M.articles_count - q.articles_count)[0]?.id ?? 0
2399
- ), p = V(!1), h = V(!0), k = V(null), u = f(
2400
- () => d.tags.map((q) => ({ value: q.id, label: `${q.title} · ${q.articles_count}` }))
2401
- ), T = f(() => d.tags.find((q) => q.id === m.value) ?? null), W = f(() => d.tags.filter((q) => q.id !== m.value)), E = f(() => W.value.reduce((q, M) => q + M.articles_count, 0)), B = f(() => W.value.map((q) => q.path).filter(Boolean));
2402
- async function _() {
2403
- if (!(T.value === null || W.value.length === 0 || p.value)) {
2404
- p.value = !0, k.value = null;
2405
- try {
2406
- o(
2407
- await t.mergeTags(
2408
- W.value.map((q) => q.id),
2409
- m.value,
2410
- h.value
2411
- )
2412
- );
2413
- } catch (q) {
2414
- k.value = l(q);
2415
- } finally {
2416
- p.value = !1;
2417
- }
2418
- }
2419
- }
2420
- return (q, M) => (y(), U(e(Fe), {
2421
- open: e(c),
2422
- "onUpdate:open": M[3] || (M[3] = ($) => Ee(c) ? c.value = $ : null),
2423
- title: e(v)("tag.merge-title"),
2424
- width: 520
2425
- }, {
2426
- footer: n(() => [
2427
- r(e(Ke), { size: "sm" }, {
2428
- default: n(() => [
2429
- r(e(le), {
2430
- variant: "outline",
2431
- onClick: M[2] || (M[2] = ($) => e(a)())
2432
- }, {
2433
- default: n(() => [
2434
- N(S(e(v)("tag.cancel")), 1)
2435
- ]),
2436
- _: 1
2437
- }),
2438
- r(e(le), {
2439
- type: "primary",
2440
- loading: p.value,
2441
- disabled: W.value.length === 0,
2442
- onClick: _
2443
- }, {
2444
- default: n(() => [
2445
- N(S(e(v)("tag.merge-confirm")), 1)
2446
- ]),
2447
- _: 1
2448
- }, 8, ["loading", "disabled"])
2449
- ]),
2450
- _: 1
2451
- })
2452
- ]),
2453
- default: n(() => [
2454
- F("div", Qa, [
2455
- F("div", Xa, [
2456
- (y(!0), G(_e, null, Ue(W.value, ($) => (y(), U(e(re), {
2457
- key: $.id,
2458
- size: "sm",
2459
- round: ""
2460
- }, {
2461
- default: n(() => [
2462
- N(S($.title) + " · " + S($.articles_count), 1)
2463
- ]),
2464
- _: 2
2465
- }, 1024))), 128)),
2466
- r(e(ke), {
2467
- name: "arrow-right",
2468
- size: "sm"
2469
- }),
2470
- T.value ? (y(), U(e(re), {
2471
- key: 0,
2472
- type: "primary",
2473
- size: "sm",
2474
- round: ""
2475
- }, {
2476
- default: n(() => [
2477
- N(S(T.value.title) + " · " + S(T.value.articles_count), 1)
2478
- ]),
2479
- _: 1
2480
- })) : J("", !0)
2481
- ]),
2482
- r(e(me), {
2483
- label: e(v)("tag.merge-keep")
2484
- }, {
2485
- default: n(() => [
2486
- r(e($e), {
2487
- modelValue: m.value,
2488
- "onUpdate:modelValue": M[0] || (M[0] = ($) => m.value = $),
2489
- options: u.value,
2490
- "aria-label": e(v)("tag.merge-keep")
2491
- }, null, 8, ["modelValue", "options", "aria-label"])
2492
- ]),
2493
- _: 1
2494
- }, 8, ["label"]),
2495
- F("div", Ya, [
2496
- r(e(Kt), {
2497
- modelValue: h.value,
2498
- "onUpdate:modelValue": M[1] || (M[1] = ($) => h.value = $),
2499
- label: e(v)("tag.merge-redirect")
2500
- }, null, 8, ["modelValue", "label"]),
2501
- r(e(ve), {
2502
- size: "sm",
2503
- tone: "muted"
2504
- }, {
2505
- default: n(() => [
2506
- N(S(B.value.length === 0 ? e(v)("tag.merge-redirect-none") : e(v)("tag.merge-redirect-help", { addresses: B.value.join(", ") })), 1)
2507
- ]),
2508
- _: 1
2509
- })
2510
- ]),
2511
- r(e(Ge), {
2512
- type: "warning",
2513
- variant: "soft",
2514
- description: e(v)("tag.merge-warning", {
2515
- count: E.value,
2516
- tag: T.value?.title ?? "",
2517
- merged: W.value.length
2518
- })
2519
- }, null, 8, ["description"]),
2520
- k.value ? (y(), U(e(Ge), {
2521
- key: 0,
2522
- type: "danger",
2523
- variant: "soft",
2524
- description: k.value
2525
- }, null, 8, ["description"])) : J("", !0)
2526
- ])
2527
- ]),
2528
- _: 1
2529
- }, 8, ["open", "title"]));
2530
- }
2531
- }), tl = /* @__PURE__ */ de(el, [["__scopeId", "data-v-aa68b3a8"]]), al = { class: "wx-tags" }, ll = /* @__PURE__ */ ie({
2532
- __name: "TagsPage",
2533
- props: {
2534
- base: { default: "/blog" }
2535
- },
2536
- setup(w) {
2537
- const d = w, c = ue(), o = ye(c), a = Me(), i = Oe();
2538
- se();
2539
- const t = Y("webx-blog"), v = Y("webx-admin"), l = be(), m = V(null), p = V(!0), h = V([]), k = V(!1), u = Re(Za), T = Re(Ga), W = Re(tl), E = f(() => c.can("blog.taxonomy.manage")), B = f(
2540
- () => c.state.manifest?.modules.find((b) => b.id === "tags")?.title ?? t("module.tags")
2541
- ), _ = f({
2542
- get: () => typeof a.query.view == "string" ? a.query.view : "",
2543
- set: (b) => {
2544
- i.replace({
2545
- query: { ...a.query, view: b === "" ? void 0 : String(b), page: void 0 }
2546
- });
2547
- }
2548
- }), q = f(() => m.value?.filters ?? { total: 0, empty: 0, noindex: 0 }), M = f(() => [
2549
- { value: "", label: t("tag.view-all"), badge: q.value.total },
2550
- { value: "empty", label: t("tag.view-empty"), badge: q.value.empty },
2551
- { value: "noindex", label: t("tag.view-noindex"), badge: q.value.noindex }
2552
- ]), $ = f(() => m.value?.data ?? []), g = f(() => $.value.filter((b) => h.value.includes(b.id))), z = f(() => [
2553
- { key: "title", label: t("tag.column-title"), minWidth: 150, sortable: !0 },
2554
- // The number is what the other columns and the narrowest the title may be add up to without
2555
- // this one: below it the address is what does not fit, and a fixed table does not shrink —
2556
- // it scrolls sideways and takes the ··· with it (CLAUDE.md §4). Measured, not guessed: at
2557
- // 375px the row is the word, the number and the menu, and nothing hangs off the edge.
2558
- { key: "path", label: t("tag.column-address"), width: 180, hideBelow: 760 },
2559
- {
2560
- key: "articles_count",
2561
- label: t("tag.column-articles"),
2562
- width: 80,
2563
- align: "right",
2564
- sortable: !0
2565
- },
2566
- // Wide enough for the longest of the three states on one line, in every language: measured
2567
- // at 180px of text, and a cell keeps 32 of its own. Narrower, the ruled row wrapped and
2568
- // stood eighteen pixels taller than the ones around it.
2569
- { key: "indexing", label: t("tag.column-indexing"), width: 230, hideBelow: 560 },
2570
- { key: "actions", label: "", width: dt, align: "right" }
2571
- ]);
2572
- function L(b) {
2573
- return {
2574
- q: b?.search ?? (typeof a.query.q == "string" ? a.query.q : ""),
2575
- empty: _.value === "empty",
2576
- noindex: _.value === "noindex",
2577
- // Only when it is not the default: most used first is what the list is, and a query
2578
- // string that repeats the default is a link that outlives a change of mind about it.
2579
- sort: te(b),
2580
- page: b?.page ?? (Number(a.query.page ?? 1) || 1),
2581
- per_page: b?.perPage
2582
- };
2583
- }
2584
- async function Q(b) {
2585
- p.value = !0;
2586
- try {
2587
- m.value = await o.tagsPage(L(b));
2588
- } catch (D) {
2589
- O.danger(l(D));
2590
- } finally {
2591
- p.value = !1;
2592
- }
2593
- }
2594
- function te(b) {
2595
- const D = b?.sort ?? K();
2596
- if (!D) return;
2597
- const P = D.key === "title" ? "name" : "articles", ee = `${D.order === "desc" ? "-" : ""}${P}`;
2598
- return ee === "articles" ? void 0 : ee;
2599
- }
2600
- function K() {
2601
- const b = typeof a.query.sort == "string" ? a.query.sort : "";
2602
- if (b === "") return null;
2603
- const D = b.startsWith("-");
2604
- return { key: (D ? b.slice(1) : b) === "name" ? "title" : "articles_count", order: D ? "desc" : "asc" };
2605
- }
2606
- function ce(b) {
2607
- const D = {
2608
- ...a.query,
2609
- q: b.search === "" ? void 0 : b.search,
2610
- sort: te(b),
2611
- page: b.page === 1 ? void 0 : String(b.page)
2612
- };
2613
- i.replace({ query: D }), Q(b);
2614
- }
2615
- he(_, () => {
2616
- h.value = [], Q();
2617
- }), Q();
2618
- async function oe() {
2619
- await T({}) && await Q();
2620
- }
2621
- async function ne(b) {
2622
- const D = await u({ name: b.title });
2623
- D && await we(b, { title: D }, t("tag.renamed"));
2624
- }
2625
- async function X(b, D) {
2626
- await we(b, { noindex: D }, t(D ? "tag.kept-out" : "tag.indexed"));
2627
- }
2628
- async function we(b, D, P) {
2629
- try {
2630
- const ee = await o.saveTag(b.id, D);
2631
- m.value && (m.value = {
2632
- ...m.value,
2633
- data: m.value.data.map((s) => s.id === ee.id ? ee : s)
2634
- }), O.success(P);
2635
- } catch (ee) {
2636
- O.danger(l(ee));
2637
- }
2638
- }
2639
- async function C(b) {
2640
- if (await pe({
2641
- title: t("tag.delete-title", { title: b.title }),
2642
- message: b.articles_count > 0 ? t("tag.delete-text-used", { count: b.articles_count }) : t("tag.delete-text"),
2643
- confirmText: t("tag.delete"),
2644
- cancelText: t("tag.cancel"),
2645
- tone: "danger"
2646
- }))
2647
- try {
2648
- await o.removeTag(b.id), O.success(t("tag.deleted")), h.value = h.value.filter((P) => P !== b.id), await Q();
2649
- } catch (P) {
2650
- O.danger(l(P));
2651
- }
2652
- }
2653
- const I = f(() => [
2654
- {
2655
- key: "index",
2656
- icon: "eye",
2657
- label: t("tag.index"),
2658
- disabled: k.value,
2659
- run: () => {
2660
- ae("index");
2661
- }
2662
- },
2663
- {
2664
- key: "noindex",
2665
- icon: "eye-off",
2666
- label: t("tag.noindex"),
2667
- disabled: k.value,
2668
- run: () => {
2669
- ae("noindex");
2670
- }
2671
- },
2672
- {
2673
- key: "delete",
2674
- icon: "trash",
2675
- label: t("tag.delete"),
2676
- danger: !0,
2677
- disabled: k.value,
2678
- run: () => {
2679
- ae("delete");
2680
- }
2681
- }
2682
- ]);
2683
- function j(b) {
2684
- if (!E.value) return [];
2685
- const D = [
2686
- { key: "rename", icon: "edit", label: t("tag.rename"), run: () => {
2687
- ne(b);
2688
- } }
2689
- ];
2690
- return b.url && D.push({
2691
- key: "site",
2692
- icon: "external-link",
2693
- label: t("tag.open-on-site"),
2694
- href: b.url
2695
- }), D.push({
2696
- key: "articles",
2697
- icon: "list",
2698
- label: t("tag.show-articles"),
2699
- run: () => {
2700
- i.push({ path: `${d.base}/articles`, query: { tag: String(b.id) } });
2701
- }
2702
- }), D.push(
2703
- b.noindex ? {
2704
- key: "index",
2705
- icon: "eye",
2706
- label: t("tag.index"),
2707
- run: () => {
2708
- X(b, !1);
2709
- }
2710
- } : {
2711
- key: "noindex",
2712
- icon: "eye-off",
2713
- label: t("tag.noindex"),
2714
- run: () => {
2715
- X(b, !0);
2716
- }
2717
- }
2718
- ), D.push({
2719
- key: "delete",
2720
- icon: "trash",
2721
- label: t("tag.delete"),
2722
- danger: !0,
2723
- run: () => {
2724
- C(b);
2725
- }
2726
- }), D;
2727
- }
2728
- function ge(b) {
2729
- return b === "noindex" ? "muted" : "success";
2730
- }
2731
- async function xe() {
2732
- if (g.value.length < 2) return;
2733
- const b = await W({ tags: g.value });
2734
- b && (O.success(t("tag.merged", { tag: b.tag.title, count: b.articles_count })), h.value = [], await Q());
2735
- }
2736
- async function ae(b) {
2737
- const D = g.value.map((P) => P.id);
2738
- if (!(D.length === 0 || k.value)) {
2739
- if (b === "delete") {
2740
- const P = g.value.reduce((s, R) => s + R.articles_count, 0);
2741
- if (!await pe({
2742
- title: t("tag.delete-many-title", { count: D.length }),
2743
- message: P > 0 ? t("tag.delete-many-text-used", { count: P }) : t("tag.delete-many-text"),
2744
- confirmText: t("tag.delete"),
2745
- cancelText: t("tag.cancel"),
2746
- tone: "danger"
2747
- })) return;
2748
- }
2749
- k.value = !0;
2750
- try {
2751
- const P = await o.massTags(D, b);
2752
- O.success(
2753
- b === "delete" ? t("tag.deleted-many", { count: P }) : b === "index" ? t("tag.indexed-many", { count: P }) : t("tag.kept-out-many", { count: P })
2754
- ), h.value = [], await Q();
2755
- } catch (P) {
2756
- O.danger(l(P));
2757
- } finally {
2758
- k.value = !1;
2759
- }
2760
- }
2761
- }
2762
- const Ve = f(
2763
- () => E.value ? [{ key: "new", label: t("tag.new"), icon: "plus", primary: !0, run: () => {
2764
- oe();
2765
- } }] : []
2766
- );
2767
- return (b, D) => (y(), G("div", al, [
2768
- r(e(je), {
2769
- view: _.value,
2770
- "onUpdate:view": D[1] || (D[1] = (P) => _.value = P),
2771
- title: B.value,
2772
- views: M.value,
2773
- actions: Ve.value
2774
- }, {
2775
- default: n(() => [
2776
- r(e(ht), {
2777
- selected: h.value,
2778
- "onUpdate:selected": D[0] || (D[0] = (P) => h.value = P),
2779
- data: m.value,
2780
- columns: z.value,
2781
- "row-key": "id",
2782
- searchable: "",
2783
- hover: "",
2784
- flush: "",
2785
- layout: "fixed",
2786
- loading: p.value,
2787
- selectable: E.value,
2788
- "select-row-label": e(v)("filters.select-row"),
2789
- "select-all-label": e(v)("filters.select-all"),
2790
- "cards-below": 0,
2791
- "search-placeholder": e(t)("tag.search"),
2792
- "empty-text": $.value.length === 0 && !p.value ? e(t)("tag.empty") : void 0,
2793
- "aria-label": B.value,
2794
- onStateChange: ce
2795
- }, {
2796
- "cell-title": n(({ row: P }) => [
2797
- r(e(ve), { truncate: "" }, {
2798
- default: n(() => [
2799
- N(S(P.title), 1)
2800
- ]),
2801
- _: 2
2802
- }, 1024)
2803
- ]),
2804
- "cell-path": n(({ row: P }) => [
2805
- r(e(ve), {
2806
- size: "sm",
2807
- tone: "muted",
2808
- mono: "",
2809
- truncate: ""
2810
- }, {
2811
- default: n(() => [
2812
- N(S(P.path ?? e(t)("tag.no-address")), 1)
2813
- ]),
2814
- _: 2
2815
- }, 1024)
2816
- ]),
2817
- "cell-articles_count": n(({ row: P }) => [
2818
- r(e(ve), {
2819
- tone: P.articles_count === 0 ? "muted" : "default"
2820
- }, {
2821
- default: n(() => [
2822
- N(S(P.articles_count), 1)
2823
- ]),
2824
- _: 2
2825
- }, 1032, ["tone"])
2826
- ]),
2827
- "cell-indexing": n(({ row: P }) => [
2828
- P.indexing === "rule" ? (y(), U(e(gt), {
2829
- key: 0,
2830
- content: e(t)("tag.indexing-rule-help")
2831
- }, {
2832
- default: n(() => [
2833
- r(e(ve), {
2834
- size: "sm",
2835
- tone: ge(P.indexing)
2836
- }, {
2837
- default: n(() => [
2838
- N(S(e(t)("tag.indexing-rule")), 1)
2839
- ]),
2840
- _: 1
2841
- }, 8, ["tone"])
2842
- ]),
2843
- _: 2
2844
- }, 1032, ["content"])) : (y(), U(e(ve), {
2845
- key: 1,
2846
- size: "sm",
2847
- tone: ge(P.indexing)
2848
- }, {
2849
- default: n(() => [
2850
- N(S(e(t)(`tag.indexing-${P.indexing}`)), 1)
2851
- ]),
2852
- _: 2
2853
- }, 1032, ["tone"]))
2854
- ]),
2855
- "cell-actions": n(({ row: P }) => [
2856
- r(e(Ie), {
2857
- actions: j(P),
2858
- label: P.title
2859
- }, null, 8, ["actions", "label"])
2860
- ]),
2861
- _: 1
2862
- }, 8, ["selected", "data", "columns", "loading", "selectable", "select-row-label", "select-all-label", "search-placeholder", "empty-text", "aria-label"])
2863
- ]),
2864
- _: 1
2865
- }, 8, ["view", "title", "views", "actions"]),
2866
- g.value.length > 0 ? (y(), U(e(tt), {
2867
- key: 0,
2868
- class: "wx-tags__bar",
2869
- sticky: ""
2870
- }, {
2871
- state: n(() => [
2872
- r(e(ve), { weight: "medium" }, {
2873
- default: n(() => [
2874
- N(S(e(t)("tag.selected", { count: g.value.length })), 1)
2875
- ]),
2876
- _: 1
2877
- })
2878
- ]),
2879
- default: n(() => [
2880
- r(e(le), {
2881
- type: "primary",
2882
- disabled: g.value.length < 2 || k.value,
2883
- onClick: xe
2884
- }, {
2885
- icon: n(() => [
2886
- r(e(ke), { name: "link" })
2887
- ]),
2888
- default: n(() => [
2889
- N(" " + S(e(t)("tag.merge")), 1)
2890
- ]),
2891
- _: 1
2892
- }, 8, ["disabled"]),
2893
- r(e(Ie), {
2894
- size: "lg",
2895
- actions: I.value,
2896
- label: e(t)("tag.selected", { count: g.value.length })
2897
- }, null, 8, ["actions", "label"])
2898
- ]),
2899
- _: 1
2900
- })) : J("", !0)
2901
- ]));
2902
- }
2903
- }), nl = /* @__PURE__ */ de(ll, [["__scopeId", "data-v-d9b8d73d"]]);
2904
- function il(w = "/blog") {
2905
- return {
2906
- api: "blog/rubrics",
2907
- path: `${w}/rubrics`,
2908
- name: "webx.blog.rubrics",
2909
- module: "rubrics",
2910
- screen: "blog.category-form",
2911
- manage: "blog.taxonomy.manage",
2912
- count: "articles_count",
2913
- items: (d) => ({ path: `${w}/articles`, query: { rubric: String(d) } }),
2914
- words: {
2915
- new: "webx-blog::rubric.new",
2916
- empty: "webx-blog::rubric.empty",
2917
- "empty-help": "webx-blog::rubric.empty-help",
2918
- order: "webx-blog::rubric.order",
2919
- hidden: "webx-blog::rubric.hidden",
2920
- "no-address": "webx-blog::rubric.no-address",
2921
- count: "webx-blog::rubric.articles",
2922
- "show-items": "webx-blog::rubric.show-articles",
2923
- "delete-blocked": "webx-blog::rubric.delete-blocked",
2924
- "delete-text": "webx-blog::rubric.delete-text",
2925
- deleted: "webx-blog::rubric.deleted",
2926
- saved: "webx-blog::rubric.saved",
2927
- "field-title": "webx-blog::rubric.field-title",
2928
- "field-slug": "webx-blog::rubric.field-slug",
2929
- "address-moving": "webx-blog::rubric.address-moving"
2930
- }
2931
- };
2932
- }
2933
- function vl(w = {}) {
2934
- const d = w.path ?? "/blog";
2935
- return [
2936
- {
2937
- id: "articles",
2938
- path: `${d}/articles`,
2939
- routes: [
2940
- // The section's own path travels as a prop, so a panel that mounted the blog somewhere
2941
- // else still links between its screens correctly.
2942
- {
2943
- path: `${d}/articles`,
2944
- name: "webx.blog.articles",
2945
- component: Ua,
2946
- props: { base: d }
2947
- },
2948
- {
2949
- path: `${d}/articles/:id(\\d+)`,
2950
- name: "webx.blog.articles.edit",
2951
- component: ta,
2952
- props: { base: d }
2953
- }
2954
- ],
2955
- /*
2956
- * The parts of `blog.article-form` that only this module can draw.
2957
- *
2958
- * The editor is a described screen so that a module can add a tab to it with a patch, and
2959
- * the price of that is that everything on it has to be a node type. Four of these are
2960
- * fields — the value is ids, and the control over them is a list that can be dragged or a
2961
- * box that makes a tag — and two only draw. Each reads the article from the editor above
2962
- * it rather than from the description, because a screen is a description and not a
2963
- * binding.
2964
- *
2965
- * The slug is here for a different reason: what it edits is an ordinary string, but the
2966
- * whole address is the prefix of the blog and that string, and the prefix is not in the
2967
- * description — it is configuration the editor was handed with the record.
2968
- */
2969
- types: {
2970
- "wx-article-slug": { component: ma, kind: "field" },
2971
- "wx-article-author": { component: Qt, kind: "field" },
2972
- "wx-article-tags": { component: ka, kind: "field" },
2973
- "wx-article-related": { component: pa, kind: "field" },
2974
- "wx-article-unpublish": { component: Ta, kind: "display" },
2975
- "wx-article-history": { component: oa, kind: "display" }
2976
- }
2977
- },
2978
- {
2979
- id: "rubrics",
2980
- path: `${d}/rubrics`,
2981
- // The list and the page of one rubric are the panel's shared category screens (§3.6 of
2982
- // the services spec); what is the blog's is the description they are handed.
2983
- routes: Ct(il(d))
2984
- },
2985
- {
2986
- id: "tags",
2987
- path: `${d}/tags`,
2988
- routes: [
2989
- {
2990
- path: `${d}/tags`,
2991
- name: "webx.blog.tags",
2992
- component: nl,
2993
- props: { base: d }
2994
- }
2995
- ]
2996
- },
2997
- {
2998
- // Only on a site with author pages (§19): the server leaves the module out of the manifest
2999
- // otherwise, and a module the manifest does not name is never drawn.
3000
- id: "authors",
3001
- path: `${d}/authors`,
3002
- routes: [
3003
- {
3004
- path: `${d}/authors`,
3005
- name: "webx.blog.authors",
3006
- component: Ja,
3007
- props: { base: d }
3008
- }
3009
- ]
3010
- }
3011
- ];
3012
- }
1
+ import "vue";
2
+ import { e as r, _ as i, W as t, f as l, g as o, h as g, i as A, j as c, k as x, A as W, l as d, b as p, T as u, m as h, n as b, o as P, q as T, d as n, c as E, p as m, r as D, s as f } from "./index-DqN5h0Ej.js";
3013
3
  export {
3014
- Qt as WxArticleAuthorField,
3015
- Aa as WxArticleCreateDialog,
3016
- ta as WxArticleEditorPage,
3017
- oa as WxArticleHistory,
3018
- pa as WxArticleRelated,
3019
- ma as WxArticleSlug,
3020
- ka as WxArticleTags,
3021
- Ta as WxArticleUnpublish,
3022
- Ua as WxArticlesPage,
3023
- Ia as WxAuthorPane,
3024
- Ja as WxAuthorsPage,
3025
- Ga as WxTagCreateDialog,
3026
- tl as WxTagMergeDialog,
3027
- nl as WxTagsPage,
3028
- ft as articleEditorKey,
3029
- vl as blog,
3030
- Gt as blogMessages,
3031
- mt as createAuthorsApi,
3032
- ye as createBlogApi,
3033
- Jt as provideArticleEditor,
3034
- il as rubricsOptions,
3035
- Ce as useArticleEditor
4
+ r as WxArticleAuthorField,
5
+ i as WxArticleCreateDialog,
6
+ t as WxArticleEditorPage,
7
+ l as WxArticleHistory,
8
+ o as WxArticleRelated,
9
+ g as WxArticleSlug,
10
+ A as WxArticleTags,
11
+ c as WxArticleUnpublish,
12
+ x as WxArticlesPage,
13
+ W as WxAuthorPane,
14
+ d as WxAuthorsPage,
15
+ p as WxTagCreateDialog,
16
+ u as WxTagMergeDialog,
17
+ h as WxTagsPage,
18
+ b as articleEditorKey,
19
+ P as blog,
20
+ T as blogMessages,
21
+ n as createAuthorsApi,
22
+ E as createBlogApi,
23
+ m as provideArticleEditor,
24
+ D as rubricsOptions,
25
+ f as useArticleEditor
3036
26
  };
3037
27
  //# sourceMappingURL=index.js.map