- disabled boolean on components table (default false) - Component list filters out disabled components - Component detail returns 404 for disabled - Delete button with confirmation on component detail page - Installation form filters out instances of disabled components Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,7 @@ export const components = pgTable(
|
|||||||
defaultCondition: text('default_condition').notNull().default('Working'),
|
defaultCondition: text('default_condition').notNull().default('Working'),
|
||||||
defaultFirmwareVersion: text('default_firmware_version'),
|
defaultFirmwareVersion: text('default_firmware_version'),
|
||||||
defaultLocationId: uuid('default_location_id').references(() => locations.id),
|
defaultLocationId: uuid('default_location_id').references(() => locations.id),
|
||||||
|
disabled: boolean('disabled').default(false).notNull(),
|
||||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
|
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const load: PageServerLoad = async ({ url }) => {
|
|||||||
const page = Math.max(1, Number(url.searchParams.get('page') ?? 1));
|
const page = Math.max(1, Number(url.searchParams.get('page') ?? 1));
|
||||||
const pageSize = 24;
|
const pageSize = 24;
|
||||||
|
|
||||||
const conditions = [];
|
const conditions = [eq(components.disabled, false)];
|
||||||
if (type) conditions.push(eq(components.componentType, type));
|
if (type) conditions.push(eq(components.componentType, type));
|
||||||
if (search) {
|
if (search) {
|
||||||
conditions.push(
|
conditions.push(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { PageServerLoad, Actions } from './$types';
|
|||||||
import { db } from '$lib/server/db/index.js';
|
import { db } from '$lib/server/db/index.js';
|
||||||
import { components, componentInstances, devices, locations, installationLog, componentImages, componentDocuments } from '$lib/server/db/schema.js';
|
import { components, componentInstances, devices, locations, installationLog, componentImages, componentDocuments } from '$lib/server/db/schema.js';
|
||||||
import { eq, desc } from 'drizzle-orm';
|
import { eq, desc } from 'drizzle-orm';
|
||||||
import { error, fail } from '@sveltejs/kit';
|
import { error, fail, redirect } from '@sveltejs/kit';
|
||||||
import { saveDocument, deleteFile } from '$lib/server/uploads.js';
|
import { saveDocument, deleteFile } from '$lib/server/uploads.js';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params }) => {
|
export const load: PageServerLoad = async ({ params }) => {
|
||||||
@@ -12,6 +12,7 @@ export const load: PageServerLoad = async ({ params }) => {
|
|||||||
.where(eq(components.id, params.id));
|
.where(eq(components.id, params.id));
|
||||||
|
|
||||||
if (!component) error(404, 'Component not found');
|
if (!component) error(404, 'Component not found');
|
||||||
|
if (component.disabled) error(404, 'Component not found');
|
||||||
|
|
||||||
// All instances with their device/location info
|
// All instances with their device/location info
|
||||||
const instances = await db
|
const instances = await db
|
||||||
@@ -161,5 +162,14 @@ export const actions: Actions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return { documentDeleted: true };
|
return { documentDeleted: true };
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: async ({ params }) => {
|
||||||
|
await db
|
||||||
|
.update(components)
|
||||||
|
.set({ disabled: true, updatedAt: new Date() })
|
||||||
|
.where(eq(components.id, params.id));
|
||||||
|
|
||||||
|
redirect(303, '/components');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
let editingInstanceId = $state<string | null>(null);
|
let editingInstanceId = $state<string | null>(null);
|
||||||
let showAddInstances = $state(false);
|
let showAddInstances = $state(false);
|
||||||
let showDocForm = $state(false);
|
let showDocForm = $state(false);
|
||||||
|
let showDeleteConfirm = $state(false);
|
||||||
|
|
||||||
const totalCount = $derived(data.instances.length);
|
const totalCount = $derived(data.instances.length);
|
||||||
const installedCount = $derived(data.instances.filter((i) => i.currentDeviceId).length);
|
const installedCount = $derived(data.instances.filter((i) => i.currentDeviceId).length);
|
||||||
@@ -56,9 +57,28 @@
|
|||||||
class="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-400 dark:hover:bg-gray-700">
|
class="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-400 dark:hover:bg-gray-700">
|
||||||
Print
|
Print
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" onclick={() => (showDeleteConfirm = !showDeleteConfirm)}
|
||||||
|
class="rounded-md border border-red-300 px-3 py-1.5 text-sm text-red-600 hover:bg-red-50 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900/20">
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if showDeleteConfirm}
|
||||||
|
<div class="mb-6 rounded-lg border border-red-200 bg-red-50 p-5 dark:border-red-800 dark:bg-red-900/20">
|
||||||
|
<p class="mb-3 text-sm text-red-700 dark:text-red-300">Are you sure you want to delete <strong>{c.title}</strong>? This will hide it from all listings.</p>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<form method="POST" action="?/disable" use:enhance>
|
||||||
|
<button type="submit" class="rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700">Yes, delete</button>
|
||||||
|
</form>
|
||||||
|
<button type="button" onclick={() => (showDeleteConfirm = false)}
|
||||||
|
class="rounded-md px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if form?.error}
|
{#if form?.error}
|
||||||
<div class="mb-4 rounded-md bg-red-50 p-3 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-300">{form.error}</div>
|
<div class="mb-4 rounded-md bg-red-50 p-3 text-sm text-red-700 dark:bg-red-900/30 dark:text-red-300">{form.error}</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const load: PageServerLoad = async ({ url }) => {
|
|||||||
})
|
})
|
||||||
.from(componentInstances)
|
.from(componentInstances)
|
||||||
.innerJoin(components, eq(componentInstances.componentId, components.id))
|
.innerJoin(components, eq(componentInstances.componentId, components.id))
|
||||||
|
.where(eq(components.disabled, false))
|
||||||
.orderBy(components.title, componentInstances.instanceNumber);
|
.orderBy(components.title, componentInstances.instanceNumber);
|
||||||
|
|
||||||
const locationList = await db
|
const locationList = await db
|
||||||
|
|||||||
Reference in New Issue
Block a user