@webx-ui/module-team 0.1.16 → 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/TeamPage-ZI9lGyZ5.js +283 -0
- package/dist/TeamPage-ZI9lGyZ5.js.map +1 -0
- package/dist/index-Dq5upQx6.js +287 -0
- package/dist/index-Dq5upQx6.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +8 -553
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Dq5upQx6.js","sources":["../src/module.ts","../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/MemberPane.vue","../src/index.ts"],"sourcesContent":["import type { AdminModule } from '@webx-ui/module-admin'\n\nexport interface TeamOptions {\n /** Where the team lives inside the panel. */\n path?: string\n}\n\n/**\n * The team as a section of the panel (§5.6): one module and one entry, without a group of its\n * own — there are no categories to stand beside it (decision 1), and a group around a single\n * item is a heading over itself. A section whose server half is not installed never appears —\n * the entry is built from the manifest.\n */\nexport function team(options: TeamOptions = {}): AdminModule {\n const path = options.path ?? '/team'\n\n return {\n id: 'team',\n path,\n // One route: the open person is in the address (`?member=`), beside the list they were\n // opened from, so a link to them is a link to both.\n routes: [\n { path, name: 'webx.team', component: () => import('./TeamPage.vue'), props: { base: path } },\n ],\n }\n}\n","import { reorderItems, type AdminContext } from '@webx-ui/module-admin'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport type { MemberDetail, MemberQuery, MemberRow, MembersList } from './types'\n\nexport interface TeamApi {\n list(query?: MemberQuery): Promise<MembersList>\n get(id: number): Promise<MemberDetail>\n /**\n * A new person out of the values of their form, in one request: the form is filled in first\n * and the record made on the first save, so nobody leaves an empty person behind.\n */\n create(values: ScreenModel): Promise<MemberDetail>\n /** Refused with a 422 under the name of the field — `socials.<n>.url` for a link. */\n save(id: number, values: ScreenModel): Promise<MemberDetail>\n remove(id: number): Promise<void>\n restore(id: number): Promise<MemberRow>\n /** The one order there is (decision 5). */\n reorder(ids: number[]): Promise<void>\n}\n\n/** The path of the section under the panel's API, and of its order. */\nexport const TEAM_API = 'team'\n\n/** Everything under `/team`, below the panel's API path (§5.7). */\nexport function createTeamApi(admin: AdminContext): TeamApi {\n const base = `${admin.apiPath}/${TEAM_API}`\n const data = <T>(body: { data: T }): T => body.data\n\n return {\n list: (query = {}) => {\n const search = new URLSearchParams()\n\n if (query.search) search.set('search', query.search)\n if (query.trashed) search.set('trashed', '1')\n\n return admin.http.get<MembersList>(search.size > 0 ? `${base}?${search}` : base)\n },\n get: (id) => admin.http.get<{ data: MemberDetail }>(`${base}/${id}`).then(data),\n create: (values) => admin.http.post<{ data: MemberDetail }>(base, { values }).then(data),\n save: (id, values) =>\n admin.http.put<{ data: MemberDetail }>(`${base}/${id}`, { values }).then(data),\n remove: (id) => admin.http.delete<void>(`${base}/${id}`).then(() => undefined),\n // The resource of the list line, and not the form's pair: a restored person stays closed.\n restore: (id) => admin.http.post<{ data: MemberRow }>(`${base}/${id}/restore`, {}).then(data),\n reorder: (ids) => reorderItems(admin, TEAM_API, ids, null),\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 in ten languages under `webx-team::` and overrides these;\n * `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const teamMessages: Record<string, Messages> = {\n module: {\n team: 'Team',\n },\n member: {\n new: 'New person',\n untitled: 'Untitled',\n search: 'Search the team',\n empty: 'Nobody on the team yet.',\n 'empty-help': 'A person reaches the site in a team block, on any page.',\n 'empty-search': 'Nothing matches that.',\n 'empty-bin': 'The bin is empty.',\n all: 'All',\n trashed: 'Bin',\n 'not-published': 'Not published',\n 'no-job-title': 'No job title',\n order: 'Drag to change the order on the site.',\n choose: 'Choose a person',\n 'choose-help': 'Or add a new one: the first line of the list.',\n save: 'Save',\n saved: 'Saved.',\n 'save-failed': 'Not saved.',\n cancel: 'Cancel',\n delete: 'Delete',\n 'delete-title': 'Delete “:name” from the team?',\n 'delete-text':\n 'They go to the bin and leave every block on the site. Restored, they come back to their place.',\n deleted: 'Moved to the bin.',\n restore: 'Restore',\n restored: 'Restored.',\n 'reorder-failed': 'The new order was not saved.',\n 'leave-title': 'Leave without saving?',\n 'leave-text': 'What you wrote about this person is not on the server.',\n leave: 'Leave',\n back: 'Back to the list',\n },\n screen: {\n person: 'Person',\n photo: 'Photo',\n 'photo-help': 'Without one, the site shows the initials of the name.',\n name: 'Name',\n 'name-help':\n 'Required in the default language. Not written in another, the default one is shown.',\n 'job-title': 'Job title',\n 'job-title-help':\n 'Printed under the name. Not written in a language, the default one is shown.',\n about: 'About',\n text: 'Text',\n 'text-help': 'Printed only in the language it is written in. The person is shown either way.',\n links: 'Links',\n socials: 'Social networks',\n 'socials-help': 'In the order the site prints them. A row left empty is dropped when you save.',\n 'socials-add': 'Add a link',\n 'socials-empty': 'No links.',\n network: 'Network',\n 'network-placeholder': 'Choose a network',\n url: 'Address',\n services: 'Services',\n 'services-help':\n 'What the person provides: a team block on a service’s page can show only them.',\n settings: 'Settings',\n published: 'Published',\n 'published-help': 'On the site in every team block, from the moment it is saved.',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { teamMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useTeamMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-team', teamMessages)\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 { onBeforeRouteLeave, onBeforeRouteUpdate, type RouteLocationNormalized } from 'vue-router'\nimport {\n confirm,\n localizedValue,\n toast,\n useLocales,\n WxActionBar,\n WxBadge,\n WxButton,\n WxSkeleton,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxSaveState,\n WxScreen,\n WxScreenHead,\n type ScreenAction,\n useBodyKeys,\n} from '@webx-ui/module-admin'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport { createTeamApi } from './api'\nimport { useTeamMessages } from './i18n'\nimport type { MemberDetail, MemberSummary } from './types'\n\n/**\n * One person: the pane beside the list, and the whole screen on a phone.\n *\n * The described screen `team.form` with a head over it and one button under it. One explicit\n * save, and no autosave: a person has no draft (decision 10), so what is saved is on the site at\n * once — the button is the moment somebody decides it is ready.\n *\n * A new person is a form first and a record on the first save: an empty row made by pressing\n * \"New person\" and walking away would be a nameless card on every team block for ever.\n *\n * The way back is drawn here and not by the pane around it: the drawer a narrow screen opens\n * this in has no close of its own on purpose (CLAUDE.md §4).\n */\ndefineOptions({ name: 'WxMemberPane' })\n\nconst props = withDefaults(\n defineProps<{\n /** `null` — a person not written yet. */\n id: number | null\n /** False in the drawer a narrow screen opens this in. */\n inline?: boolean\n }>(),\n { inline: true },\n)\n\nconst emit = defineEmits<{\n back: []\n /** The person was written; the list redraws their row. */\n saved: [member: MemberSummary]\n /** The first save of a new person: a record now, with an id to be opened by. */\n created: [member: MemberSummary]\n removed: [id: number]\n}>()\n\nconst context = useAdmin()\nconst api = createTeamApi(context)\nconst locales = useLocales()\nuseTeamMessages()\n\nconst t = useTranslate('webx-team')\n/* Not the server's `message`: the panel says how a request failed in its own words. */\nconst message = useErrorText()\n\nconst member = ref<MemberSummary | null>(null)\nconst values = ref<ScreenModel>({})\nconst snapshot = ref('')\n\nconst loading = ref(props.id !== null)\nconst saving = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst canManage = computed(() => context.can('team.manage'))\n\nconst current = computed(() => JSON.stringify(values.value))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst state = computed<'saving' | 'unsaved' | 'saved'>(() => {\n if (saving.value) return 'saving'\n\n return dirty.value || props.id === null ? 'unsaved' : 'saved'\n})\n\n/** The name follows the field rather than the answer: an edit shows at the top as it is typed. */\nconst title = computed(() => {\n const written = values.value.name as LocalizedValue | string | null | undefined\n const fallback = props.id === null ? t('member.new') : (member.value?.name ?? '')\n\n return localizedValue(written, locales.active.value, fallback) || t('member.untitled')\n})\n\nfunction take(detail: MemberDetail): void {\n member.value = detail.member\n values.value = detail.values\n snapshot.value = JSON.stringify(detail.values)\n}\n\nif (props.id === null) {\n // What the server would answer for a person with nothing in them yet. No `services`: the field\n // is there only when the site has services (decision 3), and the screen fills its own default.\n const blank: ScreenModel = {\n name: {},\n job_title: {},\n text: {},\n photo: null,\n socials: [],\n published: false,\n }\n\n values.value = blank\n snapshot.value = JSON.stringify(blank)\n}\n\nasync function load(): Promise<void> {\n if (props.id === null) return\n\n loading.value = true\n\n try {\n take(await api.get(props.id))\n } catch (error) {\n toast.danger(message(error))\n emit('back')\n } finally {\n loading.value = false\n }\n}\n\nasync function save(): Promise<void> {\n if (saving.value || !canManage.value) return\n\n saving.value = true\n errors.value = {}\n\n try {\n const made = props.id === null\n const detail = made\n ? await api.create(values.value)\n : await api.save(props.id as number, values.value)\n\n take(detail)\n toast.success(t('member.saved'))\n if (made) emit('created', detail.member)\n else emit('saved', detail.member)\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]> } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('member.save-failed'))\n } else {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n\nasync function remove(): Promise<void> {\n const record = member.value\n\n if (!record) return\n\n const agreed = await confirm({\n title: t('member.delete-title', { name: record.name }),\n message: t('member.delete-text'),\n confirmText: t('member.delete'),\n cancelText: t('member.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.remove(record.id)\n toast.success(t('member.deleted'))\n // Nothing left to protect: the record is in the bin.\n snapshot.value = current.value\n emit('removed', record.id)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\n/* The browser's own guard: it cannot wait for a request, so all it can do is ask. */\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\n/* Ctrl+S saves, as it does everywhere else that has a save button. */\nfunction onKeydown(event: KeyboardEvent): void {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {\n event.preventDefault()\n if (dirty.value || props.id === null) void save()\n }\n}\n\n// And from the page around the form, where a click on empty space leaves the focus.\nuseBodyKeys(onKeydown)\n\nonMounted(() => {\n void load()\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\nasync function mayLeave(): Promise<boolean> {\n if (!dirty.value || !canManage.value) return true\n\n return await confirm({\n title: t('member.leave-title'),\n message: t('member.leave-text'),\n confirmText: t('member.leave'),\n cancelText: t('member.cancel'),\n tone: 'danger',\n })\n}\n\n/*\n * The list and this form are one route, so another person is an update of it rather than a way\n * out — and so is every keystroke in the search above the list, which goes into the address too.\n * Only a change of the person asks.\n */\nonBeforeRouteUpdate(async (to: RouteLocationNormalized, from: RouteLocationNormalized) =>\n to.query.member === from.query.member ? true : await mayLeave(),\n)\n\nonBeforeRouteLeave(mayLeave)\n\n/* What leads away from the person. On a narrow pane the head folds them into the ···. */\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value && member.value !== null\n ? [\n {\n key: 'delete',\n label: t('member.delete'),\n icon: 'trash',\n danger: true,\n menu: true,\n run: () => void remove(),\n },\n ]\n : [],\n)\n</script>\n\n<template>\n <div class=\"wx-member\" @keydown=\"onKeydown\">\n <wx-skeleton v-if=\"loading\" class=\"wx-member__ghost\" title :rows=\"6\" />\n\n <template v-else>\n <wx-screen-head\n :level=\"3\"\n :back=\"!props.inline\"\n :back-label=\"t('member.back')\"\n :title=\"title\"\n :actions=\"actions\"\n :collapse-below=\"480\"\n @back=\"emit('back')\"\n >\n <template v-if=\"member && !member.published\" #title-after>\n <wx-badge dot>{{ t('member.not-published') }}</wx-badge>\n </template>\n </wx-screen-head>\n\n <wx-screen\n v-model=\"values\"\n name=\"team.form\"\n :errors=\"errors\"\n :disabled=\"!canManage || saving\"\n />\n\n <wx-action-bar v-if=\"canManage\">\n <template #state>\n <wx-save-state :state=\"state\" />\n </template>\n\n <wx-button\n type=\"primary\"\n :loading=\"saving\"\n :disabled=\"!dirty && props.id !== null\"\n @click=\"save\"\n >\n {{ t('member.save') }}\n </wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-member {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n padding: var(--wx-gap, var(--wx-space-16));\n container-type: inline-size;\n}\n\n.wx-member__ghost {\n max-width: 480px;\n}\n</style>\n","import { defineAsyncComponent } from 'vue'\nexport { team, type TeamOptions } from './module'\nexport { createTeamApi, TEAM_API, type TeamApi } from './api'\nexport { teamMessages } from './messages'\nexport const WxTeamPage = defineAsyncComponent(() => import('./TeamPage.vue'))\nexport { default as WxMemberPane } from './MemberPane.vue'\nexport type {\n MemberDetail,\n MemberQuery,\n MemberRow,\n MembersList,\n MemberSummary,\n SocialLink,\n} from './types'\n"],"names":["team","options","path","TEAM_API","createTeamApi","admin","base","data","body","query","search","id","values","ids","reorderItems","teamMessages","seeded","useTeamMessages","i18n","useAdmin","props","__props","emit","__emit","context","api","locales","useLocales","t","useTranslate","message","useErrorText","member","ref","snapshot","loading","saving","errors","canManage","computed","current","dirty","state","title","written","fallback","localizedValue","take","detail","blank","load","error","toast","save","made","remove","record","confirm","leaveGuard","event","onKeydown","useBodyKeys","onMounted","onBeforeUnmount","mayLeave","onBeforeRouteUpdate","to","from","onBeforeRouteLeave","actions","_createElementBlock","_createBlock","_unref","WxSkeleton","_Fragment","_createVNode","WxScreenHead","WxBadge","WxScreen","$event","WxActionBar","WxSaveState","WxButton","WxTeamPage","defineAsyncComponent"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export { team, type TeamOptions } from './module';
|
|
2
2
|
export { createTeamApi, TEAM_API, type TeamApi } from './api';
|
|
3
3
|
export { teamMessages } from './messages';
|
|
4
|
-
export
|
|
4
|
+
export declare const WxTeamPage: import('vue').DefineComponent<{
|
|
5
|
+
base?: string;
|
|
6
|
+
}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
|
|
7
|
+
base?: string;
|
|
8
|
+
}> & Readonly<{}>, {
|
|
9
|
+
base: string;
|
|
10
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
5
11
|
export { default as WxMemberPane } from './MemberPane';
|
|
6
12
|
export type { MemberDetail, MemberQuery, MemberRow, MembersList, MemberSummary, SocialLink, } from './types';
|
package/dist/index.js
CHANGED
|
@@ -1,556 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { useLocales as we, localizedValue as ge, WxSkeleton as re, WxBadge as oe, WxActionBar as xe, WxButton as _e, toast as x, confirm as G, WxCard as ke, WxListDetail as Te, WxEmpty as Z, WxInput as Se, WxIcon as ee, WxSortableList as We, WxAvatar as Ne, WxAlert as qe } from "@webx-ui/core";
|
|
4
|
-
import { reorderItems as Be, useAdmin as Q, useTranslate as se, useErrorText as ie, useBodyKeys as $e, WxScreenHead as Ce, WxScreen as Pe, WxSaveState as Ve, useItemOrder as Ae, WxListScreen as Le, WxRowMenu as Me } from "@webx-ui/module-admin";
|
|
5
|
-
const H = "team";
|
|
6
|
-
function ue(i) {
|
|
7
|
-
const u = `${i.apiPath}/${H}`, s = (t) => t.data;
|
|
8
|
-
return {
|
|
9
|
-
list: (t = {}) => {
|
|
10
|
-
const c = new URLSearchParams();
|
|
11
|
-
return t.search && c.set("search", t.search), t.trashed && c.set("trashed", "1"), i.http.get(c.size > 0 ? `${u}?${c}` : u);
|
|
12
|
-
},
|
|
13
|
-
get: (t) => i.http.get(`${u}/${t}`).then(s),
|
|
14
|
-
create: (t) => i.http.post(u, { values: t }).then(s),
|
|
15
|
-
save: (t, c) => i.http.put(`${u}/${t}`, { values: c }).then(s),
|
|
16
|
-
remove: (t) => i.http.delete(`${u}/${t}`).then(() => {
|
|
17
|
-
}),
|
|
18
|
-
// The resource of the list line, and not the form's pair: a restored person stays closed.
|
|
19
|
-
restore: (t) => i.http.post(`${u}/${t}/restore`, {}).then(s),
|
|
20
|
-
reorder: (t) => Be(i, H, t, null)
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
const Re = {
|
|
24
|
-
module: {
|
|
25
|
-
team: "Team"
|
|
26
|
-
},
|
|
27
|
-
member: {
|
|
28
|
-
new: "New person",
|
|
29
|
-
untitled: "Untitled",
|
|
30
|
-
search: "Search the team",
|
|
31
|
-
empty: "Nobody on the team yet.",
|
|
32
|
-
"empty-help": "A person reaches the site in a team block, on any page.",
|
|
33
|
-
"empty-search": "Nothing matches that.",
|
|
34
|
-
"empty-bin": "The bin is empty.",
|
|
35
|
-
all: "All",
|
|
36
|
-
trashed: "Bin",
|
|
37
|
-
"not-published": "Not published",
|
|
38
|
-
"no-job-title": "No job title",
|
|
39
|
-
order: "Drag to change the order on the site.",
|
|
40
|
-
choose: "Choose a person",
|
|
41
|
-
"choose-help": "Or add a new one: the first line of the list.",
|
|
42
|
-
save: "Save",
|
|
43
|
-
saved: "Saved.",
|
|
44
|
-
"save-failed": "Not saved.",
|
|
45
|
-
cancel: "Cancel",
|
|
46
|
-
delete: "Delete",
|
|
47
|
-
"delete-title": "Delete “:name” from the team?",
|
|
48
|
-
"delete-text": "They go to the bin and leave every block on the site. Restored, they come back to their place.",
|
|
49
|
-
deleted: "Moved to the bin.",
|
|
50
|
-
restore: "Restore",
|
|
51
|
-
restored: "Restored.",
|
|
52
|
-
"reorder-failed": "The new order was not saved.",
|
|
53
|
-
"leave-title": "Leave without saving?",
|
|
54
|
-
"leave-text": "What you wrote about this person is not on the server.",
|
|
55
|
-
leave: "Leave",
|
|
56
|
-
back: "Back to the list"
|
|
57
|
-
},
|
|
58
|
-
screen: {
|
|
59
|
-
person: "Person",
|
|
60
|
-
photo: "Photo",
|
|
61
|
-
"photo-help": "Without one, the site shows the initials of the name.",
|
|
62
|
-
name: "Name",
|
|
63
|
-
"name-help": "Required in the default language. Not written in another, the default one is shown.",
|
|
64
|
-
"job-title": "Job title",
|
|
65
|
-
"job-title-help": "Printed under the name. Not written in a language, the default one is shown.",
|
|
66
|
-
about: "About",
|
|
67
|
-
text: "Text",
|
|
68
|
-
"text-help": "Printed only in the language it is written in. The person is shown either way.",
|
|
69
|
-
links: "Links",
|
|
70
|
-
socials: "Social networks",
|
|
71
|
-
"socials-help": "In the order the site prints them. A row left empty is dropped when you save.",
|
|
72
|
-
"socials-add": "Add a link",
|
|
73
|
-
"socials-empty": "No links.",
|
|
74
|
-
network: "Network",
|
|
75
|
-
"network-placeholder": "Choose a network",
|
|
76
|
-
url: "Address",
|
|
77
|
-
services: "Services",
|
|
78
|
-
"services-help": "What the person provides: a team block on a service’s page can show only them.",
|
|
79
|
-
settings: "Settings",
|
|
80
|
-
published: "Published",
|
|
81
|
-
"published-help": "On the site in every team block, from the moment it is saved."
|
|
82
|
-
}
|
|
83
|
-
}, te = /* @__PURE__ */ new WeakSet();
|
|
84
|
-
function de() {
|
|
85
|
-
try {
|
|
86
|
-
const { i18n: i } = Q();
|
|
87
|
-
te.has(i) || (i.defaults("webx-team", Re), te.add(i));
|
|
88
|
-
} catch {
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const Ue = /* @__PURE__ */ ae({
|
|
92
|
-
name: "WxMemberPane",
|
|
93
|
-
__name: "MemberPane",
|
|
94
|
-
props: {
|
|
95
|
-
id: {},
|
|
96
|
-
inline: { type: Boolean, default: !0 }
|
|
97
|
-
},
|
|
98
|
-
emits: ["back", "saved", "created", "removed"],
|
|
99
|
-
setup(i, { emit: u }) {
|
|
100
|
-
const s = i, t = u, c = Q(), l = ue(c), $ = we();
|
|
101
|
-
de();
|
|
102
|
-
const o = se("webx-team"), W = ie(), w = S(null), _ = S({}), k = S(""), h = S(s.id !== null), g = S(!1), q = S({}), f = v(() => c.can("team.manage")), M = v(() => JSON.stringify(_.value)), B = v(() => k.value !== "" && M.value !== k.value), R = v(() => g.value ? "saving" : B.value || s.id === null ? "unsaved" : "saved"), z = v(() => {
|
|
103
|
-
const a = _.value.name, d = s.id === null ? o("member.new") : w.value?.name ?? "";
|
|
104
|
-
return ge(a, $.active.value, d) || o("member.untitled");
|
|
105
|
-
});
|
|
106
|
-
function D(a) {
|
|
107
|
-
w.value = a.member, _.value = a.values, k.value = JSON.stringify(a.values);
|
|
108
|
-
}
|
|
109
|
-
if (s.id === null) {
|
|
110
|
-
const a = {
|
|
111
|
-
name: {},
|
|
112
|
-
job_title: {},
|
|
113
|
-
text: {},
|
|
114
|
-
photo: null,
|
|
115
|
-
socials: [],
|
|
116
|
-
published: !1
|
|
117
|
-
};
|
|
118
|
-
_.value = a, k.value = JSON.stringify(a);
|
|
119
|
-
}
|
|
120
|
-
async function T() {
|
|
121
|
-
if (s.id !== null) {
|
|
122
|
-
h.value = !0;
|
|
123
|
-
try {
|
|
124
|
-
D(await l.get(s.id));
|
|
125
|
-
} catch (a) {
|
|
126
|
-
x.danger(W(a)), t("back");
|
|
127
|
-
} finally {
|
|
128
|
-
h.value = !1;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async function C() {
|
|
133
|
-
if (!(g.value || !f.value)) {
|
|
134
|
-
g.value = !0, q.value = {};
|
|
135
|
-
try {
|
|
136
|
-
const a = s.id === null, d = a ? await l.create(_.value) : await l.save(s.id, _.value);
|
|
137
|
-
D(d), x.success(o("member.saved")), t(a ? "created" : "saved", d.member);
|
|
138
|
-
} catch (a) {
|
|
139
|
-
const d = a.body;
|
|
140
|
-
d?.errors ? (q.value = d.errors, x.danger(o("member.save-failed"))) : x.danger(W(a));
|
|
141
|
-
} finally {
|
|
142
|
-
g.value = !1;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
async function U() {
|
|
147
|
-
const a = w.value;
|
|
148
|
-
if (!(!a || !await G({
|
|
149
|
-
title: o("member.delete-title", { name: a.name }),
|
|
150
|
-
message: o("member.delete-text"),
|
|
151
|
-
confirmText: o("member.delete"),
|
|
152
|
-
cancelText: o("member.cancel"),
|
|
153
|
-
tone: "danger"
|
|
154
|
-
})))
|
|
155
|
-
try {
|
|
156
|
-
await l.remove(a.id), x.success(o("member.deleted")), k.value = M.value, t("removed", a.id);
|
|
157
|
-
} catch (P) {
|
|
158
|
-
x.danger(W(P));
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
function j(a) {
|
|
162
|
-
B.value && a.preventDefault();
|
|
163
|
-
}
|
|
164
|
-
function I(a) {
|
|
165
|
-
(a.ctrlKey || a.metaKey) && a.key.toLowerCase() === "s" && (a.preventDefault(), (B.value || s.id === null) && C());
|
|
166
|
-
}
|
|
167
|
-
$e(I), me(() => {
|
|
168
|
-
T(), window.addEventListener("beforeunload", j);
|
|
169
|
-
}), ne(() => {
|
|
170
|
-
window.removeEventListener("beforeunload", j);
|
|
171
|
-
});
|
|
172
|
-
async function E() {
|
|
173
|
-
return !B.value || !f.value ? !0 : await G({
|
|
174
|
-
title: o("member.leave-title"),
|
|
175
|
-
message: o("member.leave-text"),
|
|
176
|
-
confirmText: o("member.leave"),
|
|
177
|
-
cancelText: o("member.cancel"),
|
|
178
|
-
tone: "danger"
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
pe(
|
|
182
|
-
async (a, d) => a.query.member === d.query.member ? !0 : await E()
|
|
183
|
-
), he(E);
|
|
184
|
-
const J = v(
|
|
185
|
-
() => f.value && w.value !== null ? [
|
|
186
|
-
{
|
|
187
|
-
key: "delete",
|
|
188
|
-
label: o("member.delete"),
|
|
189
|
-
icon: "trash",
|
|
190
|
-
danger: !0,
|
|
191
|
-
menu: !0,
|
|
192
|
-
run: () => {
|
|
193
|
-
U();
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
] : []
|
|
197
|
-
);
|
|
198
|
-
return (a, d) => (y(), A("div", {
|
|
199
|
-
class: "wx-member",
|
|
200
|
-
onKeydown: I
|
|
201
|
-
}, [
|
|
202
|
-
h.value ? (y(), N(n(re), {
|
|
203
|
-
key: 0,
|
|
204
|
-
class: "wx-member__ghost",
|
|
205
|
-
title: "",
|
|
206
|
-
rows: 6
|
|
207
|
-
})) : (y(), A(le, { key: 1 }, [
|
|
208
|
-
b(n(Ce), {
|
|
209
|
-
level: 3,
|
|
210
|
-
back: !s.inline,
|
|
211
|
-
"back-label": n(o)("member.back"),
|
|
212
|
-
title: z.value,
|
|
213
|
-
actions: J.value,
|
|
214
|
-
"collapse-below": 480,
|
|
215
|
-
onBack: d[0] || (d[0] = (P) => t("back"))
|
|
216
|
-
}, ve({ _: 2 }, [
|
|
217
|
-
w.value && !w.value.published ? {
|
|
218
|
-
name: "title-after",
|
|
219
|
-
fn: p(() => [
|
|
220
|
-
b(n(oe), { dot: "" }, {
|
|
221
|
-
default: p(() => [
|
|
222
|
-
O(L(n(o)("member.not-published")), 1)
|
|
223
|
-
]),
|
|
224
|
-
_: 1
|
|
225
|
-
})
|
|
226
|
-
]),
|
|
227
|
-
key: "0"
|
|
228
|
-
} : void 0
|
|
229
|
-
]), 1032, ["back", "back-label", "title", "actions"]),
|
|
230
|
-
b(n(Pe), {
|
|
231
|
-
modelValue: _.value,
|
|
232
|
-
"onUpdate:modelValue": d[1] || (d[1] = (P) => _.value = P),
|
|
233
|
-
name: "team.form",
|
|
234
|
-
errors: q.value,
|
|
235
|
-
disabled: !f.value || g.value
|
|
236
|
-
}, null, 8, ["modelValue", "errors", "disabled"]),
|
|
237
|
-
f.value ? (y(), N(n(xe), { key: 0 }, {
|
|
238
|
-
state: p(() => [
|
|
239
|
-
b(n(Ve), { state: R.value }, null, 8, ["state"])
|
|
240
|
-
]),
|
|
241
|
-
default: p(() => [
|
|
242
|
-
b(n(_e), {
|
|
243
|
-
type: "primary",
|
|
244
|
-
loading: g.value,
|
|
245
|
-
disabled: !B.value && s.id !== null,
|
|
246
|
-
onClick: C
|
|
247
|
-
}, {
|
|
248
|
-
default: p(() => [
|
|
249
|
-
O(L(n(o)("member.save")), 1)
|
|
250
|
-
]),
|
|
251
|
-
_: 1
|
|
252
|
-
}, 8, ["loading", "disabled"])
|
|
253
|
-
]),
|
|
254
|
-
_: 1
|
|
255
|
-
})) : V("", !0)
|
|
256
|
-
], 64))
|
|
257
|
-
], 32));
|
|
258
|
-
}
|
|
259
|
-
}), ce = (i, u) => {
|
|
260
|
-
const s = i.__vccOpts || i;
|
|
261
|
-
for (const [t, c] of u)
|
|
262
|
-
s[t] = c;
|
|
263
|
-
return s;
|
|
264
|
-
}, je = /* @__PURE__ */ ce(Ue, [["__scopeId", "data-v-443f6ebd"]]), ze = { class: "wx-team__bar" }, De = { class: "wx-member-row__body" }, Ie = { class: "wx-member-row__name" }, Ee = {
|
|
265
|
-
key: 0,
|
|
266
|
-
class: "wx-member-row__job"
|
|
267
|
-
}, Oe = {
|
|
268
|
-
key: 1,
|
|
269
|
-
class: "wx-member-row__facts"
|
|
270
|
-
}, Je = /* @__PURE__ */ ae({
|
|
271
|
-
__name: "TeamPage",
|
|
272
|
-
props: {
|
|
273
|
-
base: { default: "/team" }
|
|
274
|
-
},
|
|
275
|
-
setup(i) {
|
|
276
|
-
const u = Q(), s = ue(u), t = fe(), c = ye();
|
|
277
|
-
de();
|
|
278
|
-
const l = se("webx-team"), $ = ie(), o = S([]), W = S(!0), w = v(() => u.can("team.manage")), _ = v(
|
|
279
|
-
() => u.state.manifest?.modules.find((e) => e.id === "team")?.title ?? l("module.team")
|
|
280
|
-
), k = v({
|
|
281
|
-
get: () => t.query.view === "trashed" ? "trashed" : "",
|
|
282
|
-
set: (e) => {
|
|
283
|
-
const m = {
|
|
284
|
-
...t.query,
|
|
285
|
-
view: e === "" ? void 0 : String(e)
|
|
286
|
-
};
|
|
287
|
-
delete m.member, c.replace({ query: m });
|
|
288
|
-
}
|
|
289
|
-
}), h = v(() => k.value === "trashed"), g = v(() => typeof t.query.q == "string" ? t.query.q : ""), q = S(g.value), f = v(() => {
|
|
290
|
-
const e = t.query.member;
|
|
291
|
-
return e === "new" ? w.value ? "new" : null : typeof e == "string" && e !== "" && Number(e) || null;
|
|
292
|
-
}), M = v({
|
|
293
|
-
get: () => f.value !== null,
|
|
294
|
-
set: (e) => {
|
|
295
|
-
e || j();
|
|
296
|
-
}
|
|
297
|
-
}), B = v(() => [
|
|
298
|
-
{ value: "", label: l("member.all") },
|
|
299
|
-
{ value: "trashed", label: l("member.trashed"), icon: "trash" }
|
|
300
|
-
]), R = Ae(H, () => ({ q: g.value, filtered: h.value })), z = v(() => w.value && R.sortable.value), D = v(() => g.value !== "" ? l("member.empty-search") : h.value ? l("member.empty-bin") : l("member.empty"));
|
|
301
|
-
async function T() {
|
|
302
|
-
W.value = !0;
|
|
303
|
-
try {
|
|
304
|
-
const e = await s.list({ search: g.value, trashed: h.value });
|
|
305
|
-
o.value = e.data;
|
|
306
|
-
} catch (e) {
|
|
307
|
-
x.danger($(e));
|
|
308
|
-
} finally {
|
|
309
|
-
W.value = !1;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
Y(
|
|
313
|
-
() => [k.value, g.value],
|
|
314
|
-
() => {
|
|
315
|
-
T();
|
|
316
|
-
}
|
|
317
|
-
), T();
|
|
318
|
-
let C;
|
|
319
|
-
Y(q, (e) => {
|
|
320
|
-
clearTimeout(C), C = setTimeout(() => {
|
|
321
|
-
c.replace({ query: { ...t.query, q: e.trim() === "" ? void 0 : e } });
|
|
322
|
-
}, 300);
|
|
323
|
-
}), ne(() => clearTimeout(C));
|
|
324
|
-
function U(e) {
|
|
325
|
-
c.replace({ query: { ...t.query, member: String(e) } });
|
|
326
|
-
}
|
|
327
|
-
function j() {
|
|
328
|
-
const e = { ...t.query };
|
|
329
|
-
delete e.member, c.replace({ query: e });
|
|
330
|
-
}
|
|
331
|
-
function I(e) {
|
|
332
|
-
U(e.id), T();
|
|
333
|
-
}
|
|
334
|
-
async function E() {
|
|
335
|
-
try {
|
|
336
|
-
await R.move(o.value.map((e) => e.id));
|
|
337
|
-
} catch (e) {
|
|
338
|
-
x.danger($(e, l("member.reorder-failed"))), await T();
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
function J(e) {
|
|
342
|
-
return w.value ? h.value ? [
|
|
343
|
-
{
|
|
344
|
-
key: "restore",
|
|
345
|
-
icon: "refresh",
|
|
346
|
-
label: l("member.restore"),
|
|
347
|
-
run: () => {
|
|
348
|
-
P(e);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
] : [
|
|
352
|
-
{
|
|
353
|
-
key: "delete",
|
|
354
|
-
icon: "trash",
|
|
355
|
-
label: l("member.delete"),
|
|
356
|
-
danger: !0,
|
|
357
|
-
run: () => {
|
|
358
|
-
a(e);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
] : [];
|
|
362
|
-
}
|
|
363
|
-
async function a(e) {
|
|
364
|
-
if (await G({
|
|
365
|
-
title: l("member.delete-title", { name: e.name }),
|
|
366
|
-
message: l("member.delete-text"),
|
|
367
|
-
confirmText: l("member.delete"),
|
|
368
|
-
cancelText: l("member.cancel"),
|
|
369
|
-
tone: "danger"
|
|
370
|
-
}))
|
|
371
|
-
try {
|
|
372
|
-
await s.remove(e.id), x.success(l("member.deleted")), d(e.id);
|
|
373
|
-
} catch (r) {
|
|
374
|
-
x.danger($(r));
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
function d(e) {
|
|
378
|
-
f.value === e && j(), T();
|
|
379
|
-
}
|
|
380
|
-
async function P(e) {
|
|
381
|
-
try {
|
|
382
|
-
await s.restore(e.id), x.success(l("member.restored"));
|
|
383
|
-
} catch (m) {
|
|
384
|
-
x.danger($(m));
|
|
385
|
-
} finally {
|
|
386
|
-
await T();
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
return (e, m) => (y(), N(n(Le), {
|
|
390
|
-
view: k.value,
|
|
391
|
-
"onUpdate:view": m[4] || (m[4] = (r) => k.value = r),
|
|
392
|
-
title: _.value,
|
|
393
|
-
views: B.value,
|
|
394
|
-
card: !1
|
|
395
|
-
}, {
|
|
396
|
-
default: p(() => [
|
|
397
|
-
b(n(ke), {
|
|
398
|
-
class: "wx-team",
|
|
399
|
-
padding: "none"
|
|
400
|
-
}, {
|
|
401
|
-
default: p(() => [
|
|
402
|
-
b(n(Te), {
|
|
403
|
-
open: M.value,
|
|
404
|
-
"onUpdate:open": m[3] || (m[3] = (r) => M.value = r),
|
|
405
|
-
class: "wx-team__panes",
|
|
406
|
-
"list-width": 360,
|
|
407
|
-
"detail-min": 460,
|
|
408
|
-
"detail-label": n(l)("module.team")
|
|
409
|
-
}, {
|
|
410
|
-
list: p(() => [
|
|
411
|
-
K("div", ze, [
|
|
412
|
-
b(n(Se), {
|
|
413
|
-
modelValue: q.value,
|
|
414
|
-
"onUpdate:modelValue": m[0] || (m[0] = (r) => q.value = r),
|
|
415
|
-
class: "wx-team__search",
|
|
416
|
-
size: "sm",
|
|
417
|
-
clearable: "",
|
|
418
|
-
placeholder: n(l)("member.search"),
|
|
419
|
-
"aria-label": n(l)("member.search")
|
|
420
|
-
}, {
|
|
421
|
-
prefix: p(() => [
|
|
422
|
-
b(n(ee), {
|
|
423
|
-
name: "search",
|
|
424
|
-
size: "sm"
|
|
425
|
-
})
|
|
426
|
-
]),
|
|
427
|
-
_: 1
|
|
428
|
-
}, 8, ["modelValue", "placeholder", "aria-label"])
|
|
429
|
-
]),
|
|
430
|
-
w.value && !h.value ? (y(), A("button", {
|
|
431
|
-
key: 0,
|
|
432
|
-
type: "button",
|
|
433
|
-
class: F(["wx-team__new", { "is-current": f.value === "new" }]),
|
|
434
|
-
onClick: m[1] || (m[1] = (r) => U("new"))
|
|
435
|
-
}, [
|
|
436
|
-
b(n(ee), {
|
|
437
|
-
name: "plus",
|
|
438
|
-
size: "sm"
|
|
439
|
-
}),
|
|
440
|
-
O(" " + L(n(l)("member.new")), 1)
|
|
441
|
-
], 2)) : V("", !0),
|
|
442
|
-
W.value && o.value.length === 0 ? (y(), N(n(re), {
|
|
443
|
-
key: 1,
|
|
444
|
-
class: "wx-team__loading",
|
|
445
|
-
rows: 5
|
|
446
|
-
})) : o.value.length === 0 ? (y(), N(n(Z), {
|
|
447
|
-
key: 2,
|
|
448
|
-
title: D.value,
|
|
449
|
-
description: !h.value && g.value === "" ? n(l)("member.empty-help") : void 0
|
|
450
|
-
}, null, 8, ["title", "description"])) : (y(), A(le, { key: 3 }, [
|
|
451
|
-
b(n(We), {
|
|
452
|
-
modelValue: o.value,
|
|
453
|
-
"onUpdate:modelValue": m[2] || (m[2] = (r) => o.value = r),
|
|
454
|
-
class: F(["wx-team__list", { "is-loading": W.value }]),
|
|
455
|
-
hoverable: "",
|
|
456
|
-
plain: "",
|
|
457
|
-
"item-key": "id",
|
|
458
|
-
handle: z.value ? "grip" : "row",
|
|
459
|
-
"item-label": (r) => r.name,
|
|
460
|
-
disabled: !z.value,
|
|
461
|
-
onMove: E
|
|
462
|
-
}, {
|
|
463
|
-
default: p(({ item: r }) => [
|
|
464
|
-
(y(), N(be(h.value ? "div" : "button"), {
|
|
465
|
-
type: h.value ? void 0 : "button",
|
|
466
|
-
class: F(["wx-member-row", { "is-current": f.value === r.id }]),
|
|
467
|
-
onClick: (X) => h.value ? void 0 : U(r.id)
|
|
468
|
-
}, {
|
|
469
|
-
default: p(() => [
|
|
470
|
-
b(n(Ne), {
|
|
471
|
-
class: "wx-member-row__photo",
|
|
472
|
-
src: r.photo?.thumb ?? void 0,
|
|
473
|
-
name: r.name,
|
|
474
|
-
size: "md"
|
|
475
|
-
}, null, 8, ["src", "name"]),
|
|
476
|
-
K("span", De, [
|
|
477
|
-
K("span", Ie, L(r.name), 1),
|
|
478
|
-
r.job_title ? (y(), A("span", Ee, L(r.job_title), 1)) : V("", !0),
|
|
479
|
-
r.published ? V("", !0) : (y(), A("span", Oe, [
|
|
480
|
-
b(n(oe), {
|
|
481
|
-
dot: "",
|
|
482
|
-
size: "sm"
|
|
483
|
-
}, {
|
|
484
|
-
default: p(() => [
|
|
485
|
-
O(L(n(l)("member.not-published")), 1)
|
|
486
|
-
]),
|
|
487
|
-
_: 1
|
|
488
|
-
})
|
|
489
|
-
]))
|
|
490
|
-
])
|
|
491
|
-
]),
|
|
492
|
-
_: 2
|
|
493
|
-
}, 1032, ["type", "class", "onClick"]))
|
|
494
|
-
]),
|
|
495
|
-
actions: p(({ item: r }) => [
|
|
496
|
-
b(n(Me), {
|
|
497
|
-
actions: J(r),
|
|
498
|
-
label: r.name
|
|
499
|
-
}, null, 8, ["actions", "label"])
|
|
500
|
-
]),
|
|
501
|
-
_: 1
|
|
502
|
-
}, 8, ["modelValue", "class", "handle", "item-label", "disabled"]),
|
|
503
|
-
w.value && !h.value ? (y(), N(n(qe), {
|
|
504
|
-
key: 0,
|
|
505
|
-
class: "wx-team__note",
|
|
506
|
-
type: "info",
|
|
507
|
-
description: n(R).hint.value
|
|
508
|
-
}, null, 8, ["description"])) : V("", !0)
|
|
509
|
-
], 64))
|
|
510
|
-
]),
|
|
511
|
-
detail: p(({ inline: r, back: X }) => [
|
|
512
|
-
f.value !== null ? (y(), N(je, {
|
|
513
|
-
id: f.value === "new" ? null : f.value,
|
|
514
|
-
key: String(f.value),
|
|
515
|
-
inline: r,
|
|
516
|
-
onBack: X,
|
|
517
|
-
onSaved: T,
|
|
518
|
-
onCreated: I,
|
|
519
|
-
onRemoved: d
|
|
520
|
-
}, null, 8, ["id", "inline", "onBack"])) : V("", !0)
|
|
521
|
-
]),
|
|
522
|
-
empty: p(() => [
|
|
523
|
-
b(n(Z), {
|
|
524
|
-
title: n(l)("member.choose"),
|
|
525
|
-
description: w.value ? n(l)("member.choose-help") : void 0
|
|
526
|
-
}, null, 8, ["title", "description"])
|
|
527
|
-
]),
|
|
528
|
-
_: 1
|
|
529
|
-
}, 8, ["open", "detail-label"])
|
|
530
|
-
]),
|
|
531
|
-
_: 1
|
|
532
|
-
})
|
|
533
|
-
]),
|
|
534
|
-
_: 1
|
|
535
|
-
}, 8, ["view", "title", "views"]));
|
|
536
|
-
}
|
|
537
|
-
}), Ke = /* @__PURE__ */ ce(Je, [["__scopeId", "data-v-9de1c5bb"]]);
|
|
538
|
-
function Xe(i = {}) {
|
|
539
|
-
const u = i.path ?? "/team";
|
|
540
|
-
return {
|
|
541
|
-
id: "team",
|
|
542
|
-
path: u,
|
|
543
|
-
// One route: the open person is in the address (`?member=`), beside the list they were
|
|
544
|
-
// opened from, so a link to them is a link to both.
|
|
545
|
-
routes: [{ path: u, name: "webx.team", component: Ke, props: { base: u } }]
|
|
546
|
-
};
|
|
547
|
-
}
|
|
1
|
+
import "vue";
|
|
2
|
+
import { T as m, M as t, W as r, c as M, t as T, a as o } from "./index-Dq5upQx6.js";
|
|
548
3
|
export {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
4
|
+
m as TEAM_API,
|
|
5
|
+
t as WxMemberPane,
|
|
6
|
+
r as WxTeamPage,
|
|
7
|
+
M as createTeamApi,
|
|
8
|
+
T as team,
|
|
9
|
+
o as teamMessages
|
|
555
10
|
};
|
|
556
11
|
//# sourceMappingURL=index.js.map
|