fix
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
import { formatCredits, formatDate } from "$lib/utils";
|
||||
import {
|
||||
PAGE_SIZE,
|
||||
PLATFORM_DEMO_COMPANY_NAME,
|
||||
STAFF_ROLE_OPTIONS,
|
||||
assignAdminPlan,
|
||||
cloneAdminCompanyCatalog,
|
||||
@@ -93,23 +94,23 @@
|
||||
|
||||
let cloneOpen = $state(false);
|
||||
let cloneCompany = $state<AdminOrgCompany | null>(null);
|
||||
let cloneDestId = $state("");
|
||||
let cloneDestOptions = $state<AdminOrgCompany[]>([]);
|
||||
|
||||
let syncOpen = $state(false);
|
||||
let syncCompany = $state<AdminOrgCompany | null>(null);
|
||||
|
||||
const cloneDestLabel = $derived.by(() => {
|
||||
const selected = cloneDestOptions.find((c) => c.id === cloneDestId);
|
||||
if (selected?.name) return selected.name;
|
||||
return i18n.t("admin.users.cloneDestFallback");
|
||||
});
|
||||
|
||||
const usersPage = $derived(Math.floor(usersOffset / PAGE_SIZE) + 1);
|
||||
const usersPages = $derived(Math.max(1, Math.ceil(usersTotal / PAGE_SIZE)));
|
||||
const companiesPage = $derived(Math.floor(companiesOffset / PAGE_SIZE) + 1);
|
||||
const companiesPages = $derived(Math.max(1, Math.ceil(companiesTotal / PAGE_SIZE)));
|
||||
|
||||
const cloneDestLabel = $derived.by(() => {
|
||||
const me = authSession.me;
|
||||
const home = me?.staff_home_company;
|
||||
if (home?.name) return home.name;
|
||||
if (me?.company?.name) return me.company.name;
|
||||
return i18n.t("admin.users.cloneDestFallback");
|
||||
});
|
||||
|
||||
onMount(async () => {
|
||||
const gate = await requirePlatformAdmin();
|
||||
if (!gate.ok) {
|
||||
@@ -359,11 +360,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
function openCloneDialog(company: AdminOrgCompany) {
|
||||
async function openCloneDialog(company: AdminOrgCompany) {
|
||||
cloneCompany = company;
|
||||
cloneOpen = true;
|
||||
error = "";
|
||||
success = "";
|
||||
cloneDestId = "";
|
||||
const byId = new Map<string, AdminOrgCompany>();
|
||||
for (const c of companies) {
|
||||
if (c.id !== company.id) byId.set(c.id, c);
|
||||
}
|
||||
try {
|
||||
const demoRes = await listAdminCompanies({
|
||||
limit: PAGE_SIZE,
|
||||
offset: 0,
|
||||
q: PLATFORM_DEMO_COMPANY_NAME
|
||||
});
|
||||
for (const c of demoRes.companies) {
|
||||
if (c.id !== company.id) byId.set(c.id, c);
|
||||
}
|
||||
} catch {
|
||||
/* keep page companies as fallback */
|
||||
}
|
||||
const me = authSession.me;
|
||||
const home = me?.staff_home_company;
|
||||
if (home?.id && home.id !== company.id && home.name) {
|
||||
byId.set(home.id, { id: home.id, name: home.name });
|
||||
}
|
||||
for (const c of me?.companies ?? []) {
|
||||
if (c.id && c.id !== company.id && c.name) {
|
||||
byId.set(c.id, { id: c.id, name: c.name });
|
||||
}
|
||||
}
|
||||
const opts = [...byId.values()].sort((a, b) => a.name.localeCompare(b.name));
|
||||
cloneDestOptions = opts;
|
||||
const demo =
|
||||
opts.find((c) => c.name.trim().toLowerCase() === PLATFORM_DEMO_COMPANY_NAME.toLowerCase()) ??
|
||||
null;
|
||||
const homeId = (me?.staff_home_company_id || me?.staff_home_company?.id || "").trim();
|
||||
cloneDestId =
|
||||
demo?.id ||
|
||||
(homeId && homeId !== company.id ? homeId : "") ||
|
||||
opts[0]?.id ||
|
||||
"";
|
||||
}
|
||||
|
||||
function openSyncDialog(company: AdminOrgCompany) {
|
||||
@@ -373,6 +412,54 @@
|
||||
success = "";
|
||||
}
|
||||
|
||||
async function confirmCloneCatalog() {
|
||||
if (!cloneCompany) return;
|
||||
const destId = cloneDestId.trim();
|
||||
if (!destId || destId === cloneCompany.id) {
|
||||
error = i18n.t("admin.users.cloneDestRequired");
|
||||
return;
|
||||
}
|
||||
busy = true;
|
||||
error = "";
|
||||
success = "";
|
||||
try {
|
||||
const res = await cloneAdminCompanyCatalog(cloneCompany.id, {
|
||||
destCompanyId: destId
|
||||
});
|
||||
const products = Number(res.counts?.raw_products ?? 0);
|
||||
const categories = Number(res.counts?.categories ?? 0);
|
||||
const mappedWith = Number(res.counts?.mapped_with_category ?? 0);
|
||||
const activeDest = (res.active_company_id || res.dest_company_id || "").trim();
|
||||
success = i18n.t("flash.admin.catalogCloned", {
|
||||
source: cloneCompany.name,
|
||||
dest: cloneDestLabel,
|
||||
products: String(products),
|
||||
categories: String(categories),
|
||||
mapped_with: String(mappedWith)
|
||||
});
|
||||
cloneOpen = false;
|
||||
cloneCompany = null;
|
||||
cloneDestId = "";
|
||||
cloneDestOptions = [];
|
||||
if (activeDest) {
|
||||
try {
|
||||
await api("/api/auth/select-company", {
|
||||
method: "POST",
|
||||
body: { company_id: activeDest }
|
||||
});
|
||||
} catch {
|
||||
/* clone handler may already have switched the session */
|
||||
}
|
||||
window.location.assign("/products");
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
error = failureMessage(err, "Clone catalog failed");
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmSyncA1() {
|
||||
if (!syncCompany) return;
|
||||
busy = true;
|
||||
@@ -409,56 +496,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmCloneCatalog() {
|
||||
if (!cloneCompany) return;
|
||||
busy = true;
|
||||
error = "";
|
||||
success = "";
|
||||
try {
|
||||
const me = authSession.me;
|
||||
const destId =
|
||||
me?.staff_home_company_id?.trim() ||
|
||||
me?.staff_home_company?.id?.trim() ||
|
||||
undefined;
|
||||
if (!destId && me?.company?.id && me.company.id === cloneCompany.id) {
|
||||
error = i18n.t("flash.admin.cloneDestMissing");
|
||||
return;
|
||||
}
|
||||
const res = await cloneAdminCompanyCatalog(cloneCompany.id, {
|
||||
destCompanyId: destId
|
||||
});
|
||||
const products = Number(res.counts?.raw_products ?? 0);
|
||||
const categories = Number(res.counts?.categories ?? 0);
|
||||
const mappedWith = Number(res.counts?.mapped_with_category ?? 0);
|
||||
const activeDest = (res.active_company_id || res.dest_company_id || "").trim();
|
||||
success = i18n.t("flash.admin.catalogCloned", {
|
||||
source: cloneCompany.name,
|
||||
dest: cloneDestLabel,
|
||||
products: String(products),
|
||||
categories: String(categories),
|
||||
mapped_with: String(mappedWith)
|
||||
});
|
||||
cloneOpen = false;
|
||||
cloneCompany = null;
|
||||
if (activeDest) {
|
||||
try {
|
||||
await api("/api/auth/select-company", {
|
||||
method: "POST",
|
||||
body: { company_id: activeDest }
|
||||
});
|
||||
} catch {
|
||||
/* clone handler may already have switched the session */
|
||||
}
|
||||
window.location.assign("/products");
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
error = failureMessage(err, "Clone catalog failed");
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function sendSetPasswordEmails(userId?: string) {
|
||||
busy = true;
|
||||
error = "";
|
||||
@@ -998,9 +1035,15 @@
|
||||
{i18n.t("admin.users.cloneCatalogFrom", { name: cloneCompany.name })}
|
||||
</p>
|
||||
{/if}
|
||||
<p class="text-sm text-muted-foreground">
|
||||
{i18n.t("admin.users.cloneCatalogInto", { name: cloneDestLabel })}
|
||||
</p>
|
||||
<div class="space-y-2">
|
||||
<Label for="clone-dest">{i18n.t("admin.users.cloneDestLabel")}</Label>
|
||||
<Select id="clone-dest" bind:value={cloneDestId} data-testid="admin-clone-dest">
|
||||
<option value="">{i18n.t("admin.users.cloneDestSelect")}</option>
|
||||
{#each cloneDestOptions as dest}
|
||||
<option value={dest.id}>{dest.name}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
</div>
|
||||
<p class="text-xs text-muted-foreground">
|
||||
{i18n.t("admin.users.cloneCatalogWarning")}
|
||||
</p>
|
||||
@@ -1012,11 +1055,18 @@
|
||||
onclick={() => {
|
||||
cloneOpen = false;
|
||||
cloneCompany = null;
|
||||
cloneDestId = "";
|
||||
cloneDestOptions = [];
|
||||
}}
|
||||
>
|
||||
{i18n.t("admin.users.cloneCatalogCancel")}
|
||||
</Button>
|
||||
<Button type="button" loading={busy} onclick={() => confirmCloneCatalog()}>
|
||||
<Button
|
||||
type="button"
|
||||
loading={busy}
|
||||
disabled={!cloneDestId || cloneDestId === cloneCompany?.id}
|
||||
onclick={() => confirmCloneCatalog()}
|
||||
>
|
||||
{i18n.t("admin.users.cloneCatalogConfirm")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user