@webx-ui/module-catalog-manticore 0.1.1 → 0.2.0

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,14 +1,14 @@
1
- import { defineComponent as j, ref as w, computed as v, onMounted as G, onBeforeUnmount as H, openBlock as s, createBlock as c, unref as e, withCtx as l, createElementVNode as m, createVNode as r, createTextVNode as d, toDisplayString as i, createCommentVNode as b, createElementBlock as M, Fragment as J } from "vue";
2
- import { useAdmin as N, useTranslate as K, useErrorText as X, WxListScreen as Y, WxDate as E } from "@webx-ui/module-admin";
3
- import { confirm as Z, toast as L, WxText as g, WxAlert as C, WxCard as k, WxProgress as ee, WxDescriptions as R, WxDescriptionsItem as x, WxBadge as z, WxTable as ae } from "@webx-ui/core";
4
- function te(o) {
5
- const h = `${o.apiPath}/search-index`;
1
+ import { defineComponent as G, ref as T, computed as v, onMounted as H, onBeforeUnmount as J, openBlock as u, createBlock as d, unref as e, withCtx as l, createElementVNode as m, createVNode as o, createTextVNode as s, toDisplayString as i, createCommentVNode as b, createElementBlock as I, Fragment as K } from "vue";
2
+ import { useAdmin as P, useTranslate as X, useErrorText as Y, WxListScreen as Z, WxDate as L } from "@webx-ui/module-admin";
3
+ import { confirm as ee, toast as R, WxText as g, WxAlert as q, WxCard as W, WxProgress as ae, WxDescriptions as z, WxDescriptionsItem as x, WxBadge as D, WxTable as te } from "@webx-ui/core";
4
+ function le(c) {
5
+ const h = `${c.apiPath}/search-index`;
6
6
  return {
7
- report: () => o.http.get(h).then((a) => a.data),
8
- rebuild: () => o.http.post(`${h}/rebuild`, {}).then((a) => a.data)
7
+ report: () => c.http.get(h).then((a) => a.data),
8
+ rebuild: () => c.http.post(`${h}/rebuild`, {}).then((a) => a.data)
9
9
  };
10
10
  }
11
- const le = {
11
+ const ne = {
12
12
  panel: {
13
13
  title: "Search index",
14
14
  lead: "The catalogue searches, filters and counts with Manticore. The panel answers from the database when it does not.",
@@ -43,6 +43,8 @@ const le = {
43
43
  "rebuild-title": "Rebuild the search index?",
44
44
  "rebuild-text": "Every product is written again into new tables, which then replace the live ones. The storefront keeps working on the old tables meanwhile.",
45
45
  "rebuild-busy": "A rebuild is already under way.",
46
+ "rebuild-locked": "Another rebuild is running — it was started from the console. Start this one once it ends.",
47
+ "rebuild-console": "A rebuild started from the console is running: the button comes back when it ends.",
46
48
  "rebuild-queued": "Waiting for the queue worker",
47
49
  "rebuild-running": "Rebuilding: :done of :total",
48
50
  "rebuild-done": "Rebuilt: :done products",
@@ -51,215 +53,224 @@ const le = {
51
53
  "rebuild-started": "The rebuild is queued.",
52
54
  cancel: "Cancel"
53
55
  }
54
- }, D = /* @__PURE__ */ new WeakSet();
55
- function ne() {
56
+ }, N = /* @__PURE__ */ new WeakSet();
57
+ function ie() {
56
58
  try {
57
- const { i18n: o } = N();
58
- D.has(o) || (o.defaults("webx-catalog-manticore", le), D.add(o));
59
+ const { i18n: c } = P();
60
+ N.has(c) || (c.defaults("webx-catalog-manticore", ne), N.add(c));
59
61
  } catch {
60
62
  }
61
63
  }
62
- const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild-head" }, se = { class: "wx-search-index__grid" }, re = { key: 0 }, de = { key: 1 }, oe = { class: "wx-search-index__state" }, ce = 2e3, be = /* @__PURE__ */ j({
64
+ const ue = { class: "wx-search-index" }, se = { class: "wx-search-index__rebuild-head" }, re = { class: "wx-search-index__grid" }, oe = { key: 0 }, de = { key: 1 }, ce = { class: "wx-search-index__state" }, be = 2e3, he = /* @__PURE__ */ G({
63
65
  __name: "SearchIndexPage",
64
- setup(o) {
65
- const h = N();
66
- ne();
67
- const a = K("webx-catalog-manticore"), T = X(), _ = te(h), t = w(null), P = w(!0), q = w(!1), W = w(!1);
68
- let S;
69
- const V = v(() => h.can("search-index.manage")), n = v(() => t.value?.rebuild ?? null), A = v(
66
+ setup(c) {
67
+ const h = P();
68
+ ie();
69
+ const a = X("webx-catalog-manticore"), S = Y(), _ = le(h), t = T(null), V = T(!0), A = T(!1), M = T(!1);
70
+ let C;
71
+ const $ = v(() => h.can("search-index.manage")), n = v(() => t.value?.rebuild ?? null), y = v(
70
72
  () => n.value !== null && (n.value.state === "queued" || n.value.state === "running") && !n.value.stalled
71
- ), $ = v(
72
- () => A.value || (t.value?.tables.some((u) => u.rebuilding) ?? !1)
73
- ), O = v(() => {
74
- const u = [];
75
- return V.value && t.value !== null && u.push({
73
+ ), w = v(() => (t.value?.locked ?? !1) && !y.value), O = v(
74
+ () => y.value || w.value || (t.value?.tables.some((r) => r.rebuilding) ?? !1)
75
+ ), U = v(() => {
76
+ const r = [];
77
+ return $.value && t.value !== null && r.push({
76
78
  key: "rebuild",
77
79
  label: t.value.outdated ? a("panel.rebuild") : a("panel.rebuild-again"),
78
80
  icon: "refresh",
79
81
  // The section exists for it only when a table is out of date; otherwise it is a rare act.
80
82
  primary: t.value.outdated,
81
83
  menu: !t.value.outdated,
82
- disabled: A.value || !t.value.connection.available,
83
- loading: W.value,
84
+ disabled: y.value || w.value || !t.value.connection.available,
85
+ loading: M.value,
84
86
  run: () => {
85
- Q();
87
+ j();
86
88
  }
87
- }), u.push({
89
+ }), r.push({
88
90
  key: "refresh",
89
91
  label: a("panel.refresh"),
90
92
  icon: "refresh",
91
93
  menu: !0,
92
94
  run: () => {
93
- y();
95
+ k();
94
96
  }
95
- }), u;
96
- }), U = v(() => [
97
+ }), r;
98
+ }), F = v(() => [
97
99
  { key: "locale", label: a("panel.language"), width: 96 },
98
100
  { key: "table", label: a("panel.table"), minWidth: 200, hideBelow: 640 },
99
101
  { key: "documents", label: a("panel.in-index"), align: "right", width: 120 },
100
102
  { key: "products", label: a("panel.in-database"), align: "right", width: 120 },
101
103
  { key: "state", label: a("panel.state"), minWidth: 180 }
102
- ]), F = {
104
+ ]), Q = {
103
105
  ready: "success",
104
106
  stale: "warning",
105
107
  missing: "danger"
106
- }, I = v(() => {
107
- const u = n.value;
108
- if (u === null) return "";
109
- switch (u.state) {
108
+ }, B = v(() => {
109
+ const r = n.value;
110
+ if (r === null) return "";
111
+ switch (r.state) {
110
112
  case "queued":
111
113
  return a("panel.rebuild-queued");
112
114
  case "running":
113
115
  return a("panel.rebuild-running", {
114
- done: p(u.done),
115
- total: p(u.total)
116
+ done: p(r.done),
117
+ total: p(r.total)
116
118
  });
117
119
  case "done":
118
- return a("panel.rebuild-done", { done: p(u.done) });
120
+ return a("panel.rebuild-done", { done: p(r.done) });
119
121
  case "failed":
120
122
  return a("panel.rebuild-failed");
121
123
  default:
122
124
  return "";
123
125
  }
124
126
  });
125
- function p(u) {
126
- return u === null ? "—" : u.toLocaleString(h.i18n.state.locale);
127
+ function p(r) {
128
+ return r === null ? "—" : r.toLocaleString(h.i18n.state.locale);
127
129
  }
128
- async function y() {
129
- clearTimeout(S);
130
+ async function k() {
131
+ clearTimeout(C);
130
132
  try {
131
- t.value = await _.report(), q.value = !1;
133
+ t.value = await _.report(), A.value = !1;
132
134
  } catch {
133
- q.value = t.value === null;
135
+ A.value = t.value === null;
134
136
  } finally {
135
- P.value = !1;
137
+ V.value = !1;
136
138
  }
137
- $.value && (S = setTimeout(() => {
138
- y();
139
- }, ce));
139
+ O.value && (C = setTimeout(() => {
140
+ k();
141
+ }, be));
140
142
  }
141
- async function Q() {
142
- if (!(!await Z({
143
+ async function j() {
144
+ if (!(!await ee({
143
145
  title: a("panel.rebuild-title"),
144
146
  message: a("panel.rebuild-text"),
145
147
  confirmText: a("panel.rebuild"),
146
148
  cancelText: a("panel.cancel")
147
149
  }) || t.value === null)) {
148
- W.value = !0;
150
+ M.value = !0;
149
151
  try {
150
- t.value = { ...t.value, rebuild: await _.rebuild() }, L.success(a("panel.rebuild-started"));
151
- } catch (B) {
152
- L.danger(T(B));
152
+ t.value = { ...t.value, rebuild: await _.rebuild() }, R.success(a("panel.rebuild-started"));
153
+ } catch (E) {
154
+ R.danger(S(E));
153
155
  } finally {
154
- W.value = !1;
156
+ M.value = !1;
155
157
  }
156
- await y();
158
+ await k();
157
159
  }
158
160
  }
159
- return G(() => {
160
- y();
161
- }), H(() => clearTimeout(S)), (u, B) => (s(), c(e(Y), {
161
+ return H(() => {
162
+ k();
163
+ }), J(() => clearTimeout(C)), (r, E) => (u(), d(e(Z), {
162
164
  title: e(a)("panel.title"),
163
- actions: O.value,
165
+ actions: U.value,
164
166
  card: !1
165
167
  }, {
166
168
  default: l(() => [
167
- m("div", ie, [
168
- r(e(g), { tone: "muted" }, {
169
+ m("div", ue, [
170
+ o(e(g), { tone: "muted" }, {
169
171
  default: l(() => [
170
- d(i(e(a)("panel.lead")), 1)
172
+ s(i(e(a)("panel.lead")), 1)
171
173
  ]),
172
174
  _: 1
173
175
  }),
174
- q.value ? (s(), c(e(C), {
176
+ A.value ? (u(), d(e(q), {
175
177
  key: 0,
176
178
  type: "danger"
177
179
  }, {
178
180
  default: l(() => [
179
- d(i(e(a)("panel.load-failed")), 1)
181
+ s(i(e(a)("panel.load-failed")), 1)
180
182
  ]),
181
183
  _: 1
182
184
  })) : b("", !0),
183
- t.value ? (s(), M(J, { key: 1 }, [
184
- t.value.connection.available ? t.value.outdated && !A.value ? (s(), c(e(C), {
185
+ t.value ? (u(), I(K, { key: 1 }, [
186
+ t.value.connection.available ? t.value.outdated && !y.value && !w.value ? (u(), d(e(q), {
185
187
  key: 1,
186
188
  type: "warning",
187
189
  title: e(a)("panel.outdated")
188
190
  }, {
189
191
  default: l(() => [
190
- d(i(e(a)("panel.outdated-text")), 1)
192
+ s(i(e(a)("panel.outdated-text")), 1)
191
193
  ]),
192
194
  _: 1
193
- }, 8, ["title"])) : b("", !0) : (s(), c(e(C), {
195
+ }, 8, ["title"])) : b("", !0) : (u(), d(e(q), {
194
196
  key: 0,
195
197
  type: "danger",
196
198
  title: e(a)("panel.unavailable")
197
199
  }, {
198
200
  default: l(() => [
199
- d(i(t.value.connection.error), 1)
201
+ s(i(t.value.connection.error), 1)
200
202
  ]),
201
203
  _: 1
202
204
  }, 8, ["title"])),
203
- n.value && n.value.state !== "idle" ? (s(), c(e(k), {
205
+ w.value ? (u(), d(e(q), {
204
206
  key: 2,
207
+ type: "info"
208
+ }, {
209
+ default: l(() => [
210
+ s(i(e(a)("panel.rebuild-console")), 1)
211
+ ]),
212
+ _: 1
213
+ })) : b("", !0),
214
+ n.value && n.value.state !== "idle" ? (u(), d(e(W), {
215
+ key: 3,
205
216
  bordered: "",
206
217
  class: "wx-search-index__rebuild"
207
218
  }, {
208
219
  default: l(() => [
209
- m("div", ue, [
210
- r(e(g), { weight: "medium" }, {
220
+ m("div", se, [
221
+ o(e(g), { weight: "medium" }, {
211
222
  default: l(() => [
212
- d(i(I.value), 1)
223
+ s(i(B.value), 1)
213
224
  ]),
214
225
  _: 1
215
226
  }),
216
- n.value.finished_at ?? n.value.started_at ?? n.value.queued_at ? (s(), c(e(E), {
227
+ n.value.finished_at ?? n.value.started_at ?? n.value.queued_at ? (u(), d(e(L), {
217
228
  key: 0,
218
229
  value: n.value.finished_at ?? n.value.started_at ?? n.value.queued_at
219
230
  }, null, 8, ["value"])) : b("", !0)
220
231
  ]),
221
- n.value.state === "running" || n.value.state === "queued" ? (s(), c(e(ee), {
232
+ n.value.state === "running" || n.value.state === "queued" ? (u(), d(e(ae), {
222
233
  key: 0,
223
234
  value: n.value.done,
224
235
  max: Math.max(n.value.total, 1),
225
236
  indeterminate: n.value.state === "queued" || n.value.total === 0,
226
- "aria-label": I.value
237
+ "aria-label": B.value
227
238
  }, null, 8, ["value", "max", "indeterminate", "aria-label"])) : b("", !0),
228
- n.value.stalled ? (s(), c(e(g), {
239
+ n.value.stalled ? (u(), d(e(g), {
229
240
  key: 1,
230
241
  size: "sm",
231
242
  tone: "warning"
232
243
  }, {
233
244
  default: l(() => [
234
- d(i(e(a)("panel.rebuild-stalled")), 1)
245
+ s(i(e(a)("panel.rebuild-stalled")), 1)
235
246
  ]),
236
247
  _: 1
237
248
  })) : b("", !0),
238
- n.value.state === "failed" && n.value.error ? (s(), c(e(g), {
249
+ n.value.state === "failed" && n.value.error ? (u(), d(e(g), {
239
250
  key: 2,
240
251
  size: "sm",
241
252
  tone: "danger"
242
253
  }, {
243
254
  default: l(() => [
244
- d(i(n.value.error), 1)
255
+ s(i(n.value.error), 1)
245
256
  ]),
246
257
  _: 1
247
258
  })) : b("", !0)
248
259
  ]),
249
260
  _: 1
250
261
  })) : b("", !0),
251
- m("div", se, [
252
- r(e(k), {
262
+ m("div", re, [
263
+ o(e(W), {
253
264
  bordered: "",
254
265
  title: e(a)("panel.connection")
255
266
  }, {
256
267
  default: l(() => [
257
- r(e(R), {
268
+ o(e(z), {
258
269
  columns: 1,
259
270
  "label-width": "140px"
260
271
  }, {
261
272
  default: l(() => [
262
- r(e(x), {
273
+ o(e(x), {
263
274
  label: e(a)("panel.address")
264
275
  }, {
265
276
  default: l(() => [
@@ -267,31 +278,31 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
267
278
  ]),
268
279
  _: 1
269
280
  }, 8, ["label"]),
270
- r(e(x), {
281
+ o(e(x), {
271
282
  label: e(a)("panel.prefix")
272
283
  }, {
273
284
  default: l(() => [
274
- t.value.connection.prefix ? (s(), M("code", re, i(t.value.connection.prefix), 1)) : (s(), M("span", de, "—"))
285
+ t.value.connection.prefix ? (u(), I("code", oe, i(t.value.connection.prefix), 1)) : (u(), I("span", de, "—"))
275
286
  ]),
276
287
  _: 1
277
288
  }, 8, ["label"]),
278
- r(e(x), {
289
+ o(e(x), {
279
290
  label: e(a)("panel.version")
280
291
  }, {
281
292
  default: l(() => [
282
- d(i(t.value.connection.version ?? "—"), 1)
293
+ s(i(t.value.connection.version ?? "—"), 1)
283
294
  ]),
284
295
  _: 1
285
296
  }, 8, ["label"]),
286
- r(e(x), {
297
+ o(e(x), {
287
298
  label: e(a)("panel.state")
288
299
  }, {
289
300
  default: l(() => [
290
- r(e(z), {
301
+ o(e(D), {
291
302
  type: t.value.connection.available ? "success" : "danger"
292
303
  }, {
293
304
  default: l(() => [
294
- d(i(t.value.connection.available ? e(a)("panel.available") : e(a)("panel.unavailable")), 1)
305
+ s(i(t.value.connection.available ? e(a)("panel.available") : e(a)("panel.unavailable")), 1)
295
306
  ]),
296
307
  _: 1
297
308
  }, 8, ["type"])
@@ -304,30 +315,30 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
304
315
  ]),
305
316
  _: 1
306
317
  }, 8, ["title"]),
307
- r(e(k), {
318
+ o(e(W), {
308
319
  bordered: "",
309
320
  title: e(a)("panel.queue")
310
321
  }, {
311
322
  default: l(() => [
312
- r(e(R), {
323
+ o(e(z), {
313
324
  columns: 1,
314
325
  "label-width": "180px"
315
326
  }, {
316
327
  default: l(() => [
317
- r(e(x), {
328
+ o(e(x), {
318
329
  label: e(a)("panel.waiting")
319
330
  }, {
320
331
  default: l(() => [
321
- d(i(p(t.value.queue.waiting)), 1)
332
+ s(i(p(t.value.queue.waiting)), 1)
322
333
  ]),
323
334
  _: 1
324
335
  }, 8, ["label"]),
325
- t.value.queue.oldest ? (s(), c(e(x), {
336
+ t.value.queue.oldest ? (u(), d(e(x), {
326
337
  key: 0,
327
338
  label: e(a)("panel.oldest")
328
339
  }, {
329
340
  default: l(() => [
330
- r(e(E), {
341
+ o(e(L), {
331
342
  value: t.value.queue.oldest
332
343
  }, null, 8, ["value"])
333
344
  ]),
@@ -336,13 +347,13 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
336
347
  ]),
337
348
  _: 1
338
349
  }),
339
- t.value.queue.waiting === 0 ? (s(), c(e(g), {
350
+ t.value.queue.waiting === 0 ? (u(), d(e(g), {
340
351
  key: 0,
341
352
  size: "sm",
342
353
  tone: "muted"
343
354
  }, {
344
355
  default: l(() => [
345
- d(i(e(a)("panel.queue-empty")), 1)
356
+ s(i(e(a)("panel.queue-empty")), 1)
346
357
  ]),
347
358
  _: 1
348
359
  })) : b("", !0)
@@ -350,14 +361,14 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
350
361
  _: 1
351
362
  }, 8, ["title"])
352
363
  ]),
353
- r(e(k), {
364
+ o(e(W), {
354
365
  bordered: "",
355
366
  title: e(a)("panel.tables")
356
367
  }, {
357
368
  default: l(() => [
358
- r(e(ae), {
369
+ o(e(te), {
359
370
  data: t.value.tables,
360
- columns: U.value,
371
+ columns: F.value,
361
372
  "row-key": "table",
362
373
  flush: "",
363
374
  "cards-below": 560,
@@ -368,38 +379,38 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
368
379
  m("code", null, i(f.table), 1)
369
380
  ]),
370
381
  "cell-documents": l(({ row: f }) => [
371
- d(i(p(f.documents)), 1)
382
+ s(i(p(f.documents)), 1)
372
383
  ]),
373
384
  "cell-products": l(() => [
374
- d(i(p(t.value.products)), 1)
385
+ s(i(p(t.value.products)), 1)
375
386
  ]),
376
387
  "cell-state": l(({ row: f }) => [
377
- m("div", oe, [
378
- r(e(z), {
379
- type: F[f.state]
388
+ m("div", ce, [
389
+ o(e(D), {
390
+ type: Q[f.state]
380
391
  }, {
381
392
  default: l(() => [
382
- d(i(e(a)(`panel.state-${f.state}`)), 1)
393
+ s(i(e(a)(`panel.state-${f.state}`)), 1)
383
394
  ]),
384
395
  _: 2
385
396
  }, 1032, ["type"]),
386
- f.reason ? (s(), c(e(g), {
397
+ f.reason ? (u(), d(e(g), {
387
398
  key: 0,
388
399
  size: "xs",
389
400
  tone: "muted"
390
401
  }, {
391
402
  default: l(() => [
392
- d(i(f.reason), 1)
403
+ s(i(f.reason), 1)
393
404
  ]),
394
405
  _: 2
395
406
  }, 1024)) : b("", !0),
396
- f.rebuilding ? (s(), c(e(g), {
407
+ f.rebuilding ? (u(), d(e(g), {
397
408
  key: 1,
398
409
  size: "xs",
399
410
  tone: "muted"
400
411
  }, {
401
412
  default: l(() => [
402
- d(i(f.filled == null ? e(a)("panel.filling") : e(a)("panel.filled", {
413
+ s(i(f.filled == null ? e(a)("panel.filling") : e(a)("panel.filled", {
403
414
  done: p(f.filled),
404
415
  total: p(t.value.products)
405
416
  })), 1)
@@ -419,25 +430,25 @@ const ie = { class: "wx-search-index" }, ue = { class: "wx-search-index__rebuild
419
430
  _: 1
420
431
  }, 8, ["title", "actions"]));
421
432
  }
422
- }), he = (o, h) => {
423
- const a = o.__vccOpts || o;
424
- for (const [T, _] of h)
425
- a[T] = _;
433
+ }), fe = (c, h) => {
434
+ const a = c.__vccOpts || c;
435
+ for (const [S, _] of h)
436
+ a[S] = _;
426
437
  return a;
427
- }, fe = /* @__PURE__ */ he(be, [["__scopeId", "data-v-2e57f11d"]]);
428
- function me(o = {}) {
429
- const h = o.path ?? "/search-index";
438
+ }, pe = /* @__PURE__ */ fe(he, [["__scopeId", "data-v-38a4b545"]]);
439
+ function xe(c = {}) {
440
+ const h = c.path ?? "/search-index";
430
441
  return [
431
442
  {
432
443
  id: "search-index",
433
444
  path: h,
434
- routes: [{ path: h, name: "webx.search-index", component: fe }]
445
+ routes: [{ path: h, name: "webx.search-index", component: pe }]
435
446
  }
436
447
  ];
437
448
  }
438
449
  export {
439
- me as catalogManticore,
440
- le as catalogManticoreMessages,
441
- te as createSearchIndexApi
450
+ xe as catalogManticore,
451
+ ne as catalogManticoreMessages,
452
+ le as createSearchIndexApi
442
453
  };
443
454
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/SearchIndexPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type { IndexReport, RebuildProgress } from './types'\n\nexport interface SearchIndexApi {\n report(): Promise<IndexReport>\n /** The rebuild queued; refused with 409 while one is waiting or running. */\n rebuild(): Promise<RebuildProgress>\n}\n\nexport function createSearchIndexApi(admin: AdminContext): SearchIndexApi {\n const base = `${admin.apiPath}/search-index`\n\n return {\n report: () => admin.http.get<{ data: IndexReport }>(base).then((body) => body.data),\n rebuild: () =>\n admin.http.post<{ data: RebuildProgress }>(`${base}/rebuild`, {}).then((body) => body.data),\n }\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or without\n * one. The server ships the same lines under `webx-catalog-manticore::` and overrides these;\n * `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const catalogManticoreMessages: Record<string, Messages> = {\n panel: {\n title: 'Search index',\n lead: 'The catalogue searches, filters and counts with Manticore. The panel answers from the database when it does not.',\n refresh: 'Refresh',\n 'load-failed': 'Could not load the state of the index.',\n connection: 'Server',\n address: 'Address',\n prefix: 'Table prefix',\n version: 'Version',\n available: 'Answers',\n unavailable: 'Does not answer',\n tables: 'Tables',\n language: 'Language',\n table: 'Table',\n 'in-index': 'In the index',\n 'in-database': 'In the database',\n state: 'State',\n 'state-ready': 'Up to date',\n 'state-stale': 'Schema out of date',\n 'state-missing': 'Missing',\n filling: 'A rebuild is filling the table beside it.',\n filled: 'A rebuild is filling the table beside it: :done of :total',\n 'no-tables': 'The server did not say which tables it has.',\n queue: 'Queue',\n waiting: 'Waiting to be written',\n oldest: 'The oldest since',\n 'queue-empty': 'Every saved product is in the index.',\n outdated: 'The index is not of the schema the catalogue writes now',\n 'outdated-text':\n 'The storefront answers from the old tables meanwhile, but what they lack — a new filter, codes — is not searched. A rebuild fills new tables beside the live ones and swaps them in; on a large catalogue it is minutes of load, so choose the time.',\n rebuild: 'Rebuild',\n 'rebuild-again': 'Rebuild again',\n 'rebuild-title': 'Rebuild the search index?',\n 'rebuild-text':\n 'Every product is written again into new tables, which then replace the live ones. The storefront keeps working on the old tables meanwhile.',\n 'rebuild-busy': 'A rebuild is already under way.',\n 'rebuild-queued': 'Waiting for the queue worker',\n 'rebuild-running': 'Rebuilding: :done of :total',\n 'rebuild-done': 'Rebuilt: :done products',\n 'rebuild-failed': 'The rebuild failed',\n 'rebuild-stalled':\n 'Nothing has been heard from the rebuild for a quarter of an hour: the queue worker is not running or stopped. Start it again once the worker runs.',\n 'rebuild-started': 'The rebuild is queued.',\n cancel: 'Cancel',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { catalogManticoreMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/**\n * Put this package's English under the panel's dictionary, once per panel — so a page opened\n * before the server's dictionary arrives, or without one, still has words.\n */\nexport function useCatalogManticoreMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-catalog-manticore', catalogManticoreMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n WxListScreen,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n toast,\n WxAlert,\n WxBadge,\n WxCard,\n WxDescriptions,\n WxDescriptionsItem,\n WxProgress,\n WxTable,\n WxText,\n type BadgeType,\n type TableColumn,\n} from '@webx-ui/core'\nimport { createSearchIndexApi } from './api'\nimport { useCatalogManticoreMessages } from './i18n'\nimport type { IndexReport, IndexTable, RebuildProgress, TableState } from './types'\n\n/**\n * «System → Search index» (decision 27 of the Manticore spec).\n *\n * Opened when something is wrong — a product is not found, the list says it comes from the\n * database — so the page answers in that order: does the server answer, is every table of the\n * schema the catalogue writes now and as full as the database, and is the queue moving. A table\n * out of date has «Rebuild», which is a job on the queue: the page follows it by asking again,\n * and a closed tab does not stop it.\n */\nconst POLL = 2000\n\nconst context = useAdmin()\nuseCatalogManticoreMessages()\n\nconst t = useTranslate('webx-catalog-manticore')\nconst message = useErrorText()\nconst api = createSearchIndexApi(context)\n\nconst report = ref<IndexReport | null>(null)\nconst loading = ref(true)\nconst failed = ref(false)\nconst starting = ref(false)\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nconst canManage = computed(() => context.can('search-index.manage'))\nconst rebuild = computed<RebuildProgress | null>(() => report.value?.rebuild ?? null)\n\n/** Waiting or running, and still heard from: no second rebuild is offered. */\nconst underway = computed(\n () =>\n rebuild.value !== null &&\n (rebuild.value.state === 'queued' || rebuild.value.state === 'running') &&\n !rebuild.value.stalled,\n)\n\n/**\n * The page keeps asking while a rebuild is underway — or while a table is filled beside a live\n * one: a rebuild started from the console writes no progress, only the table. That alone does\n * not hold the button back, since a table left by a rebuild that was killed would hold it forever.\n */\nconst filling = computed(\n () => underway.value || (report.value?.tables.some((table) => table.rebuilding) ?? false),\n)\n\nconst actions = computed<ScreenAction[]>(() => {\n const list: ScreenAction[] = []\n\n if (canManage.value && report.value !== null) {\n list.push({\n key: 'rebuild',\n label: report.value.outdated ? t('panel.rebuild') : t('panel.rebuild-again'),\n icon: 'refresh',\n // The section exists for it only when a table is out of date; otherwise it is a rare act.\n primary: report.value.outdated,\n menu: !report.value.outdated,\n disabled: underway.value || !report.value.connection.available,\n loading: starting.value,\n run: () => void start(),\n })\n }\n\n list.push({\n key: 'refresh',\n label: t('panel.refresh'),\n icon: 'refresh',\n menu: true,\n run: () => void load(),\n })\n\n return list\n})\n\nconst columns = computed<TableColumn<IndexTable>[]>(() => [\n { key: 'locale', label: t('panel.language'), width: 96 },\n { key: 'table', label: t('panel.table'), minWidth: 200, hideBelow: 640 },\n { key: 'documents', label: t('panel.in-index'), align: 'right', width: 120 },\n { key: 'products', label: t('panel.in-database'), align: 'right', width: 120 },\n { key: 'state', label: t('panel.state'), minWidth: 180 },\n])\n\nconst STATE: Record<TableState, BadgeType> = {\n ready: 'success',\n stale: 'warning',\n missing: 'danger',\n}\n\nconst progressLine = computed(() => {\n const progress = rebuild.value\n\n if (progress === null) return ''\n\n switch (progress.state) {\n case 'queued':\n return t('panel.rebuild-queued')\n case 'running':\n return t('panel.rebuild-running', {\n done: count(progress.done),\n total: count(progress.total),\n })\n case 'done':\n return t('panel.rebuild-done', { done: count(progress.done) })\n case 'failed':\n return t('panel.rebuild-failed')\n default:\n return ''\n }\n})\n\nfunction count(value: number | null): string {\n return value === null ? '—' : value.toLocaleString(context.i18n.state.locale)\n}\n\nasync function load(): Promise<void> {\n clearTimeout(timer)\n\n try {\n report.value = await api.report()\n failed.value = false\n } catch {\n failed.value = report.value === null\n } finally {\n loading.value = false\n }\n\n if (filling.value) timer = setTimeout(() => void load(), POLL)\n}\n\nasync function start(): Promise<void> {\n const agreed = await confirm({\n title: t('panel.rebuild-title'),\n message: t('panel.rebuild-text'),\n confirmText: t('panel.rebuild'),\n cancelText: t('panel.cancel'),\n })\n\n if (!agreed || report.value === null) return\n\n starting.value = true\n\n try {\n report.value = { ...report.value, rebuild: await api.rebuild() }\n toast.success(t('panel.rebuild-started'))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n starting.value = false\n }\n\n await load()\n}\n\nonMounted(() => void load())\nonBeforeUnmount(() => clearTimeout(timer))\n</script>\n\n<template>\n <wx-list-screen :title=\"t('panel.title')\" :actions=\"actions\" :card=\"false\">\n <div class=\"wx-search-index\">\n <wx-text tone=\"muted\">{{ t('panel.lead') }}</wx-text>\n\n <wx-alert v-if=\"failed\" type=\"danger\">{{ t('panel.load-failed') }}</wx-alert>\n\n <template v-if=\"report\">\n <wx-alert v-if=\"!report.connection.available\" type=\"danger\" :title=\"t('panel.unavailable')\">\n {{ report.connection.error }}\n </wx-alert>\n\n <wx-alert\n v-else-if=\"report.outdated && !underway\"\n type=\"warning\"\n :title=\"t('panel.outdated')\"\n >\n {{ t('panel.outdated-text') }}\n </wx-alert>\n\n <!-- The rebuild started from here: what it is doing, or how it ended. -->\n <wx-card\n v-if=\"rebuild && rebuild.state !== 'idle'\"\n bordered\n class=\"wx-search-index__rebuild\"\n >\n <div class=\"wx-search-index__rebuild-head\">\n <wx-text weight=\"medium\">{{ progressLine }}</wx-text>\n <wx-date\n v-if=\"rebuild.finished_at ?? rebuild.started_at ?? rebuild.queued_at\"\n :value=\"rebuild.finished_at ?? rebuild.started_at ?? rebuild.queued_at\"\n />\n </div>\n <wx-progress\n v-if=\"rebuild.state === 'running' || rebuild.state === 'queued'\"\n :value=\"rebuild.done\"\n :max=\"Math.max(rebuild.total, 1)\"\n :indeterminate=\"rebuild.state === 'queued' || rebuild.total === 0\"\n :aria-label=\"progressLine\"\n />\n <wx-text v-if=\"rebuild.stalled\" size=\"sm\" tone=\"warning\">\n {{ t('panel.rebuild-stalled') }}\n </wx-text>\n <wx-text v-if=\"rebuild.state === 'failed' && rebuild.error\" size=\"sm\" tone=\"danger\">\n {{ rebuild.error }}\n </wx-text>\n </wx-card>\n\n <div class=\"wx-search-index__grid\">\n <wx-card bordered :title=\"t('panel.connection')\">\n <wx-descriptions :columns=\"1\" label-width=\"140px\">\n <wx-descriptions-item :label=\"t('panel.address')\">\n <code>{{ report.connection.address }}</code>\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.prefix')\">\n <code v-if=\"report.connection.prefix\">{{ report.connection.prefix }}</code>\n <span v-else>—</span>\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.version')\">\n {{ report.connection.version ?? '—' }}\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.state')\">\n <wx-badge :type=\"report.connection.available ? 'success' : 'danger'\">\n {{ report.connection.available ? t('panel.available') : t('panel.unavailable') }}\n </wx-badge>\n </wx-descriptions-item>\n </wx-descriptions>\n </wx-card>\n\n <wx-card bordered :title=\"t('panel.queue')\">\n <wx-descriptions :columns=\"1\" label-width=\"180px\">\n <wx-descriptions-item :label=\"t('panel.waiting')\">\n {{ count(report.queue.waiting) }}\n </wx-descriptions-item>\n <wx-descriptions-item v-if=\"report.queue.oldest\" :label=\"t('panel.oldest')\">\n <wx-date :value=\"report.queue.oldest\" />\n </wx-descriptions-item>\n </wx-descriptions>\n <wx-text v-if=\"report.queue.waiting === 0\" size=\"sm\" tone=\"muted\">\n {{ t('panel.queue-empty') }}\n </wx-text>\n </wx-card>\n </div>\n\n <wx-card bordered :title=\"t('panel.tables')\">\n <wx-table\n :data=\"report.tables\"\n :columns=\"columns\"\n row-key=\"table\"\n flush\n :cards-below=\"560\"\n :empty-text=\"t('panel.no-tables')\"\n :aria-label=\"t('panel.tables')\"\n >\n <template #cell-table=\"{ row }\">\n <code>{{ row.table }}</code>\n </template>\n <template #cell-documents=\"{ row }\">\n {{ count(row.documents) }}\n </template>\n <template #cell-products>\n {{ count(report.products) }}\n </template>\n <template #cell-state=\"{ row }\">\n <div class=\"wx-search-index__state\">\n <wx-badge :type=\"STATE[row.state]\">{{ t(`panel.state-${row.state}`) }}</wx-badge>\n <wx-text v-if=\"row.reason\" size=\"xs\" tone=\"muted\">{{ row.reason }}</wx-text>\n <wx-text v-if=\"row.rebuilding\" size=\"xs\" tone=\"muted\">\n {{\n row.filled == null\n ? t('panel.filling')\n : t('panel.filled', {\n done: count(row.filled),\n total: count(report.products),\n })\n }}\n </wx-text>\n </div>\n </template>\n </wx-table>\n </wx-card>\n </template>\n </div>\n </wx-list-screen>\n</template>\n\n<style scoped>\n.wx-search-index {\n container-type: inline-size;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n.wx-search-index__grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: var(--wx-space-16);\n}\n\n@container (min-width: 720px) {\n .wx-search-index__grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n.wx-search-index__rebuild :deep(.wx-card__body) {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-search-index__rebuild-head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-search-index__state {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--wx-space-4);\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.wx-search-index code {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n overflow-wrap: anywhere;\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport SearchIndexPage from './SearchIndexPage.vue'\n\nexport interface CatalogManticoreOptions {\n /** Where the page lives inside the panel. */\n path?: string\n}\n\n/**\n * «System → Search index» (decision 27 of the Manticore spec): the server, each language's table\n * against the database, the queue, and the rebuild as a job with its progress.\n *\n * The server reports the section only when the catalogue runs on Manticore, so a panel on the\n * database engine has no such entry even with this module listed. The notice over the list of\n * products, when the panel answers from the database, is the catalogue's own and needs nothing here.\n */\nexport function catalogManticore(options: CatalogManticoreOptions = {}): AdminModule[] {\n const path = options.path ?? '/search-index'\n\n return [\n {\n id: 'search-index',\n path,\n routes: [{ path, name: 'webx.search-index', component: SearchIndexPage }],\n },\n ]\n}\n"],"names":["createSearchIndexApi","admin","base","body","catalogManticoreMessages","seeded","useCatalogManticoreMessages","i18n","useAdmin","POLL","context","t","useTranslate","message","useErrorText","api","report","ref","loading","failed","starting","timer","canManage","computed","rebuild","underway","filling","table","actions","list","start","load","columns","STATE","progressLine","progress","count","value","confirm","toast","error","onMounted","onBeforeUnmount","_createBlock","_unref","WxListScreen","_createElementVNode","_hoisted_1","_createVNode","WxText","WxAlert","_createElementBlock","_Fragment","WxCard","_hoisted_2","WxDate","WxProgress","_createTextVNode","_toDisplayString","_hoisted_3","WxDescriptions","WxDescriptionsItem","_openBlock","_hoisted_4","WxBadge","WxTable","_withCtx","row","_hoisted_6","catalogManticore","options","path","SearchIndexPage"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/SearchIndexPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type { IndexReport, RebuildProgress } from './types'\n\nexport interface SearchIndexApi {\n report(): Promise<IndexReport>\n /** The rebuild queued; refused with 409 while one is waiting or running. */\n rebuild(): Promise<RebuildProgress>\n}\n\nexport function createSearchIndexApi(admin: AdminContext): SearchIndexApi {\n const base = `${admin.apiPath}/search-index`\n\n return {\n report: () => admin.http.get<{ data: IndexReport }>(base).then((body) => body.data),\n rebuild: () =>\n admin.http.post<{ data: RebuildProgress }>(`${base}/rebuild`, {}).then((body) => body.data),\n }\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or without\n * one. The server ships the same lines under `webx-catalog-manticore::` and overrides these;\n * `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const catalogManticoreMessages: Record<string, Messages> = {\n panel: {\n title: 'Search index',\n lead: 'The catalogue searches, filters and counts with Manticore. The panel answers from the database when it does not.',\n refresh: 'Refresh',\n 'load-failed': 'Could not load the state of the index.',\n connection: 'Server',\n address: 'Address',\n prefix: 'Table prefix',\n version: 'Version',\n available: 'Answers',\n unavailable: 'Does not answer',\n tables: 'Tables',\n language: 'Language',\n table: 'Table',\n 'in-index': 'In the index',\n 'in-database': 'In the database',\n state: 'State',\n 'state-ready': 'Up to date',\n 'state-stale': 'Schema out of date',\n 'state-missing': 'Missing',\n filling: 'A rebuild is filling the table beside it.',\n filled: 'A rebuild is filling the table beside it: :done of :total',\n 'no-tables': 'The server did not say which tables it has.',\n queue: 'Queue',\n waiting: 'Waiting to be written',\n oldest: 'The oldest since',\n 'queue-empty': 'Every saved product is in the index.',\n outdated: 'The index is not of the schema the catalogue writes now',\n 'outdated-text':\n 'The storefront answers from the old tables meanwhile, but what they lack — a new filter, codes — is not searched. A rebuild fills new tables beside the live ones and swaps them in; on a large catalogue it is minutes of load, so choose the time.',\n rebuild: 'Rebuild',\n 'rebuild-again': 'Rebuild again',\n 'rebuild-title': 'Rebuild the search index?',\n 'rebuild-text':\n 'Every product is written again into new tables, which then replace the live ones. The storefront keeps working on the old tables meanwhile.',\n 'rebuild-busy': 'A rebuild is already under way.',\n 'rebuild-locked':\n 'Another rebuild is running — it was started from the console. Start this one once it ends.',\n 'rebuild-console':\n 'A rebuild started from the console is running: the button comes back when it ends.',\n 'rebuild-queued': 'Waiting for the queue worker',\n 'rebuild-running': 'Rebuilding: :done of :total',\n 'rebuild-done': 'Rebuilt: :done products',\n 'rebuild-failed': 'The rebuild failed',\n 'rebuild-stalled':\n 'Nothing has been heard from the rebuild for a quarter of an hour: the queue worker is not running or stopped. Start it again once the worker runs.',\n 'rebuild-started': 'The rebuild is queued.',\n cancel: 'Cancel',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { catalogManticoreMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/**\n * Put this package's English under the panel's dictionary, once per panel — so a page opened\n * before the server's dictionary arrives, or without one, still has words.\n */\nexport function useCatalogManticoreMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-catalog-manticore', catalogManticoreMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxDate,\n WxListScreen,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n toast,\n WxAlert,\n WxBadge,\n WxCard,\n WxDescriptions,\n WxDescriptionsItem,\n WxProgress,\n WxTable,\n WxText,\n type BadgeType,\n type TableColumn,\n} from '@webx-ui/core'\nimport { createSearchIndexApi } from './api'\nimport { useCatalogManticoreMessages } from './i18n'\nimport type { IndexReport, IndexTable, RebuildProgress, TableState } from './types'\n\n/**\n * «System → Search index» (decision 27 of the Manticore spec).\n *\n * Opened when something is wrong — a product is not found, the list says it comes from the\n * database — so the page answers in that order: does the server answer, is every table of the\n * schema the catalogue writes now and as full as the database, and is the queue moving. A table\n * out of date has «Rebuild», which is a job on the queue: the page follows it by asking again,\n * and a closed tab does not stop it.\n */\nconst POLL = 2000\n\nconst context = useAdmin()\nuseCatalogManticoreMessages()\n\nconst t = useTranslate('webx-catalog-manticore')\nconst message = useErrorText()\nconst api = createSearchIndexApi(context)\n\nconst report = ref<IndexReport | null>(null)\nconst loading = ref(true)\nconst failed = ref(false)\nconst starting = ref(false)\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nconst canManage = computed(() => context.can('search-index.manage'))\nconst rebuild = computed<RebuildProgress | null>(() => report.value?.rebuild ?? null)\n\n/** Waiting or running, and still heard from: no second rebuild is offered. */\nconst underway = computed(\n () =>\n rebuild.value !== null &&\n (rebuild.value.state === 'queued' || rebuild.value.state === 'running') &&\n !rebuild.value.stalled,\n)\n\n/**\n * The console's `--rebuild` holds the lock the panel's rebuild takes too, and writes no progress\n * of its own: while it runs, the button is held back and the page says why. A lock outlives a\n * killed process by an hour at most, unlike a table left beside, which would hold it forever.\n */\nconst fromConsole = computed(() => (report.value?.locked ?? false) && !underway.value)\n\n/**\n * The page keeps asking while a rebuild is underway — or while a table is filled beside a live\n * one: a rebuild started from the console writes no progress, only the table.\n */\nconst filling = computed(\n () =>\n underway.value ||\n fromConsole.value ||\n (report.value?.tables.some((table) => table.rebuilding) ?? false),\n)\n\nconst actions = computed<ScreenAction[]>(() => {\n const list: ScreenAction[] = []\n\n if (canManage.value && report.value !== null) {\n list.push({\n key: 'rebuild',\n label: report.value.outdated ? t('panel.rebuild') : t('panel.rebuild-again'),\n icon: 'refresh',\n // The section exists for it only when a table is out of date; otherwise it is a rare act.\n primary: report.value.outdated,\n menu: !report.value.outdated,\n disabled: underway.value || fromConsole.value || !report.value.connection.available,\n loading: starting.value,\n run: () => void start(),\n })\n }\n\n list.push({\n key: 'refresh',\n label: t('panel.refresh'),\n icon: 'refresh',\n menu: true,\n run: () => void load(),\n })\n\n return list\n})\n\nconst columns = computed<TableColumn<IndexTable>[]>(() => [\n { key: 'locale', label: t('panel.language'), width: 96 },\n { key: 'table', label: t('panel.table'), minWidth: 200, hideBelow: 640 },\n { key: 'documents', label: t('panel.in-index'), align: 'right', width: 120 },\n { key: 'products', label: t('panel.in-database'), align: 'right', width: 120 },\n { key: 'state', label: t('panel.state'), minWidth: 180 },\n])\n\nconst STATE: Record<TableState, BadgeType> = {\n ready: 'success',\n stale: 'warning',\n missing: 'danger',\n}\n\nconst progressLine = computed(() => {\n const progress = rebuild.value\n\n if (progress === null) return ''\n\n switch (progress.state) {\n case 'queued':\n return t('panel.rebuild-queued')\n case 'running':\n return t('panel.rebuild-running', {\n done: count(progress.done),\n total: count(progress.total),\n })\n case 'done':\n return t('panel.rebuild-done', { done: count(progress.done) })\n case 'failed':\n return t('panel.rebuild-failed')\n default:\n return ''\n }\n})\n\nfunction count(value: number | null): string {\n return value === null ? '—' : value.toLocaleString(context.i18n.state.locale)\n}\n\nasync function load(): Promise<void> {\n clearTimeout(timer)\n\n try {\n report.value = await api.report()\n failed.value = false\n } catch {\n failed.value = report.value === null\n } finally {\n loading.value = false\n }\n\n if (filling.value) timer = setTimeout(() => void load(), POLL)\n}\n\nasync function start(): Promise<void> {\n const agreed = await confirm({\n title: t('panel.rebuild-title'),\n message: t('panel.rebuild-text'),\n confirmText: t('panel.rebuild'),\n cancelText: t('panel.cancel'),\n })\n\n if (!agreed || report.value === null) return\n\n starting.value = true\n\n try {\n report.value = { ...report.value, rebuild: await api.rebuild() }\n toast.success(t('panel.rebuild-started'))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n starting.value = false\n }\n\n await load()\n}\n\nonMounted(() => void load())\nonBeforeUnmount(() => clearTimeout(timer))\n</script>\n\n<template>\n <wx-list-screen :title=\"t('panel.title')\" :actions=\"actions\" :card=\"false\">\n <div class=\"wx-search-index\">\n <wx-text tone=\"muted\">{{ t('panel.lead') }}</wx-text>\n\n <wx-alert v-if=\"failed\" type=\"danger\">{{ t('panel.load-failed') }}</wx-alert>\n\n <template v-if=\"report\">\n <wx-alert v-if=\"!report.connection.available\" type=\"danger\" :title=\"t('panel.unavailable')\">\n {{ report.connection.error }}\n </wx-alert>\n\n <wx-alert\n v-else-if=\"report.outdated && !underway && !fromConsole\"\n type=\"warning\"\n :title=\"t('panel.outdated')\"\n >\n {{ t('panel.outdated-text') }}\n </wx-alert>\n\n <wx-alert v-if=\"fromConsole\" type=\"info\">{{ t('panel.rebuild-console') }}</wx-alert>\n\n <!-- The rebuild started from here: what it is doing, or how it ended. -->\n <wx-card\n v-if=\"rebuild && rebuild.state !== 'idle'\"\n bordered\n class=\"wx-search-index__rebuild\"\n >\n <div class=\"wx-search-index__rebuild-head\">\n <wx-text weight=\"medium\">{{ progressLine }}</wx-text>\n <wx-date\n v-if=\"rebuild.finished_at ?? rebuild.started_at ?? rebuild.queued_at\"\n :value=\"rebuild.finished_at ?? rebuild.started_at ?? rebuild.queued_at\"\n />\n </div>\n <wx-progress\n v-if=\"rebuild.state === 'running' || rebuild.state === 'queued'\"\n :value=\"rebuild.done\"\n :max=\"Math.max(rebuild.total, 1)\"\n :indeterminate=\"rebuild.state === 'queued' || rebuild.total === 0\"\n :aria-label=\"progressLine\"\n />\n <wx-text v-if=\"rebuild.stalled\" size=\"sm\" tone=\"warning\">\n {{ t('panel.rebuild-stalled') }}\n </wx-text>\n <wx-text v-if=\"rebuild.state === 'failed' && rebuild.error\" size=\"sm\" tone=\"danger\">\n {{ rebuild.error }}\n </wx-text>\n </wx-card>\n\n <div class=\"wx-search-index__grid\">\n <wx-card bordered :title=\"t('panel.connection')\">\n <wx-descriptions :columns=\"1\" label-width=\"140px\">\n <wx-descriptions-item :label=\"t('panel.address')\">\n <code>{{ report.connection.address }}</code>\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.prefix')\">\n <code v-if=\"report.connection.prefix\">{{ report.connection.prefix }}</code>\n <span v-else>—</span>\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.version')\">\n {{ report.connection.version ?? '—' }}\n </wx-descriptions-item>\n <wx-descriptions-item :label=\"t('panel.state')\">\n <wx-badge :type=\"report.connection.available ? 'success' : 'danger'\">\n {{ report.connection.available ? t('panel.available') : t('panel.unavailable') }}\n </wx-badge>\n </wx-descriptions-item>\n </wx-descriptions>\n </wx-card>\n\n <wx-card bordered :title=\"t('panel.queue')\">\n <wx-descriptions :columns=\"1\" label-width=\"180px\">\n <wx-descriptions-item :label=\"t('panel.waiting')\">\n {{ count(report.queue.waiting) }}\n </wx-descriptions-item>\n <wx-descriptions-item v-if=\"report.queue.oldest\" :label=\"t('panel.oldest')\">\n <wx-date :value=\"report.queue.oldest\" />\n </wx-descriptions-item>\n </wx-descriptions>\n <wx-text v-if=\"report.queue.waiting === 0\" size=\"sm\" tone=\"muted\">\n {{ t('panel.queue-empty') }}\n </wx-text>\n </wx-card>\n </div>\n\n <wx-card bordered :title=\"t('panel.tables')\">\n <wx-table\n :data=\"report.tables\"\n :columns=\"columns\"\n row-key=\"table\"\n flush\n :cards-below=\"560\"\n :empty-text=\"t('panel.no-tables')\"\n :aria-label=\"t('panel.tables')\"\n >\n <template #cell-table=\"{ row }\">\n <code>{{ row.table }}</code>\n </template>\n <template #cell-documents=\"{ row }\">\n {{ count(row.documents) }}\n </template>\n <template #cell-products>\n {{ count(report.products) }}\n </template>\n <template #cell-state=\"{ row }\">\n <div class=\"wx-search-index__state\">\n <wx-badge :type=\"STATE[row.state]\">{{ t(`panel.state-${row.state}`) }}</wx-badge>\n <wx-text v-if=\"row.reason\" size=\"xs\" tone=\"muted\">{{ row.reason }}</wx-text>\n <wx-text v-if=\"row.rebuilding\" size=\"xs\" tone=\"muted\">\n {{\n row.filled == null\n ? t('panel.filling')\n : t('panel.filled', {\n done: count(row.filled),\n total: count(report.products),\n })\n }}\n </wx-text>\n </div>\n </template>\n </wx-table>\n </wx-card>\n </template>\n </div>\n </wx-list-screen>\n</template>\n\n<style scoped>\n.wx-search-index {\n container-type: inline-size;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n}\n\n.wx-search-index__grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: var(--wx-space-16);\n}\n\n@container (min-width: 720px) {\n .wx-search-index__grid {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n.wx-search-index__rebuild :deep(.wx-card__body) {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-search-index__rebuild-head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-search-index__state {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--wx-space-4);\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.wx-search-index code {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n overflow-wrap: anywhere;\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport SearchIndexPage from './SearchIndexPage.vue'\n\nexport interface CatalogManticoreOptions {\n /** Where the page lives inside the panel. */\n path?: string\n}\n\n/**\n * «System → Search index» (decision 27 of the Manticore spec): the server, each language's table\n * against the database, the queue, and the rebuild as a job with its progress.\n *\n * The server reports the section only when the catalogue runs on Manticore, so a panel on the\n * database engine has no such entry even with this module listed. The notice over the list of\n * products, when the panel answers from the database, is the catalogue's own and needs nothing here.\n */\nexport function catalogManticore(options: CatalogManticoreOptions = {}): AdminModule[] {\n const path = options.path ?? '/search-index'\n\n return [\n {\n id: 'search-index',\n path,\n routes: [{ path, name: 'webx.search-index', component: SearchIndexPage }],\n },\n ]\n}\n"],"names":["createSearchIndexApi","admin","base","body","catalogManticoreMessages","seeded","useCatalogManticoreMessages","i18n","useAdmin","POLL","context","t","useTranslate","message","useErrorText","api","report","ref","loading","failed","starting","timer","canManage","computed","rebuild","underway","fromConsole","filling","table","actions","list","start","load","columns","STATE","progressLine","progress","count","value","confirm","toast","error","onMounted","onBeforeUnmount","_createBlock","_unref","WxListScreen","_createElementVNode","_hoisted_1","_createVNode","WxText","WxAlert","_createElementBlock","_Fragment","WxCard","_hoisted_2","WxDate","WxProgress","_createTextVNode","_toDisplayString","_hoisted_3","WxDescriptions","WxDescriptionsItem","_openBlock","_hoisted_4","WxBadge","WxTable","_withCtx","row","_hoisted_6","catalogManticore","options","path","SearchIndexPage"],"mappings":";;;AASO,SAASA,GAAqBC,GAAqC;AACxE,QAAMC,IAAO,GAAGD,EAAM,OAAO;AAE7B,SAAO;AAAA,IACL,QAAQ,MAAMA,EAAM,KAAK,IAA2BC,CAAI,EAAE,KAAK,CAACC,MAASA,EAAK,IAAI;AAAA,IAClF,SAAS,MACPF,EAAM,KAAK,KAAgC,GAAGC,CAAI,YAAY,CAAA,CAAE,EAAE,KAAK,CAACC,MAASA,EAAK,IAAI;AAAA,EAAA;AAEhG;ACVO,MAAMC,KAAqD;AAAA,EAChE,OAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,OAAO;AAAA,IACP,eAAe;AAAA,IACf,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,UAAU;AAAA,IACV,iBACE;AAAA,IACF,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,gBACE;AAAA,IACF,gBAAgB;AAAA,IAChB,kBACE;AAAA,IACF,mBACE;AAAA,IACF,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,mBACE;AAAA,IACF,mBAAmB;AAAA,IACnB,QAAQ;AAAA,EAAA;AAEZ,GCtDMC,wBAAa,QAAA;AAMZ,SAASC,KAAoC;AAClD,MAAI;AACF,UAAM,EAAE,MAAAC,EAAA,IAASC,EAAA;AAEjB,IAAKH,EAAO,IAAIE,CAAI,MAClBA,EAAK,SAAS,0BAA0BH,EAAwB,GAChEC,EAAO,IAAIE,CAAI;AAAA,EAEnB,QAAQ;AAAA,EAER;AACF;+MCiBME,KAAO;;;AAEb,UAAMC,IAAUF,EAAA;AAChB,IAAAF,GAAA;AAEA,UAAMK,IAAIC,EAAa,wBAAwB,GACzCC,IAAUC,EAAA,GACVC,IAAMf,GAAqBU,CAAO,GAElCM,IAASC,EAAwB,IAAI,GACrCC,IAAUD,EAAI,EAAI,GAClBE,IAASF,EAAI,EAAK,GAClBG,IAAWH,EAAI,EAAK;AAC1B,QAAII;AAEJ,UAAMC,IAAYC,EAAS,MAAMb,EAAQ,IAAI,qBAAqB,CAAC,GAC7Dc,IAAUD,EAAiC,MAAMP,EAAO,OAAO,WAAW,IAAI,GAG9ES,IAAWF;AAAA,MACf,MACEC,EAAQ,UAAU,SACjBA,EAAQ,MAAM,UAAU,YAAYA,EAAQ,MAAM,UAAU,cAC7D,CAACA,EAAQ,MAAM;AAAA,IAAA,GAQbE,IAAcH,EAAS,OAAOP,EAAO,OAAO,UAAU,OAAU,CAACS,EAAS,KAAK,GAM/EE,IAAUJ;AAAA,MACd,MACEE,EAAS,SACTC,EAAY,UACXV,EAAO,OAAO,OAAO,KAAK,CAACY,MAAUA,EAAM,UAAU,KAAK;AAAA,IAAA,GAGzDC,IAAUN,EAAyB,MAAM;AAC7C,YAAMO,IAAuB,CAAA;AAE7B,aAAIR,EAAU,SAASN,EAAO,UAAU,QACtCc,EAAK,KAAK;AAAA,QACR,KAAK;AAAA,QACL,OAAOd,EAAO,MAAM,WAAWL,EAAE,eAAe,IAAIA,EAAE,qBAAqB;AAAA,QAC3E,MAAM;AAAA;AAAA,QAEN,SAASK,EAAO,MAAM;AAAA,QACtB,MAAM,CAACA,EAAO,MAAM;AAAA,QACpB,UAAUS,EAAS,SAASC,EAAY,SAAS,CAACV,EAAO,MAAM,WAAW;AAAA,QAC1E,SAASI,EAAS;AAAA,QAClB,KAAK,MAAA;AAAM,UAAKW,EAAA;AAAA;AAAA,MAAM,CACvB,GAGHD,EAAK,KAAK;AAAA,QACR,KAAK;AAAA,QACL,OAAOnB,EAAE,eAAe;AAAA,QACxB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,KAAK,MAAA;AAAM,UAAKqB,EAAA;AAAA;AAAA,MAAK,CACtB,GAEMF;AAAA,IACT,CAAC,GAEKG,IAAUV,EAAoC,MAAM;AAAA,MACxD,EAAE,KAAK,UAAU,OAAOZ,EAAE,gBAAgB,GAAG,OAAO,GAAA;AAAA,MACpD,EAAE,KAAK,SAAS,OAAOA,EAAE,aAAa,GAAG,UAAU,KAAK,WAAW,IAAA;AAAA,MACnE,EAAE,KAAK,aAAa,OAAOA,EAAE,gBAAgB,GAAG,OAAO,SAAS,OAAO,IAAA;AAAA,MACvE,EAAE,KAAK,YAAY,OAAOA,EAAE,mBAAmB,GAAG,OAAO,SAAS,OAAO,IAAA;AAAA,MACzE,EAAE,KAAK,SAAS,OAAOA,EAAE,aAAa,GAAG,UAAU,IAAA;AAAA,IAAI,CACxD,GAEKuB,IAAuC;AAAA,MAC3C,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,IAAA,GAGLC,IAAeZ,EAAS,MAAM;AAClC,YAAMa,IAAWZ,EAAQ;AAEzB,UAAIY,MAAa,KAAM,QAAO;AAE9B,cAAQA,EAAS,OAAA;AAAA,QACf,KAAK;AACH,iBAAOzB,EAAE,sBAAsB;AAAA,QACjC,KAAK;AACH,iBAAOA,EAAE,yBAAyB;AAAA,YAChC,MAAM0B,EAAMD,EAAS,IAAI;AAAA,YACzB,OAAOC,EAAMD,EAAS,KAAK;AAAA,UAAA,CAC5B;AAAA,QACH,KAAK;AACH,iBAAOzB,EAAE,sBAAsB,EAAE,MAAM0B,EAAMD,EAAS,IAAI,GAAG;AAAA,QAC/D,KAAK;AACH,iBAAOzB,EAAE,sBAAsB;AAAA,QACjC;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC;AAED,aAAS0B,EAAMC,GAA8B;AAC3C,aAAOA,MAAU,OAAO,MAAMA,EAAM,eAAe5B,EAAQ,KAAK,MAAM,MAAM;AAAA,IAC9E;AAEA,mBAAesB,IAAsB;AACnC,mBAAaX,CAAK;AAElB,UAAI;AACF,QAAAL,EAAO,QAAQ,MAAMD,EAAI,OAAA,GACzBI,EAAO,QAAQ;AAAA,MACjB,QAAQ;AACN,QAAAA,EAAO,QAAQH,EAAO,UAAU;AAAA,MAClC,UAAA;AACE,QAAAE,EAAQ,QAAQ;AAAA,MAClB;AAEA,MAAIS,EAAQ,UAAON,IAAQ,WAAW;AAAM,QAAKW,EAAA;AAAA,SAAQvB,EAAI;AAAA,IAC/D;AAEA,mBAAesB,IAAuB;AAQpC,UAAI,GAPW,MAAMQ,GAAQ;AAAA,QAC3B,OAAO5B,EAAE,qBAAqB;AAAA,QAC9B,SAASA,EAAE,oBAAoB;AAAA,QAC/B,aAAaA,EAAE,eAAe;AAAA,QAC9B,YAAYA,EAAE,cAAc;AAAA,MAAA,CAC7B,KAEcK,EAAO,UAAU,OAEhC;AAAA,QAAAI,EAAS,QAAQ;AAEjB,YAAI;AACF,UAAAJ,EAAO,QAAQ,EAAE,GAAGA,EAAO,OAAO,SAAS,MAAMD,EAAI,UAAQ,GAC7DyB,EAAM,QAAQ7B,EAAE,uBAAuB,CAAC;AAAA,QAC1C,SAAS8B,GAAO;AACd,UAAAD,EAAM,OAAO3B,EAAQ4B,CAAK,CAAC;AAAA,QAC7B,UAAA;AACE,UAAArB,EAAS,QAAQ;AAAA,QACnB;AAEA,cAAMY,EAAA;AAAA;AAAA,IACR;AAEA,WAAAU,EAAU,MAAA;AAAM,MAAKV;KAAM,GAC3BW,EAAgB,MAAM,aAAatB,CAAK,CAAC,mBAIvCuB,EA4HiBC,EAAAC,CAAA,GAAA;AAAA,MA5HA,OAAOD,EAAAlC,CAAA,EAAC,aAAA;AAAA,MAAkB,SAASkB,EAAA;AAAA,MAAU,MAAM;AAAA,IAAA;iBAClE,MA0HM;AAAA,QA1HNkB,EA0HM,OA1HNC,IA0HM;AAAA,UAzHJC,EAAqDJ,EAAAK,CAAA,GAAA,EAA5C,MAAK,WAAO;AAAA,uBAAC,MAAqB;AAAA,kBAAlBL,EAAAlC,CAAA,EAAC,YAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAEVQ,EAAA,cAAhByB,EAA6EC,EAAAM,CAAA,GAAA;AAAA;YAArD,MAAK;AAAA,UAAA;uBAAS,MAA4B;AAAA,kBAAzBN,EAAAlC,CAAA,EAAC,mBAAA,CAAA,GAAA,CAAA;AAAA,YAAA;;;UAE1BK,EAAA,cAAhBoC,EAoHWC,GAAA,EAAA,KAAA,KAAA;AAAA,YAnHQrC,EAAA,MAAO,WAAW,YAKtBA,EAAA,MAAO,YAAQ,CAAKS,EAAA,UAAaC,EAAA,cAD9CkB,EAMWC,EAAAM,CAAA,GAAA;AAAA;cAJT,MAAK;AAAA,cACJ,OAAON,EAAAlC,CAAA,EAAC,gBAAA;AAAA,YAAA;yBAET,MAA8B;AAAA,oBAA3BkC,EAAAlC,CAAA,EAAC,qBAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;kDATNiC,EAEWC,EAAAM,CAAA,GAAA;AAAA;cAFmC,MAAK;AAAA,cAAU,OAAON,EAAAlC,CAAA,EAAC,mBAAA;AAAA,YAAA;yBACnE,MAA6B;AAAA,oBAA1BK,EAAA,MAAO,WAAW,KAAK,GAAA,CAAA;AAAA,cAAA;;;YAWZU,EAAA,cAAhBkB,EAAoFC,EAAAM,CAAA,GAAA;AAAA;cAAvD,MAAK;AAAA,YAAA;yBAAO,MAAgC;AAAA,oBAA7BN,EAAAlC,CAAA,EAAC,uBAAA,CAAA,GAAA,CAAA;AAAA,cAAA;;;YAIrCa,EAAA,SAAWA,EAAA,MAAQ,UAAK,eADhCoB,EAyBUC,EAAAS,CAAA,GAAA;AAAA;cAvBR,UAAA;AAAA,cACA,OAAM;AAAA,YAAA;yBAEN,MAMM;AAAA,gBANNP,EAMM,OANNQ,IAMM;AAAA,kBALJN,EAAqDJ,EAAAK,CAAA,GAAA,EAA5C,QAAO,YAAQ;AAAA,+BAAC,MAAkB;AAAA,0BAAff,EAAA,KAAY,GAAA,CAAA;AAAA,oBAAA;;;kBAEhCX,EAAA,MAAQ,eAAeA,EAAA,MAAQ,cAAcA,EAAA,MAAQ,kBAD7DoB,EAGEC,EAAAW,CAAA,GAAA;AAAA;oBADC,OAAOhC,EAAA,MAAQ,eAAeA,EAAA,MAAQ,cAAcA,EAAA,MAAQ;AAAA,kBAAA;;gBAIzDA,EAAA,MAAQ,UAAK,aAAkBA,EAAA,MAAQ,UAAK,iBADpDoB,EAMEC,EAAAY,EAAA,GAAA;AAAA;kBAJC,OAAOjC,EAAA,MAAQ;AAAA,kBACf,KAAK,KAAK,IAAIA,EAAA,MAAQ,OAAK,CAAA;AAAA,kBAC3B,eAAeA,EAAA,MAAQ,UAAK,YAAiBA,EAAA,MAAQ,UAAK;AAAA,kBAC1D,cAAYW,EAAA;AAAA,gBAAA;gBAEAX,EAAA,MAAQ,gBAAvBoB,EAEUC,EAAAK,CAAA,GAAA;AAAA;kBAFsB,MAAK;AAAA,kBAAK,MAAK;AAAA,gBAAA;6BAC7C,MAAgC;AAAA,wBAA7BL,EAAAlC,CAAA,EAAC,uBAAA,CAAA,GAAA,CAAA;AAAA,kBAAA;;;gBAESa,EAAA,MAAQ,UAAK,YAAiBA,EAAA,MAAQ,cAArDoB,EAEUC,EAAAK,CAAA,GAAA;AAAA;kBAFkD,MAAK;AAAA,kBAAK,MAAK;AAAA,gBAAA;6BACzE,MAAmB;AAAA,oBAAhBQ,EAAAC,EAAAnC,EAAA,MAAQ,KAAK,GAAA,CAAA;AAAA,kBAAA;;;;;;YAIpBuB,EAkCM,OAlCNa,IAkCM;AAAA,cAjCJX,EAkBUJ,EAAAS,CAAA,GAAA;AAAA,gBAlBD,UAAA;AAAA,gBAAU,OAAOT,EAAAlC,CAAA,EAAC,kBAAA;AAAA,cAAA;2BACzB,MAgBkB;AAAA,kBAhBlBsC,EAgBkBJ,EAAAgB,CAAA,GAAA;AAAA,oBAhBA,SAAS;AAAA,oBAAG,eAAY;AAAA,kBAAA;+BACxC,MAEuB;AAAA,sBAFvBZ,EAEuBJ,EAAAiB,CAAA,GAAA;AAAA,wBAFA,OAAOjB,EAAAlC,CAAA,EAAC,eAAA;AAAA,sBAAA;mCAC7B,MAA4C;AAAA,0BAA5CoC,EAA4C,QAAA,MAAAY,EAAnC3C,EAAA,MAAO,WAAW,OAAO,GAAA,CAAA;AAAA,wBAAA;;;sBAEpCiC,EAGuBJ,EAAAiB,CAAA,GAAA;AAAA,wBAHA,OAAOjB,EAAAlC,CAAA,EAAC,cAAA;AAAA,sBAAA;mCAC7B,MAA2E;AAAA,0BAA/DK,EAAA,MAAO,WAAW,UAA9B+C,KAAAX,EAA2E,QAAAY,IAAAL,EAAlC3C,EAAA,MAAO,WAAW,MAAM,GAAA,CAAA,MACjE+C,KAAAX,EAAqB,YAAR,GAAC;AAAA,wBAAA;;;sBAEhBH,EAEuBJ,EAAAiB,CAAA,GAAA;AAAA,wBAFA,OAAOjB,EAAAlC,CAAA,EAAC,eAAA;AAAA,sBAAA;mCAC7B,MAAsC;AAAA,8BAAnCK,EAAA,MAAO,WAAW,WAAO,GAAA,GAAA,CAAA;AAAA,wBAAA;;;sBAE9BiC,EAIuBJ,EAAAiB,CAAA,GAAA;AAAA,wBAJA,OAAOjB,EAAAlC,CAAA,EAAC,aAAA;AAAA,sBAAA;mCAC7B,MAEW;AAAA,0BAFXsC,EAEWJ,EAAAoB,CAAA,GAAA;AAAA,4BAFA,MAAMjD,EAAA,MAAO,WAAW,YAAS,YAAA;AAAA,0BAAA;uCAC1C,MAAiF;AAAA,8BAA9E0C,EAAAC,EAAA3C,EAAA,MAAO,WAAW,YAAY6B,EAAAlC,CAAA,uBAAuBkC,EAAAlC,CAAA,EAAC,mBAAA,CAAA,GAAA,CAAA;AAAA,4BAAA;;;;;;;;;;;;cAMjEsC,EAYUJ,EAAAS,CAAA,GAAA;AAAA,gBAZD,UAAA;AAAA,gBAAU,OAAOT,EAAAlC,CAAA,EAAC,aAAA;AAAA,cAAA;2BACzB,MAOkB;AAAA,kBAPlBsC,EAOkBJ,EAAAgB,CAAA,GAAA;AAAA,oBAPA,SAAS;AAAA,oBAAG,eAAY;AAAA,kBAAA;+BACxC,MAEuB;AAAA,sBAFvBZ,EAEuBJ,EAAAiB,CAAA,GAAA;AAAA,wBAFA,OAAOjB,EAAAlC,CAAA,EAAC,eAAA;AAAA,sBAAA;mCAC7B,MAAiC;AAAA,0BAA9B+C,EAAAC,EAAAtB,EAAMrB,EAAA,MAAO,MAAM,OAAO,CAAA,GAAA,CAAA;AAAA,wBAAA;;;sBAEHA,EAAA,MAAO,MAAM,eAAzC4B,EAEuBC,EAAAiB,CAAA,GAAA;AAAA;wBAF2B,OAAOjB,EAAAlC,CAAA,EAAC,cAAA;AAAA,sBAAA;mCACxD,MAAwC;AAAA,0BAAxCsC,EAAwCJ,EAAAW,CAAA,GAAA;AAAA,4BAA9B,OAAOxC,EAAA,MAAO,MAAM;AAAA,0BAAA;;;;;;;kBAGnBA,EAAA,MAAO,MAAM,YAAO,UAAnC4B,EAEUC,EAAAK,CAAA,GAAA;AAAA;oBAFiC,MAAK;AAAA,oBAAK,MAAK;AAAA,kBAAA;+BACxD,MAA4B;AAAA,0BAAzBL,EAAAlC,CAAA,EAAC,mBAAA,CAAA,GAAA,CAAA;AAAA,oBAAA;;;;;;;YAKVsC,EAoCUJ,EAAAS,CAAA,GAAA;AAAA,cApCD,UAAA;AAAA,cAAU,OAAOT,EAAAlC,CAAA,EAAC,cAAA;AAAA,YAAA;yBACzB,MAkCW;AAAA,gBAlCXsC,EAkCWJ,EAAAqB,EAAA,GAAA;AAAA,kBAjCR,MAAMlD,EAAA,MAAO;AAAA,kBACb,SAASiB,EAAA;AAAA,kBACV,WAAQ;AAAA,kBACR,OAAA;AAAA,kBACC,eAAa;AAAA,kBACb,cAAYY,EAAAlC,CAAA,EAAC,iBAAA;AAAA,kBACb,cAAYkC,EAAAlC,CAAA,EAAC,cAAA;AAAA,gBAAA;kBAEH,cAAUwD,EACnB,CAA4B,EADL,KAAAC,QAAG;AAAA,oBAC1BrB,EAA4B,QAAA,MAAAY,EAAnBS,EAAI,KAAK,GAAA,CAAA;AAAA,kBAAA;kBAET,kBAAcD,EACvB,CAA0B,EADC,KAAAC,QAAG;AAAA,wBAC3B/B,EAAM+B,EAAI,SAAS,CAAA,GAAA,CAAA;AAAA,kBAAA;kBAEb,mBACT,MAA4B;AAAA,wBAAzB/B,EAAMrB,EAAA,MAAO,QAAQ,CAAA,GAAA,CAAA;AAAA,kBAAA;kBAEf,cAAUmD,EACnB,CAaM,EAdiB,KAAAC,QAAG;AAAA,oBAC1BrB,EAaM,OAbNsB,IAaM;AAAA,sBAZJpB,EAAiFJ,EAAAoB,CAAA,GAAA;AAAA,wBAAtE,MAAM/B,EAAMkC,EAAI,KAAK;AAAA,sBAAA;mCAAG,MAAmC;AAAA,8BAAhCvB,EAAAlC,CAAA,EAAC,eAAgByD,EAAI,KAAK,EAAA,CAAA,GAAA,CAAA;AAAA,wBAAA;;;sBACjDA,EAAI,eAAnBxB,EAA4EC,EAAAK,CAAA,GAAA;AAAA;wBAAjD,MAAK;AAAA,wBAAK,MAAK;AAAA,sBAAA;mCAAQ,MAAgB;AAAA,0BAAbQ,EAAAC,EAAAS,EAAI,MAAM,GAAA,CAAA;AAAA,wBAAA;;;sBAChDA,EAAI,mBAAnBxB,EASUC,EAAAK,CAAA,GAAA;AAAA;wBATqB,MAAK;AAAA,wBAAK,MAAK;AAAA,sBAAA;mCAC5C,MAOE;AAAA,0BANAQ,EAAAC,EAAAS,EAAI,UAAM,OAAiCvB,EAAAlC,CAAA,EAAC,eAAA,IAA0CkC,EAAAlC,CAAA,EAAC,gBAAA;AAAA,kCAAmD0B,EAAM+B,EAAI,MAAM;AAAA,mCAAoC/B,EAAMrB,EAAA,MAAO,QAAQ;AAAA,0BAAA;;;;;;;;;;;;;;;;;;;;;;;AC/RhO,SAASsD,GAAiBC,IAAmC,IAAmB;AACrF,QAAMC,IAAOD,EAAQ,QAAQ;AAE7B,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,MAAAC;AAAA,MACA,QAAQ,CAAC,EAAE,MAAAA,GAAM,MAAM,qBAAqB,WAAWC,IAAiB;AAAA,IAAA;AAAA,EAC1E;AAEJ;"}
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .wx-search-index[data-v-2e57f11d]{container-type:inline-size;display:flex;flex-direction:column;gap:var(--wx-space-16);min-width:0}.wx-search-index__grid[data-v-2e57f11d]{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--wx-space-16)}@container (min-width: 720px){.wx-search-index__grid[data-v-2e57f11d]{grid-template-columns:repeat(2,minmax(0,1fr))}}.wx-search-index__rebuild[data-v-2e57f11d] .wx-card__body{display:flex;flex-direction:column;gap:var(--wx-space-8)}.wx-search-index__rebuild-head[data-v-2e57f11d]{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:var(--wx-space-8)}.wx-search-index__state[data-v-2e57f11d]{display:flex;flex-direction:column;align-items:flex-start;gap:var(--wx-space-4);min-width:0;overflow-wrap:anywhere}.wx-search-index code[data-v-2e57f11d]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);overflow-wrap:anywhere}
1
+ .wx-search-index[data-v-38a4b545]{container-type:inline-size;display:flex;flex-direction:column;gap:var(--wx-space-16);min-width:0}.wx-search-index__grid[data-v-38a4b545]{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--wx-space-16)}@container (min-width: 720px){.wx-search-index__grid[data-v-38a4b545]{grid-template-columns:repeat(2,minmax(0,1fr))}}.wx-search-index__rebuild[data-v-38a4b545] .wx-card__body{display:flex;flex-direction:column;gap:var(--wx-space-8)}.wx-search-index__rebuild-head[data-v-38a4b545]{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:var(--wx-space-8)}.wx-search-index__state[data-v-38a4b545]{display:flex;flex-direction:column;align-items:flex-start;gap:var(--wx-space-4);min-width:0;overflow-wrap:anywhere}.wx-search-index code[data-v-38a4b545]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);overflow-wrap:anywhere}
package/dist/types.d.ts CHANGED
@@ -52,4 +52,9 @@ export interface IndexReport {
52
52
  rebuild: RebuildProgress;
53
53
  /** Some table is missing or of an older schema. */
54
54
  outdated: boolean;
55
+ /**
56
+ * A rebuild holds the lock it shares with the console's `--rebuild` — the console's too, which
57
+ * writes no progress of its own. No second one is offered meanwhile.
58
+ */
59
+ locked?: boolean;
55
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webx-ui/module-catalog-manticore",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "The search index of the WebX UI catalogue on Manticore, in the admin panel: the server, each language's table against the database, the queue, and the rebuild as a job with its progress.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -46,8 +46,8 @@
46
46
  "vue-router": "^4.5.0"
47
47
  },
48
48
  "dependencies": {
49
- "@webx-ui/core": "^0.35.0",
50
- "@webx-ui/module-admin": "^0.23.0"
49
+ "@webx-ui/core": "^0.37.0",
50
+ "@webx-ui/module-admin": "^0.23.2"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^24.10.1",