feat: make catalog-pages dedup a choosable step in Fix alles
The maintenance "Fix alles" now has a checkbox to include or skip the duplicate catalog_pages merge, so admins can choose whether to run it. removeDuplicates takes an includePages flag and fixEverything threads it through to the action.
This commit is contained in:
1 parent
6dced0fb54
commit
3a292a44f1
3 files changed
+45
-11
No files matched your search
@@ -99,12 +99,12 @@ export async function applyAlignIdsAction(): Promise<
|
||||
}
|
||||
}
|
||||
|
||||
export async function fixEverythingAction(): Promise<
|
||||
ActionResult<maintenance.FixAllResult>
|
||||
> {
|
||||
export async function fixEverythingAction(input?: {
|
||||
dedupePages?: boolean;
|
||||
}): Promise<ActionResult<maintenance.FixAllResult>> {
|
||||
try {
|
||||
await guard();
|
||||
return actionOk(await maintenance.fixEverything());
|
||||
return actionOk(await maintenance.fixEverything(input ?? {}));
|
||||
} catch (e) {
|
||||
return handleActionError(e);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
|
||||
interface Health {
|
||||
itemsBaseTotal: number;
|
||||
@@ -38,6 +39,7 @@ export function CatalogMaintenancePanel() {
|
||||
const [health, setHealth] = useState<Health | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [busy, setBusy] = useState<string | null>(null);
|
||||
const [dedupePages, setDedupePages] = useState(true);
|
||||
const [alignPreview, setAlignPreview] = useState<{
|
||||
moves: number;
|
||||
inserted: number;
|
||||
@@ -286,12 +288,38 @@ export function CatalogMaintenancePanel() {
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="mb-3 flex items-center gap-2 rounded-md border p-2">
|
||||
<Checkbox
|
||||
id="dedupe-pages"
|
||||
checked={dedupePages}
|
||||
onCheckedChange={(v) => setDedupePages(v === true)}
|
||||
/>
|
||||
<label
|
||||
htmlFor="dedupe-pages"
|
||||
className="text-sm text-muted-foreground"
|
||||
>
|
||||
Also merge duplicate catalog pages (double links)
|
||||
</label>
|
||||
</div>
|
||||
<Button
|
||||
variant="destructive"
|
||||
disabled={busy !== null}
|
||||
onClick={() =>
|
||||
void run("all", fixEverythingAction, "All repairs applied")
|
||||
}
|
||||
onClick={async () => {
|
||||
setBusy("all");
|
||||
try {
|
||||
const res = await fixEverythingAction({ dedupePages });
|
||||
if (res.ok) {
|
||||
toast.success("All repairs applied");
|
||||
await refresh();
|
||||
} else {
|
||||
toast.error(res.error ?? "Failed");
|
||||
}
|
||||
} catch (e) {
|
||||
toast.error(String(e));
|
||||
} finally {
|
||||
setBusy(null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Fix everything now
|
||||
</Button>
|
||||
|
||||
@@ -388,9 +388,13 @@ async function dedupCatalogTable(table: string): Promise<number> {
|
||||
* product on the same page). The page merge runs before the row dedup so items
|
||||
* moved onto the survivor are still de-duplicated within the page afterwards.
|
||||
*/
|
||||
export async function removeDuplicates(): Promise<DedupResult> {
|
||||
export async function removeDuplicates(
|
||||
includePages = true,
|
||||
): Promise<DedupResult> {
|
||||
const ib = await removeDuplicateItemsBase();
|
||||
const pageDedup = await dedupeCatalogPages();
|
||||
const pageDedup = includePages
|
||||
? await dedupeCatalogPages()
|
||||
: { groups: 0, removed: 0, remapped: 0 };
|
||||
const catalogRemoved = await dedupCatalogTable("catalog_items");
|
||||
const catalogBcRemoved = await dedupCatalogTable("catalog_items_bc");
|
||||
return {
|
||||
@@ -630,12 +634,14 @@ export interface FixAllResult {
|
||||
}
|
||||
|
||||
/** Run every repair in a sensible order, then return before/after health. */
|
||||
export async function fixEverything(): Promise<FixAllResult> {
|
||||
export async function fixEverything(
|
||||
opts: { dedupePages?: boolean } = {},
|
||||
): Promise<FixAllResult> {
|
||||
const healthBefore = await getFurniHealth();
|
||||
const sprite = await fixSpriteIds();
|
||||
const offers = await fixCatalogOffers();
|
||||
const reconcile = await reconcileIds();
|
||||
const dedup = await removeDuplicates();
|
||||
const dedup = await removeDuplicates(opts.dedupePages ?? true);
|
||||
const align = await forceItemsBaseIdsToFurnidata(true);
|
||||
const healthAfter = await getFurniHealth();
|
||||
return { healthBefore, sprite, offers, reconcile, dedup, align, healthAfter };
|
||||
|
||||
Reference in new issue
Block a user