refactor(workspace-settings): extract useWorkspaceSetting hook
Deduplicate the "save a workspace setting" plumbing shared by HtmlEmbedSettings and TrackerSettings (workspace atom read, isLoading state, updateWorkspace + atom merge forcing settings[key], success/error notifications) into a new feature-scoped hook useWorkspaceSetting(key). - Each component keeps its own interaction model: html-embed is an optimistic toggle with revert-on-failure; tracker is edit-then-save on an explicit button. - Unify error handling on the better pattern: surface err.response?.data?.message and use console.error (html-embed previously used console.log + a generic message). No user-facing behavior change; client typecheck clean. Test-coverage follow-ups (untested trackerHead injection in ShareSeoController and the no-op audit branch) tracked in #100.
This commit is contained in:
@@ -87,9 +87,16 @@ export class ShareController {
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
// Resolve the identity name only when the assistant is enabled, so the
|
||||
// anonymous widget can label messages with the configured persona name.
|
||||
const aiAssistantName = aiAssistant
|
||||
? await this.aiSettings.resolvePublicShareAssistantName(workspace.id)
|
||||
: null;
|
||||
|
||||
return {
|
||||
...shareData,
|
||||
aiAssistant,
|
||||
aiAssistantName,
|
||||
features: this.licenseCheckService.resolveFeatures(
|
||||
workspace.licenseKey,
|
||||
workspace.plan,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { InjectQueue } from '@nestjs/bullmq';
|
||||
import { Queue } from 'bullmq';
|
||||
import { QueueName, QueueJob } from '../queue/constants';
|
||||
import { WorkspaceRepo } from '@docmost/db/repos/workspace/workspace.repo';
|
||||
import { AiAgentRoleRepo } from '@docmost/db/repos/ai-agent-roles/ai-agent-roles.repo';
|
||||
import { AiProviderCredentialsRepo } from '@docmost/db/repos/ai-chat/ai-provider-credentials.repo';
|
||||
import { PageEmbeddingRepo } from '@docmost/db/repos/ai-chat/page-embedding.repo';
|
||||
import { PageRepo } from '@docmost/db/repos/page/page.repo';
|
||||
@@ -49,6 +50,7 @@ export interface UpdateAiSettingsInput {
|
||||
export class AiSettingsService {
|
||||
constructor(
|
||||
private readonly workspaceRepo: WorkspaceRepo,
|
||||
private readonly aiAgentRoleRepo: AiAgentRoleRepo,
|
||||
private readonly aiProviderCredentialsRepo: AiProviderCredentialsRepo,
|
||||
private readonly pageEmbeddingRepo: PageEmbeddingRepo,
|
||||
private readonly pageRepo: PageRepo,
|
||||
@@ -110,6 +112,26 @@ export class AiSettingsService {
|
||||
return settings?.ai?.publicShareAssistant === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the display name of the agent role acting as the public-share
|
||||
* assistant's identity, so the anonymous widget can label messages with the
|
||||
* persona name instead of the generic "AI agent". Returns null when no role
|
||||
* is configured, or the referenced role is missing/disabled (built-in persona
|
||||
* → the client falls back to "AI agent"). Mirrors the role resolution in
|
||||
* PublicShareChatService.resolveShareRole.
|
||||
*/
|
||||
async resolvePublicShareAssistantName(
|
||||
workspaceId: string,
|
||||
): Promise<string | null> {
|
||||
const resolved = await this.resolve(workspaceId);
|
||||
const roleId = resolved?.publicShareAssistantRoleId;
|
||||
if (!roleId) return null;
|
||||
const role = await this.aiAgentRoleRepo.findById(roleId, workspaceId);
|
||||
if (!role || !role.enabled) return null;
|
||||
const name = role.name?.trim();
|
||||
return name ? name : null;
|
||||
}
|
||||
|
||||
/** Read the stored non-secret provider settings for a workspace. */
|
||||
private async readProvider(
|
||||
workspaceId: string,
|
||||
|
||||
Reference in New Issue
Block a user