- 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.
44 lines
1.8 KiB
TypeScript
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,
|
|
})
|
|
);
|
|
}
|
|
}
|