@jant/core 0.6.12 → 0.6.13
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/bin/commands/import-site.js +2 -10
- package/bin/commands/migrate-text-attachments.js +1 -3
- package/bin/commands/site/export.js +1 -3
- package/bin/commands/telegram/register-webhooks.js +9 -3
- package/bin/lib/site-snapshot.js +1 -5
- package/dist/app-CWJFPjuR.js +6 -0
- package/dist/{app-D-zAhayc.js → app-HnzmsaqU.js} +416 -444
- package/dist/client/.vite/manifest.json +3 -3
- package/dist/client/_assets/{client-S1cdvulk.js → client-3_OaxhTs.js} +1 -1
- package/dist/client/_assets/{client-BUxR-E8O.css → client-DCrcHVJl.css} +1 -1
- package/dist/client/_assets/{client-auth-YW92ZH7u.js → client-auth-TsYq90xm.js} +570 -567
- package/dist/{export-Ckwh4BiE.js → export-Dfbq9aot.js} +10 -13
- package/dist/{github-sync-Dl9wQMar.js → github-sync--PSoE-Ne.js} +1 -1
- package/dist/{github-sync-BMmK3JZ0.js → github-sync-BGTLx8Mf.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/node.js +4 -4
- package/package.json +1 -1
- package/src/__tests__/export-service.test.ts +1 -2
- package/src/__tests__/helpers/app.ts +3 -0
- package/src/__tests__/helpers/export-fixtures.ts +0 -1
- package/src/__tests__/import-site-command.test.ts +1 -2
- package/src/client/__tests__/site-header-nav.test.ts +36 -2
- package/src/client/components/__tests__/compose-title-from-heading.test.ts +57 -0
- package/src/client/components/__tests__/jant-compose-editor.test.ts +94 -2
- package/src/client/components/__tests__/jant-nav-manager.test.ts +107 -22
- package/src/client/components/__tests__/jant-settings-general.test.ts +1 -0
- package/src/client/components/compose-title-from-heading.ts +66 -0
- package/src/client/components/compose-types.ts +8 -0
- package/src/client/components/inline-image-issues.ts +17 -0
- package/src/client/components/jant-compose-dialog.ts +2 -0
- package/src/client/components/jant-compose-editor.ts +78 -1
- package/src/client/components/jant-compose-fullscreen.ts +2 -0
- package/src/client/components/jant-nav-manager.ts +245 -155
- package/src/client/components/nav-manager-types.ts +0 -10
- package/src/client/site-header-nav.d.ts +1 -0
- package/src/client/site-header-nav.js +105 -47
- package/src/client/tiptap/__tests__/block-insertion.test.ts +35 -0
- package/src/client/tiptap/__tests__/image-input-rules.test.ts +117 -0
- package/src/client/tiptap/create-editor.ts +7 -0
- package/src/client/tiptap/extensions.ts +7 -2
- package/src/client/tiptap/image-input-rules.ts +48 -0
- package/src/client/tiptap/image-node.ts +189 -7
- package/src/client-auth.ts +0 -1
- package/src/i18n/locales/public/en.po +20 -4
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +20 -4
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +20 -4
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +23 -20
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +23 -20
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +23 -20
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/lib/__tests__/navigation.test.ts +4 -37
- package/src/lib/__tests__/resolve-config.test.ts +6 -1
- package/src/lib/__tests__/view.test.ts +6 -30
- package/src/lib/github-sync-site-config.ts +0 -2
- package/src/lib/hugo-markdown.ts +1 -1
- package/src/lib/navigation.ts +5 -22
- package/src/lib/resolve-config.ts +9 -2
- package/src/lib/site-header-fragment.tsx +37 -0
- package/src/lib/view.ts +2 -7
- package/src/node/__tests__/cli-site-snapshot.test.ts +45 -45
- package/src/routes/api/__tests__/nav-items.test.ts +26 -0
- package/src/routes/api/export.ts +0 -2
- package/src/routes/api/internal/__tests__/uploads.test.ts +9 -13
- package/src/routes/api/internal/sites.ts +5 -5
- package/src/routes/api/nav-items.ts +25 -4
- package/src/routes/dash/settings.tsx +8 -2
- package/src/routes/feed/__tests__/feed.test.ts +42 -0
- package/src/routes/feed/__tests__/sitemap.test.ts +2 -13
- package/src/routes/feed/feed.ts +1 -0
- package/src/routes/feed/sitemap.ts +2 -6
- package/src/routes/pages/archive.tsx +1 -0
- package/src/routes/pages/collection.tsx +1 -0
- package/src/routes/pages/featured.tsx +0 -4
- package/src/routes/pages/home.tsx +4 -51
- package/src/routes/pages/latest.tsx +2 -51
- package/src/services/__tests__/github-app-installations.test.ts +10 -10
- package/src/services/__tests__/navigation.test.ts +41 -0
- package/src/services/__tests__/post-timeline.test.ts +56 -0
- package/src/services/__tests__/post.test.ts +33 -0
- package/src/services/__tests__/settings.test.ts +5 -20
- package/src/services/export-theme/assets/client-site.js +10 -10
- package/src/services/export-theme/layouts/_default/rss.xml +5 -15
- package/src/services/export-theme/layouts/index.html +26 -39
- package/src/services/export.ts +5 -10
- package/src/services/github-app-installations.ts +1 -3
- package/src/services/navigation.ts +44 -13
- package/src/services/post.ts +80 -57
- package/src/services/settings.ts +0 -10
- package/src/services/site-admin.ts +0 -2
- package/src/services/upload-session.ts +4 -18
- package/src/styles/tokens.css +2 -2
- package/src/styles/ui.css +200 -6
- package/src/types/bindings.ts +0 -1
- package/src/types/config.ts +3 -7
- package/src/ui/compose/ComposeDialog.tsx +28 -0
- package/src/ui/dash/appearance/NavigationContent.tsx +1 -1
- package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
- package/src/ui/dash/settings/SettingsRootContent.tsx +3 -3
- package/src/ui/layouts/SiteLayout.tsx +249 -216
- package/dist/app-B5P1b4TF.js +0 -6
- package/src/client/nav-manager-bridge.ts +0 -54
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - SortableJS drag-and-drop reorder with immediate preview update
|
|
8
8
|
* - Add link forms
|
|
9
9
|
* - System nav item toggles with immediate list/preview update
|
|
10
|
-
* -
|
|
10
|
+
* - Applies server-rendered site header fragments after saved changes
|
|
11
11
|
*
|
|
12
12
|
* Light DOM only — BaseCoat and Tailwind classes apply directly.
|
|
13
13
|
*/
|
|
@@ -27,16 +27,24 @@ import {
|
|
|
27
27
|
import { showConfirmDialog } from "../confirm.js";
|
|
28
28
|
import { showToast } from "../toast.js";
|
|
29
29
|
import { publicPath } from "../runtime-paths.js";
|
|
30
|
+
import { destroySiteHeaderNav, initSiteHeaderNav } from "../site-header-nav.js";
|
|
30
31
|
import type {
|
|
31
32
|
NavManagerCollection,
|
|
32
33
|
NavManagerItem,
|
|
33
34
|
NavManagerLabels,
|
|
34
|
-
NavManagerUpdateDetail,
|
|
35
|
-
NavManagerDeleteDetail,
|
|
36
35
|
NavManagerSuggestedLink,
|
|
37
36
|
SystemNavConfig,
|
|
38
37
|
} from "./nav-manager-types.js";
|
|
39
38
|
|
|
39
|
+
const SITE_HEADER_REQUEST_HEADER = "X-Jant-Site-Header";
|
|
40
|
+
const INCLUDE_SITE_HEADER_RESPONSE = "include";
|
|
41
|
+
|
|
42
|
+
type NavManagerMutationResponse<T extends object> = T & {
|
|
43
|
+
headerHtml?: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type SortableEndEvent = Parameters<NonNullable<SortableOptions["onEnd"]>>[0];
|
|
47
|
+
|
|
40
48
|
export class JantNavManager extends LitElement {
|
|
41
49
|
static properties = {
|
|
42
50
|
items: { type: Array },
|
|
@@ -174,6 +182,69 @@ export class JantNavManager extends LitElement {
|
|
|
174
182
|
this.#closePreviewMore();
|
|
175
183
|
}
|
|
176
184
|
|
|
185
|
+
#jsonMutationHeaders(): Record<string, string> {
|
|
186
|
+
return {
|
|
187
|
+
"Content-Type": "application/json",
|
|
188
|
+
Accept: "application/json",
|
|
189
|
+
[SITE_HEADER_REQUEST_HEADER]: INCLUDE_SITE_HEADER_RESPONSE,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#deleteMutationHeaders(): Record<string, string> {
|
|
194
|
+
return {
|
|
195
|
+
Accept: "application/json",
|
|
196
|
+
[SITE_HEADER_REQUEST_HEADER]: INCLUDE_SITE_HEADER_RESPONSE,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#stripHeaderHtml<T extends object>(
|
|
201
|
+
response: NavManagerMutationResponse<T>,
|
|
202
|
+
): T {
|
|
203
|
+
const body = { ...response };
|
|
204
|
+
delete (body as { headerHtml?: string }).headerHtml;
|
|
205
|
+
return body as T;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
#normalizeItem(item: NavManagerItem): NavManagerItem {
|
|
209
|
+
const systemLabel =
|
|
210
|
+
item.type === "system"
|
|
211
|
+
? this.systemNavItems.find((config) => config.key === item.systemKey)
|
|
212
|
+
?.label
|
|
213
|
+
: undefined;
|
|
214
|
+
const displayLabel =
|
|
215
|
+
item.label.trim() || systemLabel || item.displayLabel || item.label;
|
|
216
|
+
|
|
217
|
+
return { ...item, displayLabel };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
#applySiteHeaderHtml(headerHtml: string | undefined) {
|
|
221
|
+
if (!headerHtml) return;
|
|
222
|
+
|
|
223
|
+
const template = document.createElement("template");
|
|
224
|
+
template.innerHTML = headerHtml.trim();
|
|
225
|
+
|
|
226
|
+
const selectors = [
|
|
227
|
+
'[data-site-header-fragment="header"]',
|
|
228
|
+
'[data-site-header-fragment="drawer-backdrop"]',
|
|
229
|
+
'[data-site-header-fragment="drawer"]',
|
|
230
|
+
];
|
|
231
|
+
let replaced = false;
|
|
232
|
+
|
|
233
|
+
destroySiteHeaderNav(document);
|
|
234
|
+
for (const selector of selectors) {
|
|
235
|
+
const current = document.querySelector<HTMLElement>(selector);
|
|
236
|
+
const next = template.content.querySelector<HTMLElement>(selector);
|
|
237
|
+
if (!current || !next) continue;
|
|
238
|
+
|
|
239
|
+
current.replaceWith(next);
|
|
240
|
+
replaced = true;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (replaced) {
|
|
244
|
+
initSiteHeaderNav(document);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
177
248
|
// ===========================================================================
|
|
178
249
|
// SortableJS
|
|
179
250
|
// ===========================================================================
|
|
@@ -211,119 +282,115 @@ export class JantNavManager extends LitElement {
|
|
|
211
282
|
this.#revertNextSibling = captureSortableRevertNextSibling(evt);
|
|
212
283
|
},
|
|
213
284
|
onEnd: (evt) => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
targetList.id === "nav-items-header" ? "header" : "more";
|
|
219
|
-
const headerList = this.querySelector<HTMLElement>("#nav-items-header");
|
|
220
|
-
const moreList = this.querySelector<HTMLElement>("#nav-items-more");
|
|
221
|
-
|
|
222
|
-
const movedId = evt.item?.dataset?.navId;
|
|
223
|
-
if (!movedId || !headerList || !moreList) {
|
|
224
|
-
this.#revertNextSibling = null;
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
285
|
+
void this.#handleSortableEnd(evt);
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
227
289
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (this.#revertNextSibling) {
|
|
238
|
-
sourceList.insertBefore(evt.item, this.#revertNextSibling);
|
|
239
|
-
} else if (
|
|
240
|
-
evt.oldIndex != null &&
|
|
241
|
-
evt.oldIndex < sourceList.children.length
|
|
242
|
-
) {
|
|
243
|
-
sourceList.insertBefore(
|
|
244
|
-
evt.item,
|
|
245
|
-
sourceList.children[evt.oldIndex] ?? null,
|
|
246
|
-
);
|
|
247
|
-
} else {
|
|
248
|
-
sourceList.appendChild(evt.item);
|
|
249
|
-
}
|
|
250
|
-
} else {
|
|
251
|
-
revertSortableDomMove(targetList, evt, this.#revertNextSibling);
|
|
252
|
-
}
|
|
290
|
+
async #handleSortableEnd(evt: SortableEndEvent) {
|
|
291
|
+
const targetList = evt.to;
|
|
292
|
+
const sourceList = evt.from;
|
|
293
|
+
const crossList = sourceList !== targetList;
|
|
294
|
+
const targetPlacement: "header" | "more" =
|
|
295
|
+
targetList.id === "nav-items-header" ? "header" : "more";
|
|
296
|
+
const headerList = this.querySelector<HTMLElement>("#nav-items-header");
|
|
297
|
+
const moreList = this.querySelector<HTMLElement>("#nav-items-more");
|
|
298
|
+
const previousItems = this._items.map((item) => ({ ...item }));
|
|
253
299
|
|
|
254
|
-
|
|
255
|
-
|
|
300
|
+
const movedId = evt.item?.dataset?.navId;
|
|
301
|
+
if (!movedId || !headerList || !moreList) {
|
|
302
|
+
this.#revertNextSibling = null;
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
256
305
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
306
|
+
const headerIds = readSortableDataIds(headerList, "[data-nav-id]", "navId");
|
|
307
|
+
const moreIds = readSortableDataIds(moreList, "[data-nav-id]", "navId");
|
|
308
|
+
|
|
309
|
+
if (crossList) {
|
|
310
|
+
evt.item.parentNode?.removeChild(evt.item);
|
|
311
|
+
if (this.#revertNextSibling) {
|
|
312
|
+
sourceList.insertBefore(evt.item, this.#revertNextSibling);
|
|
313
|
+
} else if (
|
|
314
|
+
evt.oldIndex != null &&
|
|
315
|
+
evt.oldIndex < sourceList.children.length
|
|
316
|
+
) {
|
|
317
|
+
sourceList.insertBefore(
|
|
318
|
+
evt.item,
|
|
319
|
+
sourceList.children[evt.oldIndex] ?? null,
|
|
265
320
|
);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
321
|
+
} else {
|
|
322
|
+
sourceList.appendChild(evt.item);
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
revertSortableDomMove(targetList, evt, this.#revertNextSibling);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this.#revertNextSibling = null;
|
|
329
|
+
this.#destroySortables();
|
|
330
|
+
|
|
331
|
+
const orderedIds = [...new Set([...headerIds, ...moreIds])];
|
|
332
|
+
const itemMap = new Map(
|
|
333
|
+
this._items.map((item) => [
|
|
334
|
+
item.id,
|
|
335
|
+
item.id === movedId
|
|
336
|
+
? { ...item, placement: targetPlacement }
|
|
337
|
+
: { ...item },
|
|
338
|
+
]),
|
|
339
|
+
);
|
|
340
|
+
const reorderedItems = orderedIds
|
|
341
|
+
.map((id) => itemMap.get(id))
|
|
342
|
+
.filter((item): item is NavManagerItem => item !== undefined);
|
|
343
|
+
const remainingItems = this._items
|
|
344
|
+
.filter((item) => !orderedIds.includes(item.id))
|
|
345
|
+
.map((item) =>
|
|
346
|
+
item.id === movedId
|
|
347
|
+
? { ...item, placement: targetPlacement }
|
|
348
|
+
: { ...item },
|
|
349
|
+
);
|
|
350
|
+
this._items = [...reorderedItems, ...remainingItems];
|
|
351
|
+
|
|
352
|
+
const targetIds = targetPlacement === "header" ? headerIds : moreIds;
|
|
353
|
+
const {
|
|
354
|
+
movedId: persistedId,
|
|
355
|
+
afterId,
|
|
356
|
+
beforeId,
|
|
357
|
+
} = getSortableMove(targetIds, evt.newIndex);
|
|
358
|
+
if (!persistedId) return;
|
|
359
|
+
|
|
360
|
+
try {
|
|
361
|
+
if (crossList) {
|
|
362
|
+
const placementRes = await fetch(`/api/nav-items/${movedId}`, {
|
|
363
|
+
method: "PUT",
|
|
364
|
+
headers: {
|
|
365
|
+
"Content-Type": "application/json",
|
|
366
|
+
Accept: "application/json",
|
|
367
|
+
},
|
|
368
|
+
body: JSON.stringify({ placement: targetPlacement }),
|
|
369
|
+
});
|
|
370
|
+
if (!placementRes.ok) throw new Error(`HTTP ${placementRes.status}`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const moveRes = await fetch(`/api/nav-items/${persistedId}/move`, {
|
|
374
|
+
method: "PUT",
|
|
375
|
+
headers: this.#jsonMutationHeaders(),
|
|
376
|
+
body: JSON.stringify({
|
|
377
|
+
after: afterId ?? null,
|
|
378
|
+
before: beforeId ?? null,
|
|
379
|
+
}),
|
|
380
|
+
});
|
|
381
|
+
if (!moveRes.ok) throw new Error(`HTTP ${moveRes.status}`);
|
|
382
|
+
|
|
383
|
+
const moved =
|
|
384
|
+
(await moveRes.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
385
|
+
this.#applySiteHeaderHtml(moved.headerHtml);
|
|
386
|
+
showToast(
|
|
387
|
+
crossList ? this.labels.placementSaved : this.labels.orderSaved,
|
|
388
|
+
);
|
|
389
|
+
} catch {
|
|
390
|
+
this.#destroySortables();
|
|
391
|
+
this._items = previousItems;
|
|
392
|
+
showToast(this.labels.saveFailed, "error");
|
|
393
|
+
}
|
|
327
394
|
}
|
|
328
395
|
|
|
329
396
|
// ===========================================================================
|
|
@@ -340,25 +407,36 @@ export class JantNavManager extends LitElement {
|
|
|
340
407
|
}
|
|
341
408
|
}
|
|
342
409
|
|
|
343
|
-
#handleUpdate(item: NavManagerItem) {
|
|
410
|
+
async #handleUpdate(item: NavManagerItem) {
|
|
344
411
|
const label = this._editLabel.trim();
|
|
345
412
|
if (!label && item.type !== "system") {
|
|
346
413
|
showToast(this.labels.labelRequired, "error");
|
|
347
414
|
return;
|
|
348
415
|
}
|
|
349
416
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
417
|
+
try {
|
|
418
|
+
const res = await fetch(`/api/nav-items/${item.id}`, {
|
|
419
|
+
method: "PUT",
|
|
420
|
+
headers: this.#jsonMutationHeaders(),
|
|
421
|
+
body: JSON.stringify({
|
|
422
|
+
label,
|
|
423
|
+
...(item.type === "link" && { url: this._editUrl.trim() }),
|
|
424
|
+
}),
|
|
425
|
+
});
|
|
426
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
355
427
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
428
|
+
const response =
|
|
429
|
+
(await res.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
430
|
+
const updated = this.#normalizeItem(this.#stripHeaderHtml(response));
|
|
431
|
+
this.#destroySortables();
|
|
432
|
+
this._items = this._items.map((current) =>
|
|
433
|
+
current.id === updated.id ? updated : current,
|
|
434
|
+
);
|
|
435
|
+
this._editingId = null;
|
|
436
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
437
|
+
} catch {
|
|
438
|
+
showToast(this.labels.saveFailed, "error");
|
|
439
|
+
}
|
|
362
440
|
}
|
|
363
441
|
|
|
364
442
|
async #handleDelete(item: NavManagerItem) {
|
|
@@ -376,12 +454,23 @@ export class JantNavManager extends LitElement {
|
|
|
376
454
|
});
|
|
377
455
|
if (!confirmed) return;
|
|
378
456
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
})
|
|
384
|
-
|
|
457
|
+
try {
|
|
458
|
+
const res = await fetch(`/api/nav-items/${item.id}`, {
|
|
459
|
+
method: "DELETE",
|
|
460
|
+
headers: this.#deleteMutationHeaders(),
|
|
461
|
+
});
|
|
462
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
463
|
+
|
|
464
|
+
const response = (await res.json()) as NavManagerMutationResponse<{
|
|
465
|
+
success: true;
|
|
466
|
+
}>;
|
|
467
|
+
this.#destroySortables();
|
|
468
|
+
this._items = this._items.filter((current) => current.id !== item.id);
|
|
469
|
+
this._editingId = null;
|
|
470
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
471
|
+
} catch {
|
|
472
|
+
showToast(this.labels.deleteFailed, "error");
|
|
473
|
+
}
|
|
385
474
|
}
|
|
386
475
|
|
|
387
476
|
// ===========================================================================
|
|
@@ -400,21 +489,21 @@ export class JantNavManager extends LitElement {
|
|
|
400
489
|
try {
|
|
401
490
|
const res = await fetch("/api/nav-items", {
|
|
402
491
|
method: "POST",
|
|
403
|
-
headers:
|
|
404
|
-
"Content-Type": "application/json",
|
|
405
|
-
Accept: "application/json",
|
|
406
|
-
},
|
|
492
|
+
headers: this.#jsonMutationHeaders(),
|
|
407
493
|
body: JSON.stringify({ type: "link", label, url, placement: "header" }),
|
|
408
494
|
});
|
|
409
495
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
410
496
|
|
|
411
|
-
const
|
|
497
|
+
const response =
|
|
498
|
+
(await res.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
499
|
+
const created = this.#normalizeItem(this.#stripHeaderHtml(response));
|
|
412
500
|
this.#destroySortables();
|
|
413
501
|
this._items = [...this._items, created];
|
|
414
502
|
this._newLinkLabel = "";
|
|
415
503
|
this._newLinkUrl = "";
|
|
416
504
|
this._showLinkForm = false;
|
|
417
505
|
document.removeEventListener("click", this.#closeLinkForm);
|
|
506
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
418
507
|
} catch {
|
|
419
508
|
showToast(this.labels.saveFailed, "error");
|
|
420
509
|
} finally {
|
|
@@ -433,10 +522,7 @@ export class JantNavManager extends LitElement {
|
|
|
433
522
|
try {
|
|
434
523
|
const res = await fetch("/api/nav-items", {
|
|
435
524
|
method: "POST",
|
|
436
|
-
headers:
|
|
437
|
-
"Content-Type": "application/json",
|
|
438
|
-
Accept: "application/json",
|
|
439
|
-
},
|
|
525
|
+
headers: this.#jsonMutationHeaders(),
|
|
440
526
|
body: JSON.stringify({
|
|
441
527
|
type: "collection",
|
|
442
528
|
collectionId,
|
|
@@ -445,10 +531,13 @@ export class JantNavManager extends LitElement {
|
|
|
445
531
|
});
|
|
446
532
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
447
533
|
|
|
448
|
-
const
|
|
534
|
+
const response =
|
|
535
|
+
(await res.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
536
|
+
const created = this.#normalizeItem(this.#stripHeaderHtml(response));
|
|
449
537
|
this.#destroySortables();
|
|
450
538
|
this._items = [...this._items, created];
|
|
451
539
|
this.#closeCollectionPicker();
|
|
540
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
452
541
|
} catch {
|
|
453
542
|
showToast(this.labels.saveFailed, "error");
|
|
454
543
|
} finally {
|
|
@@ -530,17 +619,17 @@ export class JantNavManager extends LitElement {
|
|
|
530
619
|
|
|
531
620
|
const res = await fetch("/api/nav-items", {
|
|
532
621
|
method: "POST",
|
|
533
|
-
headers:
|
|
534
|
-
"Content-Type": "application/json",
|
|
535
|
-
Accept: "application/json",
|
|
536
|
-
},
|
|
622
|
+
headers: this.#jsonMutationHeaders(),
|
|
537
623
|
body: JSON.stringify(body),
|
|
538
624
|
});
|
|
539
625
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
540
626
|
|
|
541
|
-
const
|
|
627
|
+
const response =
|
|
628
|
+
(await res.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
629
|
+
const created = this.#normalizeItem(this.#stripHeaderHtml(response));
|
|
542
630
|
this.#destroySortables();
|
|
543
631
|
this._items = [...this._items, created];
|
|
632
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
544
633
|
showToast(this.labels.suggestedLinkAdded);
|
|
545
634
|
} catch {
|
|
546
635
|
showToast(this.labels.saveFailed, "error");
|
|
@@ -566,10 +655,7 @@ export class JantNavManager extends LitElement {
|
|
|
566
655
|
if (enabled) {
|
|
567
656
|
const res = await fetch("/api/nav-items", {
|
|
568
657
|
method: "POST",
|
|
569
|
-
headers:
|
|
570
|
-
"Content-Type": "application/json",
|
|
571
|
-
Accept: "application/json",
|
|
572
|
-
},
|
|
658
|
+
headers: this.#jsonMutationHeaders(),
|
|
573
659
|
body: JSON.stringify({
|
|
574
660
|
type: "system",
|
|
575
661
|
systemKey: config.key,
|
|
@@ -577,12 +663,12 @@ export class JantNavManager extends LitElement {
|
|
|
577
663
|
});
|
|
578
664
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
579
665
|
|
|
580
|
-
const
|
|
666
|
+
const response =
|
|
667
|
+
(await res.json()) as NavManagerMutationResponse<NavManagerItem>;
|
|
668
|
+
const created = this.#normalizeItem(this.#stripHeaderHtml(response));
|
|
581
669
|
this.#destroySortables();
|
|
582
|
-
this._items = [
|
|
583
|
-
|
|
584
|
-
{ ...created, displayLabel: config.label },
|
|
585
|
-
];
|
|
670
|
+
this._items = [...this._items, created];
|
|
671
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
586
672
|
} else {
|
|
587
673
|
const existing = this._items.find(
|
|
588
674
|
(item) => item.type === "system" && item.systemKey === config.key,
|
|
@@ -590,12 +676,16 @@ export class JantNavManager extends LitElement {
|
|
|
590
676
|
if (existing) {
|
|
591
677
|
const res = await fetch(`/api/nav-items/${existing.id}`, {
|
|
592
678
|
method: "DELETE",
|
|
593
|
-
headers:
|
|
679
|
+
headers: this.#deleteMutationHeaders(),
|
|
594
680
|
});
|
|
595
681
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
596
682
|
|
|
683
|
+
const response = (await res.json()) as NavManagerMutationResponse<{
|
|
684
|
+
success: true;
|
|
685
|
+
}>;
|
|
597
686
|
this.#destroySortables();
|
|
598
687
|
this._items = this._items.filter((item) => item.id !== existing.id);
|
|
688
|
+
this.#applySiteHeaderHtml(response.headerHtml);
|
|
599
689
|
}
|
|
600
690
|
}
|
|
601
691
|
} catch {
|
|
@@ -81,13 +81,3 @@ export interface NavManagerLabels {
|
|
|
81
81
|
placementSaved: string;
|
|
82
82
|
cancel: string;
|
|
83
83
|
}
|
|
84
|
-
|
|
85
|
-
export interface NavManagerUpdateDetail {
|
|
86
|
-
id: string;
|
|
87
|
-
label: string;
|
|
88
|
-
url?: string;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface NavManagerDeleteDetail {
|
|
92
|
-
id: string;
|
|
93
|
-
}
|