Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2272e4f247 | ||
|
|
f33973bc24 | ||
|
|
777a031fd2 | ||
|
|
06d8719e07 | ||
|
|
91b0937315 | ||
|
|
c30d4ea8f5 | ||
|
|
c5c77bed7d | ||
|
|
00e6f55c8d | ||
|
|
bbf875d21d | ||
|
|
99da104d94 |
@@ -70,6 +70,27 @@ export type AdminAiModels = {
|
||||
models: Array<AdminAiModelConfig>;
|
||||
};
|
||||
|
||||
export type AdminChatMessage = {
|
||||
__typename?: 'AdminChatMessage';
|
||||
createdAt: Scalars['DateTime'];
|
||||
id: Scalars['UUID'];
|
||||
parts: Array<AdminChatMessagePart>;
|
||||
role: Scalars['String'];
|
||||
};
|
||||
|
||||
export type AdminChatMessagePart = {
|
||||
__typename?: 'AdminChatMessagePart';
|
||||
textContent?: Maybe<Scalars['String']>;
|
||||
toolName?: Maybe<Scalars['String']>;
|
||||
type: Scalars['String'];
|
||||
};
|
||||
|
||||
export type AdminChatThreadMessages = {
|
||||
__typename?: 'AdminChatThreadMessages';
|
||||
messages: Array<AdminChatMessage>;
|
||||
thread: AdminWorkspaceChatThread;
|
||||
};
|
||||
|
||||
export type AdminPanelHealthServiceData = {
|
||||
__typename?: 'AdminPanelHealthServiceData';
|
||||
description: Scalars['String'];
|
||||
@@ -86,6 +107,25 @@ export enum AdminPanelHealthServiceStatus {
|
||||
OUTAGE = 'OUTAGE'
|
||||
}
|
||||
|
||||
export type AdminPanelRecentUser = {
|
||||
__typename?: 'AdminPanelRecentUser';
|
||||
createdAt: Scalars['DateTime'];
|
||||
email: Scalars['String'];
|
||||
firstName?: Maybe<Scalars['String']>;
|
||||
id: Scalars['UUID'];
|
||||
lastName?: Maybe<Scalars['String']>;
|
||||
workspaceId?: Maybe<Scalars['UUID']>;
|
||||
workspaceName?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type AdminPanelTopWorkspace = {
|
||||
__typename?: 'AdminPanelTopWorkspace';
|
||||
id: Scalars['UUID'];
|
||||
name: Scalars['String'];
|
||||
subdomain: Scalars['String'];
|
||||
totalUsers: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type AdminPanelWorkerQueueHealth = {
|
||||
__typename?: 'AdminPanelWorkerQueueHealth';
|
||||
id: Scalars['String'];
|
||||
@@ -93,6 +133,17 @@ export type AdminPanelWorkerQueueHealth = {
|
||||
status: AdminPanelHealthServiceStatus;
|
||||
};
|
||||
|
||||
export type AdminWorkspaceChatThread = {
|
||||
__typename?: 'AdminWorkspaceChatThread';
|
||||
conversationSize: Scalars['Int'];
|
||||
createdAt: Scalars['DateTime'];
|
||||
id: Scalars['UUID'];
|
||||
title?: Maybe<Scalars['String']>;
|
||||
totalInputTokens: Scalars['Int'];
|
||||
totalOutputTokens: Scalars['Int'];
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
|
||||
export type Agent = {
|
||||
__typename?: 'Agent';
|
||||
applicationId?: Maybe<Scalars['UUID']>;
|
||||
@@ -4314,6 +4365,8 @@ export type PublicWorkspaceData = {
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
adminPanelRecentUsers: Array<AdminPanelRecentUser>;
|
||||
adminPanelTopWorkspaces: Array<AdminPanelTopWorkspace>;
|
||||
agentTurns: Array<AgentTurn>;
|
||||
apiKey?: Maybe<ApiKey>;
|
||||
apiKeys: Array<ApiKey>;
|
||||
@@ -4362,6 +4415,8 @@ export type Query = {
|
||||
getAddressDetails: PlaceDetailsResult;
|
||||
getAdminAiModels: AdminAiModels;
|
||||
getAdminAiUsageByWorkspace: Array<UsageBreakdownItem>;
|
||||
getAdminChatThreadMessages: AdminChatThreadMessages;
|
||||
getAdminWorkspaceChatThreads: Array<AdminWorkspaceChatThread>;
|
||||
getAiProviders: Scalars['JSON'];
|
||||
getApprovedAccessDomains: Array<ApprovedAccessDomain>;
|
||||
getAutoCompleteAddress: Array<AutocompleteResult>;
|
||||
@@ -4427,6 +4482,17 @@ export type Query = {
|
||||
versionInfo: VersionInfo;
|
||||
webhook?: Maybe<Webhook>;
|
||||
webhooks: Array<Webhook>;
|
||||
workspaceLookupAdminPanel: UserLookup;
|
||||
};
|
||||
|
||||
|
||||
export type QueryAdminPanelRecentUsersArgs = {
|
||||
searchTerm?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryAdminPanelTopWorkspacesArgs = {
|
||||
searchTerm?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
@@ -4592,6 +4658,17 @@ export type QueryGetAdminAiUsageByWorkspaceArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryGetAdminChatThreadMessagesArgs = {
|
||||
threadId: Scalars['String'];
|
||||
workspaceId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryGetAdminWorkspaceChatThreadsArgs = {
|
||||
workspaceId: Scalars['String'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryGetAutoCompleteAddressArgs = {
|
||||
address: Scalars['String'];
|
||||
country?: InputMaybe<Scalars['String']>;
|
||||
@@ -4827,6 +4904,11 @@ export type QueryWebhookArgs = {
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryWorkspaceLookupAdminPanelArgs = {
|
||||
workspaceId: Scalars['String'];
|
||||
};
|
||||
|
||||
export type QueueJob = {
|
||||
__typename?: 'QueueJob';
|
||||
attemptsMade: Scalars['Float'];
|
||||
@@ -5850,6 +5932,7 @@ export type User = {
|
||||
|
||||
export type UserInfo = {
|
||||
__typename?: 'UserInfo';
|
||||
createdAt: Scalars['DateTime'];
|
||||
email: Scalars['String'];
|
||||
firstName?: Maybe<Scalars['String']>;
|
||||
id: Scalars['UUID'];
|
||||
@@ -6258,7 +6341,9 @@ export enum WorkspaceActivationStatus {
|
||||
|
||||
export type WorkspaceInfo = {
|
||||
__typename?: 'WorkspaceInfo';
|
||||
activationStatus: WorkspaceActivationStatus;
|
||||
allowImpersonation: Scalars['Boolean'];
|
||||
createdAt: Scalars['DateTime'];
|
||||
featureFlags: Array<FeatureFlag>;
|
||||
id: Scalars['UUID'];
|
||||
logo?: Maybe<Scalars['String']>;
|
||||
@@ -7381,13 +7466,49 @@ export type UserLookupAdminPanelMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UserLookupAdminPanelMutation = { __typename?: 'Mutation', userLookupAdminPanel: { __typename?: 'UserLookup', user: { __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }, workspaces: Array<{ __typename?: 'WorkspaceInfo', id: string, name: string, logo?: string | null, totalUsers: number, allowImpersonation: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', customUrl?: string | null, subdomainUrl: string }, users: Array<{ __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }>, featureFlags: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> }> } };
|
||||
export type UserLookupAdminPanelMutation = { __typename?: 'Mutation', userLookupAdminPanel: { __typename?: 'UserLookup', user: { __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null, createdAt: string }, workspaces: Array<{ __typename?: 'WorkspaceInfo', id: string, name: string, logo?: string | null, totalUsers: number, activationStatus: WorkspaceActivationStatus, createdAt: string, allowImpersonation: boolean, workspaceUrls: { __typename?: 'WorkspaceUrls', customUrl?: string | null, subdomainUrl: string }, users: Array<{ __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }>, featureFlags: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> }> } };
|
||||
|
||||
export type AdminPanelRecentUsersQueryVariables = Exact<{
|
||||
searchTerm?: InputMaybe<Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type AdminPanelRecentUsersQuery = { __typename?: 'Query', adminPanelRecentUsers: Array<{ __typename?: 'AdminPanelRecentUser', id: string, email: string, firstName?: string | null, lastName?: string | null, createdAt: string, workspaceName?: string | null, workspaceId?: string | null }> };
|
||||
|
||||
export type AdminPanelTopWorkspacesQueryVariables = Exact<{
|
||||
searchTerm?: InputMaybe<Scalars['String']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type AdminPanelTopWorkspacesQuery = { __typename?: 'Query', adminPanelTopWorkspaces: Array<{ __typename?: 'AdminPanelTopWorkspace', id: string, name: string, totalUsers: number, subdomain: string }> };
|
||||
|
||||
export type GetAdminChatThreadMessagesQueryVariables = Exact<{
|
||||
workspaceId: Scalars['String'];
|
||||
threadId: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type GetAdminChatThreadMessagesQuery = { __typename?: 'Query', getAdminChatThreadMessages: { __typename?: 'AdminChatThreadMessages', thread: { __typename?: 'AdminWorkspaceChatThread', id: string, title?: string | null, totalInputTokens: number, totalOutputTokens: number, conversationSize: number, createdAt: string, updatedAt: string }, messages: Array<{ __typename?: 'AdminChatMessage', id: string, role: string, createdAt: string, parts: Array<{ __typename?: 'AdminChatMessagePart', type: string, textContent?: string | null, toolName?: string | null }> }> } };
|
||||
|
||||
export type GetAdminWorkspaceChatThreadsQueryVariables = Exact<{
|
||||
workspaceId: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type GetAdminWorkspaceChatThreadsQuery = { __typename?: 'Query', getAdminWorkspaceChatThreads: Array<{ __typename?: 'AdminWorkspaceChatThread', id: string, title?: string | null, totalInputTokens: number, totalOutputTokens: number, conversationSize: number, createdAt: string, updatedAt: string }> };
|
||||
|
||||
export type GetVersionInfoQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetVersionInfoQuery = { __typename?: 'Query', versionInfo: { __typename?: 'VersionInfo', currentVersion?: string | null, latestVersion: string } };
|
||||
|
||||
export type WorkspaceLookupAdminPanelQueryVariables = Exact<{
|
||||
workspaceId: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type WorkspaceLookupAdminPanelQuery = { __typename?: 'Query', workspaceLookupAdminPanel: { __typename?: 'UserLookup', user: { __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null, createdAt: string }, workspaces: Array<{ __typename?: 'WorkspaceInfo', id: string, name: string, allowImpersonation: boolean, logo?: string | null, totalUsers: number, activationStatus: WorkspaceActivationStatus, createdAt: string, workspaceUrls: { __typename?: 'WorkspaceUrls', customUrl?: string | null, subdomainUrl: string }, users: Array<{ __typename?: 'UserInfo', id: string, email: string, firstName?: string | null, lastName?: string | null }>, featureFlags: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> }> } };
|
||||
|
||||
export type DeleteJobsMutationVariables = Exact<{
|
||||
queueName: Scalars['String'];
|
||||
jobIds: Array<Scalars['String']> | Scalars['String'];
|
||||
@@ -8562,8 +8683,13 @@ export const UpdateDatabaseConfigVariableDocument = {"kind":"Document","definiti
|
||||
export const GetConfigVariablesGroupedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetConfigVariablesGrouped"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getConfigVariablesGrouped"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"groups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"isHiddenOnLoad"}},{"kind":"Field","name":{"kind":"Name","value":"variables"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"isSensitive"}},{"kind":"Field","name":{"kind":"Name","value":"isEnvOnly"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"source"}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetConfigVariablesGroupedQuery, GetConfigVariablesGroupedQueryVariables>;
|
||||
export const GetDatabaseConfigVariableDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetDatabaseConfigVariable"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"key"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getDatabaseConfigVariable"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"key"},"value":{"kind":"Variable","name":{"kind":"Name","value":"key"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"isSensitive"}},{"kind":"Field","name":{"kind":"Name","value":"isEnvOnly"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"source"}}]}}]}}]} as unknown as DocumentNode<GetDatabaseConfigVariableQuery, GetDatabaseConfigVariableQueryVariables>;
|
||||
export const UpdateWorkspaceFeatureFlagDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspaceFeatureFlag"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"featureFlag"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"value"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateWorkspaceFeatureFlag"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"featureFlag"},"value":{"kind":"Variable","name":{"kind":"Name","value":"featureFlag"}}},{"kind":"Argument","name":{"kind":"Name","value":"value"},"value":{"kind":"Variable","name":{"kind":"Name","value":"value"}}}]}]}}]} as unknown as DocumentNode<UpdateWorkspaceFeatureFlagMutation, UpdateWorkspaceFeatureFlagMutationVariables>;
|
||||
export const UserLookupAdminPanelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UserLookupAdminPanel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userIdentifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userLookupAdminPanel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userIdentifier"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userIdentifier"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}}]}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"totalUsers"}},{"kind":"Field","name":{"kind":"Name","value":"allowImpersonation"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceUrls"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customUrl"}},{"kind":"Field","name":{"kind":"Name","value":"subdomainUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}}]}},{"kind":"Field","name":{"kind":"Name","value":"featureFlags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]}}]} as unknown as DocumentNode<UserLookupAdminPanelMutation, UserLookupAdminPanelMutationVariables>;
|
||||
export const UserLookupAdminPanelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UserLookupAdminPanel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userIdentifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userLookupAdminPanel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userIdentifier"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userIdentifier"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"totalUsers"}},{"kind":"Field","name":{"kind":"Name","value":"activationStatus"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"allowImpersonation"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceUrls"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customUrl"}},{"kind":"Field","name":{"kind":"Name","value":"subdomainUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}}]}},{"kind":"Field","name":{"kind":"Name","value":"featureFlags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]}}]} as unknown as DocumentNode<UserLookupAdminPanelMutation, UserLookupAdminPanelMutationVariables>;
|
||||
export const AdminPanelRecentUsersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AdminPanelRecentUsers"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"searchTerm"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminPanelRecentUsers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"searchTerm"},"value":{"kind":"Variable","name":{"kind":"Name","value":"searchTerm"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceName"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]}}]} as unknown as DocumentNode<AdminPanelRecentUsersQuery, AdminPanelRecentUsersQueryVariables>;
|
||||
export const AdminPanelTopWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AdminPanelTopWorkspaces"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"searchTerm"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminPanelTopWorkspaces"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"searchTerm"},"value":{"kind":"Variable","name":{"kind":"Name","value":"searchTerm"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"totalUsers"}},{"kind":"Field","name":{"kind":"Name","value":"subdomain"}}]}}]}}]} as unknown as DocumentNode<AdminPanelTopWorkspacesQuery, AdminPanelTopWorkspacesQueryVariables>;
|
||||
export const GetAdminChatThreadMessagesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAdminChatThreadMessages"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAdminChatThreadMessages"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"threadId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"threadId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"thread"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"totalInputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"totalOutputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"conversationSize"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"Field","name":{"kind":"Name","value":"messages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"parts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"textContent"}},{"kind":"Field","name":{"kind":"Name","value":"toolName"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode<GetAdminChatThreadMessagesQuery, GetAdminChatThreadMessagesQueryVariables>;
|
||||
export const GetAdminWorkspaceChatThreadsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAdminWorkspaceChatThreads"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getAdminWorkspaceChatThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"totalInputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"totalOutputTokens"}},{"kind":"Field","name":{"kind":"Name","value":"conversationSize"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<GetAdminWorkspaceChatThreadsQuery, GetAdminWorkspaceChatThreadsQueryVariables>;
|
||||
export const GetVersionInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetVersionInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"currentVersion"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}}]}}]}}]} as unknown as DocumentNode<GetVersionInfoQuery, GetVersionInfoQueryVariables>;
|
||||
export const WorkspaceLookupAdminPanelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkspaceLookupAdminPanel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceLookupAdminPanel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"allowImpersonation"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"totalUsers"}},{"kind":"Field","name":{"kind":"Name","value":"activationStatus"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceUrls"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customUrl"}},{"kind":"Field","name":{"kind":"Name","value":"subdomainUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"users"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"firstName"}},{"kind":"Field","name":{"kind":"Name","value":"lastName"}}]}},{"kind":"Field","name":{"kind":"Name","value":"featureFlags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]}}]}}]} as unknown as DocumentNode<WorkspaceLookupAdminPanelQuery, WorkspaceLookupAdminPanelQueryVariables>;
|
||||
export const DeleteJobsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteJobs"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"jobIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteJobs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"queueName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}}},{"kind":"Argument","name":{"kind":"Name","value":"jobIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"jobIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deletedCount"}},{"kind":"Field","name":{"kind":"Name","value":"results"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jobId"}},{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]}}]} as unknown as DocumentNode<DeleteJobsMutation, DeleteJobsMutationVariables>;
|
||||
export const RetryJobsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RetryJobs"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"jobIds"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"retryJobs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"queueName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}}},{"kind":"Argument","name":{"kind":"Name","value":"jobIds"},"value":{"kind":"Variable","name":{"kind":"Name","value":"jobIds"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"retriedCount"}},{"kind":"Field","name":{"kind":"Name","value":"results"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jobId"}},{"kind":"Field","name":{"kind":"Name","value":"success"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]}}]} as unknown as DocumentNode<RetryJobsMutation, RetryJobsMutationVariables>;
|
||||
export const GetIndicatorHealthStatusDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetIndicatorHealthStatus"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"indicatorId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"HealthIndicatorId"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getIndicatorHealthStatus"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"indicatorId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"indicatorId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"errorMessage"}},{"kind":"Field","name":{"kind":"Name","value":"details"}},{"kind":"Field","name":{"kind":"Name","value":"queues"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"queueName"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]} as unknown as DocumentNode<GetIndicatorHealthStatusQuery, GetIndicatorHealthStatusQueryVariables>;
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Geniet 'n 30-dae gratis proeflopie"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Voer 'n JSON-voorwerp in"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "استمتع بفترة تجريبية مجانية لمدة 30 يومً
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "أدخل كائن JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Gaudiu d'una prova gratuïta de 30 dies"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Introdueix un objecte JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Využijte 30denní bezplatnou zkušební verzi"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Zadejte objekt JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Få en 30-dages gratis prøveperiode"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Indtast et JSON-objekt"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Genießen Sie eine 30-tägige kostenlose Testphase"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Geben Sie ein JSON-Objekt ein"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Απολαύστε μια δωρεάν δοκιμή 30 ημερών"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Εισάγετε ένα αντικείμενο JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5616,11 +5616,6 @@ msgstr "Enjoy a 30-day free trial"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Enter a JSON object"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr "Enter a new secret value"
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Disfruta de una prueba gratuita de 30 días"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Introduce un objeto JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Nauti 30 päivän ilmaisesta kokeilusta"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Anna JSON-objekti"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Profitez d'un essai gratuit de 30 jours"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Saisissez un objet JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5621,11 +5621,6 @@ msgstr "התחל תקופת ניסיון חינם ל-30 יום"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "הזן אובייקט JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Élvezze a 30 napos ingyenes próbaidőszakot"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Adjon meg egy JSON objektumot"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Approfitta di una prova gratuita di 30 giorni"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Inserisci un oggetto JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "30 日間の無料トライアルをご利用ください"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "JSON オブジェクトを入力"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "30일 무료 체험을 이용해 보세요"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "JSON 객체를 입력하세요"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Profiteer van een gratis proefperiode van 30 dagen"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Voer een JSON-object in"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Få en 30-dagers gratis prøveperiode"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Skriv inn et JSON-objekt"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Skorzystaj z 30-dniowego bezpłatnego okresu próbnego"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Wprowadź obiekt JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5616,11 +5616,6 @@ msgstr ""
|
||||
msgid "Enter a JSON object"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Aproveite um teste gratuito de 30 dias"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Insira um objeto JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Aproveite uma avaliação gratuita de 30 dias"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Introduza um objeto JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Bucurați-vă de o perioadă de probă gratuită de 30 de zile"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Introduceți un obiect JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
Binary file not shown.
@@ -5621,11 +5621,6 @@ msgstr "Уживајте у 30-дневном бесплатном пробно
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Унесите JSON објекат"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Prova gratis i 30 dagar"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Ange ett JSON-objekt"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "30 günlük ücretsiz denemeden yararlanın"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Bir JSON nesnesi girin"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Скористайтеся 30-денним безкоштовним пр
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Введіть об’єкт JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "Tận hưởng bản dùng thử miễn phí 30 ngày"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "Nhập một đối tượng JSON"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "享受 30 天免费试用"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "输入 JSON 对象"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -5621,11 +5621,6 @@ msgstr "享有 30 天免費試用"
|
||||
msgid "Enter a JSON object"
|
||||
msgstr "輸入 JSON 物件"
|
||||
|
||||
#. js-lingui-id: peBb6B
|
||||
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableValueInput.tsx
|
||||
msgid "Enter a new secret value"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: u2fAme
|
||||
#: src/modules/object-record/record-field/ui/form-types/components/FormNumberFieldInput.tsx
|
||||
msgid "Enter a number"
|
||||
|
||||
@@ -4,13 +4,12 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AIChatSuggestedPrompts } from '@/ai/components/suggested-prompts/AIChatSuggestedPrompts';
|
||||
import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { agentChatErrorState } from '@/ai/states/agentChatErrorState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSkeletonUntilLoadedState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
@@ -27,11 +26,7 @@ type AIChatEmptyStateProps = {
|
||||
};
|
||||
|
||||
export const AIChatEmptyState = ({ editor }: AIChatEmptyStateProps) => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
const agentChatError = useAtomStateValue(agentChatErrorState);
|
||||
const agentChatThreadsLoading = useAtomStateValue(
|
||||
agentChatThreadsLoadingState,
|
||||
);
|
||||
@@ -41,6 +36,7 @@ export const AIChatEmptyState = ({ editor }: AIChatEmptyStateProps) => {
|
||||
const skipMessagesSkeletonUntilLoaded = useAtomStateValue(
|
||||
skipMessagesSkeletonUntilLoadedState,
|
||||
);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
|
||||
const hasMessages = useAtomComponentSelectorValue(
|
||||
agentChatHasMessageComponentSelector,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
|
||||
import { AgentMessageRole } from '@/ai/constants/AgentMessageRole';
|
||||
import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThreadState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { agentChatErrorState } from '@/ai/states/agentChatErrorState';
|
||||
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
|
||||
import { agentChatMessageComponentFamilySelector } from '@/ai/states/agentChatMessageComponentFamilySelector';
|
||||
import { agentChatMessageIdsComponentSelector } from '@/ai/states/agentChatMessageIdsComponentSelector';
|
||||
import { useAtomComponentFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilySelectorValue';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
@@ -17,17 +15,8 @@ const StyledErrorWrapper = styled.div`
|
||||
`;
|
||||
|
||||
export const AIChatErrorUnderMessageList = () => {
|
||||
const agentChatDisplayedThread = useAtomStateValue(
|
||||
agentChatDisplayedThreadState,
|
||||
);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: agentChatDisplayedThread },
|
||||
);
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: agentChatDisplayedThread },
|
||||
);
|
||||
const agentChatError = useAtomStateValue(agentChatErrorState);
|
||||
const agentChatIsStreaming = useAtomStateValue(agentChatIsStreamingState);
|
||||
|
||||
const agentChatMessageIds = useAtomComponentSelectorValue(
|
||||
agentChatMessageIdsComponentSelector,
|
||||
|
||||
+4
-15
@@ -1,9 +1,7 @@
|
||||
import { AIChatMessage } from '@/ai/components/AIChatMessage';
|
||||
import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThreadState';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { agentChatErrorState } from '@/ai/states/agentChatErrorState';
|
||||
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
|
||||
import { agentChatLastMessageIdComponentSelector } from '@/ai/states/agentChatLastMessageIdComponentSelector';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -13,17 +11,8 @@ export const AIChatLastMessageWithStreamingState = () => {
|
||||
agentChatLastMessageIdComponentSelector,
|
||||
);
|
||||
|
||||
const agentChatDisplayedThread = useAtomStateValue(
|
||||
agentChatDisplayedThreadState,
|
||||
);
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: agentChatDisplayedThread },
|
||||
);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: agentChatDisplayedThread },
|
||||
);
|
||||
const agentChatIsStreaming = useAtomStateValue(agentChatIsStreamingState);
|
||||
const agentChatError = useAtomStateValue(agentChatErrorState);
|
||||
|
||||
if (!isDefined(lastMessageId)) {
|
||||
return null;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { AIChatErrorRenderer } from '@/ai/components/AIChatErrorRenderer';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatErrorState } from '@/ai/states/agentChatErrorState';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -20,11 +18,7 @@ const StyledErrorContainer = styled.div`
|
||||
export const AIChatStandaloneError = () => {
|
||||
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const agentChatError = useAtomComponentFamilyStateValue(
|
||||
agentChatErrorComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
const agentChatError = useAtomStateValue(agentChatErrorState);
|
||||
|
||||
const hasMessages = useAtomComponentSelectorValue(
|
||||
agentChatHasMessageComponentSelector,
|
||||
|
||||
@@ -4,8 +4,8 @@ import { type AgentChatSubscriptionEvent } from 'twenty-shared/ai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AGENT_CHAT_REFETCH_MESSAGES_EVENT_NAME } from '@/ai/constants/AgentChatRefetchMessagesEventName';
|
||||
import { agentChatFirstLiveSeqComponentFamilyState } from '@/ai/states/agentChatFirstLiveSeqComponentFamilyState';
|
||||
import { agentChatHandleEventCallbackComponentFamilyState } from '@/ai/states/agentChatHandleEventCallbackComponentFamilyState';
|
||||
import { agentChatFirstLiveSeqState } from '@/ai/states/agentChatFirstLiveSeqState';
|
||||
import { agentChatHandleEventCallbackState } from '@/ai/states/agentChatHandleEventCallbackState';
|
||||
import { AGENT_CHAT_NEW_THREAD_DRAFT_KEY } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatFetchedMessagesComponentFamilyState } from '@/ai/states/agentChatFetchedMessagesComponentFamilyState';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
@@ -15,7 +15,6 @@ import { skipMessagesSkeletonUntilLoadedState } from '@/ai/states/skipMessagesSk
|
||||
import { mapDBMessagesToUIMessages } from '@/ai/utils/mapDBMessagesToUIMessages';
|
||||
import { useQueryWithCallbacks } from '@/apollo/hooks/useQueryWithCallbacks';
|
||||
import { useListenToBrowserEvent } from '@/browser-event/hooks/useListenToBrowserEvent';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomComponentFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentFamilyState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
@@ -53,14 +52,6 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
|
||||
const handleEventCallbackFamilyCallback =
|
||||
useAtomComponentFamilyStateCallbackState(
|
||||
agentChatHandleEventCallbackComponentFamilyState,
|
||||
);
|
||||
const firstLiveSeqFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatFirstLiveSeqComponentFamilyState,
|
||||
);
|
||||
|
||||
const handleFirstLoad = useCallback(
|
||||
(_data: GetChatMessagesQuery) => {
|
||||
setSkipMessagesSkeletonUntilLoaded(false);
|
||||
@@ -84,23 +75,13 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const threadId = store.get(currentAIChatThreadState.atom);
|
||||
|
||||
if (!isDefined(threadId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const familyKey = { threadId };
|
||||
|
||||
const handleEvent = store.get(
|
||||
handleEventCallbackFamilyCallback(familyKey),
|
||||
);
|
||||
const handleEvent = store.get(agentChatHandleEventCallbackState.atom);
|
||||
|
||||
if (!isDefined(handleEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstLiveSeq = store.get(firstLiveSeqFamilyCallback(familyKey));
|
||||
const firstLiveSeq = store.get(agentChatFirstLiveSeqState.atom);
|
||||
|
||||
for (let index = 0; index < catchup.chunks.length; index++) {
|
||||
const chunkSeq = index + 1;
|
||||
@@ -116,13 +97,7 @@ export const AgentChatMessagesFetchEffect = () => {
|
||||
} as AgentChatSubscriptionEvent);
|
||||
}
|
||||
},
|
||||
[
|
||||
setAgentChatFetchedMessages,
|
||||
setAgentChatQueuedMessages,
|
||||
store,
|
||||
handleEventCallbackFamilyCallback,
|
||||
firstLiveSeqFamilyCallback,
|
||||
],
|
||||
[setAgentChatFetchedMessages, setAgentChatQueuedMessages, store],
|
||||
);
|
||||
|
||||
const handleLoadingChange = useCallback(
|
||||
|
||||
+2
-5
@@ -11,7 +11,7 @@ import { agentChatDisplayedThreadState } from '@/ai/states/agentChatDisplayedThr
|
||||
import { agentChatFetchedMessagesComponentFamilyState } from '@/ai/states/agentChatFetchedMessagesComponentFamilyState';
|
||||
import { agentChatIsInitialScrollPendingOnThreadChangeState } from '@/ai/states/agentChatIsInitialScrollPendingOnThreadChangeState';
|
||||
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { agentChatMessagesLoadingState } from '@/ai/states/agentChatMessagesLoadingState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
@@ -57,10 +57,7 @@ export const AgentChatStreamSubscriptionEffect = () => {
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
const agentChatIsStreaming = useAtomStateValue(agentChatIsStreamingState);
|
||||
|
||||
const agentChatDisplayedThread = useAtomStateValue(
|
||||
agentChatDisplayedThreadState,
|
||||
|
||||
+12
-20
@@ -9,16 +9,15 @@ import {
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatThreadsLoadingState } from '@/ai/states/agentChatThreadsLoadingState';
|
||||
import { agentChatThreadsSelector } from '@/ai/states/agentChatThreadsSelector';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { agentChatUsageState } from '@/ai/states/agentChatUsageState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState';
|
||||
import { hasInitializedAgentChatThreadsState } from '@/ai/states/hasInitializedAgentChatThreadsState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { useUpdateMetadataStoreDraft } from '@/metadata-store/hooks/useUpdateMetadataStoreDraft';
|
||||
import { metadataStoreState } from '@/metadata-store/states/metadataStoreState';
|
||||
import { type FlatAgentChatThread } from '@/metadata-store/types/FlatAgentChatThread';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
@@ -38,15 +37,13 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const setCurrentAIChatThread = useSetAtomState(currentAIChatThreadState);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatUsage = useSetAtomState(agentChatUsageState);
|
||||
const setCurrentAIChatThreadTitle = useSetAtomState(
|
||||
currentAIChatThreadTitleState,
|
||||
);
|
||||
const setAgentChatThreadsLoading = useSetAtomState(
|
||||
agentChatThreadsLoadingState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
const agentChatUsageFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatUsageComponentFamilyState,
|
||||
);
|
||||
const store = useStore();
|
||||
const agentChatThreads = useAtomStateValue(agentChatThreadsSelector);
|
||||
const storeEntry = useAtomValue(
|
||||
@@ -116,20 +113,13 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
|
||||
setCurrentAIChatThread(firstThread.id);
|
||||
setAgentChatInput(draftForThread);
|
||||
|
||||
const firstThreadFamilyKey = { threadId: firstThread.id };
|
||||
|
||||
store.set(
|
||||
threadTitleFamilyCallback(firstThreadFamilyKey),
|
||||
firstThread.title ?? null,
|
||||
);
|
||||
setCurrentAIChatThreadTitle(firstThread.title ?? null);
|
||||
|
||||
const hasUsageData =
|
||||
(firstThread.conversationSize ?? 0) > 0 &&
|
||||
isDefined(firstThread.contextWindowTokens);
|
||||
|
||||
store.set(
|
||||
agentChatUsageFamilyCallback(firstThreadFamilyKey),
|
||||
setAgentChatUsage(
|
||||
hasUsageData
|
||||
? {
|
||||
lastMessage: null,
|
||||
@@ -150,6 +140,8 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
AGENT_CHAT_NEW_THREAD_DRAFT_KEY
|
||||
] ?? '',
|
||||
);
|
||||
setCurrentAIChatThreadTitle(null);
|
||||
setAgentChatUsage(null);
|
||||
}
|
||||
}, [
|
||||
agentChatThreads,
|
||||
@@ -160,9 +152,9 @@ export const AgentChatThreadInitializationEffect = () => {
|
||||
storeEntry.status,
|
||||
setCurrentAIChatThread,
|
||||
setAgentChatInput,
|
||||
setCurrentAIChatThreadTitle,
|
||||
setAgentChatUsage,
|
||||
store,
|
||||
threadTitleFamilyCallback,
|
||||
agentChatUsageFamilyCallback,
|
||||
]);
|
||||
|
||||
return null;
|
||||
|
||||
+3
-9
@@ -10,13 +10,11 @@ import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { ContextUsageProgressRing } from '@/ai/components/internal/ContextUsageProgressRing';
|
||||
import { agentChatHasMessageComponentSelector } from '@/ai/states/agentChatHasMessageComponentSelector';
|
||||
import {
|
||||
agentChatUsageComponentFamilyState,
|
||||
agentChatUsageState,
|
||||
type AgentChatLastMessageUsage,
|
||||
} from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
} from '@/ai/states/agentChatUsageState';
|
||||
import { SettingsBillingLabelValueItem } from '@/settings/billing/components/internal/SettingsBillingLabelValueItem';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { formatNumber } from '~/utils/format/formatNumber';
|
||||
@@ -96,11 +94,7 @@ const getCachedLabel = (lastMessage: AgentChatLastMessageUsage): string => {
|
||||
export const AIChatContextUsageButton = () => {
|
||||
const { t } = useLingui();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const agentChatUsage = useAtomComponentFamilyStateValue(
|
||||
agentChatUsageComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
const agentChatUsage = useAtomStateValue(agentChatUsageState);
|
||||
const billing = useAtomStateValue(billingState);
|
||||
const isBillingEnabled = billing?.isBillingEnabled ?? false;
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { AGENT_CHAT_STOP_EVENT_NAME } from '@/ai/constants/AgentChatStopEventName';
|
||||
import { agentChatInputIsEmptySelector } from '@/ai/states/agentChatInputIsEmptySelector';
|
||||
import { agentChatIsLoadingState } from '@/ai/states/agentChatIsLoadingState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
|
||||
import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent';
|
||||
import { useAtomComponentFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { IconArrowUp, IconPlayerStop } from 'twenty-ui/display';
|
||||
import { RoundedIconButton } from 'twenty-ui/input';
|
||||
@@ -20,11 +18,7 @@ export const SendMessageButton = ({ onSend }: SendMessageButtonProps) => {
|
||||
|
||||
const agentChatIsLoading = useAtomStateValue(agentChatIsLoadingState);
|
||||
|
||||
const currentAIChatThread = useAtomStateValue(currentAIChatThreadState);
|
||||
const agentChatIsStreaming = useAtomComponentFamilyStateValue(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
{ threadId: currentAIChatThread },
|
||||
);
|
||||
const agentChatIsStreaming = useAtomStateValue(agentChatIsStreamingState);
|
||||
|
||||
const handleStopClick = () => {
|
||||
dispatchBrowserEvent(AGENT_CHAT_STOP_EVENT_NAME);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { agentChatDraftsByThreadIdState } from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { agentChatUsageState } from '@/ai/states/agentChatUsageState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState';
|
||||
import { threadIdCreatedFromDraftState } from '@/ai/states/threadIdCreatedFromDraftState';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { useStore } from 'jotai';
|
||||
@@ -27,15 +26,13 @@ export const useAIChatThreadClick = (
|
||||
currentAIChatThreadState,
|
||||
);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setCurrentAIChatThreadTitle = useSetAtomState(
|
||||
currentAIChatThreadTitleState,
|
||||
);
|
||||
const setAgentChatUsage = useSetAtomState(agentChatUsageState);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
agentChatDraftsByThreadIdState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
const agentChatUsageFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatUsageComponentFamilyState,
|
||||
);
|
||||
const store = useStore();
|
||||
const { openAskAIPage } = useOpenAskAIPageInSidePanel();
|
||||
|
||||
@@ -57,18 +54,12 @@ export const useAIChatThreadClick = (
|
||||
setAgentChatInput(newDraft);
|
||||
}
|
||||
|
||||
const clickedFamilyKey = { threadId: thread.id };
|
||||
|
||||
store.set(
|
||||
threadTitleFamilyCallback(clickedFamilyKey),
|
||||
thread.title ?? null,
|
||||
);
|
||||
setCurrentAIChatThreadTitle(thread.title ?? null);
|
||||
|
||||
const hasUsageData =
|
||||
(thread.conversationSize ?? 0) > 0 &&
|
||||
isDefined(thread.contextWindowTokens);
|
||||
store.set(
|
||||
agentChatUsageFamilyCallback(clickedFamilyKey),
|
||||
setAgentChatUsage(
|
||||
hasUsageData
|
||||
? {
|
||||
lastMessage: null,
|
||||
|
||||
@@ -10,17 +10,17 @@ import {
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { AGENT_CHAT_INSTANCE_ID } from '@/ai/constants/AgentChatInstanceId';
|
||||
import { AGENT_CHAT_REFETCH_MESSAGES_EVENT_NAME } from '@/ai/constants/AgentChatRefetchMessagesEventName';
|
||||
import { ON_AGENT_CHAT_EVENT } from '@/ai/graphql/subscriptions/OnAgentChatEvent';
|
||||
import { agentChatErrorComponentFamilyState } from '@/ai/states/agentChatErrorComponentFamilyState';
|
||||
import { agentChatFirstLiveSeqComponentFamilyState } from '@/ai/states/agentChatFirstLiveSeqComponentFamilyState';
|
||||
import { agentChatHandleEventCallbackComponentFamilyState } from '@/ai/states/agentChatHandleEventCallbackComponentFamilyState';
|
||||
import { agentChatIsStreamingComponentFamilyState } from '@/ai/states/agentChatIsStreamingComponentFamilyState';
|
||||
import { agentChatErrorState } from '@/ai/states/agentChatErrorState';
|
||||
import { agentChatFirstLiveSeqState } from '@/ai/states/agentChatFirstLiveSeqState';
|
||||
import { agentChatHandleEventCallbackState } from '@/ai/states/agentChatHandleEventCallbackState';
|
||||
import { agentChatIsStreamingState } from '@/ai/states/agentChatIsStreamingState';
|
||||
import { agentChatMessagesComponentFamilyState } from '@/ai/states/agentChatMessagesComponentFamilyState';
|
||||
import { agentChatUsageComponentFamilyState } from '@/ai/states/agentChatUsageComponentFamilyState';
|
||||
import { currentAIChatThreadTitleComponentFamilyState } from '@/ai/states/currentAIChatThreadTitleComponentFamilyState';
|
||||
import { agentChatUsageState } from '@/ai/states/agentChatUsageState';
|
||||
import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState';
|
||||
import { dispatchBrowserEvent } from '@/browser-event/utils/dispatchBrowserEvent';
|
||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { sseClientState } from '@/sse-db-event/states/sseClientState';
|
||||
|
||||
@@ -96,52 +96,18 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
const store = useStore();
|
||||
const sseClient = useAtomStateValue(sseClientState);
|
||||
|
||||
const errorFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatErrorComponentFamilyState,
|
||||
);
|
||||
const isStreamingFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatIsStreamingComponentFamilyState,
|
||||
);
|
||||
const firstLiveSeqFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatFirstLiveSeqComponentFamilyState,
|
||||
);
|
||||
const handleEventCallbackFamilyCallback =
|
||||
useAtomComponentFamilyStateCallbackState(
|
||||
agentChatHandleEventCallbackComponentFamilyState,
|
||||
);
|
||||
const messagesFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatMessagesComponentFamilyState,
|
||||
);
|
||||
const usageFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
agentChatUsageComponentFamilyState,
|
||||
);
|
||||
const threadTitleFamilyCallback = useAtomComponentFamilyStateCallbackState(
|
||||
currentAIChatThreadTitleComponentFamilyState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(threadId) || !isDefined(sseClient)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const familyKey = { threadId };
|
||||
|
||||
const errorAtom = errorFamilyCallback(familyKey);
|
||||
const isStreamingAtom = isStreamingFamilyCallback(familyKey);
|
||||
const firstLiveSeqAtom = firstLiveSeqFamilyCallback(familyKey);
|
||||
const handleEventCallbackAtom =
|
||||
handleEventCallbackFamilyCallback(familyKey);
|
||||
const messagesAtom = messagesFamilyCallback(familyKey);
|
||||
const usageAtom = usageFamilyCallback(familyKey);
|
||||
const threadTitleAtom = threadTitleFamilyCallback(familyKey);
|
||||
|
||||
let bridge: TransformStream<UIMessageChunk> | null = null;
|
||||
let throttleTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
let latestMessage: ExtendedUIMessage | null = null;
|
||||
let writer: WritableStreamDefaultWriter<UIMessageChunk> | null = null;
|
||||
let disposed = false;
|
||||
|
||||
store.set(firstLiveSeqAtom, null);
|
||||
store.set(agentChatFirstLiveSeqState.atom, null);
|
||||
|
||||
const closeWriter = () => {
|
||||
if (isDefined(writer)) {
|
||||
@@ -153,8 +119,8 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
const cleanupStream = () => {
|
||||
closeWriter();
|
||||
|
||||
if (store.get(isStreamingAtom)) {
|
||||
store.set(isStreamingAtom, false);
|
||||
if (store.get(agentChatIsStreamingState.atom)) {
|
||||
store.set(agentChatIsStreamingState.atom, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -165,7 +131,14 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentMessages = store.get(messagesAtom);
|
||||
const atomKey = {
|
||||
instanceId: AGENT_CHAT_INSTANCE_ID,
|
||||
familyKey: { threadId },
|
||||
};
|
||||
|
||||
const currentMessages = store.get(
|
||||
agentChatMessagesComponentFamilyState.atomFamily(atomKey),
|
||||
);
|
||||
|
||||
const streamingMsgIndex = currentMessages.findIndex(
|
||||
(message) => message.id === messageToFlush.id,
|
||||
@@ -175,9 +148,15 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
const updatedMessages = [...currentMessages];
|
||||
|
||||
updatedMessages[streamingMsgIndex] = messageToFlush;
|
||||
store.set(messagesAtom, updatedMessages);
|
||||
store.set(
|
||||
agentChatMessagesComponentFamilyState.atomFamily(atomKey),
|
||||
updatedMessages,
|
||||
);
|
||||
} else {
|
||||
store.set(messagesAtom, [...currentMessages, messageToFlush]);
|
||||
store.set(agentChatMessagesComponentFamilyState.atomFamily(atomKey), [
|
||||
...currentMessages,
|
||||
messageToFlush,
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -205,7 +184,7 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
);
|
||||
|
||||
if (isDefined(titlePart) && titlePart.type === 'data-thread-title') {
|
||||
store.set(threadTitleAtom, titlePart.data.title);
|
||||
store.set(currentAIChatThreadTitleState.atom, titlePart.data.title);
|
||||
}
|
||||
|
||||
const metadata = extendedMessage.metadata as
|
||||
@@ -228,7 +207,7 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
const usage = metadata.usage;
|
||||
const model = metadata.model;
|
||||
|
||||
store.set(usageAtom, (prev) => ({
|
||||
store.set(agentChatUsageState.atom, (prev) => ({
|
||||
lastMessage: {
|
||||
inputTokens: usage.inputTokens,
|
||||
outputTokens: usage.outputTokens,
|
||||
@@ -255,20 +234,22 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
flushToAtom();
|
||||
|
||||
if (!disposed) {
|
||||
store.set(isStreamingAtom, false);
|
||||
store.set(agentChatIsStreamingState.atom, false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEvent = (event: AgentChatSubscriptionEvent) => {
|
||||
switch (event.type) {
|
||||
case 'stream-chunk': {
|
||||
if (isDefined(event.seq) && store.get(firstLiveSeqAtom) === null) {
|
||||
store.set(firstLiveSeqAtom, event.seq);
|
||||
if (
|
||||
isDefined(event.seq) &&
|
||||
store.get(agentChatFirstLiveSeqState.atom) === null
|
||||
) {
|
||||
store.set(agentChatFirstLiveSeqState.atom, event.seq);
|
||||
}
|
||||
|
||||
if (!store.get(isStreamingAtom)) {
|
||||
store.set(isStreamingAtom, true);
|
||||
store.set(errorAtom, null);
|
||||
if (!store.get(agentChatIsStreamingState.atom)) {
|
||||
store.set(agentChatIsStreamingState.atom, true);
|
||||
|
||||
bridge = new TransformStream<UIMessageChunk>();
|
||||
writer = bridge.writable.getWriter();
|
||||
@@ -279,7 +260,7 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
|
||||
startReadLoop(adaptedReadable).catch(() => {
|
||||
if (!disposed) {
|
||||
store.set(isStreamingAtom, false);
|
||||
store.set(agentChatIsStreamingState.atom, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -307,16 +288,16 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
};
|
||||
|
||||
streamError.code = event.code;
|
||||
store.set(errorAtom, streamError);
|
||||
store.set(agentChatErrorState.atom, streamError);
|
||||
|
||||
closeWriter();
|
||||
store.set(isStreamingAtom, false);
|
||||
store.set(agentChatIsStreamingState.atom, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
store.set(handleEventCallbackAtom, () => handleEvent);
|
||||
store.set(agentChatHandleEventCallbackState.atom, () => handleEvent);
|
||||
|
||||
const dispose = sseClient.subscribe<AgentChatEventPayload>(
|
||||
{
|
||||
@@ -344,23 +325,12 @@ export const useAgentChatSubscription = (threadId: string | null) => {
|
||||
|
||||
return () => {
|
||||
disposed = true;
|
||||
store.set(handleEventCallbackAtom, null);
|
||||
store.set(agentChatHandleEventCallbackState.atom, null);
|
||||
if (isDefined(throttleTimer)) {
|
||||
clearTimeout(throttleTimer);
|
||||
}
|
||||
cleanupStream();
|
||||
dispose();
|
||||
};
|
||||
}, [
|
||||
threadId,
|
||||
sseClient,
|
||||
store,
|
||||
errorFamilyCallback,
|
||||
isStreamingFamilyCallback,
|
||||
firstLiveSeqFamilyCallback,
|
||||
handleEventCallbackFamilyCallback,
|
||||
messagesFamilyCallback,
|
||||
usageFamilyCallback,
|
||||
threadTitleFamilyCallback,
|
||||
]);
|
||||
}, [threadId, sseClient, store]);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,9 @@ import {
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatUsageState } from '@/ai/states/agentChatUsageState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState';
|
||||
import { shouldFocusChatEditorState } from '@/ai/states/shouldFocusChatEditorState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { isCreatingChatThreadState } from '@/ai/states/isCreatingChatThreadState';
|
||||
@@ -22,6 +24,10 @@ import { CreateChatThreadDocument } from '~/generated-metadata/graphql';
|
||||
export const useCreateAgentChatThread = () => {
|
||||
const setCurrentAIChatThread = useSetAtomState(currentAIChatThreadState);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatUsage = useSetAtomState(agentChatUsageState);
|
||||
const setCurrentAIChatThreadTitle = useSetAtomState(
|
||||
currentAIChatThreadTitleState,
|
||||
);
|
||||
const setIsCreatingChatThread = useSetAtomState(isCreatingChatThreadState);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
agentChatDraftsByThreadIdState,
|
||||
@@ -81,6 +87,8 @@ export const useCreateAgentChatThread = () => {
|
||||
|
||||
setCurrentAIChatThread(newThreadId);
|
||||
setAgentChatInput(newDraft);
|
||||
setCurrentAIChatThreadTitle(null);
|
||||
setAgentChatUsage(null);
|
||||
},
|
||||
onError: () => {
|
||||
setIsCreatingChatThread(false);
|
||||
|
||||
@@ -5,7 +5,9 @@ import {
|
||||
agentChatDraftsByThreadIdState,
|
||||
} from '@/ai/states/agentChatDraftsByThreadIdState';
|
||||
import { agentChatInputState } from '@/ai/states/agentChatInputState';
|
||||
import { agentChatUsageState } from '@/ai/states/agentChatUsageState';
|
||||
import { currentAIChatThreadState } from '@/ai/states/currentAIChatThreadState';
|
||||
import { currentAIChatThreadTitleState } from '@/ai/states/currentAIChatThreadTitleState';
|
||||
import { shouldFocusChatEditorState } from '@/ai/states/shouldFocusChatEditorState';
|
||||
import { hasTriggeredCreateForDraftState } from '@/ai/states/hasTriggeredCreateForDraftState';
|
||||
import { threadIdCreatedFromDraftState } from '@/ai/states/threadIdCreatedFromDraftState';
|
||||
@@ -21,6 +23,10 @@ export const useSwitchToNewAIChat = () => {
|
||||
currentAIChatThreadState,
|
||||
);
|
||||
const setAgentChatInput = useSetAtomState(agentChatInputState);
|
||||
const setAgentChatUsage = useSetAtomState(agentChatUsageState);
|
||||
const setCurrentAIChatThreadTitle = useSetAtomState(
|
||||
currentAIChatThreadTitleState,
|
||||
);
|
||||
const setAgentChatDraftsByThreadId = useSetAtomState(
|
||||
agentChatDraftsByThreadIdState,
|
||||
);
|
||||
@@ -42,6 +48,8 @@ export const useSwitchToNewAIChat = () => {
|
||||
store.set(hasTriggeredCreateForDraftState.atom, false);
|
||||
setCurrentAIChatThread(AGENT_CHAT_NEW_THREAD_DRAFT_KEY);
|
||||
setAgentChatInput(newChatDraft);
|
||||
setCurrentAIChatThreadTitle(null);
|
||||
setAgentChatUsage(null);
|
||||
openAskAIPage();
|
||||
store.set(shouldFocusChatEditorState.atom, true);
|
||||
};
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const agentChatErrorComponentFamilyState =
|
||||
createAtomComponentFamilyState<Error | null, { threadId: string | null }>({
|
||||
key: 'agentChatErrorComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const agentChatErrorState = createAtomState<Error | undefined | null>({
|
||||
key: 'agentChatErrorState',
|
||||
defaultValue: null,
|
||||
});
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const agentChatFirstLiveSeqComponentFamilyState =
|
||||
createAtomComponentFamilyState<number | null, { threadId: string | null }>({
|
||||
key: 'agentChatFirstLiveSeqComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const agentChatFirstLiveSeqState = createAtomState<number | null>({
|
||||
key: 'agentChatFirstLiveSeqState',
|
||||
defaultValue: null,
|
||||
});
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
import { type AgentChatSubscriptionEvent } from 'twenty-shared/ai';
|
||||
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const agentChatHandleEventCallbackComponentFamilyState =
|
||||
createAtomComponentFamilyState<
|
||||
((event: AgentChatSubscriptionEvent) => void) | null,
|
||||
{ threadId: string | null }
|
||||
>({
|
||||
key: 'agentChatHandleEventCallbackComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { type AgentChatSubscriptionEvent } from 'twenty-shared/ai';
|
||||
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const agentChatHandleEventCallbackState = createAtomState<
|
||||
((event: AgentChatSubscriptionEvent) => void) | null
|
||||
>({
|
||||
key: 'agentChatHandleEventCallbackState',
|
||||
defaultValue: null,
|
||||
});
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const agentChatIsStreamingComponentFamilyState =
|
||||
createAtomComponentFamilyState<boolean, { threadId: string | null }>({
|
||||
key: 'agentChatIsStreamingComponentFamilyState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const agentChatIsStreamingState = createAtomState({
|
||||
key: 'agentChatIsStreamingState',
|
||||
defaultValue: false,
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export type AgentChatLastMessageUsage = {
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
cachedInputTokens: number;
|
||||
inputCredits: number;
|
||||
outputCredits: number;
|
||||
};
|
||||
|
||||
export type AgentChatUsageState = {
|
||||
lastMessage: AgentChatLastMessageUsage | null;
|
||||
conversationSize: number;
|
||||
contextWindowTokens: number;
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
inputCredits: number;
|
||||
outputCredits: number;
|
||||
};
|
||||
|
||||
export const agentChatUsageComponentFamilyState =
|
||||
createAtomComponentFamilyState<
|
||||
AgentChatUsageState | null,
|
||||
{ threadId: string | null }
|
||||
>({
|
||||
key: 'agentChatUsageComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export type AgentChatLastMessageUsage = {
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
cachedInputTokens: number;
|
||||
inputCredits: number;
|
||||
outputCredits: number;
|
||||
};
|
||||
|
||||
export type AgentChatUsageState = {
|
||||
lastMessage: AgentChatLastMessageUsage | null;
|
||||
conversationSize: number;
|
||||
contextWindowTokens: number;
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
inputCredits: number;
|
||||
outputCredits: number;
|
||||
};
|
||||
|
||||
export const agentChatUsageState = createAtomState<AgentChatUsageState | null>({
|
||||
key: 'agentChatUsageState',
|
||||
defaultValue: null,
|
||||
});
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { AgentChatComponentInstanceContext } from '@/ai/states/AgentChatComponentInstanceContext';
|
||||
import { createAtomComponentFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomComponentFamilyState';
|
||||
|
||||
export const currentAIChatThreadTitleComponentFamilyState =
|
||||
createAtomComponentFamilyState<string | null, { threadId: string | null }>({
|
||||
key: 'currentAIChatThreadTitleComponentFamilyState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: AgentChatComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const currentAIChatThreadTitleState = createAtomState<string | null>({
|
||||
key: 'ai/currentAIChatThreadTitleState',
|
||||
defaultValue: null,
|
||||
});
|
||||
@@ -425,6 +425,30 @@ const SettingsAdminNewAiModel = lazy(() =>
|
||||
),
|
||||
);
|
||||
|
||||
const SettingsAdminUserDetail = lazy(() =>
|
||||
import('~/pages/settings/admin-panel/SettingsAdminUserDetail').then(
|
||||
(module) => ({
|
||||
default: module.SettingsAdminUserDetail,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const SettingsAdminWorkspaceDetail = lazy(() =>
|
||||
import('~/pages/settings/admin-panel/SettingsAdminWorkspaceDetail').then(
|
||||
(module) => ({
|
||||
default: module.SettingsAdminWorkspaceDetail,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const SettingsAdminWorkspaceChatThread = lazy(() =>
|
||||
import('~/pages/settings/admin-panel/SettingsAdminWorkspaceChatThread').then(
|
||||
(module) => ({
|
||||
default: module.SettingsAdminWorkspaceChatThread,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const SettingsUpdates = lazy(() =>
|
||||
import('~/pages/settings/updates/SettingsUpdates').then((module) => ({
|
||||
default: module.SettingsUpdates,
|
||||
@@ -770,6 +794,18 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => (
|
||||
path={SettingsPath.AdminPanelAiProviderDetail}
|
||||
element={<SettingsAdminAiProviderDetail />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AdminPanelUserDetail}
|
||||
element={<SettingsAdminUserDetail />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AdminPanelWorkspaceDetail}
|
||||
element={<SettingsAdminWorkspaceDetail />}
|
||||
/>
|
||||
<Route
|
||||
path={SettingsPath.AdminPanelWorkspaceChatThread}
|
||||
element={<SettingsAdminWorkspaceChatThread />}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
import { isAppEffectRedirectEnabledState } from '@/app/states/isAppEffectRedirectEnabledState';
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
import { useClearSseClient } from '@/sse-db-event/hooks/useClearSseClient';
|
||||
import { useLoadCurrentUser } from '@/users/hooks/useLoadCurrentUser';
|
||||
import { type AuthTokenPair } from '~/generated-metadata/graphql';
|
||||
|
||||
const IMPERSONATION_SESSION_KEY = 'impersonation_original_session';
|
||||
|
||||
type StoredImpersonationSession = {
|
||||
tokenPair: AuthTokenPair;
|
||||
returnPath: string;
|
||||
};
|
||||
|
||||
export const useImpersonationSession = () => {
|
||||
const store = useStore();
|
||||
const client = useApolloClient();
|
||||
const navigate = useNavigate();
|
||||
const { getAuthTokensFromLoginToken, signOut } = useAuth();
|
||||
const { clearSseClient } = useClearSseClient();
|
||||
const { loadCurrentUser } = useLoadCurrentUser();
|
||||
|
||||
const startImpersonating = useCallback(
|
||||
async (loginToken: string, returnPath?: string) => {
|
||||
const currentTokenPair = store.get(tokenPairState.atom);
|
||||
|
||||
if (currentTokenPair) {
|
||||
const session: StoredImpersonationSession = {
|
||||
tokenPair: currentTokenPair,
|
||||
returnPath: returnPath ?? window.location.pathname,
|
||||
};
|
||||
sessionStorage.setItem(
|
||||
IMPERSONATION_SESSION_KEY,
|
||||
JSON.stringify(session),
|
||||
);
|
||||
}
|
||||
|
||||
clearSseClient();
|
||||
await client.clearStore();
|
||||
|
||||
store.set(isAppEffectRedirectEnabledState.atom, false);
|
||||
await getAuthTokensFromLoginToken(loginToken);
|
||||
store.set(isAppEffectRedirectEnabledState.atom, true);
|
||||
},
|
||||
[store, client, clearSseClient, getAuthTokensFromLoginToken],
|
||||
);
|
||||
|
||||
const stopImpersonating = useCallback(async () => {
|
||||
const raw = sessionStorage.getItem(IMPERSONATION_SESSION_KEY);
|
||||
|
||||
if (!raw) {
|
||||
// No stored session — likely a cross-workspace tab opened via redirect.
|
||||
// Try closing the tab (works when opened via window.open or target=_blank).
|
||||
window.close();
|
||||
// If window.close() was blocked by the browser, fall back to sign out.
|
||||
await signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
let session: StoredImpersonationSession;
|
||||
|
||||
try {
|
||||
session = JSON.parse(raw);
|
||||
} catch {
|
||||
sessionStorage.removeItem(IMPERSONATION_SESSION_KEY);
|
||||
await signOut();
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.removeItem(IMPERSONATION_SESSION_KEY);
|
||||
|
||||
clearSseClient();
|
||||
await client.clearStore();
|
||||
|
||||
store.set(isAppEffectRedirectEnabledState.atom, false);
|
||||
store.set(tokenPairState.atom, session.tokenPair);
|
||||
|
||||
await loadCurrentUser();
|
||||
|
||||
store.set(isAppEffectRedirectEnabledState.atom, true);
|
||||
|
||||
navigate(session.returnPath);
|
||||
}, [store, client, clearSseClient, loadCurrentUser, signOut, navigate]);
|
||||
|
||||
const hasStoredSession = useCallback(() => {
|
||||
return sessionStorage.getItem(IMPERSONATION_SESSION_KEY) !== null;
|
||||
}, []);
|
||||
|
||||
return { startImpersonating, stopImpersonating, hasStoredSession };
|
||||
};
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { useImpersonationSession } from '@/auth/hooks/useImpersonationSession';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { isImpersonatingState } from '@/auth/states/isImpersonatingState';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
@@ -11,7 +11,7 @@ export const InformationBannerIsImpersonating = () => {
|
||||
const currentWorkspaceMember = useAtomStateValue(currentWorkspaceMemberState);
|
||||
const isImpersonating = useAtomStateValue(isImpersonatingState);
|
||||
|
||||
const { signOut } = useAuth();
|
||||
const { stopImpersonating } = useImpersonationSession();
|
||||
|
||||
if (!isDefined(currentWorkspaceMember) || !isImpersonating) {
|
||||
return null;
|
||||
@@ -25,7 +25,7 @@ export const InformationBannerIsImpersonating = () => {
|
||||
message={t`Logged in as ${impersonatedUser}`}
|
||||
buttonTitle={t`Stop impersonating`}
|
||||
buttonIcon={IconLogout}
|
||||
buttonOnClick={signOut}
|
||||
buttonOnClick={stopImpersonating}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+5
@@ -2,6 +2,8 @@ import { useMemo, useState } from 'react';
|
||||
|
||||
import { useMutation, useQuery } from '@apollo/client/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { Tag } from 'twenty-ui/components';
|
||||
import { H2Title, IconBolt, IconLock, IconRobot } from 'twenty-ui/display';
|
||||
import { Card, Section } from 'twenty-ui/layout';
|
||||
@@ -319,6 +321,9 @@ export const SettingsAdminAI = () => {
|
||||
<TableRow
|
||||
key={item.key}
|
||||
gridTemplateColumns={USAGE_TABLE_GRID_TEMPLATE_COLUMNS}
|
||||
to={getSettingsPath(SettingsPath.AdminPanelWorkspaceDetail, {
|
||||
workspaceId: item.key,
|
||||
})}
|
||||
>
|
||||
<TableCell color={themeCssVariables.font.color.primary}>
|
||||
{item.label ?? item.key}
|
||||
|
||||
+139
-158
@@ -1,134 +1,73 @@
|
||||
import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
|
||||
import { SettingsAdminWorkspaceContent } from '@/settings/admin-panel/components/SettingsAdminWorkspaceContent';
|
||||
import { userLookupResultState } from '@/settings/admin-panel/states/userLookupResultState';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { SettingsAdminVersionContainer } from '@/settings/admin-panel/components/SettingsAdminVersionContainer';
|
||||
import { ADMIN_PANEL_RECENT_USERS } from '@/settings/admin-panel/graphql/queries/adminPanelRecentUsers';
|
||||
import { ADMIN_PANEL_TOP_WORKSPACES } from '@/settings/admin-panel/graphql/queries/adminPanelTopWorkspaces';
|
||||
import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useQuery } from '@apollo/client/react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useState } from 'react';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { UserLookupAdminPanelDocument } from '~/generated-metadata/graphql';
|
||||
import { useDebounce } from 'use-debounce';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { SettingsTableCard } from '@/settings/components/SettingsTableCard';
|
||||
import { SettingsAdminVersionContainer } from '@/settings/admin-panel/components/SettingsAdminVersionContainer';
|
||||
import { SETTINGS_ADMIN_USER_LOOKUP_WORKSPACE_TABS_ID } from '@/settings/admin-panel/constants/SettingsAdminUserLookupWorkspaceTabsId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
|
||||
import { getImageAbsoluteURI, isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
H2Title,
|
||||
IconId,
|
||||
IconMail,
|
||||
IconSearch,
|
||||
IconUser,
|
||||
} from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { H2Title } from 'twenty-ui/display';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
const StyledEmptyState = styled.div`
|
||||
color: ${themeCssVariables.font.color.tertiary};
|
||||
padding: ${themeCssVariables.spacing[4]} 0;
|
||||
`;
|
||||
|
||||
export const SettingsAdminGeneral = () => {
|
||||
const [userIdentifier, setUserIdentifier] = useState('');
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const [userSearchTerm, setUserSearchTerm] = useState('');
|
||||
const [debouncedUserSearchTerm] = useDebounce(userSearchTerm, 300);
|
||||
|
||||
const [activeTabId, setActiveTabId] = useAtomComponentState(
|
||||
activeTabIdComponentState,
|
||||
SETTINGS_ADMIN_USER_LOOKUP_WORKSPACE_TABS_ID,
|
||||
);
|
||||
const [userLookupResult, setUserLookupResult] = useAtomState(
|
||||
userLookupResultState,
|
||||
);
|
||||
const [isUserLookupLoading, setIsUserLookupLoading] = useState(false);
|
||||
|
||||
const [userLookup] = useMutation(UserLookupAdminPanelDocument);
|
||||
const [workspaceSearchTerm, setWorkspaceSearchTerm] = useState('');
|
||||
const [debouncedWorkspaceSearchTerm] = useDebounce(workspaceSearchTerm, 300);
|
||||
|
||||
const currentUser = useAtomStateValue(currentUserState);
|
||||
|
||||
const canAccessFullAdminPanel = currentUser?.canAccessFullAdminPanel;
|
||||
|
||||
const canImpersonate = currentUser?.canImpersonate;
|
||||
|
||||
const canManageFeatureFlags = useAtomStateValue(canManageFeatureFlagsState);
|
||||
|
||||
const handleSearch = async () => {
|
||||
setActiveTabId('');
|
||||
setIsUserLookupLoading(true);
|
||||
setUserLookupResult(null);
|
||||
const { data: recentUsersData, loading: isLoadingUsers } = useQuery<{
|
||||
adminPanelRecentUsers: {
|
||||
id: string;
|
||||
email: string;
|
||||
firstName?: string | null;
|
||||
lastName?: string | null;
|
||||
createdAt: string;
|
||||
workspaceName?: string | null;
|
||||
workspaceId?: string | null;
|
||||
}[];
|
||||
}>(ADMIN_PANEL_RECENT_USERS, {
|
||||
variables: { searchTerm: debouncedUserSearchTerm },
|
||||
skip: !canImpersonate,
|
||||
});
|
||||
|
||||
const response = await userLookup({
|
||||
variables: { userIdentifier },
|
||||
onCompleted: (data) => {
|
||||
setIsUserLookupLoading(false);
|
||||
if (isDefined(data?.userLookupAdminPanel)) {
|
||||
setUserLookupResult(data.userLookupAdminPanel);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
setIsUserLookupLoading(false);
|
||||
enqueueErrorSnackBar({
|
||||
apolloError: error,
|
||||
});
|
||||
},
|
||||
});
|
||||
const { data: topWorkspacesData, loading: isLoadingWorkspaces } = useQuery<{
|
||||
adminPanelTopWorkspaces: {
|
||||
id: string;
|
||||
name: string;
|
||||
totalUsers: number;
|
||||
subdomain: string;
|
||||
}[];
|
||||
}>(ADMIN_PANEL_TOP_WORKSPACES, {
|
||||
variables: { searchTerm: debouncedWorkspaceSearchTerm },
|
||||
skip: !canImpersonate,
|
||||
});
|
||||
|
||||
const result = response.data?.userLookupAdminPanel;
|
||||
|
||||
if (isDefined(result?.workspaces) && result.workspaces.length > 0) {
|
||||
setActiveTabId(result.workspaces[0].id);
|
||||
}
|
||||
};
|
||||
|
||||
const activeWorkspace = userLookupResult?.workspaces.find(
|
||||
(workspace) => workspace.id === activeTabId,
|
||||
);
|
||||
|
||||
const tabs =
|
||||
userLookupResult?.workspaces.map((workspace) => ({
|
||||
id: workspace.id,
|
||||
title: workspace.name,
|
||||
logo:
|
||||
getImageAbsoluteURI({
|
||||
imageUrl: isNonEmptyString(workspace.logo)
|
||||
? workspace.logo
|
||||
: DEFAULT_WORKSPACE_LOGO,
|
||||
baseUrl: REACT_APP_SERVER_BASE_URL,
|
||||
}) ?? '',
|
||||
})) ?? [];
|
||||
|
||||
const userFullName = `${userLookupResult?.user.firstName || ''} ${
|
||||
userLookupResult?.user.lastName || ''
|
||||
}`.trim();
|
||||
|
||||
const userInfoItems = [
|
||||
{
|
||||
Icon: IconUser,
|
||||
label: t`Name`,
|
||||
value: userFullName,
|
||||
},
|
||||
{
|
||||
Icon: IconMail,
|
||||
label: t`Email`,
|
||||
value: userLookupResult?.user.email,
|
||||
},
|
||||
{
|
||||
Icon: IconId,
|
||||
label: t`ID`,
|
||||
value: userLookupResult?.user.id,
|
||||
},
|
||||
];
|
||||
const recentUsers = recentUsersData?.adminPanelRecentUsers ?? [];
|
||||
const topWorkspaces = topWorkspacesData?.adminPanelTopWorkspaces ?? [];
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -143,63 +82,105 @@ export const SettingsAdminGeneral = () => {
|
||||
)}
|
||||
|
||||
{canImpersonate && (
|
||||
<Section>
|
||||
<H2Title
|
||||
title={
|
||||
canManageFeatureFlags
|
||||
? t`Feature Flags & Impersonation`
|
||||
: t`User Impersonation`
|
||||
}
|
||||
description={
|
||||
canManageFeatureFlags
|
||||
? t`Look up users and manage their workspace feature flags or impersonate them.`
|
||||
: t`Look up users to impersonate them.`
|
||||
}
|
||||
/>
|
||||
|
||||
<StyledContainer>
|
||||
<SettingsTextInput
|
||||
instanceId="admin-user-lookup"
|
||||
value={userIdentifier}
|
||||
onChange={setUserIdentifier}
|
||||
onInputEnter={handleSearch}
|
||||
placeholder={t`Enter user ID or email address`}
|
||||
fullWidth
|
||||
disabled={isUserLookupLoading}
|
||||
/>
|
||||
<Button
|
||||
Icon={IconSearch}
|
||||
variant="primary"
|
||||
accent="blue"
|
||||
title={t`Search`}
|
||||
onClick={handleSearch}
|
||||
disabled={!userIdentifier.trim() || isUserLookupLoading}
|
||||
/>
|
||||
</StyledContainer>
|
||||
</Section>
|
||||
)}
|
||||
|
||||
{isDefined(userLookupResult) && (
|
||||
<>
|
||||
<Section>
|
||||
<H2Title title={t`User Info`} description={t`About this user`} />
|
||||
<SettingsTableCard
|
||||
items={userInfoItems}
|
||||
rounded
|
||||
gridAutoColumns="1fr 4fr"
|
||||
<H2Title
|
||||
title={t`Recent Users`}
|
||||
description={
|
||||
canManageFeatureFlags
|
||||
? t`Last 10 users created. Click to manage feature flags or impersonate.`
|
||||
: t`Last 10 users created. Click to impersonate.`
|
||||
}
|
||||
/>
|
||||
<SettingsTextInput
|
||||
instanceId="admin-panel-user-search"
|
||||
value={userSearchTerm}
|
||||
onChange={setUserSearchTerm}
|
||||
placeholder={t`Search by name, email, or user ID...`}
|
||||
fullWidth
|
||||
/>
|
||||
{recentUsers.length === 0 ? (
|
||||
<StyledEmptyState>
|
||||
{isLoadingUsers
|
||||
? t`Loading...`
|
||||
: t`No users found matching your search criteria.`}
|
||||
</StyledEmptyState>
|
||||
) : (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow gridTemplateColumns="1fr 2fr 1fr">
|
||||
<TableHeader>{t`Name`}</TableHeader>
|
||||
<TableHeader>{t`Email`}</TableHeader>
|
||||
<TableHeader align="right">{t`Workspace`}</TableHeader>
|
||||
</TableRow>
|
||||
{recentUsers.map((user) => (
|
||||
<TableRow
|
||||
key={user.id}
|
||||
gridTemplateColumns="1fr 2fr 1fr"
|
||||
to={getSettingsPath(SettingsPath.AdminPanelUserDetail, {
|
||||
userId: user.id,
|
||||
})}
|
||||
>
|
||||
<TableCell color={themeCssVariables.font.color.primary}>
|
||||
{`${user.firstName || ''} ${user.lastName || ''}`.trim() ||
|
||||
'\u2014'}
|
||||
</TableCell>
|
||||
<TableCell>{user.email}</TableCell>
|
||||
<TableCell align="right">
|
||||
{user.workspaceName || '\u2014'}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</Section>
|
||||
|
||||
<Section>
|
||||
<H2Title
|
||||
title={t`Workspaces`}
|
||||
description={t`All workspaces this user is a member of`}
|
||||
title={t`Top Workspaces`}
|
||||
description={t`Top 10 workspaces by number of users`}
|
||||
/>
|
||||
<TabList
|
||||
tabs={tabs}
|
||||
behaveAsLinks={false}
|
||||
componentInstanceId={SETTINGS_ADMIN_USER_LOOKUP_WORKSPACE_TABS_ID}
|
||||
<SettingsTextInput
|
||||
instanceId="admin-panel-workspace-search"
|
||||
value={workspaceSearchTerm}
|
||||
onChange={setWorkspaceSearchTerm}
|
||||
placeholder={t`Search by workspace name, subdomain, or ID...`}
|
||||
fullWidth
|
||||
/>
|
||||
<SettingsAdminWorkspaceContent activeWorkspace={activeWorkspace} />
|
||||
{topWorkspaces.length === 0 ? (
|
||||
<StyledEmptyState>
|
||||
{isLoadingWorkspaces
|
||||
? t`Loading...`
|
||||
: t`No workspaces found matching your search criteria.`}
|
||||
</StyledEmptyState>
|
||||
) : (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow gridTemplateColumns="2fr 1fr">
|
||||
<TableHeader>{t`Workspace`}</TableHeader>
|
||||
<TableHeader align="right">{t`Users`}</TableHeader>
|
||||
</TableRow>
|
||||
{topWorkspaces.map((workspace) => (
|
||||
<TableRow
|
||||
key={workspace.id}
|
||||
gridTemplateColumns="2fr 1fr"
|
||||
to={getSettingsPath(
|
||||
SettingsPath.AdminPanelWorkspaceDetail,
|
||||
{ workspaceId: workspace.id },
|
||||
)}
|
||||
>
|
||||
<TableCell color={themeCssVariables.font.color.primary}>
|
||||
{workspace.name || '\u2014'}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
{workspace.totalUsers}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</Section>
|
||||
</>
|
||||
)}
|
||||
|
||||
+28
-165
@@ -1,46 +1,29 @@
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { canManageFeatureFlagsState } from '@/client-config/states/canManageFeatureFlagsState';
|
||||
import { SettingsTableCard } from '@/settings/components/SettingsTableCard';
|
||||
import { useFeatureFlagState } from '@/settings/admin-panel/hooks/useFeatureFlagState';
|
||||
import { useImpersonationAuth } from '@/settings/admin-panel/hooks/useImpersonationAuth';
|
||||
import { useImpersonationRedirect } from '@/settings/admin-panel/hooks/useImpersonationRedirect';
|
||||
import { userLookupResultState } from '@/settings/admin-panel/states/userLookupResultState';
|
||||
import { type WorkspaceInfo } from '@/settings/admin-panel/types/WorkspaceInfo';
|
||||
import { getWorkspaceSchemaName } from '@/settings/admin-panel/utils/getWorkspaceSchemaName';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useState } from 'react';
|
||||
import { getImageAbsoluteURI, isDefined } from 'twenty-shared/utils';
|
||||
import { AvatarOrIcon, Chip } from 'twenty-ui/components';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import {
|
||||
getImageAbsoluteURI,
|
||||
getSettingsPath,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
import { AvatarOrIcon, LinkChip } from 'twenty-ui/components';
|
||||
import {
|
||||
H2Title,
|
||||
IconEyeShare,
|
||||
IconCalendar,
|
||||
IconHome,
|
||||
IconId,
|
||||
IconLink,
|
||||
IconStatusChange,
|
||||
IconUser,
|
||||
} from 'twenty-ui/display';
|
||||
import { Button, Toggle } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import {
|
||||
type FeatureFlagKey,
|
||||
ImpersonateDocument,
|
||||
UpdateWorkspaceFeatureFlagDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type SettingsAdminWorkspaceContentProps = {
|
||||
activeWorkspace: WorkspaceInfo | undefined;
|
||||
@@ -53,93 +36,11 @@ const StyledContainer = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[6]};
|
||||
`;
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
margin-top: ${themeCssVariables.spacing[3]};
|
||||
`;
|
||||
|
||||
export const SettingsAdminWorkspaceContent = ({
|
||||
activeWorkspace,
|
||||
}: SettingsAdminWorkspaceContentProps) => {
|
||||
const canManageFeatureFlags = useAtomStateValue(canManageFeatureFlagsState);
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const [currentUser] = useAtomState(currentUserState);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
|
||||
const [updateFeatureFlag] = useMutation(UpdateWorkspaceFeatureFlagDocument);
|
||||
const [isImpersonateLoading, setIsImpersonationLoading] = useState(false);
|
||||
const { executeImpersonationAuth } = useImpersonationAuth();
|
||||
const { executeImpersonationRedirect } = useImpersonationRedirect();
|
||||
const [impersonate] = useMutation(ImpersonateDocument);
|
||||
|
||||
const { updateFeatureFlagState } = useFeatureFlagState();
|
||||
const userLookupResult = useAtomStateValue(userLookupResultState);
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
const handleImpersonate = async (workspaceId: string) => {
|
||||
if (!userLookupResult?.user.id) {
|
||||
enqueueErrorSnackBar({ message: t`Please search for a user first` });
|
||||
return;
|
||||
}
|
||||
|
||||
setIsImpersonationLoading(true);
|
||||
|
||||
await impersonate({
|
||||
variables: { userId: userLookupResult.user.id, workspaceId },
|
||||
onCompleted: async (data) => {
|
||||
const { loginToken, workspace } = data.impersonate;
|
||||
const isCurrentWorkspace = workspace.id === currentWorkspace?.id;
|
||||
if (isCurrentWorkspace) {
|
||||
await executeImpersonationAuth(loginToken.token);
|
||||
return;
|
||||
}
|
||||
|
||||
return executeImpersonationRedirect(
|
||||
workspace.workspaceUrls,
|
||||
loginToken.token,
|
||||
'_blank',
|
||||
);
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error.message;
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to impersonate user. ${errorMessage}`,
|
||||
});
|
||||
},
|
||||
}).finally(() => {
|
||||
setIsImpersonationLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleFeatureFlagUpdate = async (
|
||||
workspaceId: string,
|
||||
featureFlag: FeatureFlagKey,
|
||||
value: boolean,
|
||||
) => {
|
||||
const previousValue = userLookupResult?.workspaces
|
||||
.find((workspace) => workspace.id === workspaceId)
|
||||
?.featureFlags.find((flag) => flag.key === featureFlag)?.value;
|
||||
|
||||
updateFeatureFlagState(workspaceId, featureFlag, value);
|
||||
await updateFeatureFlag({
|
||||
variables: {
|
||||
workspaceId,
|
||||
featureFlag,
|
||||
value,
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
if (isDefined(previousValue)) {
|
||||
updateFeatureFlagState(workspaceId, featureFlag, previousValue);
|
||||
}
|
||||
const errorMessage = error.message;
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to update feature flag. ${errorMessage}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const getWorkspaceUrl = (workspaceUrls: WorkspaceInfo['workspaceUrls']) => {
|
||||
return workspaceUrls.customUrl ?? workspaceUrls.subdomainUrl;
|
||||
};
|
||||
@@ -148,10 +49,13 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
{
|
||||
Icon: IconHome,
|
||||
label: t`Name`,
|
||||
value: (
|
||||
<Chip
|
||||
value: activeWorkspace?.id ? (
|
||||
<LinkChip
|
||||
label={activeWorkspace?.name ?? ''}
|
||||
emptyLabel={t`Untitled`}
|
||||
to={getSettingsPath(SettingsPath.AdminPanelWorkspaceDetail, {
|
||||
workspaceId: activeWorkspace.id,
|
||||
})}
|
||||
leftComponent={
|
||||
<AvatarOrIcon
|
||||
avatarUrl={
|
||||
@@ -165,6 +69,8 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
(activeWorkspace?.name ?? '')
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -191,6 +97,18 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
label: t`Members`,
|
||||
value: activeWorkspace?.totalUsers,
|
||||
},
|
||||
{
|
||||
Icon: IconStatusChange,
|
||||
label: t`Status`,
|
||||
value: activeWorkspace?.activationStatus,
|
||||
},
|
||||
{
|
||||
Icon: IconCalendar,
|
||||
label: t`Created`,
|
||||
value: activeWorkspace?.createdAt
|
||||
? new Date(activeWorkspace.createdAt).toLocaleDateString()
|
||||
: '',
|
||||
},
|
||||
];
|
||||
|
||||
if (!activeWorkspace) return null;
|
||||
@@ -206,62 +124,7 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
items={workspaceInfoItems}
|
||||
gridAutoColumns="1fr 4fr"
|
||||
/>
|
||||
<StyledButtonContainer>
|
||||
{currentUser?.canImpersonate && (
|
||||
<Button
|
||||
Icon={IconEyeShare}
|
||||
variant="primary"
|
||||
accent="default"
|
||||
title={
|
||||
activeWorkspace.allowImpersonation === false
|
||||
? t`Impersonation is disabled for this workspace`
|
||||
: t`Impersonate`
|
||||
}
|
||||
onClick={() => handleImpersonate(activeWorkspace.id)}
|
||||
disabled={
|
||||
isImpersonateLoading ||
|
||||
activeWorkspace.allowImpersonation === false
|
||||
}
|
||||
dataTestId="impersonate-button"
|
||||
/>
|
||||
)}
|
||||
</StyledButtonContainer>
|
||||
</Section>
|
||||
{canManageFeatureFlags && (
|
||||
<Table>
|
||||
<TableBody>
|
||||
<TableRow
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
>
|
||||
<TableHeader>{t`Feature Flag`}</TableHeader>
|
||||
<TableHeader align="right">{t`Status`}</TableHeader>
|
||||
</TableRow>
|
||||
|
||||
{activeWorkspace.featureFlags.map((flag) => (
|
||||
<TableRow
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
key={flag.key}
|
||||
>
|
||||
<TableCell>{flag.key}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Toggle
|
||||
value={flag.value}
|
||||
onChange={(newValue) =>
|
||||
handleFeatureFlagUpdate(
|
||||
activeWorkspace.id,
|
||||
flag.key,
|
||||
newValue,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-5
@@ -41,11 +41,7 @@ export const ConfigVariableValueInput = ({
|
||||
options={variable.options}
|
||||
disabled={disabled}
|
||||
placeholder={
|
||||
disabled
|
||||
? t`Undefined`
|
||||
: variable.isSensitive
|
||||
? t`Enter a new secret value`
|
||||
: t`Enter a value to store in database`
|
||||
disabled ? t`Undefined` : t`Enter a value to store in database`
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
|
||||
+17
-23
@@ -9,19 +9,6 @@ type FormValues = {
|
||||
value: ConfigVariableValue;
|
||||
};
|
||||
|
||||
const hasMeaningfulValue = (value: ConfigVariableValue): boolean => {
|
||||
if (value === null || value === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.trim() !== '';
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const useConfigVariableForm = (variable?: ConfigVariable) => {
|
||||
const validationSchema = z.object({
|
||||
value: z.union([
|
||||
@@ -35,10 +22,9 @@ export const useConfigVariableForm = (variable?: ConfigVariable) => {
|
||||
});
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { isSubmitting, isDirty },
|
||||
setValue,
|
||||
formState: { isSubmitting },
|
||||
watch,
|
||||
} = useForm<FormValues>({
|
||||
resolver: zodResolver(validationSchema),
|
||||
@@ -46,19 +32,27 @@ export const useConfigVariableForm = (variable?: ConfigVariable) => {
|
||||
});
|
||||
|
||||
const currentValue = watch('value');
|
||||
const isValueValid =
|
||||
variable !== undefined &&
|
||||
const hasValueChanged = currentValue !== variable?.value;
|
||||
const isValueValid = !!(
|
||||
variable &&
|
||||
!variable.isEnvOnly &&
|
||||
isDirty &&
|
||||
hasMeaningfulValue(currentValue);
|
||||
hasValueChanged &&
|
||||
((typeof currentValue === 'string' && currentValue.trim() !== '') ||
|
||||
typeof currentValue === 'boolean' ||
|
||||
typeof currentValue === 'number' ||
|
||||
(Array.isArray(currentValue) && currentValue.length > 0) ||
|
||||
(typeof currentValue === 'object' &&
|
||||
currentValue !== null &&
|
||||
!Array.isArray(currentValue)))
|
||||
);
|
||||
|
||||
return {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
setValue,
|
||||
isSubmitting,
|
||||
watch,
|
||||
currentValue,
|
||||
hasValueChanged: isDirty,
|
||||
hasValueChanged,
|
||||
isValueValid,
|
||||
};
|
||||
};
|
||||
|
||||
+3
@@ -8,12 +8,15 @@ export const USER_LOOKUP_ADMIN_PANEL = gql`
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
createdAt
|
||||
}
|
||||
workspaces {
|
||||
id
|
||||
name
|
||||
logo
|
||||
totalUsers
|
||||
activationStatus
|
||||
createdAt
|
||||
allowImpersonation
|
||||
workspaceUrls {
|
||||
customUrl
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ADMIN_PANEL_RECENT_USERS = gql`
|
||||
query AdminPanelRecentUsers($searchTerm: String) {
|
||||
adminPanelRecentUsers(searchTerm: $searchTerm) {
|
||||
id
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
createdAt
|
||||
workspaceName
|
||||
workspaceId
|
||||
}
|
||||
}
|
||||
`;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ADMIN_PANEL_TOP_WORKSPACES = gql`
|
||||
query AdminPanelTopWorkspaces($searchTerm: String) {
|
||||
adminPanelTopWorkspaces(searchTerm: $searchTerm) {
|
||||
id
|
||||
name
|
||||
totalUsers
|
||||
subdomain
|
||||
}
|
||||
}
|
||||
`;
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_ADMIN_CHAT_THREAD_MESSAGES = gql`
|
||||
query GetAdminChatThreadMessages($workspaceId: String!, $threadId: String!) {
|
||||
getAdminChatThreadMessages(workspaceId: $workspaceId, threadId: $threadId) {
|
||||
thread {
|
||||
id
|
||||
title
|
||||
totalInputTokens
|
||||
totalOutputTokens
|
||||
conversationSize
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
messages {
|
||||
id
|
||||
role
|
||||
parts {
|
||||
type
|
||||
textContent
|
||||
toolName
|
||||
}
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user