@webx-ui/module-vacancies 0.2.6 → 0.3.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/VacanciesPage-C99Ki3hv.js +512 -0
- package/dist/VacanciesPage-C99Ki3hv.js.map +1 -0
- package/dist/VacancyEditorPage-Dw_pfwyv.js +378 -0
- package/dist/VacancyEditorPage-Dw_pfwyv.js.map +1 -0
- package/dist/days-BPKXoD8l.js +24 -0
- package/dist/days-BPKXoD8l.js.map +1 -0
- package/dist/index-V7QvGgXw.js +467 -0
- package/dist/index-V7QvGgXw.js.map +1 -0
- package/dist/index.d.ts +14 -2
- package/dist/index.js +14 -1343
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { defineComponent as xe, ref as U, computed as s, watch as O, onBeforeUnmount as ke, openBlock as i, createElementBlock as z, createVNode as r, unref as l, withCtx as o, createElementVNode as y, createBlock as d, createCommentVNode as m, createTextVNode as _, toDisplayString as v, Fragment as Q, normalizeClass as qe, resolveDynamicComponent as We, mergeProps as $e, renderList as Ve } from "vue";
|
|
2
|
+
import { useRoute as Te, useRouter as ze } from "vue-router";
|
|
3
|
+
import { useAdmin as Be, useTranslate as Ce, useErrorText as Se, WxListScreen as Ne, WxFilterChips as Ue, WxRowMenu as Ae, WxAddressNote as Fe } from "@webx-ui/module-admin";
|
|
4
|
+
import { createModal as Ie, WxInput as Me, WxIcon as A, WxPopover as De, WxFormItem as X, WxSelect as Y, WxButton as Ee, WxIndicator as Pe, WxAction as Le, WxSkeleton as Re, WxEmpty as je, WxSortableList as Ke, WxTooltip as Z, WxBadge as F, WxAlert as Ge, toast as p, confirm as R } from "@webx-ui/core";
|
|
5
|
+
import { c as He, u as Je, _ as Oe, e as Qe, a as Xe } from "./index-V7QvGgXw.js";
|
|
6
|
+
import { l as Ye, f as Ze } from "./days-BPKXoD8l.js";
|
|
7
|
+
const ea = { class: "wx-vacancies" }, aa = { class: "wx-vacancies__bar" }, la = { class: "wx-vacancies__filters" }, ta = {
|
|
8
|
+
key: 0,
|
|
9
|
+
class: "wx-vacancies__applied"
|
|
10
|
+
}, na = { class: "wx-vacancy-row__name" }, sa = { class: "wx-vacancy-row__title" }, oa = { class: "wx-vacancy-row__address" }, ra = { class: "wx-vacancy-row__facts" }, ia = { class: "wx-vacancy-row__where" }, ua = {
|
|
11
|
+
key: 0,
|
|
12
|
+
class: "wx-vacancy-row__employment"
|
|
13
|
+
}, ca = { class: "wx-vacancy-row__until" }, da = { class: "wx-vacancy-row__state" }, pa = /* @__PURE__ */ xe({
|
|
14
|
+
__name: "VacanciesPage",
|
|
15
|
+
props: {
|
|
16
|
+
base: { default: "/vacancies" }
|
|
17
|
+
},
|
|
18
|
+
setup(ee) {
|
|
19
|
+
const j = ee, B = Be(), f = He(B), u = Te(), x = ze();
|
|
20
|
+
Je();
|
|
21
|
+
const a = Ce("webx-vacancies"), k = Se(), w = U([]), I = U({ categories: [] }), C = U(!0), ae = Ie(Oe), S = s(() => B.can("vacancies.manage")), le = s(
|
|
22
|
+
() => B.state.manifest?.modules.find((e) => e.id === "vacancies")?.title ?? a("module.vacancies")
|
|
23
|
+
), K = s(() => B.i18n.state.locale), g = s({
|
|
24
|
+
get: () => typeof u.query.view == "string" ? u.query.view : "",
|
|
25
|
+
set: (e) => {
|
|
26
|
+
x.replace({
|
|
27
|
+
query: { ...u.query, view: e === "" ? void 0 : String(e) }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}), c = s(() => g.value === "trashed"), b = s(() => g.value === "closed" ? "closed" : g.value === "all" ? "all" : "open"), q = s(() => {
|
|
31
|
+
const e = u.query.category;
|
|
32
|
+
return typeof e == "string" && e !== "" && Number(e) || null;
|
|
33
|
+
}), h = s(
|
|
34
|
+
() => typeof u.query.status == "string" ? u.query.status : ""
|
|
35
|
+
), W = s(() => typeof u.query.q == "string" ? u.query.q : ""), M = U(W.value), te = s(() => [
|
|
36
|
+
{ value: "", label: a("panel.view-open") },
|
|
37
|
+
{ value: "closed", label: a("panel.view-closed") },
|
|
38
|
+
{ value: "all", label: a("panel.view-all") },
|
|
39
|
+
{ value: "trashed", label: a("panel.bin"), icon: "trash" }
|
|
40
|
+
]), ne = s(
|
|
41
|
+
() => ["published", "draft", "unpublished"].map((e) => ({
|
|
42
|
+
value: e,
|
|
43
|
+
label: a(`panel.status-${e}`)
|
|
44
|
+
}))
|
|
45
|
+
), D = s(
|
|
46
|
+
() => W.value.trim() === "" && q.value === null && h.value === ""
|
|
47
|
+
), G = s(() => b.value !== "closed" && !c.value), H = s(() => S.value && G.value && D.value), se = s(() => G.value ? a(D.value ? "panel.order-all" : "panel.order-locked") : a("panel.order-closed")), oe = s(() => W.value !== "" ? a("panel.empty-search") : c.value ? a("panel.empty-bin") : b.value === "closed" ? a("panel.empty-closed") : b.value === "all" ? a("panel.empty") : a("panel.empty-open")), $ = s(() => {
|
|
48
|
+
const e = [];
|
|
49
|
+
h.value !== "" && e.push({
|
|
50
|
+
key: "status",
|
|
51
|
+
label: `${a("panel.filter-status")}: ${a(`panel.status-${h.value}`)}`,
|
|
52
|
+
clear: () => N("status", void 0)
|
|
53
|
+
});
|
|
54
|
+
const n = I.value.categories.find((t) => t.id === q.value);
|
|
55
|
+
return n && e.push({
|
|
56
|
+
key: "category",
|
|
57
|
+
label: `${a("panel.filter-category")}: ${n.title}`,
|
|
58
|
+
clear: () => N("category", void 0)
|
|
59
|
+
}), e;
|
|
60
|
+
});
|
|
61
|
+
async function V() {
|
|
62
|
+
C.value = !0;
|
|
63
|
+
try {
|
|
64
|
+
const e = await f.list({
|
|
65
|
+
state: b.value,
|
|
66
|
+
q: W.value,
|
|
67
|
+
category: q.value,
|
|
68
|
+
status: c.value ? "" : h.value,
|
|
69
|
+
trashed: c.value
|
|
70
|
+
});
|
|
71
|
+
w.value = e.data, I.value = e.filters;
|
|
72
|
+
} catch (e) {
|
|
73
|
+
p.danger(k(e));
|
|
74
|
+
} finally {
|
|
75
|
+
C.value = !1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
O([g, q, h, W], () => {
|
|
79
|
+
V();
|
|
80
|
+
}), V();
|
|
81
|
+
let E;
|
|
82
|
+
O(M, (e) => {
|
|
83
|
+
clearTimeout(E), E = setTimeout(() => {
|
|
84
|
+
x.replace({ query: { ...u.query, q: e.trim() === "" ? void 0 : e } });
|
|
85
|
+
}, 300);
|
|
86
|
+
}), ke(() => clearTimeout(E));
|
|
87
|
+
function N(e, n) {
|
|
88
|
+
x.replace({
|
|
89
|
+
query: {
|
|
90
|
+
...u.query,
|
|
91
|
+
[e]: typeof n == "number" || typeof n == "string" && n !== "" ? String(n) : void 0
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function re() {
|
|
96
|
+
const e = { ...u.query };
|
|
97
|
+
delete e.category, delete e.status, x.replace({ query: e });
|
|
98
|
+
}
|
|
99
|
+
function P(e) {
|
|
100
|
+
x.push({ path: `${j.base}/${e.id}`, query: { ...u.query } });
|
|
101
|
+
}
|
|
102
|
+
async function ie() {
|
|
103
|
+
const e = await ae({});
|
|
104
|
+
e && P(e);
|
|
105
|
+
}
|
|
106
|
+
async function ue() {
|
|
107
|
+
try {
|
|
108
|
+
await f.reorder(w.value.map((e) => e.id));
|
|
109
|
+
} catch (e) {
|
|
110
|
+
p.danger(k(e, a("panel.reorder-failed"))), await V();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const L = (e) => e.status === "published" || e.status === "modified";
|
|
114
|
+
function ce(e) {
|
|
115
|
+
if (!S.value) return [];
|
|
116
|
+
if (c.value)
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
key: "restore",
|
|
120
|
+
icon: "refresh",
|
|
121
|
+
label: a("panel.restore"),
|
|
122
|
+
run: () => {
|
|
123
|
+
ye(e);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
const n = [
|
|
128
|
+
{ key: "open", icon: "edit", label: a("panel.open"), run: () => P(e) },
|
|
129
|
+
{
|
|
130
|
+
key: "duplicate",
|
|
131
|
+
icon: "copy",
|
|
132
|
+
label: a("panel.duplicate"),
|
|
133
|
+
run: () => {
|
|
134
|
+
de(e);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
];
|
|
138
|
+
return e.url && e.status !== "draft" && n.push({
|
|
139
|
+
key: "site",
|
|
140
|
+
icon: "external-link",
|
|
141
|
+
label: a("panel.open-on-site"),
|
|
142
|
+
href: e.url
|
|
143
|
+
}), L(e) && e.closed_reason === "manual" ? n.push({
|
|
144
|
+
key: "reopen",
|
|
145
|
+
icon: "refresh",
|
|
146
|
+
label: a("panel.reopen"),
|
|
147
|
+
run: () => {
|
|
148
|
+
ve(e);
|
|
149
|
+
}
|
|
150
|
+
}) : L(e) && e.closed_reason === null && n.push({
|
|
151
|
+
key: "close",
|
|
152
|
+
icon: "lock",
|
|
153
|
+
label: a("panel.close"),
|
|
154
|
+
run: () => {
|
|
155
|
+
pe(e);
|
|
156
|
+
}
|
|
157
|
+
}), n.push(
|
|
158
|
+
L(e) ? {
|
|
159
|
+
key: "unpublish",
|
|
160
|
+
icon: "eye-off",
|
|
161
|
+
label: a("panel.unpublish"),
|
|
162
|
+
run: () => {
|
|
163
|
+
T(() => f.unpublish(e.id), a("panel.unpublished-done"));
|
|
164
|
+
}
|
|
165
|
+
} : {
|
|
166
|
+
key: "publish",
|
|
167
|
+
icon: "upload",
|
|
168
|
+
label: a("panel.publish"),
|
|
169
|
+
run: () => {
|
|
170
|
+
T(() => f.publish(e.id), a("panel.published"));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
), n.push({
|
|
174
|
+
key: "delete",
|
|
175
|
+
icon: "trash",
|
|
176
|
+
label: a("panel.delete"),
|
|
177
|
+
danger: !0,
|
|
178
|
+
run: () => {
|
|
179
|
+
fe(e);
|
|
180
|
+
}
|
|
181
|
+
}), n;
|
|
182
|
+
}
|
|
183
|
+
async function de(e) {
|
|
184
|
+
try {
|
|
185
|
+
const n = await f.duplicate(e.id);
|
|
186
|
+
p.success(a("panel.duplicated")), P(n.vacancy);
|
|
187
|
+
} catch (n) {
|
|
188
|
+
p.danger(k(n));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function pe(e) {
|
|
192
|
+
if (e.status === "modified") {
|
|
193
|
+
p.warning(a("panel.close-edits"));
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
await R({
|
|
197
|
+
title: a("panel.close-title", { title: e.title }),
|
|
198
|
+
message: a("panel.close-text"),
|
|
199
|
+
confirmText: a("panel.close"),
|
|
200
|
+
cancelText: a("panel.cancel")
|
|
201
|
+
}) && await T(() => f.close(e.id), a("panel.closed"));
|
|
202
|
+
}
|
|
203
|
+
async function ve(e) {
|
|
204
|
+
if (e.status === "modified") {
|
|
205
|
+
p.warning(a("panel.close-edits"));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (await R({
|
|
209
|
+
title: a("panel.reopen-title", { title: e.title }),
|
|
210
|
+
message: a("panel.reopen-text"),
|
|
211
|
+
confirmText: a("panel.reopen"),
|
|
212
|
+
cancelText: a("panel.cancel")
|
|
213
|
+
}))
|
|
214
|
+
try {
|
|
215
|
+
(await f.reopen(e.id)).closed ? p.warning(a("panel.reopen-expired")) : p.success(a("panel.reopened"));
|
|
216
|
+
} catch (t) {
|
|
217
|
+
p.danger(k(t));
|
|
218
|
+
} finally {
|
|
219
|
+
await V();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async function fe(e) {
|
|
223
|
+
await R({
|
|
224
|
+
title: a("panel.delete-title", { title: e.title }),
|
|
225
|
+
message: a("panel.delete-text"),
|
|
226
|
+
confirmText: a("panel.delete"),
|
|
227
|
+
cancelText: a("panel.cancel"),
|
|
228
|
+
tone: "danger"
|
|
229
|
+
}) && await T(() => f.remove(e.id), a("panel.deleted"));
|
|
230
|
+
}
|
|
231
|
+
async function ye(e) {
|
|
232
|
+
await T(() => f.restore(e.id), a("panel.restored"));
|
|
233
|
+
}
|
|
234
|
+
async function T(e, n) {
|
|
235
|
+
try {
|
|
236
|
+
await e(), p.success(n);
|
|
237
|
+
} catch (t) {
|
|
238
|
+
p.danger(k(t));
|
|
239
|
+
} finally {
|
|
240
|
+
await V();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function me(e) {
|
|
244
|
+
return e === "published" || e === "modified" ? "success" : "default";
|
|
245
|
+
}
|
|
246
|
+
function _e(e) {
|
|
247
|
+
return c.value ? "—" : e.path === null ? a("panel.no-address") : `/${e.path}`;
|
|
248
|
+
}
|
|
249
|
+
function he(e) {
|
|
250
|
+
if (e.workplace === "remote") return a("vacancy.workplace.remote");
|
|
251
|
+
const n = e.city !== "" ? e.city : a("panel.no-city");
|
|
252
|
+
return e.workplace === "hybrid" ? `${n} · ${a("vacancy.workplace.hybrid")}` : n;
|
|
253
|
+
}
|
|
254
|
+
function we(e) {
|
|
255
|
+
return e.employment_types.map((n) => a(Qe(n))).join(", ");
|
|
256
|
+
}
|
|
257
|
+
function ge(e) {
|
|
258
|
+
return e.closed && b.value === "all" && !c.value;
|
|
259
|
+
}
|
|
260
|
+
const be = s(
|
|
261
|
+
() => S.value ? [{ key: "new", label: a("panel.new"), icon: "plus", primary: !0, run: () => {
|
|
262
|
+
ie();
|
|
263
|
+
} }] : []
|
|
264
|
+
);
|
|
265
|
+
return (e, n) => (i(), z("div", ea, [
|
|
266
|
+
r(l(Ne), {
|
|
267
|
+
view: g.value,
|
|
268
|
+
"onUpdate:view": n[4] || (n[4] = (t) => g.value = t),
|
|
269
|
+
title: le.value,
|
|
270
|
+
views: te.value,
|
|
271
|
+
actions: be.value,
|
|
272
|
+
padding: "sm"
|
|
273
|
+
}, {
|
|
274
|
+
default: o(() => [
|
|
275
|
+
y("div", aa, [
|
|
276
|
+
r(l(Me), {
|
|
277
|
+
modelValue: M.value,
|
|
278
|
+
"onUpdate:modelValue": n[0] || (n[0] = (t) => M.value = t),
|
|
279
|
+
class: "wx-vacancies__search",
|
|
280
|
+
size: "sm",
|
|
281
|
+
clearable: "",
|
|
282
|
+
placeholder: l(a)("panel.search"),
|
|
283
|
+
"aria-label": l(a)("panel.search")
|
|
284
|
+
}, {
|
|
285
|
+
prefix: o(() => [
|
|
286
|
+
r(l(A), {
|
|
287
|
+
name: "search",
|
|
288
|
+
size: "sm"
|
|
289
|
+
})
|
|
290
|
+
]),
|
|
291
|
+
_: 1
|
|
292
|
+
}, 8, ["modelValue", "placeholder", "aria-label"]),
|
|
293
|
+
r(l(De), {
|
|
294
|
+
title: l(a)("panel.filters"),
|
|
295
|
+
width: 280,
|
|
296
|
+
side: "bottom",
|
|
297
|
+
align: "end"
|
|
298
|
+
}, {
|
|
299
|
+
trigger: o(() => [
|
|
300
|
+
r(l(Pe), {
|
|
301
|
+
class: "wx-vacancies__funnel",
|
|
302
|
+
value: $.value.length,
|
|
303
|
+
hidden: $.value.length === 0,
|
|
304
|
+
type: "primary",
|
|
305
|
+
label: l(a)("panel.filters")
|
|
306
|
+
}, {
|
|
307
|
+
default: o(() => [
|
|
308
|
+
r(l(Le), {
|
|
309
|
+
icon: "filter",
|
|
310
|
+
size: "sm",
|
|
311
|
+
title: l(a)("panel.filters")
|
|
312
|
+
}, null, 8, ["title"])
|
|
313
|
+
]),
|
|
314
|
+
_: 1
|
|
315
|
+
}, 8, ["value", "hidden", "label"])
|
|
316
|
+
]),
|
|
317
|
+
default: o(() => [
|
|
318
|
+
y("div", la, [
|
|
319
|
+
c.value ? m("", !0) : (i(), d(l(X), {
|
|
320
|
+
key: 0,
|
|
321
|
+
label: l(a)("panel.filter-status")
|
|
322
|
+
}, {
|
|
323
|
+
default: o(() => [
|
|
324
|
+
r(l(Y), {
|
|
325
|
+
"model-value": h.value === "" ? null : h.value,
|
|
326
|
+
options: ne.value,
|
|
327
|
+
placeholder: l(a)("panel.any-status"),
|
|
328
|
+
clearable: "",
|
|
329
|
+
size: "sm",
|
|
330
|
+
"onUpdate:modelValue": n[1] || (n[1] = (t) => N("status", t))
|
|
331
|
+
}, null, 8, ["model-value", "options", "placeholder"])
|
|
332
|
+
]),
|
|
333
|
+
_: 1
|
|
334
|
+
}, 8, ["label"])),
|
|
335
|
+
r(l(X), {
|
|
336
|
+
label: l(a)("panel.filter-category")
|
|
337
|
+
}, {
|
|
338
|
+
default: o(() => [
|
|
339
|
+
r(l(Y), {
|
|
340
|
+
"model-value": q.value,
|
|
341
|
+
options: I.value.categories.map((t) => ({ value: t.id, label: t.title })),
|
|
342
|
+
placeholder: l(a)("panel.any-category"),
|
|
343
|
+
clearable: "",
|
|
344
|
+
size: "sm",
|
|
345
|
+
"onUpdate:modelValue": n[2] || (n[2] = (t) => N("category", t))
|
|
346
|
+
}, null, 8, ["model-value", "options", "placeholder"])
|
|
347
|
+
]),
|
|
348
|
+
_: 1
|
|
349
|
+
}, 8, ["label"]),
|
|
350
|
+
$.value.length > 0 ? (i(), d(l(Ee), {
|
|
351
|
+
key: 1,
|
|
352
|
+
variant: "text",
|
|
353
|
+
size: "sm",
|
|
354
|
+
block: "",
|
|
355
|
+
onClick: re
|
|
356
|
+
}, {
|
|
357
|
+
icon: o(() => [
|
|
358
|
+
r(l(A), { name: "close" })
|
|
359
|
+
]),
|
|
360
|
+
default: o(() => [
|
|
361
|
+
_(" " + v(l(a)("panel.filters-reset")), 1)
|
|
362
|
+
]),
|
|
363
|
+
_: 1
|
|
364
|
+
})) : m("", !0)
|
|
365
|
+
])
|
|
366
|
+
]),
|
|
367
|
+
_: 1
|
|
368
|
+
}, 8, ["title"])
|
|
369
|
+
]),
|
|
370
|
+
$.value.length > 0 ? (i(), z("div", ta, [
|
|
371
|
+
r(l(Ue), { filters: $.value }, null, 8, ["filters"])
|
|
372
|
+
])) : m("", !0),
|
|
373
|
+
C.value && w.value.length === 0 ? (i(), d(l(Re), {
|
|
374
|
+
key: 1,
|
|
375
|
+
class: "wx-vacancies__loading",
|
|
376
|
+
rows: 5
|
|
377
|
+
})) : w.value.length === 0 ? (i(), d(l(je), {
|
|
378
|
+
key: 2,
|
|
379
|
+
title: oe.value,
|
|
380
|
+
description: b.value === "all" && !c.value && D.value ? l(a)("panel.empty-help") : void 0
|
|
381
|
+
}, null, 8, ["title", "description"])) : (i(), z(Q, { key: 3 }, [
|
|
382
|
+
r(l(Ke), {
|
|
383
|
+
modelValue: w.value,
|
|
384
|
+
"onUpdate:modelValue": n[3] || (n[3] = (t) => w.value = t),
|
|
385
|
+
class: qe(["wx-vacancies__list", { "is-loading": C.value }]),
|
|
386
|
+
plain: "",
|
|
387
|
+
"item-key": "id",
|
|
388
|
+
handle: H.value ? "grip" : "row",
|
|
389
|
+
"item-label": (t) => t.title,
|
|
390
|
+
disabled: !H.value,
|
|
391
|
+
onMove: ue
|
|
392
|
+
}, {
|
|
393
|
+
default: o(({ item: t }) => [
|
|
394
|
+
(i(), d(We(c.value ? "div" : "router-link"), $e({
|
|
395
|
+
class: ["wx-vacancy-row", { "is-closed": ge(t) }]
|
|
396
|
+
}, c.value ? {} : { to: { path: `${j.base}/${t.id}`, query: l(u).query } }), {
|
|
397
|
+
default: o(() => [
|
|
398
|
+
y("span", na, [
|
|
399
|
+
y("span", sa, v(t.title), 1),
|
|
400
|
+
y("span", oa, [
|
|
401
|
+
_(v(_e(t)), 1),
|
|
402
|
+
c.value ? m("", !0) : (i(), d(l(Fe), {
|
|
403
|
+
key: 0,
|
|
404
|
+
locale: t.address_locale
|
|
405
|
+
}, null, 8, ["locale"]))
|
|
406
|
+
])
|
|
407
|
+
]),
|
|
408
|
+
y("span", ra, [
|
|
409
|
+
y("span", ia, [
|
|
410
|
+
r(l(A), {
|
|
411
|
+
name: t.workplace === "remote" ? "monitor" : "map-pin",
|
|
412
|
+
size: "sm"
|
|
413
|
+
}, null, 8, ["name"]),
|
|
414
|
+
_(" " + v(he(t)), 1)
|
|
415
|
+
]),
|
|
416
|
+
t.employment_types.length > 0 ? (i(), z("span", ua, v(we(t)), 1)) : m("", !0),
|
|
417
|
+
t.valid_through ? (i(), d(l(Z), {
|
|
418
|
+
key: 1,
|
|
419
|
+
content: l(a)("panel.until-help", { date: l(Ye)(t.valid_through, K.value) })
|
|
420
|
+
}, {
|
|
421
|
+
default: o(() => [
|
|
422
|
+
y("span", ca, [
|
|
423
|
+
r(l(A), {
|
|
424
|
+
name: "calendar",
|
|
425
|
+
size: "sm"
|
|
426
|
+
}),
|
|
427
|
+
_(" " + v(l(a)("panel.until", { date: l(Ze)(t.valid_through, K.value) })), 1)
|
|
428
|
+
])
|
|
429
|
+
]),
|
|
430
|
+
_: 2
|
|
431
|
+
}, 1032, ["content"])) : m("", !0)
|
|
432
|
+
]),
|
|
433
|
+
y("span", da, [
|
|
434
|
+
(i(!0), z(Q, null, Ve(t.categories, (J) => (i(), d(l(F), {
|
|
435
|
+
key: J.id,
|
|
436
|
+
size: "sm",
|
|
437
|
+
round: ""
|
|
438
|
+
}, {
|
|
439
|
+
default: o(() => [
|
|
440
|
+
_(v(J.title), 1)
|
|
441
|
+
]),
|
|
442
|
+
_: 2
|
|
443
|
+
}, 1024))), 128)),
|
|
444
|
+
t.closed_reason ? (i(), d(l(Z), {
|
|
445
|
+
key: 0,
|
|
446
|
+
content: l(a)(`panel.closed-${t.closed_reason}-help`)
|
|
447
|
+
}, {
|
|
448
|
+
default: o(() => [
|
|
449
|
+
r(l(F), {
|
|
450
|
+
type: "warning",
|
|
451
|
+
size: "sm",
|
|
452
|
+
round: ""
|
|
453
|
+
}, {
|
|
454
|
+
default: o(() => [
|
|
455
|
+
_(v(l(a)(`panel.closed-${t.closed_reason}`)), 1)
|
|
456
|
+
]),
|
|
457
|
+
_: 2
|
|
458
|
+
}, 1024)
|
|
459
|
+
]),
|
|
460
|
+
_: 2
|
|
461
|
+
}, 1032, ["content"])) : m("", !0),
|
|
462
|
+
r(l(F), {
|
|
463
|
+
type: me(t.status),
|
|
464
|
+
dot: "",
|
|
465
|
+
size: "sm"
|
|
466
|
+
}, {
|
|
467
|
+
default: o(() => [
|
|
468
|
+
_(v(l(a)(`panel.status-${t.status}`)), 1)
|
|
469
|
+
]),
|
|
470
|
+
_: 2
|
|
471
|
+
}, 1032, ["type"]),
|
|
472
|
+
t.status === "modified" ? (i(), d(l(F), {
|
|
473
|
+
key: 1,
|
|
474
|
+
type: "primary",
|
|
475
|
+
size: "sm",
|
|
476
|
+
round: ""
|
|
477
|
+
}, {
|
|
478
|
+
default: o(() => [
|
|
479
|
+
_(v(l(a)("panel.edits")), 1)
|
|
480
|
+
]),
|
|
481
|
+
_: 1
|
|
482
|
+
})) : m("", !0)
|
|
483
|
+
])
|
|
484
|
+
]),
|
|
485
|
+
_: 2
|
|
486
|
+
}, 1040, ["class"]))
|
|
487
|
+
]),
|
|
488
|
+
actions: o(({ item: t }) => [
|
|
489
|
+
r(l(Ae), {
|
|
490
|
+
actions: ce(t),
|
|
491
|
+
label: t.title
|
|
492
|
+
}, null, 8, ["actions", "label"])
|
|
493
|
+
]),
|
|
494
|
+
_: 1
|
|
495
|
+
}, 8, ["modelValue", "class", "handle", "item-label", "disabled"]),
|
|
496
|
+
S.value && !c.value ? (i(), d(l(Ge), {
|
|
497
|
+
key: 0,
|
|
498
|
+
class: "wx-vacancies__note",
|
|
499
|
+
type: "info",
|
|
500
|
+
description: se.value
|
|
501
|
+
}, null, 8, ["description"])) : m("", !0)
|
|
502
|
+
], 64))
|
|
503
|
+
]),
|
|
504
|
+
_: 1
|
|
505
|
+
}, 8, ["view", "title", "views", "actions"])
|
|
506
|
+
]));
|
|
507
|
+
}
|
|
508
|
+
}), wa = /* @__PURE__ */ Xe(pa, [["__scopeId", "data-v-491c2b10"]]);
|
|
509
|
+
export {
|
|
510
|
+
wa as default
|
|
511
|
+
};
|
|
512
|
+
//# sourceMappingURL=VacanciesPage-C99Ki3hv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VacanciesPage-C99Ki3hv.js","sources":["../src/VacanciesPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\nimport { useRoute, useRouter, type LocationQueryRaw } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxFilterChips,\n WxListScreen,\n WxRowMenu,\n type AppliedFilter,\n type RowAction,\n type ScreenAction,\n WxAddressNote,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n createModal,\n toast,\n WxAction,\n WxAlert,\n WxBadge,\n WxButton,\n WxEmpty,\n WxFormItem,\n WxIcon,\n WxIndicator,\n WxInput,\n WxPopover,\n WxSelect,\n WxSkeleton,\n WxSortableList,\n WxTooltip,\n type TabItem,\n type TabValue,\n} from '@webx-ui/core'\nimport { createVacanciesApi } from './api'\nimport { formatDay, longDay } from './days'\nimport { useVacanciesMessages } from './i18n'\nimport { employmentKey } from './messages'\nimport VacancyCreateDialog from './VacancyCreateDialog.vue'\nimport type { VacanciesList, VacancyRow, VacancyState, VacancyStatus } from './types'\n\n/**\n * Every vacancy at once, in the order the site lists them (§4.10).\n *\n * The shape of the recipes, with the tabs of the events: no paginator, because this is where the\n * order is dragged and a drag cannot cross a page — a site has tens of vacancies, not thousands.\n * The tabs are *open or closed*, not the state: the open ones are what the site lists and what an\n * editor comes here for, so they are the list with nothing chosen. \"All\" draws the closed ones\n * muted, so the line between the two can be seen at a glance; the category, the state and the\n * search narrow any of them.\n *\n * One order, and only one (§4.11). The grips are there on \"Open\" and \"All\" while nothing narrows\n * the list — a selection has invisible gaps in it, and a closed vacancy is on no list of the site,\n * so ordering the \"Closed\" tab would be ordering nothing. The line under the rows says which of\n * the three it is.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/vacancies' })\n\nconst context = useAdmin()\nconst api = createVacanciesApi(context)\nconst route = useRoute()\nconst router = useRouter()\nuseVacanciesMessages()\n\nconst t = useTranslate('webx-vacancies')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst rows = ref<VacancyRow[]>([])\nconst filters = ref<VacanciesList['filters']>({ categories: [] })\nconst loading = ref(true)\n\nconst create = createModal<VacancyRow, Record<string, never>>(VacancyCreateDialog)\n\nconst canManage = computed(() => context.can('vacancies.manage'))\n\nconst title = computed(\n () =>\n context.state.manifest?.modules.find((module) => module.id === 'vacancies')?.title ??\n t('module.vacancies'),\n)\n\nconst locale = computed(() => context.i18n.state.locale)\n\n/*\n * Everything the list is looking at lives in the address, so coming back from a vacancy lands on\n * the same tab, the same filters and the same search.\n */\nconst view = computed<TabValue>({\n get: () => (typeof route.query.view === 'string' ? route.query.view : ''),\n set: (value) => {\n void router.replace({\n query: { ...route.query, view: value === '' ? undefined : String(value) },\n })\n },\n})\n\nconst inBin = computed(() => view.value === 'trashed')\n\nconst state = computed<VacancyState>(() => {\n if (view.value === 'closed') return 'closed'\n\n return view.value === 'all' ? 'all' : 'open'\n})\n\nconst category = computed(() => {\n const raw = route.query.category\n\n return typeof raw === 'string' && raw !== '' ? Number(raw) || null : null\n})\n\nconst status = computed(\n () => (typeof route.query.status === 'string' ? route.query.status : '') as VacancyStatus | '',\n)\n\nconst q = computed(() => (typeof route.query.q === 'string' ? route.query.q : ''))\n\n/* What is typed, ahead of the address: the address follows it after a pause. */\nconst typed = ref(q.value)\n\nconst views = computed<TabItem[]>(() => [\n { value: '', label: t('panel.view-open') },\n { value: 'closed', label: t('panel.view-closed') },\n { value: 'all', label: t('panel.view-all') },\n { value: 'trashed', label: t('panel.bin'), icon: 'trash' },\n])\n\nconst statuses = computed(() =>\n (['published', 'draft', 'unpublished'] as const).map((one) => ({\n value: one,\n label: t(`panel.status-${one}`),\n })),\n)\n\n/** Nothing narrows the list: no search, no category, no state. */\nconst unfiltered = computed(\n () => q.value.trim() === '' && category.value === null && status.value === '',\n)\n\n/** The one order, as far as this tab can show it (§4.10). */\nconst ordered = computed(() => state.value !== 'closed' && !inBin.value)\n\n/* Dragged only by somebody who may write, and only in a list that is the whole order. */\nconst sortable = computed(() => canManage.value && ordered.value && unfiltered.value)\n\nconst hint = computed(() => {\n if (!ordered.value) return t('panel.order-closed')\n\n return t(unfiltered.value ? 'panel.order-all' : 'panel.order-locked')\n})\n\nconst emptyText = computed(() => {\n if (q.value !== '') return t('panel.empty-search')\n if (inBin.value) return t('panel.empty-bin')\n if (state.value === 'closed') return t('panel.empty-closed')\n\n return state.value === 'all' ? t('panel.empty') : t('panel.empty-open')\n})\n\n/**\n * What the dropdowns behind the funnel are set to, said in the reader's words. A shut panel says\n * nothing about itself, and a list narrowed by something nobody can see is a list that looks\n * wrong — here doubly, because it is also why the grips went away.\n */\nconst applied = computed<AppliedFilter[]>(() => {\n const chips: AppliedFilter[] = []\n\n if (status.value !== '') {\n chips.push({\n key: 'status',\n label: `${t('panel.filter-status')}: ${t(`panel.status-${status.value}`)}`,\n clear: () => narrow('status', undefined),\n })\n }\n\n const chosen = filters.value.categories.find((item) => item.id === category.value)\n\n if (chosen) {\n chips.push({\n key: 'category',\n label: `${t('panel.filter-category')}: ${chosen.title}`,\n clear: () => narrow('category', undefined),\n })\n }\n\n return chips\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const answer = await api.list({\n state: state.value,\n q: q.value,\n category: category.value,\n status: inBin.value ? '' : status.value,\n trashed: inBin.value,\n })\n\n rows.value = answer.data\n filters.value = answer.filters\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\n/*\n * Sources one by one, not a getter returning an array: a fresh array is a new value on every\n * change of the address, and the list would be read twice for one click.\n */\nwatch([view, category, status, q], () => void load())\nvoid load()\n\nlet pause: ReturnType<typeof setTimeout> | undefined\n\nwatch(typed, (value) => {\n clearTimeout(pause)\n pause = setTimeout(() => {\n void router.replace({ query: { ...route.query, q: value.trim() === '' ? undefined : value } })\n }, 300)\n})\n\nonBeforeUnmount(() => clearTimeout(pause))\n\nfunction narrow(name: 'category' | 'status', value: unknown): void {\n void router.replace({\n query: {\n ...route.query,\n [name]:\n typeof value === 'number' || (typeof value === 'string' && value !== '')\n ? String(value)\n : undefined,\n },\n })\n}\n\nfunction clearFilters(): void {\n const query: LocationQueryRaw = { ...route.query }\n\n delete query.category\n delete query.status\n void router.replace({ query })\n}\n\nfunction open(vacancy: VacancyRow): void {\n void router.push({ path: `${props.base}/${vacancy.id}`, query: { ...route.query } })\n}\n\n/** A new vacancy: the dialog asks for the position, the editor opens. */\nasync function add(): Promise<void> {\n const made = await create({})\n\n if (made) open(made)\n}\n\n/**\n * The order on screen, written as a whole. The list is already in its new order\n * (`WxSortableList` reorders the model before it says so), so a failure has to put it back\n * rather than leave the screen disagreeing with the database.\n */\nasync function reorder(): Promise<void> {\n try {\n await api.reorder(rows.value.map((row) => row.id))\n } catch (error) {\n toast.danger(message(error, t('panel.reorder-failed')))\n await load()\n }\n}\n\nconst live = (vacancy: VacancyRow) =>\n vacancy.status === 'published' || vacancy.status === 'modified'\n\nfunction actionsFor(vacancy: VacancyRow): RowAction[] {\n if (!canManage.value) return []\n\n if (inBin.value) {\n return [\n {\n key: 'restore',\n icon: 'refresh',\n label: t('panel.restore'),\n run: () => void restore(vacancy),\n },\n ]\n }\n\n const actions: RowAction[] = [\n { key: 'open', icon: 'edit', label: t('panel.open'), run: () => open(vacancy) },\n {\n key: 'duplicate',\n icon: 'copy',\n label: t('panel.duplicate'),\n run: () => void duplicate(vacancy),\n },\n ]\n\n if (vacancy.url && vacancy.status !== 'draft') {\n actions.push({\n key: 'site',\n icon: 'external-link',\n label: t('panel.open-on-site'),\n href: vacancy.url,\n })\n }\n\n /*\n * Closing is a publication of `is_closed` (§4.11), so it is offered only for what is on the\n * site: closing a draft would publish it. A vacancy closed only by its date is not reopened\n * here — its date is what closes it, and that is changed in the editor.\n */\n if (live(vacancy) && vacancy.closed_reason === 'manual') {\n actions.push({\n key: 'reopen',\n icon: 'refresh',\n label: t('panel.reopen'),\n run: () => void reopen(vacancy),\n })\n } else if (live(vacancy) && vacancy.closed_reason === null) {\n actions.push({\n key: 'close',\n icon: 'lock',\n label: t('panel.close'),\n run: () => void close(vacancy),\n })\n }\n\n actions.push(\n live(vacancy)\n ? {\n key: 'unpublish',\n icon: 'eye-off',\n label: t('panel.unpublish'),\n run: () => void run(() => api.unpublish(vacancy.id), t('panel.unpublished-done')),\n }\n : {\n key: 'publish',\n icon: 'upload',\n label: t('panel.publish'),\n run: () => void run(() => api.publish(vacancy.id), t('panel.published')),\n },\n )\n\n actions.push({\n key: 'delete',\n icon: 'trash',\n label: t('panel.delete'),\n danger: true,\n run: () => void remove(vacancy),\n })\n\n return actions\n}\n\n/**\n * The same position somewhere else (decision 20): a copy as a draft, opened straight away — the\n * city is the first thing that differs, and it is on the editor, not here.\n */\nasync function duplicate(vacancy: VacancyRow): Promise<void> {\n try {\n const copy = await api.duplicate(vacancy.id)\n\n toast.success(t('panel.duplicated'))\n open(copy.vacancy)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/**\n * Closing publishes, so edits waiting in the draft would go out with it; the server refuses that\n * with a 409, and the panel says so before asking — the answer is the same, and a question whose\n * only answer is \"no\" is not one to put.\n */\nasync function close(vacancy: VacancyRow): Promise<void> {\n if (vacancy.status === 'modified') {\n toast.warning(t('panel.close-edits'))\n\n return\n }\n\n const agreed = await confirm({\n title: t('panel.close-title', { title: vacancy.title }),\n message: t('panel.close-text'),\n confirmText: t('panel.close'),\n cancelText: t('panel.cancel'),\n })\n\n if (!agreed) return\n\n await run(() => api.close(vacancy.id), t('panel.closed'))\n}\n\nasync function reopen(vacancy: VacancyRow): Promise<void> {\n if (vacancy.status === 'modified') {\n toast.warning(t('panel.close-edits'))\n\n return\n }\n\n const agreed = await confirm({\n title: t('panel.reopen-title', { title: vacancy.title }),\n message: t('panel.reopen-text'),\n confirmText: t('panel.reopen'),\n cancelText: t('panel.cancel'),\n })\n\n if (!agreed) return\n\n try {\n const row = await api.reopen(vacancy.id)\n\n // Taken off by hand and past its day as well: it is open to the switch, closed to the date.\n if (row.closed) toast.warning(t('panel.reopen-expired'))\n else toast.success(t('panel.reopened'))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n await load()\n }\n}\n\nasync function remove(vacancy: VacancyRow): Promise<void> {\n const agreed = await confirm({\n title: t('panel.delete-title', { title: vacancy.title }),\n message: t('panel.delete-text'),\n confirmText: t('panel.delete'),\n cancelText: t('panel.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n await run(() => api.remove(vacancy.id), t('panel.deleted'))\n}\n\nasync function restore(vacancy: VacancyRow): Promise<void> {\n await run(() => api.restore(vacancy.id), t('panel.restored'))\n}\n\n/** One request, one sentence about it, and the list as the server now sees it. */\nasync function run(request: () => Promise<unknown>, said: string): Promise<void> {\n try {\n await request()\n toast.success(said)\n } catch (error) {\n toast.danger(message(error))\n } finally {\n await load()\n }\n}\n\n/* Live and live-with-edits are the same green; what is waiting has a chip of its own. */\nfunction badge(value: VacancyStatus): 'default' | 'success' {\n return value === 'published' || value === 'modified' ? 'success' : 'default'\n}\n\nfunction address(vacancy: VacancyRow): string {\n if (inBin.value) return '—'\n\n return vacancy.path === null ? t('panel.no-address') : `/${vacancy.path}`\n}\n\n/** Where: the city, \"Remote\", or the city and \"Hybrid\" — what a candidate reads first. */\nfunction where(vacancy: VacancyRow): string {\n if (vacancy.workplace === 'remote') return t('vacancy.workplace.remote')\n\n const city = vacancy.city !== '' ? vacancy.city : t('panel.no-city')\n\n return vacancy.workplace === 'hybrid' ? `${city} · ${t('vacancy.workplace.hybrid')}` : city\n}\n\nfunction employment(vacancy: VacancyRow): string {\n return vacancy.employment_types.map((code) => t(employmentKey(code))).join(', ')\n}\n\n/* In \"all\" the closed ones are muted, so the line between the two halves shows. */\nfunction muted(vacancy: VacancyRow): boolean {\n return vacancy.closed && state.value === 'all' && !inBin.value\n}\n\n/* What the section offers. Declared, because on a phone the head folds it into the ···. */\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value\n ? [{ key: 'new', label: t('panel.new'), icon: 'plus', primary: true, run: () => void add() }]\n : [],\n)\n</script>\n\n<template>\n <div class=\"wx-vacancies\">\n <wx-list-screen\n v-model:view=\"view\"\n :title=\"title\"\n :views=\"views\"\n :actions=\"actions\"\n padding=\"sm\"\n >\n <div class=\"wx-vacancies__bar\">\n <wx-input\n v-model=\"typed\"\n class=\"wx-vacancies__search\"\n size=\"sm\"\n clearable\n :placeholder=\"t('panel.search')\"\n :aria-label=\"t('panel.search')\"\n >\n <template #prefix><wx-icon name=\"search\" size=\"sm\" /></template>\n </wx-input>\n\n <!--\n The funnel, the way `WxTable` draws its own: the panel hangs off the indicator rather\n than off the button, because `WxAction` carries its tooltip beside itself and a trigger\n has to be one element (CLAUDE.md §4).\n -->\n <wx-popover :title=\"t('panel.filters')\" :width=\"280\" side=\"bottom\" align=\"end\">\n <template #trigger>\n <wx-indicator\n class=\"wx-vacancies__funnel\"\n :value=\"applied.length\"\n :hidden=\"applied.length === 0\"\n type=\"primary\"\n :label=\"t('panel.filters')\"\n >\n <wx-action icon=\"filter\" size=\"sm\" :title=\"t('panel.filters')\" />\n </wx-indicator>\n </template>\n\n <div class=\"wx-vacancies__filters\">\n <wx-form-item v-if=\"!inBin\" :label=\"t('panel.filter-status')\">\n <wx-select\n :model-value=\"status === '' ? null : status\"\n :options=\"statuses\"\n :placeholder=\"t('panel.any-status')\"\n clearable\n size=\"sm\"\n @update:model-value=\"(value: unknown) => narrow('status', value)\"\n />\n </wx-form-item>\n\n <wx-form-item :label=\"t('panel.filter-category')\">\n <wx-select\n :model-value=\"category\"\n :options=\"filters.categories.map((item) => ({ value: item.id, label: item.title }))\"\n :placeholder=\"t('panel.any-category')\"\n clearable\n size=\"sm\"\n @update:model-value=\"(value: unknown) => narrow('category', value)\"\n />\n </wx-form-item>\n\n <wx-button\n v-if=\"applied.length > 0\"\n variant=\"text\"\n size=\"sm\"\n block\n @click=\"clearFilters\"\n >\n <template #icon><wx-icon name=\"close\" /></template>\n {{ t('panel.filters-reset') }}\n </wx-button>\n </div>\n </wx-popover>\n </div>\n\n <div v-if=\"applied.length > 0\" class=\"wx-vacancies__applied\">\n <wx-filter-chips :filters=\"applied\" />\n </div>\n\n <wx-skeleton v-if=\"loading && rows.length === 0\" class=\"wx-vacancies__loading\" :rows=\"5\" />\n\n <wx-empty\n v-else-if=\"rows.length === 0\"\n :title=\"emptyText\"\n :description=\"state === 'all' && !inBin && unfiltered ? t('panel.empty-help') : undefined\"\n />\n\n <template v-else>\n <!--\n A grip and not the whole row: the row opens a vacancy, and a row that both opens and\n drags is one where one of the two happens by accident. No grips at all where the list\n is a selection — a handle that moves rows past invisible ones would be lying.\n -->\n <wx-sortable-list\n v-model=\"rows\"\n class=\"wx-vacancies__list\"\n :class=\"{ 'is-loading': loading }\"\n plain\n item-key=\"id\"\n :handle=\"sortable ? 'grip' : 'row'\"\n :item-label=\"(item: VacancyRow) => item.title\"\n :disabled=\"!sortable\"\n @move=\"reorder\"\n >\n <template #default=\"{ item }\">\n <component\n :is=\"inBin ? 'div' : 'router-link'\"\n class=\"wx-vacancy-row\"\n :class=\"{ 'is-closed': muted(item) }\"\n v-bind=\"inBin ? {} : { to: { path: `${props.base}/${item.id}`, query: route.query } }\"\n >\n <span class=\"wx-vacancy-row__name\">\n <span class=\"wx-vacancy-row__title\">{{ item.title }}</span>\n <span class=\"wx-vacancy-row__address\"\n >{{ address(item) }}<wx-address-note v-if=\"!inBin\" :locale=\"item.address_locale\"\n /></span>\n </span>\n\n <span class=\"wx-vacancy-row__facts\">\n <span class=\"wx-vacancy-row__where\">\n <wx-icon :name=\"item.workplace === 'remote' ? 'monitor' : 'map-pin'\" size=\"sm\" />\n {{ where(item) }}\n </span>\n <span v-if=\"item.employment_types.length > 0\" class=\"wx-vacancy-row__employment\">\n {{ employment(item) }}\n </span>\n <wx-tooltip\n v-if=\"item.valid_through\"\n :content=\"t('panel.until-help', { date: longDay(item.valid_through, locale) })\"\n >\n <span class=\"wx-vacancy-row__until\">\n <wx-icon name=\"calendar\" size=\"sm\" />\n {{ t('panel.until', { date: formatDay(item.valid_through, locale) }) }}\n </span>\n </wx-tooltip>\n </span>\n\n <span class=\"wx-vacancy-row__state\">\n <wx-badge v-for=\"chip in item.categories\" :key=\"chip.id\" size=\"sm\" round>\n {{ chip.title }}\n </wx-badge>\n <wx-tooltip\n v-if=\"item.closed_reason\"\n :content=\"t(`panel.closed-${item.closed_reason}-help`)\"\n >\n <wx-badge type=\"warning\" size=\"sm\" round>\n {{ t(`panel.closed-${item.closed_reason}`) }}\n </wx-badge>\n </wx-tooltip>\n <wx-badge :type=\"badge(item.status)\" dot size=\"sm\">\n {{ t(`panel.status-${item.status}`) }}\n </wx-badge>\n <wx-badge v-if=\"item.status === 'modified'\" type=\"primary\" size=\"sm\" round>\n {{ t('panel.edits') }}\n </wx-badge>\n </span>\n </component>\n </template>\n\n <template #actions=\"{ item }\">\n <wx-row-menu :actions=\"actionsFor(item)\" :label=\"item.title\" />\n </template>\n </wx-sortable-list>\n\n <!-- What a drag does here, or why there is nothing to drag — under the rows it is about. -->\n <wx-alert\n v-if=\"canManage && !inBin\"\n class=\"wx-vacancies__note\"\n type=\"info\"\n :description=\"hint\"\n />\n </template>\n </wx-list-screen>\n </div>\n</template>\n\n<style scoped>\n.wx-vacancies {\n min-width: 0;\n container-type: inline-size;\n}\n\n.wx-vacancies__bar {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-4) var(--wx-space-8) var(--wx-space-8);\n}\n\n.wx-vacancies__search {\n flex: 1 1 240px;\n min-width: 0;\n max-width: 420px;\n}\n\n.wx-vacancies__funnel {\n flex: none;\n}\n\n.wx-vacancies__filters {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n\n.wx-vacancies__applied {\n padding: 0 var(--wx-space-8) var(--wx-space-8);\n}\n\n.wx-vacancies__loading {\n padding: var(--wx-space-8);\n}\n\n.wx-vacancies__list.is-loading {\n opacity: 0.6;\n}\n\n.wx-vacancies__list :deep(.wx-sortable-list__row) {\n padding-inline: var(--wx-space-8);\n}\n\n.wx-vacancies__list :deep(.wx-sortable-list__row:hover) {\n background: var(--wx-bg-subtle);\n border-radius: var(--wx-radius-sm);\n}\n\n.wx-vacancies__note {\n margin-block-start: var(--wx-space-8);\n}\n\n/*\n * Three columns on a wide list: who, the facts a candidate reads, the state. The facts are\n * the ones that fold first — under the name on a narrow list.\n */\n.wx-vacancy-row {\n display: grid;\n /* Each row is a grid of its own, so the state column has a width rather than `auto`: sized by\n its badges, it would start the facts at a different place on every row. */\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 260px;\n grid-template-areas: 'name facts state';\n align-items: center;\n gap: var(--wx-space-4) var(--wx-space-16);\n flex: 1 1 auto;\n min-width: 0;\n padding-block: var(--wx-space-6);\n color: inherit;\n text-decoration: none;\n}\n\n.wx-vacancy-row__name {\n grid-area: name;\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.wx-vacancy-row__title {\n overflow: hidden;\n font-weight: var(--wx-font-weight-medium);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.wx-vacancy-row__address {\n overflow: hidden;\n color: var(--wx-text-muted);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.wx-vacancy-row__facts {\n grid-area: facts;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-2) var(--wx-space-12);\n min-width: 0;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-vacancy-row__where,\n.wx-vacancy-row__until {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n white-space: nowrap;\n}\n\n.wx-vacancy-row__employment {\n min-width: 0;\n}\n\n.wx-vacancy-row__state {\n grid-area: state;\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-end;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n/*\n * A closed vacancy in \"all\": the whole row a step quieter rather than a badge alone — \"is this\n * still open\" is answered by the eye running down the list, not by reading.\n */\n.wx-vacancy-row.is-closed .wx-vacancy-row__title,\n.wx-vacancy-row.is-closed .wx-vacancy-row__facts {\n color: var(--wx-text-muted);\n}\n\n/*\n * Narrow: the facts and the state go under the name rather than beside it, so the name keeps the\n * width. By the width of the list, not of the window — the panel's sidebar decides how much the\n * list has.\n */\n@container (max-width: 720px) {\n .wx-vacancy-row {\n grid-template-columns: minmax(0, 1fr);\n grid-template-areas:\n 'name'\n 'facts'\n 'state';\n align-items: start;\n }\n\n .wx-vacancy-row__state {\n justify-content: flex-start;\n }\n\n .wx-vacancies__list :deep(.wx-sortable-list__row) {\n gap: var(--wx-space-8);\n padding-inline: var(--wx-space-4);\n }\n\n .wx-vacancies__bar,\n .wx-vacancies__applied {\n padding-inline: var(--wx-space-4);\n }\n\n .wx-vacancies__search {\n max-width: none;\n }\n}\n</style>\n"],"names":["props","__props","context","useAdmin","api","createVacanciesApi","route","useRoute","router","useRouter","useVacanciesMessages","t","useTranslate","message","useErrorText","rows","ref","filters","loading","create","createModal","VacancyCreateDialog","canManage","computed","title","module","locale","view","value","inBin","state","category","raw","status","q","typed","views","statuses","one","unfiltered","ordered","sortable","hint","emptyText","applied","chips","narrow","chosen","item","load","answer","error","toast","watch","pause","onBeforeUnmount","name","clearFilters","query","open","vacancy","add","made","reorder","row","live","actionsFor","restore","actions","duplicate","reopen","close","run","remove","copy","confirm","request","said","badge","address","where","city","employment","code","employmentKey","muted","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","WxListScreen","$event","_createElementVNode","_hoisted_2","WxInput","WxIcon","WxPopover","WxIndicator","WxAction","_hoisted_3","_createBlock","WxFormItem","WxSelect","_cache","WxButton","_createTextVNode","_hoisted_4","WxFilterChips","WxSkeleton","WxEmpty","_Fragment","WxSortableList","_normalizeClass","_withCtx","_resolveDynamicComponent","_mergeProps","_hoisted_5","_hoisted_6","_toDisplayString","_hoisted_7","WxAddressNote","_hoisted_8","_hoisted_9","_hoisted_10","WxTooltip","longDay","_hoisted_11","formatDay","_hoisted_12","_renderList","chip","WxBadge","WxRowMenu","WxAlert"],"mappings":"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"}
|