Espace de consultation
Consulter, modifier, lire l’activité, annuler et enregistrer une vue.
Copiez le stockage et l’adaptateur communs, le catalogue produit et les fichiers de consultation et de vues ci-dessous. Cet exemple requiert le registre courant ou l’instantané v3.1.0, pas l’ancien v3.0.0.
record-config.ts
import { defineTableConfig } from "@/components/ui/yayaw-table/config/helpers";
import { productConfig } from "./product-config";
export const recordConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
allowEdit: true,
enableViews: true,
allowViewSave: true,
rowClickMode: "default",
},
form: { editFormType: "products" },
});import { defineTableConfig } from "@/components/ui/yayaw-table-vue/config";
import { productConfig } from "./product-config";
export const recordConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
allowEdit: true,
enableViews: true,
allowViewSave: true,
rowClickMode: "default",
},
form: { editFormType: "products" },
});product-details.ts
import type {
DetailRevertHandler,
RecordDetailsConfig,
} from "@/components/ui/yayaw-table/utils/record-details";
import { productStore } from "../shared/store";
export const productDetails: RecordDetailsConfig = {
presentation: "drawer",
title: (row) => String(row.name),
updatedAt: (row) => String(row.updatedAt),
sections: [
{
id: "product",
title: "Product",
fields: [
{ id: "name", label: "Name", type: "text" },
{
id: "price",
label: "Price",
type: "number",
numberFormat: { style: "currency", currency: "EUR" },
},
{ id: "stock", label: "Stock", type: "number" },
{ id: "status", label: "Status", type: "text" },
],
},
],
activity: (row) => productStore.activity(String(row.id)),
};
export const revertActivity: DetailRevertHandler = (row, entry) =>
productStore.revert(String(row.id), entry.id);import type {
DetailRevertHandler,
RecordDetailsConfig,
} from "@/components/ui/yayaw-table-vue/record-details";
import { productStore } from "../shared/store";
export const productDetails: RecordDetailsConfig = {
presentation: "drawer",
title: (row) => String(row.name),
updatedAt: (row) => String(row.updatedAt),
sections: [
{
id: "product",
title: "Product",
fields: [
{ id: "name", label: "Name", type: "text" },
{
id: "price",
label: "Price",
type: "number",
numberFormat: { style: "currency", currency: "EUR" },
},
{ id: "stock", label: "Stock", type: "number" },
{ id: "status", label: "Status", type: "text" },
],
},
],
activity: (row) => productStore.activity(String(row.id)),
};
export const revertActivity: DetailRevertHandler = (row, entry) =>
productStore.revert(String(row.id), entry.id);view-actions.ts
import type {
TableView,
TableViewActions,
} from "@/components/ui/yayaw-table/types/view-types";
/** Demo persistence lasts for this module's lifetime. Scope server storage by user and organization. */
const views = new Map<string, TableView>();
const favorites = new Map<string, string | null>();
export const viewActions: TableViewActions = {
list: ({ tableId }) =>
Promise.resolve({
data: [...views.values()].filter((view) => view.tableId === tableId),
}),
create: (input) => {
const view = {
...input,
id: crypto.randomUUID(),
createdById: "demo-user",
};
views.set(view.id, structuredClone(view));
return Promise.resolve({ success: true, data: view });
},
update: (id, input) => {
const current = views.get(id);
if (!current || (input.tableId && input.tableId !== current.tableId)) {
return Promise.resolve({ success: false, error: "View not found." });
}
const view = { ...current, ...input };
views.set(id, structuredClone(view));
return Promise.resolve({ success: true, data: view });
},
delete: (id, { tableId }) => {
if (views.get(id)?.tableId !== tableId) {
return Promise.resolve({ success: false, error: "View not found." });
}
views.delete(id);
if (favorites.get(tableId) === id) {
favorites.delete(tableId);
}
return Promise.resolve({ success: true, data: { id } });
},
getFavorite: ({ tableId }) =>
Promise.resolve({
success: true,
data: { viewId: favorites.get(tableId) ?? null },
}),
setFavorite: (viewId, { tableId }) => {
if (viewId && views.get(viewId)?.tableId !== tableId) {
return Promise.resolve({ success: false, error: "View not found." });
}
favorites.set(tableId, viewId);
return Promise.resolve({ success: true, data: { viewId } });
},
};import type {
TableView,
TableViewActions,
} from "@/components/ui/yayaw-table-vue/types";
/** Demo persistence lasts for this module's lifetime. Scope server storage by user and organization. */
const views = new Map<string, TableView>();
const favorites = new Map<string, string | null>();
export const viewActions: TableViewActions = {
list: ({ tableId }) =>
Promise.resolve({
data: [...views.values()].filter((view) => view.tableId === tableId),
}),
create: (input) => {
const view = {
...input,
id: crypto.randomUUID(),
createdById: "demo-user",
};
views.set(view.id, structuredClone(view));
return Promise.resolve({ success: true, data: view });
},
update: (id, input) => {
const current = views.get(id);
if (!current || (input.tableId && input.tableId !== current.tableId)) {
return Promise.resolve({ success: false, error: "View not found." });
}
const view = { ...current, ...input };
views.set(id, structuredClone(view));
return Promise.resolve({ success: true, data: view });
},
delete: (id, { tableId }) => {
if (views.get(id)?.tableId !== tableId) {
return Promise.resolve({ success: false, error: "View not found." });
}
views.delete(id);
if (favorites.get(tableId) === id) {
favorites.delete(tableId);
}
return Promise.resolve({ success: true });
},
getFavorite: ({ tableId }) =>
Promise.resolve({
success: true,
data: { viewId: favorites.get(tableId) ?? null },
}),
setFavorite: (viewId, { tableId }) => {
if (viewId && views.get(viewId)?.tableId !== tableId) {
return Promise.resolve({ success: false, error: "View not found." });
}
favorites.set(tableId, viewId);
return Promise.resolve({ success: true, data: { viewId } });
},
};Composant d’entrée
Données de démonstration. Les modifications restent dans cet aperçu.
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { NuqsAdapter } from "nuqs/adapters/react";
import { useState } from "react";
import { Toaster } from "sonner";
import { DataTable } from "@/components/ui/yayaw-table";
import { editableActions } from "./editable-actions";
import { getFormConfig } from "./get-form-config";
import type { ExamplePresentation } from "./presentation";
import { productDetails, revertActivity } from "./product-details";
import { recordConfig } from "./record-config";
import { viewActions } from "./view-actions";
const getConfig = () => recordConfig;
const recordActions = { ...editableActions, views: viewActions };
const getRecordActions = () => recordActions;
export default function RecordRecipe(presentation: ExamplePresentation = {}) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
<NuqsAdapter>
<DataTable
{...presentation}
details={productDetails}
getFormConfig={getFormConfig}
getRowId={(row) => String(row.id)}
getTableActions={getRecordActions}
getTableConfig={getConfig}
onRevertActivity={revertActivity}
tableId="recipe-record"
tableType="products"
title={presentation.title ?? "Record"}
/>
<Toaster />
</NuqsAdapter>
</QueryClientProvider>
);
}Données de démonstration. Les modifications restent dans cet aperçu.
<script setup lang="ts">
import type { ExamplePresentation } from "./presentation";
defineProps<ExamplePresentation>();
import { YayawDataTable } from "@/components/ui/yayaw-table-vue";
import { editableActions } from "./editable-actions";
import { getFormConfig } from "./get-form-config";
import { productDetails, revertActivity } from "./product-details";
import { recordConfig } from "./record-config";
import { viewActions } from "./view-actions";
const recordActions = { ...editableActions, views: viewActions };
const getRecordActions = () => recordActions;
const getRowId = (row: Record<string, unknown>) => String(row.id);
</script>
<template>
<YayawDataTable v-bind="$props" table-type="products" table-id="recipe-record" :title="title ?? 'Record'"
:config="recordConfig" :get-table-actions="getRecordActions" :get-row-id="getRowId"
:get-form-config="getFormConfig" :details="productDetails" :on-revert-activity="revertActivity" />
</template>Vérifier le résultat
Ouvrez Oak desk et consultez ses champs typés.
Passez le stock à 15 et enregistrez.
Ouvrez Activity : le changement 12 → 15 apparaît.
Annulez-le : le stock revient à 12 et un nouvel événement référence l’original.
Vérifiez qu’une seconde annulation est indisponible.
Modifiez les colonnes, enregistrez une vue, choisissez-la comme favori et remontez le tableau : elle est restaurée. Recharger le navigateur réinitialise ce stockage en mémoire.
Utilisez le playground existant pour explorer les contrôles de la bibliothèque.