Separación y reorganización de componentes visuales
This commit is contained in:
parent
cec61688a6
commit
6f83ceb0b4
@ -88,6 +88,30 @@ export async function verifyBrands(
|
||||
.status,
|
||||
403
|
||||
);
|
||||
await error(`${path}/${builtin.id}/delete`, {}, 409, "BUILTIN_PROTECTED");
|
||||
await error(`${path}/invalid/delete`, {}, 400, "INVALID_REQUEST");
|
||||
await error(`${path}/${randomUUID()}/delete`, {}, 404, "BRAND_NOT_FOUND");
|
||||
for (const active of [true, false]) {
|
||||
const unused = await save({ name: `Eliminar ${randomUUID()}`, active, logoSvg });
|
||||
const url = `${path}/${unused.id}/delete`;
|
||||
await error(url, { unexpected: true }, 400, "INVALID_REQUEST");
|
||||
await error(`${url}?unexpected=true`, {}, 400, "INVALID_REQUEST");
|
||||
assert.equal((await request(url, {}, undefined, "invalid")).status, 403);
|
||||
assert.ok((await list()).some((brand) => brand.id === unused.id));
|
||||
const response = await request(url, {});
|
||||
assert.equal(response.status, 200, await response.clone().text());
|
||||
assert.deepEqual(BrandResponseSchema.parse(await response.json()).brand, unused);
|
||||
await error(url, {}, 404, "BRAND_NOT_FOUND");
|
||||
await migrateBrands(database);
|
||||
await importLegacyBrands(database);
|
||||
assert.equal(
|
||||
(await list()).some((brand) => brand.id === unused.id),
|
||||
false
|
||||
);
|
||||
const recreated = await save({ name: unused.name, active });
|
||||
assert.notEqual(recreated.id, unused.id);
|
||||
assert.equal((await request(`${path}/${recreated.id}/delete`, {})).status, 200);
|
||||
}
|
||||
const name = `Marca prueba ${randomUUID()}`;
|
||||
const created = await save({ name: ` ${name} `, active: true, logoSvg });
|
||||
assert.equal(created.name, name);
|
||||
@ -137,6 +161,8 @@ export async function verifyBrands(
|
||||
assert.ok(foreignTemplate);
|
||||
const second = await asset(otherId, { ...values, templateId: foreignTemplate.id });
|
||||
assert.equal(second.values.brandId, created.id);
|
||||
await error(`${path}/${created.id}/delete`, {}, 409, "BRAND_IN_USE");
|
||||
assert.ok((await list()).some((brand) => brand.id === created.id));
|
||||
await save({ name, active: false }, created.id);
|
||||
assert.equal((await list()).find((brand) => brand.id === created.id)?.logoSvg, logoSvg);
|
||||
await error(`/assets/${companyId}`, { values }, 409, "BRAND_UNAVAILABLE");
|
||||
@ -207,4 +233,25 @@ export async function verifyBrands(
|
||||
assert.equal((await list()).find((brand) => brand.id === builtin.id)?.logoSvg, null);
|
||||
assert.equal((await list()).length, new Set((await list()).map((brand) => brand.id)).size);
|
||||
await save({ name: builtin.name, active: true, logoSvg: builtin.logoSvg }, builtin.id);
|
||||
// El historial sigue protegiendo la marca aunque ningún activo la use actualmente.
|
||||
await asset(companyId, { ...renamed.values, brandId: null }, first.id);
|
||||
await asset(otherId, { ...second.values, brandId: null }, second.id);
|
||||
await error(`${path}/${created.id}/delete`, {}, 409, "BRAND_IN_USE");
|
||||
assert.ok((await list()).some((brand) => brand.id === created.id));
|
||||
const racing = await save({ name: `Concurrente eliminación ${randomUUID()}`, active: true });
|
||||
const [association, deletion] = await Promise.all([
|
||||
request(`/assets/${companyId}`, { values: { ...values, brandId: racing.id } }),
|
||||
request(`${path}/${racing.id}/delete`, {}),
|
||||
]);
|
||||
if (deletion.status === 200) {
|
||||
assert.equal(association.status, 409, await association.clone().text());
|
||||
assert.equal(
|
||||
(await list()).some((brand) => brand.id === racing.id),
|
||||
false
|
||||
);
|
||||
} else {
|
||||
assert.equal(association.status, 201, await association.clone().text());
|
||||
assert.equal(deletion.status, 409, await deletion.clone().text());
|
||||
assert.equal(z.object({ code: z.string() }).parse(await deletion.json()).code, "BRAND_IN_USE");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { once } from "node:events";
|
||||
import { test } from "node:test";
|
||||
|
||||
@ -211,6 +212,11 @@ test("HTTP y MariaDB: configuración única, usuarios, sesiones y protección de
|
||||
await competitor.session();
|
||||
await expectError(await admin.request("/users"), 401, "UNAUTHENTICATED");
|
||||
await expectError(await admin.request("/asset-catalog/global"), 401, "UNAUTHENTICATED");
|
||||
await expectError(
|
||||
await admin.request(`/asset-brands/${randomUUID()}/delete`, {}),
|
||||
401,
|
||||
"UNAUTHENTICATED"
|
||||
);
|
||||
await expectError(await admin.request("/resource-catalog/global"), 401, "UNAUTHENTICATED");
|
||||
const first = {
|
||||
name: "Admin test",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
@import "@repo/shadcn-ui/globals.css";
|
||||
|
||||
@source "../../../modules";
|
||||
@source "../../../packages/rdx-ui/src";
|
||||
@source "../../../packages/shadcn-ui/src/components";
|
||||
|
||||
/* El shell conserva su identidad visual sin alterar los tokens semánticos del vendor. */
|
||||
|
||||
@ -14,7 +14,8 @@ Se incluyen 24 marcas habituales: Acer, Apple, ASUS, Brother, Canon, Clónico, D
|
||||
- Renombrar y activar/desactivar marcas personalizadas.
|
||||
- Activar/desactivar marcas de serie, conservando su nombre protegido.
|
||||
- Añadir, sustituir o quitar el logotipo de cualquier marca, incluidas las de serie.
|
||||
- No hay borrado físico ni conversión de origen.
|
||||
- Eliminar marcas personalizadas sin referencias en activos ni revisiones, previa confirmación. Las marcas de serie no se eliminan; no hay conversión de origen.
|
||||
- Una referencia histórica impide borrar la marca aunque ya no la use ningún activo. En ese caso se puede desactivar, sin modificar activos ni historial.
|
||||
- Una marca desactivada queda fuera de nuevas selecciones. Los activos que ya la tienen pueden conservarla, cambiarla o retirarla.
|
||||
- Marca continúa siendo opcional, salvo que una plantilla marque expresamente este campo obligatorio.
|
||||
|
||||
@ -30,6 +31,8 @@ En un activo, el campo de serie Marca usa BrandSelect, adaptador funcional de Se
|
||||
|
||||
El botón de añadir abre el mismo BrandForm, mantiene el borrador del activo y selecciona el nuevo UUID. En este contexto la marca se crea activa. Cancelar el activo no elimina una marca que se haya guardado. Se respeta el límite existente de una sola alta anidada. Carga, error, reintento, etiqueta accesible y español/inglés siguen los componentes existentes.
|
||||
|
||||
La eliminación aparece únicamente en las acciones de marcas personalizadas. DeleteBrandDialog, en `web/brands/delete/ui`, confirma la marca y mantiene los errores dentro del modal. Cancelar no modifica datos; durante la petición se bloquean acciones duplicadas y cierre. Tras el éxito se actualiza e invalida únicamente la consulta de marcas, también compartida por los selectores.
|
||||
|
||||
La biblioteca genérica sigue independiente del dominio; consultas, DTO y reglas de marcas permanecen en el módulo assets.
|
||||
|
||||
## Dominio, persistencia e historial
|
||||
@ -59,8 +62,9 @@ Un marcador transaccional evita que reinicios posteriores vuelvan a crear nombre
|
||||
- GET /api/asset-brands: listado global.
|
||||
- POST /api/asset-brands: alta con { values: { name, active, logoSvg } }.
|
||||
- POST /api/asset-brands/:id/update: actualización del mismo contrato.
|
||||
- POST /api/asset-brands/:id/delete: eliminación de una marca personalizada no referenciada, con cuerpo vacío `{}` y respuesta BrandResponseSchema de la marca eliminada.
|
||||
|
||||
Respuestas BrandsResponseSchema y BrandResponseSchema; parámetros, cuerpo y consultas estrictos. Duplicados y protección de serie devuelven 409, entrada inválida 400 y marca ausente 404. No se incorporan endpoints de eliminación ni nuevos permisos.
|
||||
Respuestas BrandsResponseSchema y BrandResponseSchema; parámetros, cuerpo y consultas estrictos. Duplicados, protección de serie y BRAND_IN_USE devuelven 409, entrada inválida 400 y marca ausente 404. La eliminación conserva autenticación y CSRF; no introduce nuevos permisos. Comprobar referencias y borrar se hace en una transacción, conservando las claves foráneas RESTRICT. Primero se bloquea el catálogo global de activos y después el catálogo de marcas, en el mismo orden que las escrituras del inventario, para evitar asociaciones concurrentes y lecturas con instantáneas anteriores al borrado en MariaDB. Repetir la eliminación devuelve 404 sin efectos adicionales; las migraciones no recrean marcas personalizadas eliminadas.
|
||||
|
||||
logoSvg contiene el SVG o null para ausencia/eliminación. Si se omite en una actualización, se conserva el logotipo: cambiar el estado o el nombre no debe borrarlo de forma implícita. En altas, la omisión significa ausencia. Las respuestas incluyen siempre logoSvg, nullable. Los permisos de sesión y CSRF existentes también protegen este campo.
|
||||
|
||||
@ -70,6 +74,8 @@ Pruebas de dominio y mappers: normalización, límites, UUID v7, origen protegid
|
||||
|
||||
La integración HTTP/MariaDB cubre autenticación y CSRF, unicidad concurrente, uso global en compañías diferentes, referencias válidas, nombre canónico, conservación de marca inactiva, revisión histórica tras renombrado, importación sin cambios del historial y semillas idempotentes.
|
||||
|
||||
La eliminación se prueba en marcas personalizadas activas e inactivas, con entradas inválidas, CSRF, protección de serie, referencias actuales e históricas, repetición, reutilización del nombre y asociación concurrente de un activo. No se borran marcas de la base de desarrollo durante las pruebas.
|
||||
|
||||
|
||||
### Resultado de la entrega (7 de octubre de 2026)
|
||||
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
# Componentes de interfaz
|
||||
|
||||
Metis Desk usa shadcn/ui, con Base UI y el estilo base-vega, siguiendo la organización de factuges-erp.
|
||||
Los componentes viven en packages/shadcn-ui y se consumen mediante el paquete @repo/shadcn-ui.
|
||||
El código se genera desde el registro oficial y queda versionado en este repositorio, sin depender del ERP.
|
||||
`packages/shadcn-ui` contiene únicamente el código del registro oficial y no se adapta ni se
|
||||
extiende desde este proyecto. Se consume mediante `@repo/shadcn-ui`.
|
||||
|
||||
Los componentes genéricos compuestos o reutilizables propios viven en `packages/rdx-ui` y se
|
||||
consumen mediante `@repo/rdx-ui`. Los componentes que conocen contratos, textos, consultas o
|
||||
reglas de Metis viven en el módulo o aplicación que los utiliza; nunca en ninguno de los dos
|
||||
paquetes genéricos.
|
||||
|
||||
## Componentes actuales
|
||||
|
||||
@ -13,7 +18,8 @@ El código se genera desde el registro oficial y queda versionado en este reposi
|
||||
- Checkbox: estado activo de usuarios, compañías, personas y departamentos.
|
||||
- Table: listados de usuarios, compañías, personas y departamentos.
|
||||
- Textarea: dirección opcional de las sedes, con varias líneas.
|
||||
- Dialog: formularios de alta y edición, con foco y cierre por teclado. FormDialog comparte el título y la cancelación traducidos.
|
||||
- Dialog: primitiva de shadcn/ui, con foco y cierre por teclado.
|
||||
- RDX UI: FormDialog, FormActions, ContextHelp, SelectWithAction, EntityTable y StatisticCard.
|
||||
|
||||
## Convención de navegación
|
||||
|
||||
@ -30,8 +36,9 @@ El paquete exporta componentes individuales. Importar solo el componente necesar
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
```
|
||||
|
||||
El tema se define una sola vez en packages/shadcn-ui/src/styles/globals.css.
|
||||
La aplicación importa ese CSS y declara las fuentes de Tailwind de los módulos y del paquete compartido.
|
||||
El tema base se define en `packages/shadcn-ui/src/styles/globals.css`; las extensiones propias
|
||||
se declaran fuera del vendor. La aplicación importa ese CSS y declara las fuentes de Tailwind de
|
||||
los módulos y de `packages/rdx-ui`.
|
||||
Usar tokens semánticos como bg-background, text-foreground y border-border en vez de repetir colores por pantalla.
|
||||
|
||||
## Añadir componentes
|
||||
@ -50,8 +57,8 @@ y los componentes equivalentes existentes. Ubicar cada componente en la entidad
|
||||
responsables, o en su ámbito compartido cuando tenga varios consumidores reales. Los
|
||||
componentes específicos de Metis Desk no pertenecen al paquete visual genérico.
|
||||
|
||||
La incorporación de primitivas al paquete vendor requiere una instrucción explícita del
|
||||
usuario según `AGENTS.md`. En ese caso, utilizar el procedimiento siguiente.
|
||||
La incorporación o actualización de primitivas en el paquete vendor requiere una instrucción
|
||||
explícita del usuario según `AGENTS.md`. En ese caso, utilizar el procedimiento siguiente.
|
||||
|
||||
Desde la raíz del proyecto, dentro de WSL:
|
||||
|
||||
@ -85,7 +92,10 @@ La ayuda de los formularios se coloca en su parte inferior, inmediatamente antes
|
||||
|
||||
## SelectWithAction: desplegable con acción integrada
|
||||
|
||||
El componente compartido vive en `@repo/shadcn-ui/components/select-with-action`. Compone Select, Button y ButtonGroup de shadcn/ui (Base UI, Vega). Presenta selección y botón «+» como un único grupo visual, manteniendo controles separados para teclado y lectores de pantalla. ButtonGroup utiliza fieldset para expresar semánticamente la agrupación.
|
||||
El componente compartido vive en `@repo/rdx-ui/components/select-with-action`. Compone Select,
|
||||
Button y ButtonGroup de shadcn/ui (Base UI, Vega). Presenta selección y botón «+» como un único
|
||||
grupo visual, manteniendo controles separados para teclado y lectores de pantalla. ButtonGroup
|
||||
utiliza fieldset para expresar semánticamente la agrupación.
|
||||
|
||||
Su contrato recibe id, etiqueta, opciones, placeholder, valor controlado y callback de selección. La acción es opcional y contiene etiqueta accesible, callback y estado deshabilitado. Admite opciones deshabilitadas, estado inválido, descripción accesible y obligatoriedad. Deshabilitar el selector también deshabilita la acción. El botón usa type=button y no envía el formulario.
|
||||
|
||||
@ -112,7 +122,7 @@ El inventario añade altas rápidas de plantilla, sede y persona en los activos.
|
||||
|
||||
## Listados de entidades
|
||||
|
||||
El estándar se define en [Patrón de listados de entidades](patron-de-listados-de-entidades.md), con inventario de pantallas y excepciones. EntityListHeader, EntityTable, EntityRowActions, EntityAction y EntityStatus viven en @repo/shadcn-ui/components/entity-list.
|
||||
El estándar se define en [Patrón de listados de entidades](patron-de-listados-de-entidades.md), con inventario de pantallas y excepciones. EntityListHeader, EntityTable, EntityRowActions, EntityAction y EntityStatus viven en @repo/rdx-ui/components/entity-list.
|
||||
|
||||
EntityTable recibe datos y columnas tipadas; utiliza TanStack Table para búsqueda, ordenación, visibilidad y paginación local. Admite búsqueda y filtros controlados por el módulo, conservando su semántica y ámbito. Las columnas de identificación y acciones quedan visibles. Los menús utilizan Base UI y conservan los callbacks de las acciones originales. No realiza peticiones ni conoce DTO de negocio.
|
||||
|
||||
@ -129,6 +139,8 @@ BrandCatalogPage reutiliza EntityListHeader/EntityTable con búsqueda, filtro de
|
||||
|
||||
BrandLogo y BrandLogoField muestran y permiten seleccionar SVG estáticos locales, con vista previa, errores de campo y acción de quitar. La columna de logotipo reutiliza esa presentación. Los límites, validación y fuentes se describen en [Catálogo global de marcas](catalogo-global-de-marcas.md).
|
||||
|
||||
DeleteBrandDialog compone FormDialog y DialogFooter para confirmar la eliminación de una marca personalizada. El listado solo coordina selección y cierre; el controller de `brands/delete` gestiona mutación y caché. Conserva cancelación y Escape, bloquea cierre y botones durante la petición y mantiene errores en el modal. Las referencias actuales o históricas se protegen en el servidor.
|
||||
|
||||
BrandSelect, dentro del módulo assets, adapta SelectWithAction al catálogo remoto: filtra marcas activas, conserva la selección inactiva actual y textos anteriores, ofrece alta rápida y respeta una sola anidación. El borrador padre se conserva y la nueva marca se selecciona por UUID. El componente genérico no conoce BrandDTO, consultas ni endpoints. Véase [Catálogo global de marcas](catalogo-global-de-marcas.md).
|
||||
|
||||
|
||||
@ -158,7 +170,7 @@ EntityRowActions muestra un botón icon-sm con EllipsisIcon, etiqueta accesible
|
||||
|
||||
## Tarjetas de indicadores
|
||||
|
||||
StatisticCard (`@repo/shadcn-ui/components/statistic-card`) representa un indicador con etiqueta, valor, icono y tinte discreto. Admite carga/error, evita sustituir datos desconocidos por cero y utiliza un botón con foco visible cuando hay navegación. No depende de DTO ni endpoints. Inicio la reutiliza para sus cinco KPI; la organización de bloques y sus estados permanece local al dashboard.
|
||||
StatisticCard (`@repo/rdx-ui/components/statistic-card`) representa un indicador con etiqueta, valor, icono y tinte discreto. Admite carga/error, evita sustituir datos desconocidos por cero y utiliza un botón con foco visible cuando hay navegación. No depende de DTO ni endpoints. Inicio la reutiliza para sus cinco KPI; la organización de bloques y sus estados permanece local al dashboard.
|
||||
|
||||
## Shell global
|
||||
|
||||
|
||||
@ -6,11 +6,16 @@ Drawer, FormDialog, portales, elementos dialog, aria-modal y roles dialog/alertd
|
||||
La búsqueda no dependió del nombre de los componentes.
|
||||
|
||||
El código propio contiene **81 componentes que construyen una interacción modal**. Todos
|
||||
usan FormDialog de @repo/shadcn-ui y tienen un componente principal por fichero. Un componente
|
||||
usan FormDialog de @repo/rdx-ui y tienen un componente principal por fichero. Un componente
|
||||
puede representar variantes de alta, edición o copia, y catálogos con distintos tipos; el número
|
||||
no es un recuento de todos los estados posibles de las ventanas. No se encontraron otras
|
||||
implementaciones propias con AlertDialog, Sheet, Drawer ni diálogos HTML/manuales.
|
||||
|
||||
Actualización de 2026-10-09: se añade DeleteBrandDialog para confirmar la eliminación de
|
||||
marcas personalizadas; el inventario pasa a 82 componentes. Se ha comprobado esta operación
|
||||
en navegador con API simulada: Cancelar/Escape, errores, bloqueo durante el envío, éxito,
|
||||
español/inglés y anchura móvil. Esta comprobación no amplía la revisión al resto de modales.
|
||||
|
||||
La implementación vendor de packages/shadcn-ui queda fuera de la refactorización según AGENTS.md.
|
||||
Sus primitivas y el diálogo de configuración de tablas se consultan y consumen, no se duplican
|
||||
ni reorganizan. Los popovers de selectores y menús de acciones no se contabilizan como formularios
|
||||
@ -42,6 +47,7 @@ Las rutas reflejan la [estructura por entidades y operaciones](estructura-web-po
|
||||
- [AssetDetailDialog](../modules/assets/src/web/assets/detail/ui/asset-detail-dialog.tsx)
|
||||
- [AssetEditorDialog](../modules/assets/src/web/assets/shared/ui/asset-editor-dialog.tsx)
|
||||
- [BrandEditorDialog](../modules/assets/src/web/brands/shared/ui/brand-editor-dialog.tsx)
|
||||
- [DeleteBrandDialog](../modules/assets/src/web/brands/delete/ui/delete-brand-dialog.tsx)
|
||||
- [CatalogDefinitionDialog](../modules/assets/src/web/catalog/detail/ui/catalog-definition-dialog.tsx)
|
||||
- [CatalogEditorDialog](../modules/assets/src/web/catalog/shared/ui/catalog-editor-dialog.tsx)
|
||||
- [CatalogFieldCreateDialog](../modules/assets/src/web/catalog-fields/create/ui/catalog-field-create-dialog.tsx)
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
"@hookform/resolvers": "5.2.2",
|
||||
"@metis/core": "workspace:*",
|
||||
"@repo/rdx-ddd": "workspace:*",
|
||||
"@repo/rdx-ui": "workspace:*",
|
||||
"@repo/rdx-utils": "workspace:*",
|
||||
"@repo/shadcn-ui": "workspace:*",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { test } from "node:test";
|
||||
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
|
||||
import type { IBrandRepository } from "../application/brand.repository";
|
||||
import { BrandUseCases } from "../application/brand.use-cases";
|
||||
import { mapBrandInput } from "../application/brand-input.mapper";
|
||||
@ -152,10 +154,17 @@ test("Marcas: mapper bidireccional conserva identidad y rechaza persistencia inv
|
||||
assert.throws(() => mapper.toDomain({ ...row, id: "invalid" }));
|
||||
assert.throws(() => mapper.toDomain({ ...row, name: " " }));
|
||||
});
|
||||
test("Marcas: catálogo rechaza duplicados, también inactivos, y permite renombrar personalizados", async () => {
|
||||
test("Marcas: unicidad, edición y eliminación de personalizadas, con protección de serie", async () => {
|
||||
let brands: Brand[] = [brand(), brand("Propia", false)];
|
||||
const repository: IBrandRepository = {
|
||||
list: async () => brands,
|
||||
remove: async (action) => {
|
||||
const result = action(brands);
|
||||
if (result.isSuccess) {
|
||||
brands = brands.filter((item) => !item.id.equals(result.data.id));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
save: async (action) => {
|
||||
const result = action(brands);
|
||||
if (result.isSuccess) {
|
||||
@ -182,4 +191,29 @@ test("Marcas: catálogo rechaza duplicados, también inactivos, y permite renomb
|
||||
assert.equal(renamed.data.id.toPrimitive(), existing.id.toPrimitive());
|
||||
const invalid = await useCases.save("invalid", { name: "Nueva", active: true });
|
||||
assert.equal(invalid.isSuccess, false);
|
||||
const builtin = brands.find((item) => item.builtin);
|
||||
assert.ok(builtin);
|
||||
for (const [id, code] of [
|
||||
["invalid", "INVALID_REQUEST"],
|
||||
[UniqueID.generateNewID().toPrimitive(), "BRAND_NOT_FOUND"],
|
||||
[builtin.id.toPrimitive(), "BUILTIN_PROTECTED"],
|
||||
]) {
|
||||
assert.ok(id);
|
||||
const result = await useCases.remove(id);
|
||||
assert.equal(result.isSuccess, false);
|
||||
if (!result.isSuccess) {
|
||||
assert.equal(result.error.code, code);
|
||||
}
|
||||
assert.equal(brands.length, 2);
|
||||
}
|
||||
const removed = await useCases.remove(existing.id.toPrimitive().toUpperCase());
|
||||
assert.ok(removed.isSuccess);
|
||||
assert.ok(removed.data.id.equals(existing.id));
|
||||
assert.deepEqual(brands, [builtin]);
|
||||
const repeated = await useCases.remove(existing.id.toPrimitive());
|
||||
assert.equal(repeated.isSuccess, false);
|
||||
if (!repeated.isSuccess) {
|
||||
assert.equal(repeated.error.code, "BRAND_NOT_FOUND");
|
||||
}
|
||||
assert.deepEqual(brands, [builtin]);
|
||||
});
|
||||
|
||||
@ -31,7 +31,11 @@ export function registerBrandRoutes(
|
||||
router.post("/:id/delete", (request, response, next) => {
|
||||
const params = z.strictObject({ id: z.uuid() }).safeParse(request.params);
|
||||
if (
|
||||
!(params.success && Empty.safeParse(request.body).success && Empty.safeParse(request.query).success)
|
||||
!(
|
||||
params.success &&
|
||||
Empty.safeParse(request.body).success &&
|
||||
Empty.safeParse(request.query).success
|
||||
)
|
||||
) {
|
||||
fail(response, "INVALID_REQUEST");
|
||||
return;
|
||||
|
||||
@ -26,6 +26,12 @@ export class SequelizeBrandRepository implements IBrandRepository {
|
||||
}
|
||||
remove(action: Parameters<IBrandRepository["remove"]>[0]) {
|
||||
return this.database.transaction(async (transaction) => {
|
||||
// El catálogo se bloquea antes que las marcas, igual que al escribir el inventario.
|
||||
// Evita que una lectura iniciada antes del borrado mezcle instantáneas de MariaDB.
|
||||
await this.database.query(
|
||||
"SELECT id FROM asset_catalogs WHERE catalogKey='global' FOR UPDATE",
|
||||
{ transaction, type: QueryTypes.SELECT }
|
||||
);
|
||||
const result = action(await readBrands(this.database, transaction, true));
|
||||
if (!result.isSuccess) {
|
||||
return result;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FormActions, FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions, FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { InventoryFeedback } from "../../../shared";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { RelationshipForm } from "./relationship-form";
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { BrowserLink, EntityNotFound } from "@metis/core/client";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CatalogError } from "../../../catalog";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AssetCharacteristic, AssetInput } from "../../../../common/inventory";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import type { z } from "zod/v4";
|
||||
|
||||
import type { BrandsResponseSchema } from "../../../../common/brands";
|
||||
import type { z } from "zod/v4";
|
||||
import { brandApi, brandKeys } from "../../shared/api";
|
||||
import type { DeleteBrandDialogProps } from "../types";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { DialogFooter } from "@repo/shadcn-ui/components/dialog";
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BrandApiError } from "../../shared/api";
|
||||
@ -11,13 +11,14 @@ export function DeleteBrandDialog(props: DeleteBrandDialogProps) {
|
||||
const { brand, onClose } = props;
|
||||
const mutation = useDeleteBrandController(props);
|
||||
const { t } = useTranslation("assets");
|
||||
const errorCode = mutation.error instanceof BrandApiError ? mutation.error.code : "INTERNAL_ERROR";
|
||||
const errorCode =
|
||||
mutation.error instanceof BrandApiError ? mutation.error.code : "INTERNAL_ERROR";
|
||||
return (
|
||||
<FormDialog
|
||||
cancelLabel={t("cancel")}
|
||||
formActions
|
||||
onOpenChange={(open) => {
|
||||
if (!open && !mutation.isPending) {
|
||||
if (!(open || mutation.isPending)) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BrandEditorDialog } from "../../shared";
|
||||
import { DeleteBrandDialog } from "../../delete";
|
||||
import { BrandEditorDialog } from "../../shared";
|
||||
import { BrandLogo } from "../../shared/ui";
|
||||
import { useBrandCatalogPageController } from "../controllers";
|
||||
import type { BrandCatalogPageProps } from "../types";
|
||||
|
||||
@ -8,14 +8,16 @@ export class BrandApiError extends Error {
|
||||
super(code);
|
||||
}
|
||||
}
|
||||
async function request(path = "", body?: { values: BrandInput } | Record<string, never>, token?: string) {
|
||||
async function request(
|
||||
path = "",
|
||||
body?: { values: BrandInput } | Record<string, never>,
|
||||
token?: string
|
||||
) {
|
||||
const response = await fetch(`/api/asset-brands${path}`, {
|
||||
method: body === undefined ? "GET" : "POST",
|
||||
credentials: "same-origin",
|
||||
headers:
|
||||
body === undefined
|
||||
? {}
|
||||
: { "content-type": "application/json", "x-csrf-token": token ?? "" },
|
||||
body === undefined ? {} : { "content-type": "application/json", "x-csrf-token": token ?? "" },
|
||||
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
||||
});
|
||||
const data: unknown = await response.json();
|
||||
|
||||
@ -16,7 +16,7 @@ import { AssetForm } from "../../assets";
|
||||
import { assetsEnglish, assetsSpanish } from "../../shared";
|
||||
import { BrandCatalogPage } from "../list";
|
||||
|
||||
import { brandKeys } from "./api";
|
||||
import { BrandApiError, brandApi, brandKeys } from "./api";
|
||||
import { BrandForm, BrandSelect } from "./ui";
|
||||
|
||||
const brand = {
|
||||
@ -74,6 +74,39 @@ test("Marcas: nombre de serie protegido y ayuda inferior; alta rápida siempre a
|
||||
assert.equal(quick.includes('type="checkbox"'), false);
|
||||
assert.ok(quick.includes("Global scope"));
|
||||
});
|
||||
test("Marcas: eliminar envía CSRF y cuerpo vacío, valida la respuesta y propaga conflictos", async () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
let status = 200;
|
||||
let response: unknown = { brand: { ...brand, builtin: false } };
|
||||
globalThis.fetch = async (input, options) => {
|
||||
assert.equal(input, `/api/asset-brands/${brand.id}/delete`);
|
||||
assert.equal(options?.method, "POST");
|
||||
assert.equal(options?.credentials, "same-origin");
|
||||
assert.equal(options?.body, "{}");
|
||||
const headers = new Headers(options?.headers);
|
||||
assert.equal(headers.get("x-csrf-token"), "test");
|
||||
assert.equal(headers.get("content-type"), "application/json");
|
||||
return new Response(JSON.stringify(response), {
|
||||
status,
|
||||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
};
|
||||
try {
|
||||
assert.deepEqual(await brandApi.remove(brand.id, "test"), response);
|
||||
response = { brand: { id: "invalid" } };
|
||||
await assert.rejects(() => brandApi.remove(brand.id, "test"));
|
||||
for (const code of ["BRAND_IN_USE", "BUILTIN_PROTECTED", "BRAND_NOT_FOUND"]) {
|
||||
status = code === "BRAND_NOT_FOUND" ? 404 : 409;
|
||||
response = { code };
|
||||
await assert.rejects(
|
||||
() => brandApi.remove(brand.id, "test"),
|
||||
(error: unknown) => error instanceof BrandApiError && error.code === code
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch;
|
||||
}
|
||||
});
|
||||
test("Marcas: selector mantiene valores antiguos e inactivos y respeta el límite de alta anidada", async () => {
|
||||
const props = {
|
||||
id: "brand",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { useId } from "react";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useBrandSelectController } from "../controllers";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CatalogFieldForm } from "../../shared";
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CatalogRelationForm } from "../../shared";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Checkbox } from "@repo/shadcn-ui/components/checkbox";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CatalogItemDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EntityRowActions, EntityStatus } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { EntityRowActions, EntityStatus } from "@repo/rdx-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CatalogItemDTO } from "../../../../common";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { EntityListHeader, EntityTable } from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { EntityListHeader, EntityTable } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CatalogDefinitionDialog } from "../../detail";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EntityAction } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { EntityAction } from "@repo/rdx-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CatalogItemDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CatalogItemDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { useTranslation } from "react-i18next";
|
||||
export function CatalogHelp({
|
||||
kind,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { SupportConnectionDTO, SupportToolDTO } from "../../../../common/support";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export function SupportHelp({ tool = false }: { tool?: boolean }) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { SupportTools } from "./support-tools";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { SupportToolEditorDialog } from "../../shared";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { useId } from "react";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { WorkstationDTO } from "../../../../common";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { InventoryFeedback } from "../../../shared";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"@metis/assets": "workspace:*",
|
||||
"@metis/resources": "workspace:*",
|
||||
"@repo/rdx-ddd": "workspace:*",
|
||||
"@repo/rdx-ui": "workspace:*",
|
||||
"@repo/rdx-utils": "workspace:*",
|
||||
"@repo/shadcn-ui": "workspace:*",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { PersonForm } from "../../../people";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FormActions, FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions, FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { useId } from "react";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AccessKind } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { HelpKind } from "../../shared/i18n";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AccessItemDTO, PersonDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EntityAction, EntityRowActions } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { EntityAction, EntityRowActions } from "@repo/rdx-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AccessItemDTO, AccessResponseDTO, PersonDTO } from "../../../../common";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { EntityListHeader, EntityTable } from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { EntityListHeader, EntityTable } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { AccessHelpDialog } from "../../help";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EntityStatus } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { EntityStatus } from "@repo/rdx-ui/components/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AccessFieldsDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { SelectAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Checkbox } from "@repo/shadcn-ui/components/checkbox";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import type { SelectAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import type { ComponentType } from "react";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ResourceEditor } from "@metis/resources/client";
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CompanyDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { ApplicationConfigurationDTO } from "../../../../common";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { ApplicationHistoryDialog } from "../../history";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CompanyDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Checkbox } from "@repo/shadcn-ui/components/checkbox";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ResourceEditor } from "@metis/resources/client";
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CompanyDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { CertificateConfigurationDTO } from "../../../../common";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CertificateHistoryDialog } from "../../history";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { BrowserLink } from "@metis/core/client";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
BoxIcon,
|
||||
BriefcaseIcon,
|
||||
@ -11,7 +10,8 @@ import {
|
||||
MailIcon,
|
||||
MapPinIcon,
|
||||
UsersIcon,
|
||||
} from "@repo/shadcn-ui/lib/icons";
|
||||
} from "@repo/rdx-ui/lib/icons";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { companySectionHref } from "../../../workspace/shared/helpers";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { PersonForm } from "../../../people";
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { BrowserLink } from "@metis/core/client";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { companySectionHref } from "../../../workspace/shared/helpers";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Checkbox } from "@repo/shadcn-ui/components/checkbox";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { useId } from "react";
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { ButtonGroup } from "@repo/rdx-ui/components/button-group";
|
||||
import type { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ButtonGroup } from "@repo/shadcn-ui/components/button-group";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@ -7,7 +8,6 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@repo/shadcn-ui/components/select";
|
||||
import type { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { CompanyIdentity } from "./company-identity";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CompanyEditorDialog } from "../../../companies/shared/ui/company-editor-dialog";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { EntityTable } from "@repo/rdx-ui/components/entity-list";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { entityListLabels } from "@repo/rdx-ui/lib/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { EntityTable } from "@repo/shadcn-ui/components/entity-list";
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { entityListLabels } from "@repo/shadcn-ui/lib/entity-list";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { CompanyIdentity } from "../../../companies/shared/ui/company-identity";
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
TicketIcon,
|
||||
UsersIcon,
|
||||
WrenchIcon,
|
||||
} from "@repo/shadcn-ui/lib/icons";
|
||||
} from "@repo/rdx-ui/lib/icons";
|
||||
export const KIND_ICONS = {
|
||||
ticket: TicketIcon,
|
||||
intervention: WrenchIcon,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChevronRightIcon } from "@repo/rdx-ui/lib/icons";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ChevronRightIcon } from "@repo/shadcn-ui/lib/icons";
|
||||
import type { ReactNode } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ClockIcon } from "@repo/shadcn-ui/lib/icons";
|
||||
import { ClockIcon } from "@repo/rdx-ui/lib/icons";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
TriangleAlertIcon,
|
||||
UserRoundXIcon,
|
||||
UsersIcon,
|
||||
} from "@repo/shadcn-ui/lib/icons";
|
||||
} from "@repo/rdx-ui/lib/icons";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Building2Icon } from "@repo/shadcn-ui/lib/icons";
|
||||
import { Building2Icon } from "@repo/rdx-ui/lib/icons";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Building2Icon } from "@repo/rdx-ui/lib/icons";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Building2Icon } from "@repo/shadcn-ui/lib/icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { DashboardQuickCreate } from "../../create";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { StatisticCard } from "@repo/shadcn-ui/components/statistic-card";
|
||||
import { StatisticCard } from "@repo/rdx-ui/components/statistic-card";
|
||||
import {
|
||||
Building2Icon,
|
||||
DatabaseIcon,
|
||||
LaptopIcon,
|
||||
TicketIcon,
|
||||
WrenchIcon,
|
||||
} from "@repo/shadcn-ui/lib/icons";
|
||||
} from "@repo/rdx-ui/lib/icons";
|
||||
import type { UseQueryResult } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { TicketIcon } from "@repo/shadcn-ui/lib/icons";
|
||||
import { TicketIcon } from "@repo/rdx-ui/lib/icons";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { Checkbox } from "@repo/shadcn-ui/components/checkbox";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { useId } from "react";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { AccessResponseDTO, CompanyDTO, WorkProfileDTO } from "../../../../common";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type { FolderMappingDTO } from "../../../../common/folder-mappings";
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import {
|
||||
EntityAction,
|
||||
EntityListHeader,
|
||||
EntityRowActions,
|
||||
EntityStatus,
|
||||
EntityTable,
|
||||
} from "@repo/shadcn-ui/components/entity-list";
|
||||
} from "@repo/rdx-ui/components/entity-list";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { FolderMappingHistoryDialog } from "../../history";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FormDialog } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { FormDialog } from "@repo/rdx-ui/components/form-dialog";
|
||||
import type { ComponentProps } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ContextHelp } from "@repo/rdx-ui/components/context-help";
|
||||
import { FormActions } from "@repo/rdx-ui/components/form-dialog";
|
||||
import { SelectWithAction } from "@repo/rdx-ui/components/select-with-action";
|
||||
import { Button } from "@repo/shadcn-ui/components/button";
|
||||
import { ContextHelp } from "@repo/shadcn-ui/components/context-help";
|
||||
import { FormActions } from "@repo/shadcn-ui/components/form-dialog";
|
||||
import { Input } from "@repo/shadcn-ui/components/input";
|
||||
import { Label } from "@repo/shadcn-ui/components/label";
|
||||
import { SelectWithAction } from "@repo/shadcn-ui/components/select-with-action";
|
||||
import { Textarea } from "@repo/shadcn-ui/components/textarea";
|
||||
import { useId } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user