metis-desk/modules/resources/src/api/infrastructure/persistence/network-share-options.ts
David 0a34ddf752 feat: add local identity management features and UI components
- Implement folder account options helper for filtering access items based on person ID and date.
- Create FolderAccessAccountField component for selecting accounts with profile integration.
- Develop AssetLocalIdentities component for managing local identities associated with assets.
- Introduce LocalIdentityOwner component to display and manage local identity ownership.
- Add LocalIdentityEditor for creating, associating, and retiring local identities.
- Implement local identity API for fetching and executing local identity commands.
- Create tests for local identity UI components to ensure functionality and correctness.
- Add NetworkShareOptions class for structured and paginated SMB selection.
- Introduce NetworkShareAddress component for displaying and copying network share addresses.
- Create RemoteOptionList and RemoteOptionPicker components for remote option selection with pagination and search.
- Add tests for RemoteOptionList to validate rendering and behavior under various states.
2026-10-21 12:37:59 +02:00

44 lines
1.8 KiB
TypeScript

import type { RelationshipContext, RelationshipReadAccess } from "@metis/relationship-contracts";
import { Result } from "@repo/rdx-utils";
import type { Sequelize } from "sequelize";
import { QueryTypes } from "sequelize";
import type { z } from "zod/v4";
import type { NetworkShareOptionsQuerySchema } from "../../../common/network-shares";
import { NetworkShareOptionsSchema } from "../../../common/network-shares";
/** Selección SMB estructurada y paginada, sin descargar recursos o revisiones de la compañía. */
export class NetworkShareOptions {
constructor(
private readonly database: Sequelize,
private readonly access: RelationshipReadAccess
) {}
async list(query: z.infer<typeof NetworkShareOptionsQuerySchema>, context: RelationshipContext) {
const allowed = await this.access.authorize(context);
if (!allowed.isSuccess) {
return allowed;
}
const rows = await this.database.query<{ id: string; name: string; address: string }>(
`SELECT r.id,r.name,c.textValue AS address FROM resources r JOIN resource_network_shares s ON s.resourceId=r.id AND s.companyId=r.companyId JOIN resource_characteristics c ON c.resourceId=r.id JOIN resource_definitions f ON f.id=c.fieldId AND f.stockKey='field:unc' WHERE r.companyId=:companyId AND r.active=1 AND (:search = '' OR LOCATE(:search,r.name)>0 OR LOCATE(:search,c.textValue)>0) AND (:cursor IS NULL OR r.id>:cursor) ORDER BY r.id LIMIT 21`,
{
replacements: {
companyId: context.companyId,
search: query.search,
cursor: query.cursor ?? null,
},
type: QueryTypes.SELECT,
}
);
const items = rows.slice(0, 20);
return Result.ok(
NetworkShareOptionsSchema.parse({
items,
nextCursor: rows.length > 20 ? items.at(-1)?.id : null,
})
);
}
}