feat(ui) : clickable entity links, site→machines links, DataTable fixedLayout
- Add NuxtLink on component/piece/product names in machine hierarchy
(using composantId, pieceId, product.id)
- Make site machine count badges clickable → /machines?sites={id}
- Add opt-in fixedLayout prop and minWidth to DataTable columns
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,15 @@
|
|||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex items-center gap-2 flex-wrap">
|
<div class="flex items-center gap-2 flex-wrap">
|
||||||
<h3 class="text-sm font-semibold truncate" :class="component.pendingEntity ? 'text-error' : 'text-base-content'">
|
<h3 class="text-sm font-semibold truncate" :class="component.pendingEntity ? 'text-error' : 'text-base-content'">
|
||||||
{{ component.name }}
|
<NuxtLink
|
||||||
|
v-if="!isEditMode && !component.pendingEntity && component.composantId"
|
||||||
|
:to="`/component/${component.composantId}`"
|
||||||
|
class="hover:underline hover:text-primary transition-colors"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
{{ component.name }}
|
||||||
|
</NuxtLink>
|
||||||
|
<span v-else>{{ component.name }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
v-if="component.pendingEntity"
|
v-if="component.pendingEntity"
|
||||||
|
|||||||
@@ -29,7 +29,15 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<h3 class="text-lg font-semibold" :class="{ 'text-error': piece._emptySlot || piece.pendingEntity }">
|
<h3 class="text-lg font-semibold" :class="{ 'text-error': piece._emptySlot || piece.pendingEntity }">
|
||||||
{{ pieceData.name }}
|
<NuxtLink
|
||||||
|
v-if="!isEditMode && !piece.pendingEntity && !piece._emptySlot && piece.pieceId"
|
||||||
|
:to="`/piece/${piece.pieceId}`"
|
||||||
|
class="hover:underline hover:text-primary transition-colors"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
{{ pieceData.name }}
|
||||||
|
</NuxtLink>
|
||||||
|
<template v-else>{{ pieceData.name }}</template>
|
||||||
<span v-if="piece._emptySlot" class="text-sm font-semibold text-error ml-1">— manquant</span>
|
<span v-if="piece._emptySlot" class="text-sm font-semibold text-error ml-1">— manquant</span>
|
||||||
<button
|
<button
|
||||||
v-if="piece.pendingEntity"
|
v-if="piece.pendingEntity"
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
>
|
>
|
||||||
<span class="loading loading-spinner text-primary" aria-hidden="true" />
|
<span class="loading loading-spinner text-primary" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
<table :class="['table table-sm md:table-md', tableClass]">
|
<table :class="['table table-sm md:table-md', tableClass, { 'table-fixed': fixedLayout }]">
|
||||||
<thead>
|
<thead>
|
||||||
<!-- Header labels + sort -->
|
<!-- Header labels + sort -->
|
||||||
<tr>
|
<tr>
|
||||||
@@ -85,6 +85,7 @@
|
|||||||
alignClass(col),
|
alignClass(col),
|
||||||
{ 'hidden sm:table-cell': col.hiddenMobile },
|
{ 'hidden sm:table-cell': col.hiddenMobile },
|
||||||
]"
|
]"
|
||||||
|
:style="col.minWidth ? { minWidth: col.minWidth } : undefined"
|
||||||
>
|
>
|
||||||
<slot :name="`header-${col.key}`" :column="col">
|
<slot :name="`header-${col.key}`" :column="col">
|
||||||
<span
|
<span
|
||||||
@@ -221,6 +222,8 @@ const props = withDefaults(defineProps<{
|
|||||||
tableClass?: string
|
tableClass?: string
|
||||||
showCounter?: boolean
|
showCounter?: boolean
|
||||||
showPerPage?: boolean
|
showPerPage?: boolean
|
||||||
|
/** Use table-layout: fixed for stable column widths. Only enable on tables where columns define width/minWidth. */
|
||||||
|
fixedLayout?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|||||||
@@ -29,7 +29,14 @@
|
|||||||
>
|
>
|
||||||
<div class="flex items-center justify-between flex-wrap gap-2">
|
<div class="flex items-center justify-between flex-wrap gap-2">
|
||||||
<p class="font-semibold" :class="product.pendingEntity ? 'text-error' : 'text-base-content'">
|
<p class="font-semibold" :class="product.pendingEntity ? 'text-error' : 'text-base-content'">
|
||||||
{{ product.name }}
|
<NuxtLink
|
||||||
|
v-if="!product.pendingEntity && product.id"
|
||||||
|
:to="`/product/${product.id}`"
|
||||||
|
class="hover:underline hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
{{ product.name }}
|
||||||
|
</NuxtLink>
|
||||||
|
<span v-else>{{ product.name }}</span>
|
||||||
</p>
|
</p>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -11,13 +11,14 @@
|
|||||||
<h3 class="card-title text-lg text-base-content">
|
<h3 class="card-title text-lg text-base-content">
|
||||||
{{ site.name }}
|
{{ site.name }}
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<NuxtLink
|
||||||
class="badge font-bold"
|
:to="`/machines?sites=${site.id}`"
|
||||||
|
class="badge font-bold hover:opacity-80 transition-opacity"
|
||||||
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
||||||
:class="!site.color ? 'badge-primary' : ''"
|
:class="!site.color ? 'badge-primary' : ''"
|
||||||
>
|
>
|
||||||
{{ machineCount }} machines
|
{{ machineCount }} machines
|
||||||
</div>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-3 text-sm">
|
<div class="space-y-3 text-sm">
|
||||||
@@ -39,10 +40,10 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-2 text-base-content/60">
|
<NuxtLink :to="`/machines?sites=${site.id}`" class="flex items-center gap-2 text-base-content/60 hover:text-primary transition-colors">
|
||||||
<IconLucideFactory class="w-4 h-4 text-blue-500" aria-hidden="true" />
|
<IconLucideFactory class="w-4 h-4 text-blue-500" aria-hidden="true" />
|
||||||
<span>{{ machineCount }} machine(s)</span>
|
<span>{{ machineCount }} machine(s)</span>
|
||||||
</div>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-actions justify-end mt-4">
|
<div class="card-actions justify-end mt-4">
|
||||||
|
|||||||
@@ -141,13 +141,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2 shrink-0">
|
<div class="flex items-center gap-2 shrink-0">
|
||||||
<span
|
<NuxtLink
|
||||||
class="badge font-bold"
|
:to="`/machines?sites=${site.id}`"
|
||||||
|
class="badge font-bold hover:opacity-80 transition-opacity"
|
||||||
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
:style="site.color ? { backgroundColor: site.color + '30', color: site.color, borderColor: site.color + '50' } : {}"
|
||||||
:class="!site.color ? 'badge-primary' : ''"
|
:class="!site.color ? 'badge-primary' : ''"
|
||||||
>
|
>
|
||||||
{{ site.machines?.length || 0 }}
|
{{ site.machines?.length || 0 }} machine{{ (site.machines?.length || 0) > 1 ? 's' : '' }}
|
||||||
</span>
|
</NuxtLink>
|
||||||
<button
|
<button
|
||||||
class="btn btn-ghost btn-xs btn-circle"
|
class="btn btn-ghost btn-xs btn-circle"
|
||||||
@click="toggleSiteCollapse(site.id)"
|
@click="toggleSiteCollapse(site.id)"
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ export interface DataTableColumn {
|
|||||||
headerClass?: string
|
headerClass?: string
|
||||||
/** Width hint (e.g. 'w-24', 'min-w-[10rem]') */
|
/** Width hint (e.g. 'w-24', 'min-w-[10rem]') */
|
||||||
width?: string
|
width?: string
|
||||||
|
/** Inline min-width style (e.g. '120px', '8rem'). Only effective with fixedLayout. */
|
||||||
|
minWidth?: string
|
||||||
/** Text alignment: 'left' (default), 'center', 'right' */
|
/** Text alignment: 'left' (default), 'center', 'right' */
|
||||||
align?: 'left' | 'center' | 'right'
|
align?: 'left' | 'center' | 'right'
|
||||||
/** Hide on mobile (adds 'hidden sm:table-cell') */
|
/** Hide on mobile (adds 'hidden sm:table-cell') */
|
||||||
|
|||||||
Reference in New Issue
Block a user