diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 17c12ee169..3cc0baab97 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -1737,6 +1737,12 @@ enum FeatureFlagKey { IS_DATASOURCE_MIGRATED } +type ClientConfigMaintenanceMode { + startAt: DateTime! + endAt: DateTime! + link: String +} + type ClientConfig { appVersion: String authProviders: AuthProviders! @@ -1765,6 +1771,8 @@ type ClientConfig { calendarBookingPageId: String isCloudflareIntegrationEnabled: Boolean! isClickHouseConfigured: Boolean! + isWorkspaceSchemaDDLLocked: Boolean! + maintenance: ClientConfigMaintenanceMode } type UsageBreakdownItem { @@ -1961,6 +1969,12 @@ type AdminPanelHealthServiceData { queues: [AdminPanelWorkerQueueHealth!] } +type MaintenanceMode { + startAt: DateTime! + endAt: DateTime! + link: String +} + type ModelsDevModelSuggestion { modelId: String! name: String! @@ -3225,6 +3239,7 @@ type Query { getModelsDevProviders: [ModelsDevProviderSuggestion!]! getModelsDevSuggestions(providerType: String!): [ModelsDevModelSuggestion!]! getAdminAiUsageByWorkspace(periodStart: DateTime, periodEnd: DateTime): [UsageBreakdownItem!]! + getMaintenanceMode: MaintenanceMode getUsageAnalytics(input: UsageAnalyticsInput): UsageAnalytics! getPostgresCredentials: PostgresCredentials findManyPublicDomains: [PublicDomain!]! @@ -3545,6 +3560,8 @@ type Mutation { removeAiProvider(providerName: String!): Boolean! addModelToProvider(providerName: String!, modelConfig: JSON!): Boolean! removeModelFromProvider(providerName: String!, modelName: String!): Boolean! + setMaintenanceMode(startAt: DateTime!, endAt: DateTime!, link: String): Boolean! + clearMaintenanceMode: Boolean! enablePostgresProxy: PostgresCredentials! disablePostgresProxy: PostgresCredentials! createPublicDomain(domain: String!): PublicDomain! diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 28984f6949..629156e268 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -1424,6 +1424,13 @@ export interface PublicFeatureFlag { export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_GRAPHQL_QUERY_TIMING_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED' +export interface ClientConfigMaintenanceMode { + startAt: Scalars['DateTime'] + endAt: Scalars['DateTime'] + link?: Scalars['String'] + __typename: 'ClientConfigMaintenanceMode' +} + export interface ClientConfig { appVersion?: Scalars['String'] authProviders: AuthProviders @@ -1452,6 +1459,8 @@ export interface ClientConfig { calendarBookingPageId?: Scalars['String'] isCloudflareIntegrationEnabled: Scalars['Boolean'] isClickHouseConfigured: Scalars['Boolean'] + isWorkspaceSchemaDDLLocked: Scalars['Boolean'] + maintenance?: ClientConfigMaintenanceMode __typename: 'ClientConfig' } @@ -1621,6 +1630,13 @@ export interface AdminPanelHealthServiceData { __typename: 'AdminPanelHealthServiceData' } +export interface MaintenanceMode { + startAt: Scalars['DateTime'] + endAt: Scalars['DateTime'] + link?: Scalars['String'] + __typename: 'MaintenanceMode' +} + export interface ModelsDevModelSuggestion { modelId: Scalars['String'] name: Scalars['String'] @@ -2776,6 +2792,7 @@ export interface Query { getModelsDevProviders: ModelsDevProviderSuggestion[] getModelsDevSuggestions: ModelsDevModelSuggestion[] getAdminAiUsageByWorkspace: UsageBreakdownItem[] + getMaintenanceMode?: MaintenanceMode getUsageAnalytics: UsageAnalytics getPostgresCredentials?: PostgresCredentials findManyPublicDomains: PublicDomain[] @@ -2991,6 +3008,8 @@ export interface Mutation { removeAiProvider: Scalars['Boolean'] addModelToProvider: Scalars['Boolean'] removeModelFromProvider: Scalars['Boolean'] + setMaintenanceMode: Scalars['Boolean'] + clearMaintenanceMode: Scalars['Boolean'] enablePostgresProxy: PostgresCredentials disablePostgresProxy: PostgresCredentials createPublicDomain: PublicDomain @@ -4508,6 +4527,14 @@ export interface PublicFeatureFlagGenqlSelection{ __scalar?: boolean | number } +export interface ClientConfigMaintenanceModeGenqlSelection{ + startAt?: boolean | number + endAt?: boolean | number + link?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + export interface ClientConfigGenqlSelection{ appVersion?: boolean | number authProviders?: AuthProvidersGenqlSelection @@ -4536,6 +4563,8 @@ export interface ClientConfigGenqlSelection{ calendarBookingPageId?: boolean | number isCloudflareIntegrationEnabled?: boolean | number isClickHouseConfigured?: boolean | number + isWorkspaceSchemaDDLLocked?: boolean | number + maintenance?: ClientConfigMaintenanceModeGenqlSelection __typename?: boolean | number __scalar?: boolean | number } @@ -4711,6 +4740,14 @@ export interface AdminPanelHealthServiceDataGenqlSelection{ __scalar?: boolean | number } +export interface MaintenanceModeGenqlSelection{ + startAt?: boolean | number + endAt?: boolean | number + link?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + export interface ModelsDevModelSuggestionGenqlSelection{ modelId?: boolean | number name?: boolean | number @@ -5966,6 +6003,7 @@ export interface QueryGenqlSelection{ getModelsDevProviders?: ModelsDevProviderSuggestionGenqlSelection getModelsDevSuggestions?: (ModelsDevModelSuggestionGenqlSelection & { __args: {providerType: Scalars['String']} }) getAdminAiUsageByWorkspace?: (UsageBreakdownItemGenqlSelection & { __args?: {periodStart?: (Scalars['DateTime'] | null), periodEnd?: (Scalars['DateTime'] | null)} }) + getMaintenanceMode?: MaintenanceModeGenqlSelection getUsageAnalytics?: (UsageAnalyticsGenqlSelection & { __args?: {input?: (UsageAnalyticsInput | null)} }) getPostgresCredentials?: PostgresCredentialsGenqlSelection findManyPublicDomains?: PublicDomainGenqlSelection @@ -6200,6 +6238,8 @@ export interface MutationGenqlSelection{ removeAiProvider?: { __args: {providerName: Scalars['String']} } addModelToProvider?: { __args: {providerName: Scalars['String'], modelConfig: Scalars['JSON']} } removeModelFromProvider?: { __args: {providerName: Scalars['String'], modelName: Scalars['String']} } + setMaintenanceMode?: { __args: {startAt: Scalars['DateTime'], endAt: Scalars['DateTime'], link?: (Scalars['String'] | null)} } + clearMaintenanceMode?: boolean | number enablePostgresProxy?: PostgresCredentialsGenqlSelection disablePostgresProxy?: PostgresCredentialsGenqlSelection createPublicDomain?: (PublicDomainGenqlSelection & { __args: {domain: Scalars['String']} }) @@ -7502,6 +7542,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null + const ClientConfigMaintenanceMode_possibleTypes: string[] = ['ClientConfigMaintenanceMode'] + export const isClientConfigMaintenanceMode = (obj?: { __typename?: any } | null): obj is ClientConfigMaintenanceMode => { + if (!obj?.__typename) throw new Error('__typename is missing in "isClientConfigMaintenanceMode"') + return ClientConfigMaintenanceMode_possibleTypes.includes(obj.__typename) + } + + + const ClientConfig_possibleTypes: string[] = ['ClientConfig'] export const isClientConfig = (obj?: { __typename?: any } | null): obj is ClientConfig => { if (!obj?.__typename) throw new Error('__typename is missing in "isClientConfig"') @@ -7662,6 +7710,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null + const MaintenanceMode_possibleTypes: string[] = ['MaintenanceMode'] + export const isMaintenanceMode = (obj?: { __typename?: any } | null): obj is MaintenanceMode => { + if (!obj?.__typename) throw new Error('__typename is missing in "isMaintenanceMode"') + return MaintenanceMode_possibleTypes.includes(obj.__typename) + } + + + const ModelsDevModelSuggestion_possibleTypes: string[] = ['ModelsDevModelSuggestion'] export const isModelsDevModelSuggestion = (obj?: { __typename?: any } | null): obj is ModelsDevModelSuggestion => { if (!obj?.__typename) throw new Error('__typename is missing in "isModelsDevModelSuggestion"') diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index 2c65955b40..8e313d11eb 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -54,43 +54,43 @@ export default { 171, 174, 178, - 182, 183, - 185, - 190, - 195, + 184, + 186, + 191, 196, - 211, - 228, - 245, - 281, - 282, - 293, - 294, - 322, - 323, + 197, + 213, + 230, + 247, + 283, + 284, + 295, + 296, 324, 325, - 328, - 329, + 326, + 327, 330, 331, 332, 333, 334, + 335, 336, 338, - 346, - 352, - 353, + 340, + 348, 354, + 355, 356, - 363, - 370, - 396, - 480, - 485, - 486 + 358, + 365, + 372, + 398, + 482, + 487, + 488 ], "types": { "BillingProductDTO": { @@ -782,10 +782,10 @@ export default { 3 ], "relation": [ - 244 + 246 ], "morphRelations": [ - 244 + 246 ], "object": [ 46 @@ -844,7 +844,7 @@ export default { 36 ], "objectMetadata": [ - 237, + 239, { "paging": [ 39, @@ -857,7 +857,7 @@ export default { } ], "indexFieldMetadatas": [ - 235, + 237, { "paging": [ 39, @@ -1102,7 +1102,7 @@ export default { 37 ], "fields": [ - 242, + 244, { "paging": [ 39, @@ -1115,7 +1115,7 @@ export default { } ], "indexMetadatas": [ - 240, + 242, { "paging": [ 39, @@ -1687,7 +1687,7 @@ export default { 49 ], "featureFlags": [ - 198 + 199 ], "billingSubscriptions": [ 130 @@ -1696,7 +1696,7 @@ export default { 130 ], "billingEntitlements": [ - 227 + 229 ], "hasValidEnterpriseKey": [ 6 @@ -1800,7 +1800,7 @@ export default { 20 ], "deletedWorkspaceMembers": [ - 226 + 228 ], "hasPassword": [ 6 @@ -1812,7 +1812,7 @@ export default { 17 ], "availableWorkspaces": [ - 225 + 227 ], "__typename": [ 1 @@ -3464,6 +3464,20 @@ export default { ] }, "FeatureFlagKey": {}, + "ClientConfigMaintenanceMode": { + "startAt": [ + 4 + ], + "endAt": [ + 4 + ], + "link": [ + 1 + ], + "__typename": [ + 1 + ] + }, "ClientConfig": { "appVersion": [ 1 @@ -3546,6 +3560,12 @@ export default { "isClickHouseConfigured": [ 6 ], + "isWorkspaceSchemaDDLLocked": [ + 6 + ], + "maintenance": [ + 179 + ], "__typename": [ 1 ] @@ -3578,13 +3598,13 @@ export default { 6 ], "source": [ - 182 + 183 ], "isEnvOnly": [ 6 ], "type": [ - 183 + 184 ], "options": [ 15 @@ -3597,10 +3617,10 @@ export default { "ConfigVariableType": {}, "ConfigVariablesGroupData": { "variables": [ - 181 + 182 ], "name": [ - 185 + 186 ], "description": [ 1 @@ -3615,7 +3635,7 @@ export default { "ConfigVariablesGroup": {}, "ConfigVariables": { "groups": [ - 184 + 185 ], "__typename": [ 1 @@ -3640,7 +3660,7 @@ export default { 21 ], "results": [ - 187 + 188 ], "__typename": [ 1 @@ -3657,7 +3677,7 @@ export default { 15 ], "state": [ - 190 + 191 ], "timestamp": [ 11 @@ -3707,7 +3727,7 @@ export default { }, "QueueJobsResponse": { "jobs": [ - 189 + 190 ], "count": [ 11 @@ -3719,7 +3739,7 @@ export default { 6 ], "retentionConfig": [ - 191 + 192 ], "__typename": [ 1 @@ -3730,7 +3750,7 @@ export default { 21 ], "results": [ - 187 + 188 ], "__typename": [ 1 @@ -3738,13 +3758,13 @@ export default { }, "SystemHealthService": { "id": [ - 195 + 196 ], "label": [ 1 ], "status": [ - 196 + 197 ], "__typename": [ 1 @@ -3754,7 +3774,7 @@ export default { "AdminPanelHealthServiceStatus": {}, "SystemHealth": { "services": [ - 194 + 195 ], "__typename": [ 1 @@ -3808,10 +3828,10 @@ export default { 157 ], "users": [ - 199 + 200 ], "featureFlags": [ - 198 + 199 ], "__typename": [ 1 @@ -3819,10 +3839,10 @@ export default { }, "UserLookup": { "user": [ - 199 + 200 ], "workspaces": [ - 200 + 201 ], "__typename": [ 1 @@ -3847,7 +3867,7 @@ export default { 1 ], "status": [ - 196 + 197 ], "__typename": [ 1 @@ -3855,7 +3875,7 @@ export default { }, "AdminPanelHealthServiceData": { "id": [ - 195 + 196 ], "label": [ 1 @@ -3864,7 +3884,7 @@ export default { 1 ], "status": [ - 196 + 197 ], "errorMessage": [ 1 @@ -3873,7 +3893,21 @@ export default { 1 ], "queues": [ - 203 + 204 + ], + "__typename": [ + 1 + ] + }, + "MaintenanceMode": { + "startAt": [ + 4 + ], + "endAt": [ + 4 + ], + "link": [ + 1 ], "__typename": [ 1 @@ -3944,7 +3978,7 @@ export default { 1 ], "data": [ - 207 + 209 ], "__typename": [ 1 @@ -3987,13 +4021,13 @@ export default { 11 ], "timeRange": [ - 211 + 213 ], "details": [ - 209 + 211 ], "data": [ - 208 + 210 ], "__typename": [ 1 @@ -4019,7 +4053,7 @@ export default { 1 ], "versionDistribution": [ - 212 + 214 ], "__typename": [ 1 @@ -4128,7 +4162,7 @@ export default { 160 ], "workspace": [ - 220 + 222 ], "__typename": [ 1 @@ -4197,7 +4231,7 @@ export default { 1 ], "sso": [ - 223 + 225 ], "__typename": [ 1 @@ -4205,10 +4239,10 @@ export default { }, "AvailableWorkspaces": { "availableWorkspacesForSignIn": [ - 224 + 226 ], "availableWorkspacesForSignUp": [ - 224 + 226 ], "__typename": [ 1 @@ -4236,7 +4270,7 @@ export default { }, "BillingEntitlement": { "key": [ - 228 + 230 ], "value": [ 6 @@ -4274,7 +4308,7 @@ export default { 1 ], "records": [ - 229 + 231 ], "__typename": [ 1 @@ -4310,10 +4344,10 @@ export default { }, "IndexConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 231 + 233 ], "__typename": [ 1 @@ -4332,10 +4366,10 @@ export default { }, "IndexIndexFieldMetadatasConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 234 + 236 ], "__typename": [ 1 @@ -4354,10 +4388,10 @@ export default { }, "IndexObjectMetadataConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 236 + 238 ], "__typename": [ 1 @@ -4376,10 +4410,10 @@ export default { }, "ObjectConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 236 + 238 ], "__typename": [ 1 @@ -4387,10 +4421,10 @@ export default { }, "ObjectIndexMetadatasConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 231 + 233 ], "__typename": [ 1 @@ -4409,10 +4443,10 @@ export default { }, "ObjectFieldsConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 241 + 243 ], "__typename": [ 1 @@ -4431,7 +4465,7 @@ export default { }, "Relation": { "type": [ - 245 + 247 ], "sourceObjectMetadata": [ 46 @@ -4452,10 +4486,10 @@ export default { "RelationType": {}, "FieldConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 241 + 243 ], "__typename": [ 1 @@ -4514,10 +4548,10 @@ export default { }, "AuthTokenPair": { "accessOrWorkspaceAgnosticToken": [ - 252 + 254 ], "refreshToken": [ - 252 + 254 ], "__typename": [ 1 @@ -4525,10 +4559,10 @@ export default { }, "AvailableWorkspacesAndAccessTokens": { "tokens": [ - 253 + 255 ], "availableWorkspaces": [ - 225 + 227 ], "__typename": [ 1 @@ -4577,10 +4611,10 @@ export default { }, "SignUp": { "loginToken": [ - 252 + 254 ], "workspace": [ - 258 + 260 ], "__typename": [ 1 @@ -4588,7 +4622,7 @@ export default { }, "TransientToken": { "transientToken": [ - 252 + 254 ], "__typename": [ 1 @@ -4610,7 +4644,7 @@ export default { }, "VerifyEmailAndGetLoginToken": { "loginToken": [ - 252 + 254 ], "workspaceUrls": [ 157 @@ -4629,7 +4663,7 @@ export default { }, "AuthTokens": { "tokens": [ - 253 + 255 ], "__typename": [ 1 @@ -4637,7 +4671,7 @@ export default { }, "LoginToken": { "loginToken": [ - 252 + 254 ], "__typename": [ 1 @@ -4667,10 +4701,10 @@ export default { }, "Impersonate": { "loginToken": [ - 252 + 254 ], "workspace": [ - 258 + 260 ], "__typename": [ 1 @@ -4692,7 +4726,7 @@ export default { 1 ], "dailyUsage": [ - 269 + 271 ], "__typename": [ 1 @@ -4700,16 +4734,16 @@ export default { }, "UsageAnalytics": { "usageByUser": [ - 180 + 181 ], "usageByOperationType": [ - 180 + 181 ], "usageByModel": [ - 180 + 181 ], "timeSeries": [ - 269 + 271 ], "periodStart": [ 4 @@ -4718,7 +4752,7 @@ export default { 4 ], "userDailyUsage": [ - 270 + 272 ], "__typename": [ 1 @@ -4748,10 +4782,10 @@ export default { }, "ApplicationTokenPair": { "applicationAccessToken": [ - 252 + 254 ], "applicationRefreshToken": [ - 252 + 254 ], "__typename": [ 1 @@ -4886,13 +4920,13 @@ export default { 1 ], "driver": [ - 281 + 283 ], "status": [ - 282 + 284 ], "verificationRecords": [ - 279 + 281 ], "verifiedAt": [ 4 @@ -4939,7 +4973,7 @@ export default { 1 ], "location": [ - 284 + 286 ], "__typename": [ 1 @@ -4967,13 +5001,13 @@ export default { }, "ImapSmtpCaldavConnectionParameters": { "IMAP": [ - 286 + 288 ], "SMTP": [ - 286 + 288 ], "CALDAV": [ - 286 + 288 ], "__typename": [ 1 @@ -4993,7 +5027,7 @@ export default { 3 ], "connectionParameters": [ - 287 + 289 ], "__typename": [ 1 @@ -5068,7 +5102,7 @@ export default { 6 ], "applicationTokenPair": [ - 274 + 276 ], "__typename": [ 1 @@ -5085,10 +5119,10 @@ export default { 3 ], "frontComponent": [ - 291 + 293 ], "engineComponentKey": [ - 293 + 295 ], "label": [ 1 @@ -5106,7 +5140,7 @@ export default { 6 ], "availabilityType": [ - 294 + 296 ], "hotKeys": [ 1 @@ -5265,7 +5299,7 @@ export default { 1 ], "series": [ - 298 + 300 ], "xAxisLabel": [ 1 @@ -5314,7 +5348,7 @@ export default { 1 ], "data": [ - 300 + 302 ], "__typename": [ 1 @@ -5322,7 +5356,7 @@ export default { }, "LineChartData": { "series": [ - 301 + 303 ], "xAxisLabel": [ 1 @@ -5359,7 +5393,7 @@ export default { }, "PieChartData": { "data": [ - 303 + 305 ], "showLegend": [ 6 @@ -5442,13 +5476,13 @@ export default { }, "EventLogQueryResult": { "records": [ - 306 + 308 ], "totalCount": [ 21 ], "pageInfo": [ - 307 + 309 ], "__typename": [ 1 @@ -5547,7 +5581,7 @@ export default { 1 ], "parts": [ - 296 + 298 ], "processedAt": [ 4 @@ -5575,7 +5609,7 @@ export default { }, "AISystemPromptPreview": { "sections": [ - 312 + 314 ], "estimatedTokenCount": [ 21 @@ -5622,7 +5656,7 @@ export default { }, "AgentChatThreadEdge": { "node": [ - 310 + 312 ], "cursor": [ 40 @@ -5633,10 +5667,10 @@ export default { }, "AgentChatThreadConnection": { "pageInfo": [ - 232 + 234 ], "edges": [ - 317 + 319 ], "__typename": [ 1 @@ -5673,10 +5707,10 @@ export default { 3 ], "evaluations": [ - 319 + 321 ], "messages": [ - 311 + 313 ], "createdAt": [ 4 @@ -5693,19 +5727,19 @@ export default { 1 ], "syncStatus": [ - 322 + 324 ], "syncStage": [ - 323 + 325 ], "visibility": [ - 324 + 326 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 325 + 327 ], "isSyncEnabled": [ 6 @@ -5779,22 +5813,22 @@ export default { 3 ], "visibility": [ - 328 + 330 ], "handle": [ 1 ], "type": [ - 329 + 331 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 330 + 332 ], "messageFolderImportPolicy": [ - 331 + 333 ], "excludeNonProfessionalEmails": [ 6 @@ -5803,7 +5837,7 @@ export default { 6 ], "pendingGroupEmailsAction": [ - 332 + 334 ], "isSyncEnabled": [ 6 @@ -5812,10 +5846,10 @@ export default { 4 ], "syncStatus": [ - 333 + 335 ], "syncStage": [ - 334 + 336 ], "syncStageStartedAt": [ 4 @@ -5866,7 +5900,7 @@ export default { 1 ], "pendingSyncAction": [ - 336 + 338 ], "messageChannelId": [ 3 @@ -5884,7 +5918,7 @@ export default { "MessageFolderPendingSyncAction": {}, "CollectionHash": { "collectionName": [ - 338 + 340 ], "hash": [ 1 @@ -5951,13 +5985,13 @@ export default { }, "MinimalMetadata": { "objectMetadataItems": [ - 339 + 341 ], "views": [ - 340 + 342 ], "collectionHashes": [ - 337 + 339 ], "__typename": [ 1 @@ -6105,7 +6139,7 @@ export default { 2, { "input": [ - 344, + 346, "GetApiKeyInput!" ] } @@ -6209,7 +6243,7 @@ export default { 32, { "input": [ - 345, + 347, "LogicFunctionIdInput!" ] } @@ -6221,7 +6255,7 @@ export default { 15, { "input": [ - 345, + 347, "LogicFunctionIdInput!" ] } @@ -6230,16 +6264,16 @@ export default { 1, { "input": [ - 345, + 347, "LogicFunctionIdInput!" ] } ], "commandMenuItems": [ - 292 + 294 ], "commandMenuItem": [ - 292, + 294, { "id": [ 3, @@ -6248,10 +6282,10 @@ export default { } ], "frontComponents": [ - 291 + 293 ], "frontComponent": [ - 291, + 293, { "id": [ 3, @@ -6260,7 +6294,7 @@ export default { } ], "objectRecordCounts": [ - 238 + 240 ], "object": [ 46, @@ -6272,7 +6306,7 @@ export default { } ], "objects": [ - 239, + 241, { "paging": [ 39, @@ -6312,7 +6346,7 @@ export default { } ], "indexMetadatas": [ - 233, + 235, { "paging": [ 39, @@ -6331,7 +6365,7 @@ export default { 25, { "input": [ - 347, + 349, "AgentIdInput!" ] } @@ -6340,7 +6374,7 @@ export default { 29 ], "getToolIndex": [ - 295 + 297 ], "getToolInputSchema": [ 15, @@ -6361,7 +6395,7 @@ export default { } ], "fields": [ - 246, + 248, { "paging": [ 39, @@ -6391,7 +6425,7 @@ export default { } ], "myMessageFolders": [ - 335, + 337, { "messageChannelId": [ 3 @@ -6399,7 +6433,7 @@ export default { } ], "myMessageChannels": [ - 327, + 329, { "connectedAccountId": [ 3 @@ -6407,13 +6441,13 @@ export default { } ], "myConnectedAccounts": [ - 326 + 328 ], "connectedAccounts": [ - 326 + 328 ], "myCalendarChannels": [ - 321, + 323, { "connectedAccountId": [ 3 @@ -6421,10 +6455,10 @@ export default { } ], "webhooks": [ - 342 + 344 ], "webhook": [ - 342, + 344, { "id": [ 3, @@ -6433,10 +6467,10 @@ export default { } ], "minimalMetadata": [ - 341 + 343 ], "chatThread": [ - 310, + 312, { "id": [ 3, @@ -6445,7 +6479,7 @@ export default { } ], "chatMessages": [ - 311, + 313, { "threadId": [ 3, @@ -6454,7 +6488,7 @@ export default { } ], "chatStreamCatchupChunks": [ - 314, + 316, { "threadId": [ 3, @@ -6463,13 +6497,13 @@ export default { } ], "getAISystemPromptPreview": [ - 313 + 315 ], "skills": [ - 309 + 311 ], "skill": [ - 309, + 311, { "id": [ 3, @@ -6478,24 +6512,24 @@ export default { } ], "chatThreads": [ - 318, + 320, { "paging": [ 39, "CursorPaging!" ], "filter": [ - 348, + 350, "AgentChatThreadFilter!" ], "sorting": [ - 351, + 353, "[AgentChatThreadSort!]!" ] } ], "agentTurns": [ - 320, + 322, { "agentId": [ 3, @@ -6504,43 +6538,43 @@ export default { } ], "eventLogs": [ - 308, + 310, { "input": [ - 355, + 357, "EventLogQueryInput!" ] } ], "pieChartData": [ - 304, + 306, { "input": [ - 359, + 361, "PieChartDataInput!" ] } ], "lineChartData": [ - 302, + 304, { "input": [ - 360, + 362, "LineChartDataInput!" ] } ], "barChartData": [ - 299, + 301, { "input": [ - 361, + 363, "BarChartDataInput!" ] } ], "checkUserExists": [ - 266, + 268, { "email": [ 1, @@ -6552,7 +6586,7 @@ export default { } ], "checkWorkspaceInviteHashIsValid": [ - 267, + 269, { "inviteHash": [ 1, @@ -6570,7 +6604,7 @@ export default { } ], "validatePasswordResetToken": [ - 261, + 263, { "passwordResetToken": [ 1, @@ -6579,7 +6613,7 @@ export default { } ], "findApplicationRegistrationByClientId": [ - 215, + 217, { "clientId": [ 1, @@ -6609,7 +6643,7 @@ export default { } ], "findApplicationRegistrationStats": [ - 213, + 215, { "id": [ 1, @@ -6659,10 +6693,10 @@ export default { } ], "getSSOIdentityProviders": [ - 221 + 223 ], "getConnectedImapSmtpCaldavAccount": [ - 288, + 290, { "id": [ 3, @@ -6671,7 +6705,7 @@ export default { } ], "getAutoCompleteAddress": [ - 283, + 285, { "address": [ 1, @@ -6690,7 +6724,7 @@ export default { } ], "getAddressDetails": [ - 285, + 287, { "placeId": [ 1, @@ -6703,40 +6737,40 @@ export default { } ], "getConfigVariablesGrouped": [ - 186 + 187 ], "getSystemHealthStatus": [ - 197 + 198 ], "getIndicatorHealthStatus": [ - 204, + 205, { "indicatorId": [ - 195, + 196, "HealthIndicatorId!" ] } ], "getQueueMetrics": [ - 210, + 212, { "queueName": [ 1, "String!" ], "timeRange": [ - 211 + 213 ] } ], "versionInfo": [ - 202 + 203 ], "getAdminAiModels": [ 168 ], "getDatabaseConfigVariable": [ - 181, + 182, { "key": [ 1, @@ -6745,14 +6779,14 @@ export default { } ], "getQueueJobs": [ - 192, + 193, { "queueName": [ 1, "String!" ], "state": [ - 190, + 191, "JobState!" ], "limit": [ @@ -6770,10 +6804,10 @@ export default { 15 ], "getModelsDevProviders": [ - 206 + 208 ], "getModelsDevSuggestions": [ - 205, + 207, { "providerType": [ 1, @@ -6782,7 +6816,7 @@ export default { } ], "getAdminAiUsageByWorkspace": [ - 180, + 181, { "periodStart": [ 4 @@ -6792,28 +6826,31 @@ export default { ] } ], + "getMaintenanceMode": [ + 206 + ], "getUsageAnalytics": [ - 271, + 273, { "input": [ - 362 + 364 ] } ], "getPostgresCredentials": [ - 290 + 292 ], "findManyPublicDomains": [ - 278 - ], - "getEmailingDomains": [ 280 ], + "getEmailingDomains": [ + 282 + ], "findManyMarketplaceApps": [ - 276 + 278 ], "findMarketplaceAppDetail": [ - 277, + 279, { "universalIdentifier": [ 1, @@ -6849,7 +6886,7 @@ export default { }, "LogicFunctionIdInput": { "id": [ - 346 + 348 ], "__typename": [ 1 @@ -6866,16 +6903,16 @@ export default { }, "AgentChatThreadFilter": { "and": [ - 348 + 350 ], "or": [ - 348 + 350 ], "id": [ 42 ], "updatedAt": [ - 349 + 351 ], "__typename": [ 1 @@ -6913,10 +6950,10 @@ export default { 4 ], "between": [ - 350 + 352 ], "notBetween": [ - 350 + 352 ], "__typename": [ 1 @@ -6935,13 +6972,13 @@ export default { }, "AgentChatThreadSort": { "field": [ - 352 + 354 ], "direction": [ - 353 + 355 ], "nulls": [ - 354 + 356 ], "__typename": [ 1 @@ -6952,10 +6989,10 @@ export default { "SortNulls": {}, "EventLogQueryInput": { "table": [ - 356 + 358 ], "filters": [ - 357 + 359 ], "first": [ 21 @@ -6976,7 +7013,7 @@ export default { 1 ], "dateRange": [ - 358 + 360 ], "recordId": [ 1 @@ -7043,7 +7080,7 @@ export default { 1 ], "operationTypes": [ - 363 + 365 ], "__typename": [ 1 @@ -7055,7 +7092,7 @@ export default { 6, { "input": [ - 365, + 367, "AddQuerySubscriptionInput!" ] } @@ -7064,7 +7101,7 @@ export default { 6, { "input": [ - 366, + 368, "RemoveQueryFromEventStreamInput!" ] } @@ -7073,7 +7110,7 @@ export default { 145, { "inputs": [ - 367, + 369, "[CreateNavigationMenuItemInput!]!" ] } @@ -7082,7 +7119,7 @@ export default { 145, { "input": [ - 367, + 369, "CreateNavigationMenuItemInput!" ] } @@ -7091,7 +7128,7 @@ export default { 145, { "inputs": [ - 368, + 370, "[UpdateOneNavigationMenuItemInput!]!" ] } @@ -7100,7 +7137,7 @@ export default { 145, { "input": [ - 368, + 370, "UpdateOneNavigationMenuItemInput!" ] } @@ -7127,7 +7164,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ] } @@ -7136,7 +7173,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ] } @@ -7145,7 +7182,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ] } @@ -7154,7 +7191,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ] } @@ -7163,7 +7200,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ], "fieldMetadataId": [ @@ -7176,7 +7213,7 @@ export default { 141, { "file": [ - 370, + 372, "Upload!" ], "fieldMetadataUniversalIdentifier": [ @@ -7189,7 +7226,7 @@ export default { 52, { "input": [ - 371, + 373, "CreateViewFilterGroupInput!" ] } @@ -7202,7 +7239,7 @@ export default { "String!" ], "input": [ - 372, + 374, "UpdateViewFilterGroupInput!" ] } @@ -7229,7 +7266,7 @@ export default { 54, { "input": [ - 373, + 375, "CreateViewFilterInput!" ] } @@ -7238,7 +7275,7 @@ export default { 54, { "input": [ - 374, + 376, "UpdateViewFilterInput!" ] } @@ -7247,7 +7284,7 @@ export default { 54, { "input": [ - 376, + 378, "DeleteViewFilterInput!" ] } @@ -7256,7 +7293,7 @@ export default { 54, { "input": [ - 377, + 379, "DestroyViewFilterInput!" ] } @@ -7265,7 +7302,7 @@ export default { 60, { "input": [ - 378, + 380, "CreateViewInput!" ] } @@ -7278,7 +7315,7 @@ export default { "String!" ], "input": [ - 379, + 381, "UpdateViewInput!" ] } @@ -7305,7 +7342,7 @@ export default { 57, { "input": [ - 380, + 382, "CreateViewSortInput!" ] } @@ -7314,7 +7351,7 @@ export default { 57, { "input": [ - 381, + 383, "UpdateViewSortInput!" ] } @@ -7323,7 +7360,7 @@ export default { 6, { "input": [ - 383, + 385, "DeleteViewSortInput!" ] } @@ -7332,7 +7369,7 @@ export default { 6, { "input": [ - 384, + 386, "DestroyViewSortInput!" ] } @@ -7341,7 +7378,7 @@ export default { 59, { "input": [ - 385, + 387, "UpdateViewFieldGroupInput!" ] } @@ -7350,7 +7387,7 @@ export default { 59, { "input": [ - 387, + 389, "CreateViewFieldGroupInput!" ] } @@ -7359,7 +7396,7 @@ export default { 59, { "inputs": [ - 387, + 389, "[CreateViewFieldGroupInput!]!" ] } @@ -7368,7 +7405,7 @@ export default { 59, { "input": [ - 388, + 390, "DeleteViewFieldGroupInput!" ] } @@ -7377,7 +7414,7 @@ export default { 59, { "input": [ - 389, + 391, "DestroyViewFieldGroupInput!" ] } @@ -7386,7 +7423,7 @@ export default { 60, { "input": [ - 390, + 392, "UpsertFieldsWidgetInput!" ] } @@ -7395,7 +7432,7 @@ export default { 2, { "input": [ - 393, + 395, "CreateApiKeyInput!" ] } @@ -7404,7 +7441,7 @@ export default { 2, { "input": [ - 394, + 396, "UpdateApiKeyInput!" ] } @@ -7413,7 +7450,7 @@ export default { 2, { "input": [ - 395, + 397, "RevokeApiKeyInput!" ] } @@ -7455,7 +7492,7 @@ export default { 115, { "type": [ - 396, + 398, "AnalyticsType!" ], "name": [ @@ -7568,7 +7605,7 @@ export default { 140, { "input": [ - 397, + 399, "CreateApprovedAccessDomainInput!" ] } @@ -7577,7 +7614,7 @@ export default { 6, { "input": [ - 398, + 400, "DeleteApprovedAccessDomainInput!" ] } @@ -7586,7 +7623,7 @@ export default { 140, { "input": [ - 399, + 401, "ValidateApprovedAccessDomainInput!" ] } @@ -7595,7 +7632,7 @@ export default { 112, { "input": [ - 400, + 402, "CreatePageLayoutTabInput!" ] } @@ -7608,7 +7645,7 @@ export default { "String!" ], "input": [ - 401, + 403, "UpdatePageLayoutTabInput!" ] } @@ -7626,7 +7663,7 @@ export default { 113, { "input": [ - 402, + 404, "CreatePageLayoutInput!" ] } @@ -7639,7 +7676,7 @@ export default { "String!" ], "input": [ - 403, + 405, "UpdatePageLayoutInput!" ] } @@ -7661,7 +7698,7 @@ export default { "String!" ], "input": [ - 404, + 406, "UpdatePageLayoutWithTabsInput!" ] } @@ -7670,7 +7707,7 @@ export default { 75, { "input": [ - 408, + 410, "CreatePageLayoutWidgetInput!" ] } @@ -7683,7 +7720,7 @@ export default { "String!" ], "input": [ - 409, + 411, "UpdatePageLayoutWidgetInput!" ] } @@ -7701,7 +7738,7 @@ export default { 32, { "input": [ - 345, + 347, "LogicFunctionIdInput!" ] } @@ -7710,7 +7747,7 @@ export default { 32, { "input": [ - 410, + 412, "CreateLogicFunctionFromSourceInput!" ] } @@ -7719,7 +7756,7 @@ export default { 154, { "input": [ - 411, + 413, "ExecuteOneLogicFunctionInput!" ] } @@ -7728,31 +7765,31 @@ export default { 6, { "input": [ - 412, + 414, "UpdateLogicFunctionFromSourceInput!" ] } ], "createCommandMenuItem": [ - 292, + 294, { "input": [ - 414, + 416, "CreateCommandMenuItemInput!" ] } ], "updateCommandMenuItem": [ - 292, + 294, { "input": [ - 415, + 417, "UpdateCommandMenuItemInput!" ] } ], "deleteCommandMenuItem": [ - 292, + 294, { "id": [ 3, @@ -7761,25 +7798,25 @@ export default { } ], "createFrontComponent": [ - 291, + 293, { "input": [ - 416, + 418, "CreateFrontComponentInput!" ] } ], "updateFrontComponent": [ - 291, + 293, { "input": [ - 417, + 419, "UpdateFrontComponentInput!" ] } ], "deleteFrontComponent": [ - 291, + 293, { "id": [ 3, @@ -7791,7 +7828,7 @@ export default { 46, { "input": [ - 419, + 421, "CreateOneObjectInput!" ] } @@ -7800,7 +7837,7 @@ export default { 46, { "input": [ - 421, + 423, "DeleteOneObjectInput!" ] } @@ -7809,7 +7846,7 @@ export default { 46, { "input": [ - 422, + 424, "UpdateOneObjectInput!" ] } @@ -7818,7 +7855,7 @@ export default { 50, { "input": [ - 424, + 426, "UpdateViewFieldInput!" ] } @@ -7827,7 +7864,7 @@ export default { 50, { "input": [ - 426, + 428, "CreateViewFieldInput!" ] } @@ -7836,7 +7873,7 @@ export default { 50, { "inputs": [ - 426, + 428, "[CreateViewFieldInput!]!" ] } @@ -7845,7 +7882,7 @@ export default { 50, { "input": [ - 427, + 429, "DeleteViewFieldInput!" ] } @@ -7854,7 +7891,7 @@ export default { 50, { "input": [ - 428, + 430, "DestroyViewFieldInput!" ] } @@ -7863,7 +7900,7 @@ export default { 25, { "input": [ - 429, + 431, "CreateAgentInput!" ] } @@ -7872,7 +7909,7 @@ export default { 25, { "input": [ - 430, + 432, "UpdateAgentInput!" ] } @@ -7881,7 +7918,7 @@ export default { 25, { "input": [ - 347, + 349, "AgentIdInput!" ] } @@ -7903,7 +7940,7 @@ export default { 29, { "createRoleInput": [ - 431, + 433, "CreateRoleInput!" ] } @@ -7912,7 +7949,7 @@ export default { 29, { "updateRoleInput": [ - 432, + 434, "UpdateRoleInput!" ] } @@ -7930,7 +7967,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 434, + 436, "UpsertObjectPermissionsInput!" ] } @@ -7939,7 +7976,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 436, + 438, "UpsertPermissionFlagsInput!" ] } @@ -7948,16 +7985,16 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 437, + 439, "UpsertFieldPermissionsInput!" ] } ], "upsertRowLevelPermissionPredicates": [ - 243, + 245, { "input": [ - 439, + 441, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -7988,7 +8025,7 @@ export default { 34, { "input": [ - 442, + 444, "CreateOneFieldMetadataInput!" ] } @@ -7997,7 +8034,7 @@ export default { 34, { "input": [ - 444, + 446, "UpdateOneFieldMetadataInput!" ] } @@ -8006,7 +8043,7 @@ export default { 34, { "input": [ - 446, + 448, "DeleteOneFieldInput!" ] } @@ -8015,7 +8052,7 @@ export default { 56, { "input": [ - 447, + 449, "CreateViewGroupInput!" ] } @@ -8024,7 +8061,7 @@ export default { 56, { "inputs": [ - 447, + 449, "[CreateViewGroupInput!]!" ] } @@ -8033,7 +8070,7 @@ export default { 56, { "input": [ - 448, + 450, "UpdateViewGroupInput!" ] } @@ -8042,7 +8079,7 @@ export default { 56, { "inputs": [ - 448, + 450, "[UpdateViewGroupInput!]!" ] } @@ -8051,7 +8088,7 @@ export default { 56, { "input": [ - 450, + 452, "DeleteViewGroupInput!" ] } @@ -8060,40 +8097,40 @@ export default { 56, { "input": [ - 451, + 453, "DestroyViewGroupInput!" ] } ], "updateMessageFolder": [ - 335, + 337, { "input": [ - 452, + 454, "UpdateMessageFolderInput!" ] } ], "updateMessageFolders": [ - 335, + 337, { "input": [ - 454, + 456, "UpdateMessageFoldersInput!" ] } ], "updateMessageChannel": [ - 327, + 329, { "input": [ - 455, + 457, "UpdateMessageChannelInput!" ] } ], "deleteConnectedAccount": [ - 326, + 328, { "id": [ 3, @@ -8102,34 +8139,34 @@ export default { } ], "updateCalendarChannel": [ - 321, + 323, { "input": [ - 457, + 459, "UpdateCalendarChannelInput!" ] } ], "createWebhook": [ - 342, + 344, { "input": [ - 459, + 461, "CreateWebhookInput!" ] } ], "updateWebhook": [ - 342, + 344, { "input": [ - 460, + 462, "UpdateWebhookInput!" ] } ], "deleteWebhook": [ - 342, + 344, { "id": [ 3, @@ -8138,10 +8175,10 @@ export default { } ], "createChatThread": [ - 310 + 312 ], "sendChatMessage": [ - 315, + 317, { "threadId": [ 3, @@ -8182,25 +8219,25 @@ export default { } ], "createSkill": [ - 309, + 311, { "input": [ - 462, + 464, "CreateSkillInput!" ] } ], "updateSkill": [ - 309, + 311, { "input": [ - 463, + 465, "UpdateSkillInput!" ] } ], "deleteSkill": [ - 309, + 311, { "id": [ 3, @@ -8209,7 +8246,7 @@ export default { } ], "activateSkill": [ - 309, + 311, { "id": [ 3, @@ -8218,7 +8255,7 @@ export default { } ], "deactivateSkill": [ - 309, + 311, { "id": [ 3, @@ -8227,7 +8264,7 @@ export default { } ], "evaluateAgentTurn": [ - 319, + 321, { "turnId": [ 3, @@ -8236,7 +8273,7 @@ export default { } ], "runEvaluationInput": [ - 320, + 322, { "agentId": [ 3, @@ -8249,7 +8286,7 @@ export default { } ], "duplicateDashboard": [ - 305, + 307, { "id": [ 3, @@ -8258,16 +8295,16 @@ export default { } ], "getAuthorizationUrlForSSO": [ - 256, + 258, { "input": [ - 464, + 466, "GetAuthorizationUrlForSSOInput!" ] } ], "getLoginTokenFromCredentials": [ - 265, + 267, { "email": [ 1, @@ -8293,7 +8330,7 @@ export default { } ], "signIn": [ - 254, + 256, { "email": [ 1, @@ -8315,7 +8352,7 @@ export default { } ], "verifyEmailAndGetLoginToken": [ - 262, + 264, { "emailVerificationToken": [ 1, @@ -8335,7 +8372,7 @@ export default { } ], "verifyEmailAndGetWorkspaceAgnosticToken": [ - 254, + 256, { "emailVerificationToken": [ 1, @@ -8351,7 +8388,7 @@ export default { } ], "getAuthTokensFromOTP": [ - 264, + 266, { "otp": [ 1, @@ -8371,7 +8408,7 @@ export default { } ], "signUp": [ - 254, + 256, { "email": [ 1, @@ -8393,7 +8430,7 @@ export default { } ], "signUpInWorkspace": [ - 259, + 261, { "email": [ 1, @@ -8424,13 +8461,13 @@ export default { } ], "signUpInNewWorkspace": [ - 259 + 261 ], "generateTransientToken": [ - 260 + 262 ], "getAuthTokensFromLoginToken": [ - 264, + 266, { "loginToken": [ 1, @@ -8443,7 +8480,7 @@ export default { } ], "authorizeApp": [ - 251, + 253, { "clientId": [ 1, @@ -8465,7 +8502,7 @@ export default { } ], "renewToken": [ - 264, + 266, { "appToken": [ 1, @@ -8474,7 +8511,7 @@ export default { } ], "generateApiKeyToken": [ - 263, + 265, { "apiKeyId": [ 3, @@ -8487,7 +8524,7 @@ export default { } ], "emailPasswordResetLink": [ - 255, + 257, { "email": [ 1, @@ -8499,7 +8536,7 @@ export default { } ], "updatePasswordViaResetToken": [ - 257, + 259, { "passwordResetToken": [ 1, @@ -8512,10 +8549,10 @@ export default { } ], "createApplicationRegistration": [ - 214, + 216, { "input": [ - 465, + 467, "CreateApplicationRegistrationInput!" ] } @@ -8524,7 +8561,7 @@ export default { 7, { "input": [ - 466, + 468, "UpdateApplicationRegistrationInput!" ] } @@ -8539,7 +8576,7 @@ export default { } ], "rotateApplicationRegistrationClientSecret": [ - 216, + 218, { "id": [ 1, @@ -8551,7 +8588,7 @@ export default { 5, { "input": [ - 468, + 470, "CreateApplicationRegistrationVariableInput!" ] } @@ -8560,7 +8597,7 @@ export default { 5, { "input": [ - 469, + 471, "UpdateApplicationRegistrationVariableInput!" ] } @@ -8578,7 +8615,7 @@ export default { 7, { "file": [ - 370, + 372, "Upload!" ], "universalIdentifier": [ @@ -8600,7 +8637,7 @@ export default { } ], "initiateOTPProvisioning": [ - 249, + 251, { "loginToken": [ 1, @@ -8613,10 +8650,10 @@ export default { } ], "initiateOTPProvisioningForAuthenticatedUser": [ - 249 + 251 ], "deleteTwoFactorAuthenticationMethod": [ - 248, + 250, { "twoFactorAuthenticationMethodId": [ 3, @@ -8625,7 +8662,7 @@ export default { } ], "verifyTwoFactorAuthenticationMethodForAuthenticatedUser": [ - 250, + 252, { "otp": [ 1, @@ -8658,7 +8695,7 @@ export default { } ], "resendEmailVerificationToken": [ - 217, + 219, { "email": [ 1, @@ -8674,7 +8711,7 @@ export default { 66, { "data": [ - 471, + 473, "ActivateWorkspaceInput!" ] } @@ -8683,7 +8720,7 @@ export default { 66, { "data": [ - 472, + 474, "UpdateWorkspaceInput!" ] } @@ -8692,46 +8729,46 @@ export default { 66 ], "checkCustomDomainValidRecords": [ - 230 + 232 ], "createOIDCIdentityProvider": [ - 222, + 224, { "input": [ - 473, + 475, "SetupOIDCSsoInput!" ] } ], "createSAMLIdentityProvider": [ - 222, + 224, { "input": [ - 474, + 476, "SetupSAMLSsoInput!" ] } ], "deleteSSOIdentityProvider": [ - 218, + 220, { "input": [ - 475, + 477, "DeleteSsoInput!" ] } ], "editSSOIdentityProvider": [ - 219, + 221, { "input": [ - 476, + 478, "EditSsoInput!" ] } ], "impersonate": [ - 268, + 270, { "userId": [ 3, @@ -8744,7 +8781,7 @@ export default { } ], "startChannelSync": [ - 297, + 299, { "connectedAccountId": [ 3, @@ -8753,7 +8790,7 @@ export default { } ], "saveImapSmtpCaldavAccount": [ - 289, + 291, { "accountOwnerId": [ 3, @@ -8764,7 +8801,7 @@ export default { "String!" ], "connectionParameters": [ - 477, + 479, "EmailAccountConnectionParameters!" ], "id": [ @@ -8773,16 +8810,16 @@ export default { } ], "updateLabPublicFeatureFlag": [ - 198, + 199, { "input": [ - 479, + 481, "UpdateLabPublicFeatureFlagInput!" ] } ], "userLookupAdminPanel": [ - 201, + 202, { "userIdentifier": [ 1, @@ -8837,7 +8874,7 @@ export default { 6, { "role": [ - 480, + 482, "AiModelRole!" ], "modelId": [ @@ -8882,7 +8919,7 @@ export default { } ], "retryJobs": [ - 193, + 194, { "queueName": [ 1, @@ -8895,7 +8932,7 @@ export default { } ], "deleteJobs": [ - 188, + 189, { "queueName": [ 1, @@ -8955,14 +8992,33 @@ export default { ] } ], + "setMaintenanceMode": [ + 6, + { + "startAt": [ + 4, + "DateTime!" + ], + "endAt": [ + 4, + "DateTime!" + ], + "link": [ + 1 + ] + } + ], + "clearMaintenanceMode": [ + 6 + ], "enablePostgresProxy": [ - 290 + 292 ], "disablePostgresProxy": [ - 290 + 292 ], "createPublicDomain": [ - 278, + 280, { "domain": [ 1, @@ -8980,7 +9036,7 @@ export default { } ], "checkPublicDomainValidRecords": [ - 230, + 232, { "domain": [ 1, @@ -8989,14 +9045,14 @@ export default { } ], "createEmailingDomain": [ - 280, + 282, { "domain": [ 1, "String!" ], "driver": [ - 281, + 283, "EmailingDomainDriver!" ] } @@ -9011,7 +9067,7 @@ export default { } ], "verifyEmailingDomain": [ - 280, + 282, { "id": [ 1, @@ -9023,7 +9079,7 @@ export default { 68, { "input": [ - 481, + 483, "CreateOneAppTokenInput!" ] } @@ -9059,7 +9115,7 @@ export default { 6, { "workspaceMigration": [ - 483, + 485, "WorkspaceMigrationInput!" ] } @@ -9091,7 +9147,7 @@ export default { } ], "createDevelopmentApplication": [ - 272, + 274, { "universalIdentifier": [ 1, @@ -9104,7 +9160,7 @@ export default { } ], "generateApplicationToken": [ - 274, + 276, { "applicationId": [ 3, @@ -9113,7 +9169,7 @@ export default { } ], "syncApplication": [ - 273, + 275, { "manifest": [ 15, @@ -9122,10 +9178,10 @@ export default { } ], "uploadApplicationFile": [ - 275, + 277, { "file": [ - 370, + 372, "Upload!" ], "applicationUniversalIdentifier": [ @@ -9133,7 +9189,7 @@ export default { "String!" ], "fileFolder": [ - 486, + 488, "FileFolder!" ], "filePath": [ @@ -9156,7 +9212,7 @@ export default { } ], "renewApplicationToken": [ - 274, + 276, { "applicationRefreshToken": [ 1, @@ -9239,7 +9295,7 @@ export default { 3 ], "update": [ - 369 + 371 ], "__typename": [ 1 @@ -9343,7 +9399,7 @@ export default { 3 ], "update": [ - 375 + 377 ], "__typename": [ 1 @@ -9516,7 +9572,7 @@ export default { 3 ], "update": [ - 382 + 384 ], "__typename": [ 1 @@ -9551,7 +9607,7 @@ export default { 3 ], "update": [ - 386 + 388 ], "__typename": [ 1 @@ -9615,10 +9671,10 @@ export default { 3 ], "groups": [ - 391 + 393 ], "fields": [ - 392 + 394 ], "__typename": [ 1 @@ -9638,7 +9694,7 @@ export default { 6 ], "fields": [ - 392 + 394 ], "__typename": [ 1 @@ -9807,7 +9863,7 @@ export default { 3 ], "tabs": [ - 405 + 407 ], "__typename": [ 1 @@ -9830,7 +9886,7 @@ export default { 79 ], "widgets": [ - 406 + 408 ], "__typename": [ 1 @@ -9853,7 +9909,7 @@ export default { 3 ], "gridPosition": [ - 407 + 409 ], "position": [ 15 @@ -9899,7 +9955,7 @@ export default { 3 ], "gridPosition": [ - 407 + 409 ], "position": [ 15 @@ -9922,7 +9978,7 @@ export default { 3 ], "gridPosition": [ - 407 + 409 ], "position": [ 15 @@ -9991,7 +10047,7 @@ export default { 3 ], "update": [ - 413 + 415 ], "__typename": [ 1 @@ -10043,7 +10099,7 @@ export default { 3 ], "engineComponentKey": [ - 293 + 295 ], "label": [ 1 @@ -10061,7 +10117,7 @@ export default { 6 ], "availabilityType": [ - 294 + 296 ], "hotKeys": [ 1 @@ -10096,13 +10152,13 @@ export default { 6 ], "availabilityType": [ - 294 + 296 ], "availabilityObjectMetadataId": [ 3 ], "engineComponentKey": [ - 293 + 295 ], "hotKeys": [ 1 @@ -10142,7 +10198,7 @@ export default { 3 ], "update": [ - 418 + 420 ], "__typename": [ 1 @@ -10161,7 +10217,7 @@ export default { }, "CreateOneObjectInput": { "object": [ - 420 + 422 ], "__typename": [ 1 @@ -10221,7 +10277,7 @@ export default { }, "UpdateOneObjectInput": { "update": [ - 423 + 425 ], "id": [ 3 @@ -10279,7 +10335,7 @@ export default { 3 ], "update": [ - 425 + 427 ], "__typename": [ 1 @@ -10469,7 +10525,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 433 + 435 ], "id": [ 3 @@ -10524,7 +10580,7 @@ export default { 3 ], "objectPermissions": [ - 435 + 437 ], "__typename": [ 1 @@ -10566,7 +10622,7 @@ export default { 3 ], "fieldPermissions": [ - 438 + 440 ], "__typename": [ 1 @@ -10597,10 +10653,10 @@ export default { 3 ], "predicates": [ - 440 + 442 ], "predicateGroups": [ - 441 + 443 ], "__typename": [ 1 @@ -10660,7 +10716,7 @@ export default { }, "CreateOneFieldMetadataInput": { "field": [ - 443 + 445 ], "__typename": [ 1 @@ -10733,7 +10789,7 @@ export default { 3 ], "update": [ - 445 + 447 ], "__typename": [ 1 @@ -10825,7 +10881,7 @@ export default { 3 ], "update": [ - 449 + 451 ], "__typename": [ 1 @@ -10869,7 +10925,7 @@ export default { 3 ], "update": [ - 453 + 455 ], "__typename": [ 1 @@ -10888,7 +10944,7 @@ export default { 3 ], "update": [ - 453 + 455 ], "__typename": [ 1 @@ -10899,7 +10955,7 @@ export default { 3 ], "update": [ - 456 + 458 ], "__typename": [ 1 @@ -10907,16 +10963,16 @@ export default { }, "UpdateMessageChannelInputUpdates": { "visibility": [ - 328 + 330 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 330 + 332 ], "messageFolderImportPolicy": [ - 331 + 333 ], "isSyncEnabled": [ 6 @@ -10936,7 +10992,7 @@ export default { 3 ], "update": [ - 458 + 460 ], "__typename": [ 1 @@ -10944,13 +11000,13 @@ export default { }, "UpdateCalendarChannelInputUpdates": { "visibility": [ - 324 + 326 ], "isContactAutoCreationEnabled": [ 6 ], "contactAutoCreationPolicy": [ - 325 + 327 ], "isSyncEnabled": [ 6 @@ -10984,7 +11040,7 @@ export default { 3 ], "update": [ - 461 + 463 ], "__typename": [ 1 @@ -11089,7 +11145,7 @@ export default { 1 ], "update": [ - 467 + 469 ], "__typename": [ 1 @@ -11137,7 +11193,7 @@ export default { 1 ], "update": [ - 470 + 472 ], "__typename": [ 1 @@ -11297,13 +11353,13 @@ export default { }, "EmailAccountConnectionParameters": { "IMAP": [ - 478 + 480 ], "SMTP": [ - 478 + 480 ], "CALDAV": [ - 478 + 480 ], "__typename": [ 1 @@ -11343,7 +11399,7 @@ export default { "AiModelRole": {}, "CreateOneAppTokenInput": { "appToken": [ - 482 + 484 ], "__typename": [ 1 @@ -11359,7 +11415,7 @@ export default { }, "WorkspaceMigrationInput": { "actions": [ - 484 + 486 ], "__typename": [ 1 @@ -11367,10 +11423,10 @@ export default { }, "WorkspaceMigrationDeleteActionInput": { "type": [ - 485 + 487 ], "metadataName": [ - 338 + 340 ], "universalIdentifier": [ 1 @@ -11392,16 +11448,16 @@ export default { } ], "logicFunctionLogs": [ - 247, + 249, { "input": [ - 488, + 490, "LogicFunctionLogsInput!" ] } ], "onAgentChatEvent": [ - 316, + 318, { "threadId": [ 3, diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 2d2f59ee40..daa6add585 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -904,12 +904,21 @@ export type ClientConfig = { isMicrosoftCalendarEnabled: Scalars['Boolean']; isMicrosoftMessagingEnabled: Scalars['Boolean']; isMultiWorkspaceEnabled: Scalars['Boolean']; + isWorkspaceSchemaDDLLocked: Scalars['Boolean']; + maintenance?: Maybe; publicFeatureFlags: Array; sentry: Sentry; signInPrefilled: Scalars['Boolean']; support: Support; }; +export type ClientConfigMaintenanceMode = { + __typename?: 'ClientConfigMaintenanceMode'; + endAt: Scalars['DateTime']; + link?: Maybe; + startAt: Scalars['DateTime']; +}; + export type CollectionHash = { __typename?: 'CollectionHash'; collectionName: AllMetadataName; @@ -2289,6 +2298,13 @@ export type LoginToken = { loginToken: AuthToken; }; +export type MaintenanceMode = { + __typename?: 'MaintenanceMode'; + endAt: Scalars['DateTime']; + link?: Maybe; + startAt: Scalars['DateTime']; +}; + export type MarketplaceApp = { __typename?: 'MarketplaceApp'; author: Scalars['String']; @@ -2496,6 +2512,7 @@ export type Mutation = { checkCustomDomainValidRecords?: Maybe; checkPublicDomainValidRecords?: Maybe; checkoutSession: BillingSession; + clearMaintenanceMode: Scalars['Boolean']; createApiKey: ApiKey; createApplicationRegistration: CreateApplicationRegistration; createApplicationRegistrationVariable: ApplicationRegistrationVariable; @@ -2618,6 +2635,7 @@ export type Mutation = { setAdminAiModelRecommended: Scalars['Boolean']; setAdminDefaultAiModel: Scalars['Boolean']; setEnterpriseKey: EnterpriseLicenseInfoDto; + setMaintenanceMode: Scalars['Boolean']; setMeteredSubscriptionPrice: BillingUpdate; signIn: AvailableWorkspacesAndAccessTokens; signUp: AvailableWorkspacesAndAccessTokens; @@ -3358,6 +3376,13 @@ export type MutationSetEnterpriseKeyArgs = { }; +export type MutationSetMaintenanceModeArgs = { + endAt: Scalars['DateTime']; + link?: InputMaybe; + startAt: Scalars['DateTime']; +}; + + export type MutationSetMeteredSubscriptionPriceArgs = { priceId: Scalars['String']; }; @@ -4246,6 +4271,7 @@ export type Query = { getEmailingDomains: Array; getIndicatorHealthStatus: AdminPanelHealthServiceData; getLogicFunctionSourceCode?: Maybe; + getMaintenanceMode?: Maybe; getMeteredProductsUsage: Array; getModelsDevProviders: Array; getModelsDevSuggestions: Array; @@ -7215,6 +7241,25 @@ export type GetSystemHealthStatusQueryVariables = Exact<{ [key: string]: never; export type GetSystemHealthStatusQuery = { __typename?: 'Query', getSystemHealthStatus: { __typename?: 'SystemHealth', services: Array<{ __typename?: 'SystemHealthService', id: HealthIndicatorId, label: string, status: AdminPanelHealthServiceStatus }> } }; +export type ClearMaintenanceModeMutationVariables = Exact<{ [key: string]: never; }>; + + +export type ClearMaintenanceModeMutation = { __typename?: 'Mutation', clearMaintenanceMode: boolean }; + +export type SetMaintenanceModeMutationVariables = Exact<{ + startAt: Scalars['DateTime']; + endAt: Scalars['DateTime']; + link?: InputMaybe; +}>; + + +export type SetMaintenanceModeMutation = { __typename?: 'Mutation', setMaintenanceMode: boolean }; + +export type GetMaintenanceModeQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetMaintenanceModeQuery = { __typename?: 'Query', getMaintenanceMode?: { __typename?: 'MaintenanceMode', startAt: string, endAt: string, link?: string | null } | null }; + export type ApplicationRegistrationFragmentFragment = { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, sourceType: ApplicationRegistrationSourceType, sourcePackage?: string | null, latestAvailableVersion?: string | null, isListed: boolean, isFeatured: boolean, ownerWorkspaceId?: string | null, createdAt: string, updatedAt: string }; export type DeleteApplicationRegistrationMutationVariables = Exact<{ @@ -8330,6 +8375,9 @@ export const GetIndicatorHealthStatusDocument = {"kind":"Document","definitions" export const GetQueueJobsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQueueJobs"},"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":"state"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"JobState"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"offset"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getQueueJobs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"queueName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}}},{"kind":"Argument","name":{"kind":"Name","value":"state"},"value":{"kind":"Variable","name":{"kind":"Name","value":"state"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"offset"},"value":{"kind":"Variable","name":{"kind":"Name","value":"offset"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jobs"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"failedReason"}},{"kind":"Field","name":{"kind":"Name","value":"processedOn"}},{"kind":"Field","name":{"kind":"Name","value":"finishedOn"}},{"kind":"Field","name":{"kind":"Name","value":"attemptsMade"}},{"kind":"Field","name":{"kind":"Name","value":"returnValue"}},{"kind":"Field","name":{"kind":"Name","value":"logs"}},{"kind":"Field","name":{"kind":"Name","value":"stackTrace"}}]}},{"kind":"Field","name":{"kind":"Name","value":"count"}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"hasMore"}},{"kind":"Field","name":{"kind":"Name","value":"retentionConfig"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"completedMaxAge"}},{"kind":"Field","name":{"kind":"Name","value":"completedMaxCount"}},{"kind":"Field","name":{"kind":"Name","value":"failedMaxAge"}},{"kind":"Field","name":{"kind":"Name","value":"failedMaxCount"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetQueueMetricsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQueueMetrics"},"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":"timeRange"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"QueueMetricsTimeRange"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getQueueMetrics"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"queueName"},"value":{"kind":"Variable","name":{"kind":"Name","value":"queueName"}}},{"kind":"Argument","name":{"kind":"Name","value":"timeRange"},"value":{"kind":"Variable","name":{"kind":"Name","value":"timeRange"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"queueName"}},{"kind":"Field","name":{"kind":"Name","value":"timeRange"}},{"kind":"Field","name":{"kind":"Name","value":"workers"}},{"kind":"Field","name":{"kind":"Name","value":"details"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"failed"}},{"kind":"Field","name":{"kind":"Name","value":"completed"}},{"kind":"Field","name":{"kind":"Name","value":"waiting"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"delayed"}},{"kind":"Field","name":{"kind":"Name","value":"failureRate"}}]}},{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"x"}},{"kind":"Field","name":{"kind":"Name","value":"y"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const GetSystemHealthStatusDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSystemHealthStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getSystemHealthStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]} as unknown as DocumentNode; +export const ClearMaintenanceModeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ClearMaintenanceMode"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"clearMaintenanceMode"}}]}}]} as unknown as DocumentNode; +export const SetMaintenanceModeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SetMaintenanceMode"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"startAt"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"endAt"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"link"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"setMaintenanceMode"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"startAt"},"value":{"kind":"Variable","name":{"kind":"Name","value":"startAt"}}},{"kind":"Argument","name":{"kind":"Name","value":"endAt"},"value":{"kind":"Variable","name":{"kind":"Name","value":"endAt"}}},{"kind":"Argument","name":{"kind":"Name","value":"link"},"value":{"kind":"Variable","name":{"kind":"Name","value":"link"}}}]}]}}]} as unknown as DocumentNode; +export const GetMaintenanceModeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMaintenanceMode"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getMaintenanceMode"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"startAt"}},{"kind":"Field","name":{"kind":"Name","value":"endAt"}},{"kind":"Field","name":{"kind":"Name","value":"link"}}]}}]}}]} as unknown as DocumentNode; export const DeleteApplicationRegistrationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteApplicationRegistration"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteApplicationRegistration"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}]}}]} as unknown as DocumentNode; export const RotateApplicationRegistrationClientSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RotateApplicationRegistrationClientSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rotateApplicationRegistrationClientSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"clientSecret"}}]}}]}}]} as unknown as DocumentNode; export const TransferApplicationRegistrationOwnershipDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"TransferApplicationRegistrationOwnership"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"targetWorkspaceSubdomain"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"transferApplicationRegistrationOwnership"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"applicationRegistrationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"applicationRegistrationId"}}},{"kind":"Argument","name":{"kind":"Name","value":"targetWorkspaceSubdomain"},"value":{"kind":"Variable","name":{"kind":"Name","value":"targetWorkspaceSubdomain"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index 14c3eca01a..e1fefa6204 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -129,6 +129,7 @@ export type Mutation = { deactivateWorkflowVersion: Scalars['Boolean']; deleteWorkflowVersionEdge: WorkflowVersionStepChanges; deleteWorkflowVersionStep: WorkflowVersionStepChanges; + dismissMaintenanceModeBanner: Scalars['Boolean']; dismissReconnectAccountBanner: Scalars['Boolean']; duplicateWorkflow: WorkflowVersionDto; duplicateWorkflowVersionStep: WorkflowVersionStepChanges; @@ -249,6 +250,7 @@ export type Query = { getTimelineThreadsFromCompanyId: TimelineThreadsWithTotal; getTimelineThreadsFromOpportunityId: TimelineThreadsWithTotal; getTimelineThreadsFromPersonId: TimelineThreadsWithTotal; + isMaintenanceModeBannerDismissed: Scalars['Boolean']; search: SearchResultConnection; }; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpGlobalScopeForm.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpGlobalScopeForm.tsx index dad28239e0..1c0a447914 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpGlobalScopeForm.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpGlobalScopeForm.tsx @@ -19,6 +19,7 @@ import { } from '@/auth/states/signInUpStepState'; import { getAvailableWorkspacePathAndSearchParams } from '@/auth/utils/availableWorkspacesUtils'; import { authProvidersState } from '@/client-config/states/authProvidersState'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { isNonEmptyString } from '@sniptt/guards'; @@ -136,6 +137,7 @@ const StyledForgotPasswordLinkContainer = styled.div` export const SignInUpGlobalScopeForm = () => { const { theme } = useContext(ThemeContext); const authProviders = useAtomStateValue(authProvidersState); + const isDDLLocked = useAtomStateValue(isDDLLockedState); const signInUpStep = useAtomStateValue(signInUpStepState); const { buildWorkspaceUrl } = useBuildWorkspaceUrl(); const { signOut } = useAuth(); @@ -206,19 +208,21 @@ export const SignInUpGlobalScopeForm = () => { ))} - createWorkspace()}> - - - - - - {t`Create a workspace`} - - - - - - + {!isDDLLocked && ( + createWorkspace()}> + + + + + + {t`Create a workspace`} + + + + + + + )} diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/internal/SignInUpWithCredentials.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/internal/SignInUpWithCredentials.tsx index 730d5d70ff..38d5cadfe6 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/internal/SignInUpWithCredentials.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/internal/SignInUpWithCredentials.tsx @@ -15,6 +15,7 @@ import { AuthenticatedMethod } from '@/auth/types/AuthenticatedMethod.enum'; import { SignInUpMode } from '@/auth/types/signInUpMode'; import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState'; import { captchaState } from '@/client-config/states/captchaState'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { styled } from '@linaria/react'; import { useLingui } from '@lingui/react/macro'; import { useMemo, useState } from 'react'; @@ -22,6 +23,7 @@ import { useFormContext } from 'react-hook-form'; import { isDefined } from 'twenty-shared/utils'; import { Loader } from 'twenty-ui/feedback'; import { MainButton } from 'twenty-ui/input'; +import { InputHint } from '@/ui/input/components/InputHint'; import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; @@ -29,6 +31,7 @@ const StyledForm = styled.form` align-items: center; display: flex; flex-direction: column; + max-width: 100%; width: 100%; `; @@ -43,6 +46,7 @@ export const SignInUpWithCredentials = ({ const [signInUpStep, setSignInUpStep] = useAtomState(signInUpStepState); const [showErrors, setShowErrors] = useState(false); const captcha = useAtomStateValue(captchaState); + const isDDLLocked = useAtomStateValue(isDDLLockedState); const isRequestingCaptchaToken = useAtomStateValue( isRequestingCaptchaTokenState, ); @@ -129,9 +133,15 @@ export const SignInUpWithCredentials = ({ form.formState.isSubmitting || shouldWaitForCaptchaToken); + const isSignUpBlockedByDDLLock = + isDDLLocked && + signInUpMode === SignInUpMode.SignUp && + signInUpStep === SignInUpStep.Password; + const isSubmitButtonDisabled = isEmailStepSubmitButtonDisabledCondition || - isPasswordStepSubmitButtonDisabledCondition; + isPasswordStepSubmitButtonDisabledCondition || + isSignUpBlockedByDDLLock; return ( <> @@ -163,6 +173,9 @@ export const SignInUpWithCredentials = ({ fullWidth /> {isLastUsed && } + {isSignUpBlockedByDDLLock && ( + {t`Sign-up is temporarily unavailable during maintenance.`} + )} )} diff --git a/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts b/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts index efd8970b61..65f9688bf9 100644 --- a/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts +++ b/packages/twenty-front/src/modules/client-config/hooks/useClientConfig.ts @@ -12,6 +12,8 @@ import { isConfigVariablesInDbEnabledState } from '@/client-config/states/isConf import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState'; import { isClickHouseConfiguredState } from '@/client-config/states/isClickHouseConfiguredState'; import { isCloudflareIntegrationEnabledState } from '@/client-config/states/isCloudflareIntegrationEnabledState'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; +import { maintenanceModeState } from '@/client-config/states/maintenanceModeState'; import { isEmailingDomainsEnabledState } from '@/client-config/states/isEmailingDomainsEnabledState'; import { isEmailVerificationRequiredState } from '@/client-config/states/isEmailVerificationRequiredState'; import { isGoogleCalendarEnabledState } from '@/client-config/states/isGoogleCalendarEnabledState'; @@ -117,6 +119,10 @@ export const useClientConfig = (): UseClientConfigResult => { isClickHouseConfiguredState, ); + const setIsDDLLocked = useSetAtomState(isDDLLockedState); + + const setMaintenanceMode = useSetAtomState(maintenanceModeState); + const setAppVersion = useSetAtomState(appVersionState); const fetchClientConfig = useCallback(async () => { @@ -195,6 +201,8 @@ export const useClientConfig = (): UseClientConfigResult => { clientConfig?.isCloudflareIntegrationEnabled, ); setIsClickHouseConfigured(clientConfig?.isClickHouseConfigured ?? false); + setIsDDLLocked(clientConfig?.isWorkspaceSchemaDDLLocked ?? false); + setMaintenanceMode(clientConfig?.maintenance ?? null); } catch (err) { const error = err instanceof Error ? err : new Error('Failed to fetch client config'); @@ -229,7 +237,9 @@ export const useClientConfig = (): UseClientConfigResult => { setIsEmailingDomainsEnabled, setIsClickHouseConfigured, setIsCloudflareIntegrationEnabled, + setIsDDLLocked, setLabPublicFeatureFlags, + setMaintenanceMode, setIsMicrosoftCalendarEnabled, setIsMicrosoftMessagingEnabled, setSentryConfig, diff --git a/packages/twenty-front/src/modules/client-config/states/isDDLLockedState.ts b/packages/twenty-front/src/modules/client-config/states/isDDLLockedState.ts new file mode 100644 index 0000000000..8c8d8c32fc --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/isDDLLockedState.ts @@ -0,0 +1,6 @@ +import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState'; + +export const isDDLLockedState = createAtomState({ + key: 'isDDLLocked', + defaultValue: false, +}); diff --git a/packages/twenty-front/src/modules/client-config/states/maintenanceModeState.ts b/packages/twenty-front/src/modules/client-config/states/maintenanceModeState.ts new file mode 100644 index 0000000000..50208c4b81 --- /dev/null +++ b/packages/twenty-front/src/modules/client-config/states/maintenanceModeState.ts @@ -0,0 +1,13 @@ +import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState'; +import { type ClientConfigMaintenanceMode } from '~/generated-metadata/graphql'; + +type MaintenanceModeState = Pick< + ClientConfigMaintenanceMode, + 'startAt' | 'endAt' | 'link' +>; + +export const maintenanceModeState = + createAtomState({ + key: 'maintenanceModeState', + defaultValue: null, + }); diff --git a/packages/twenty-front/src/modules/client-config/types/ClientConfig.ts b/packages/twenty-front/src/modules/client-config/types/ClientConfig.ts index 4a6ad3884c..660e2b7555 100644 --- a/packages/twenty-front/src/modules/client-config/types/ClientConfig.ts +++ b/packages/twenty-front/src/modules/client-config/types/ClientConfig.ts @@ -4,6 +4,7 @@ import { type Billing, type Captcha, type ClientAiModelConfig, + type ClientConfigMaintenanceMode, type PublicFeatureFlag, type Sentry, type Support, @@ -33,10 +34,12 @@ export type ClientConfig = { isEmailingDomainsEnabled: boolean; isCloudflareIntegrationEnabled: boolean; isClickHouseConfigured: boolean; + isWorkspaceSchemaDDLLocked: boolean; publicFeatureFlags: Array; sentry: Sentry; signInPrefilled: boolean; support: Support; isTwoFactorAuthenticationEnabled: boolean; allowRequestsToTwentyIcons: boolean; + maintenance?: ClientConfigMaintenanceMode; }; diff --git a/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx b/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx index 8c720608a1..2078444a24 100644 --- a/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx +++ b/packages/twenty-front/src/modules/information-banner/components/InformationBanner.tsx @@ -5,6 +5,7 @@ import { styled } from '@linaria/react'; import { t } from '@lingui/core/macro'; import { Banner, + type BannerColor, type BannerVariant, type IconComponent, IconX, @@ -21,6 +22,10 @@ const StyledInvertedIconButton = styled(IconButton)` color: ${themeCssVariables.font.color.inverted} !important; `; +const StyledSecondaryIconButton = styled(IconButton)` + color: inherit !important; +`; + const StyledContent = styled.div<{ hasCloseButton: boolean }>` align-items: center; display: flex; @@ -32,7 +37,8 @@ const StyledContent = styled.div<{ hasCloseButton: boolean }>` export const InformationBanner = ({ message, - variant = 'default', + color = 'blue', + variant = 'primary', buttonTitle, buttonIcon, buttonOnClick, @@ -41,6 +47,7 @@ export const InformationBanner = ({ componentInstanceId, }: { message: string; + color?: BannerColor; variant?: BannerVariant; buttonTitle?: string; buttonIcon?: IconComponent; @@ -54,6 +61,12 @@ export const InformationBanner = ({ componentInstanceId, ); + const isPrimary = variant === 'primary'; + + const CloseIconButton = isPrimary + ? StyledInvertedIconButton + : StyledSecondaryIconButton; + return ( {informationBannerIsOpen && ( - + {message} {buttonTitle && buttonOnClick && ( @@ -70,14 +83,14 @@ export const InformationBanner = ({ title={buttonTitle} Icon={buttonIcon} size="small" - inverted + inverted={isPrimary} onClick={buttonOnClick} disabled={isButtonDisabled} /> )} {onClose && ( - { return ( + {isAccountSyncEnabled && ( diff --git a/packages/twenty-front/src/modules/information-banner/components/billing/InformationBannerBillingSubscriptionPaused.tsx b/packages/twenty-front/src/modules/information-banner/components/billing/InformationBannerBillingSubscriptionPaused.tsx index 7f0e659ac9..88048a9c43 100644 --- a/packages/twenty-front/src/modules/information-banner/components/billing/InformationBannerBillingSubscriptionPaused.tsx +++ b/packages/twenty-front/src/modules/information-banner/components/billing/InformationBannerBillingSubscriptionPaused.tsx @@ -35,7 +35,8 @@ export const InformationBannerBillingSubscriptionPaused = () => { return ( { return ( { return ( { return ( { return ( { + const zonedDateTime = + Temporal.Instant.from(isoString).toZonedDateTimeISO(timeZone); + + return zonedDateTime.toLocaleString(undefined, { + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZoneName: 'short', + }); +}; + +export const InformationBannerMaintenance = () => { + const maintenanceMode = useAtomStateValue(maintenanceModeState); + const { timeZone } = useDateTimeFormat(); + const { dismissBanner, isDismissed, isLoading } = + useMaintenanceModeBannerDismissal({ + enabled: isDefined(maintenanceMode), + maintenanceStartAt: maintenanceMode?.startAt, + }); + + if (!isDefined(maintenanceMode) || isLoading || isDismissed) { + return null; + } + + const startFormatted = formatMaintenanceDateTime( + maintenanceMode.startAt, + timeZone, + ); + const endFormatted = formatMaintenanceDateTime( + maintenanceMode.endAt, + timeZone, + ); + + const message = t`Scheduled maintenance: ${startFormatted} — ${endFormatted}`; + const maintenanceLink = isNonEmptyString(maintenanceMode.link?.trim()) + ? maintenanceMode.link.trim() + : undefined; + + return ( + window.open(maintenanceLink, '_blank', 'noopener,noreferrer') + : undefined + } + onClose={dismissBanner} + /> + ); +}; diff --git a/packages/twenty-front/src/modules/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases.tsx b/packages/twenty-front/src/modules/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases.tsx index a9fe3c9664..69b6c52f05 100644 --- a/packages/twenty-front/src/modules/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases.tsx +++ b/packages/twenty-front/src/modules/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases.tsx @@ -32,6 +32,7 @@ export const InformationBannerReconnectAccountEmailAliases = () => { return ( { return ( { + const apolloCoreClient = useApolloCoreClient(); + const [isDismissed, setIsDismissed] = useState(false); + + const { data, loading, refetch } = useQuery<{ + isMaintenanceModeBannerDismissed: boolean; + }>(IS_MAINTENANCE_MODE_BANNER_DISMISSED, { + client: apolloCoreClient, + skip: !enabled, + fetchPolicy: 'network-only', + }); + + const [mutate] = useMutation<{ + dismissMaintenanceModeBanner: boolean; + }>(DISMISS_MAINTENANCE_MODE_BANNER, { + client: apolloCoreClient, + }); + + useEffect(() => { + if (!enabled) { + setIsDismissed(false); + + return; + } + }, [enabled]); + + useEffect(() => { + if (!enabled) { + return; + } + + setIsDismissed(false); + void refetch(); + }, [enabled, maintenanceStartAt, refetch]); + + const dismissBanner = async () => { + await mutate(); + setIsDismissed(true); + }; + + return { + dismissBanner, + isDismissed: isDismissed || data?.isMaintenanceModeBannerDismissed === true, + isLoading: enabled ? loading : false, + }; +}; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/SettingsAdminHealthStatus.tsx b/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/SettingsAdminHealthStatus.tsx index a0e90d0397..91f028af0f 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/SettingsAdminHealthStatus.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/components/SettingsAdminHealthStatus.tsx @@ -1,5 +1,7 @@ import { SettingsAdminTabSkeletonLoader } from '@/settings/admin-panel/components/SettingsAdminTabSkeletonLoader'; import { SettingsAdminHealthStatusListCard } from '@/settings/admin-panel/health-status/components/SettingsAdminHealthStatusListCard'; +import { SettingsAdminMaintenanceModeFetchEffect } from '@/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceModeFetchEffect'; +import { SettingsAdminMaintenanceMode } from '@/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode'; import { t } from '@lingui/core/macro'; import { H2Title } from 'twenty-ui/display'; import { Section } from 'twenty-ui/layout'; @@ -22,6 +24,7 @@ export const SettingsAdminHealthStatus = () => { return ( <> +
{ loading={loadingHealthStatus} />
+ ); }; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx new file mode 100644 index 0000000000..57cbbab1a5 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx @@ -0,0 +1,244 @@ +import { useMutation } from '@apollo/client/react'; +import { styled } from '@linaria/react'; +import { t } from '@lingui/core/macro'; +import { isNonEmptyString } from '@sniptt/guards'; +import { useCallback } from 'react'; +import { isDefined } from 'twenty-shared/utils'; +import { H2Title, IconLink, IconTool, Status } from 'twenty-ui/display'; +import { Card, CardContent, Section } from 'twenty-ui/layout'; +import { themeCssVariables } from 'twenty-ui/theme-constants'; + +import { maintenanceModeState } from '@/client-config/states/maintenanceModeState'; +import { CLEAR_MAINTENANCE_MODE } from '@/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/clearMaintenanceMode'; +import { SET_MAINTENANCE_MODE } from '@/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/setMaintenanceMode'; +import { adminPanelMaintenanceModeState } from '@/settings/admin-panel/health-status/maintenance-mode/states/adminPanelMaintenanceModeState'; +import { SettingsDatePickerInput } from '@/settings/components/SettingsDatePickerInput'; +import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle'; +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { InputHint } from '@/ui/input/components/InputHint'; +import { TextInput } from '@/ui/input/components/TextInput'; +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'; + +const StyledFormContainer = styled.div` + display: flex; + flex-direction: column; + gap: ${themeCssVariables.spacing[4]}; +`; + +const StyledStatusRow = styled.div` + display: flex; + justify-content: flex-end; +`; + +export const SettingsAdminMaintenanceMode = () => { + const [adminPanelMaintenanceMode, setAdminPanelMaintenanceMode] = + useAtomState(adminPanelMaintenanceModeState); + + const maintenanceMode = useAtomStateValue(maintenanceModeState); + const setMaintenanceMode = useSetAtomState(maintenanceModeState); + + const { enqueueErrorSnackBar } = useSnackBar(); + + const [setMaintenanceModeMutation] = useMutation(SET_MAINTENANCE_MODE); + const [clearMaintenanceModeMutation] = useMutation(CLEAR_MAINTENANCE_MODE); + + const isEnabled = isDefined(adminPanelMaintenanceMode); + + const startDate = + isEnabled && isNonEmptyString(adminPanelMaintenanceMode.startAt) + ? new Date(adminPanelMaintenanceMode.startAt) + : undefined; + + const endDate = + isEnabled && isNonEmptyString(adminPanelMaintenanceMode.endAt) + ? new Date(adminPanelMaintenanceMode.endAt) + : undefined; + + const hasValidDateRange = + isDefined(startDate) && + isDefined(endDate) && + endDate.getTime() > startDate.getTime(); + + const isScheduled = + isDefined(maintenanceMode) && + isNonEmptyString(maintenanceMode.startAt) && + isNonEmptyString(maintenanceMode.endAt); + + const saveToBackend = useCallback( + async (startAt: string, endAt: string, link?: string) => { + if (!isNonEmptyString(startAt) || !isNonEmptyString(endAt)) { + return; + } + + if (new Date(endAt).getTime() <= new Date(startAt).getTime()) { + return; + } + + try { + await setMaintenanceModeMutation({ + variables: { startAt, endAt, link }, + }); + + setMaintenanceMode({ + startAt, + endAt, + link, + }); + } catch (error: unknown) { + enqueueErrorSnackBar({ + message: + error instanceof Error + ? error.message + : t`Failed to set maintenance mode.`, + }); + } + }, + [setMaintenanceModeMutation, setMaintenanceMode, enqueueErrorSnackBar], + ); + + const handleToggle = useCallback( + async (checked: boolean) => { + if (checked) { + setAdminPanelMaintenanceMode({ startAt: '', endAt: '' }); + } else { + await clearMaintenanceModeMutation(); + setAdminPanelMaintenanceMode(null); + setMaintenanceMode(null); + } + }, + [ + clearMaintenanceModeMutation, + setAdminPanelMaintenanceMode, + setMaintenanceMode, + ], + ); + + const handleDateChange = useCallback( + (field: 'startAt' | 'endAt') => (value: Date | undefined) => { + if (!isDefined(adminPanelMaintenanceMode)) { + return; + } + + const isoValue = isDefined(value) ? value.toISOString() : ''; + const nextState = { ...adminPanelMaintenanceMode, [field]: isoValue }; + + setAdminPanelMaintenanceMode(nextState); + saveToBackend( + nextState.startAt, + nextState.endAt, + isNonEmptyString(nextState.link) ? nextState.link : undefined, + ); + }, + [adminPanelMaintenanceMode, setAdminPanelMaintenanceMode, saveToBackend], + ); + + const handleLinkChange = useCallback( + (value: string) => { + if (!isDefined(adminPanelMaintenanceMode)) { + return; + } + + setAdminPanelMaintenanceMode({ + ...adminPanelMaintenanceMode, + link: value, + }); + }, + [adminPanelMaintenanceMode, setAdminPanelMaintenanceMode], + ); + + const handleLinkBlur = useCallback(() => { + if (!isDefined(adminPanelMaintenanceMode)) { + return; + } + + saveToBackend( + adminPanelMaintenanceMode.startAt, + adminPanelMaintenanceMode.endAt, + isNonEmptyString(adminPanelMaintenanceMode.link) + ? adminPanelMaintenanceMode.link + : undefined, + ); + }, [adminPanelMaintenanceMode, saveToBackend]); + + const scheduledStartDate = isScheduled + ? new Date(maintenanceMode.startAt) + : undefined; + + const formattedStartDate = isDefined(scheduledStartDate) + ? scheduledStartDate.toLocaleDateString(undefined, { + month: '2-digit', + day: '2-digit', + year: 'numeric', + }) + : ''; + + const toggleDescription = isScheduled + ? t`Planned for ${formattedStartDate}` + : undefined; + + return ( +
+ + + + {isEnabled && ( + + + +
+ + {isDefined(startDate) && + isDefined(endDate) && + !hasValidDateRange && ( + {t`End date must be after start date.`} + )} +
+
+ + + {t`If there's no link, no button will appear.`} + +
+ {isScheduled && ( + + + + )} +
+
+ )} +
+
+ ); +}; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceModeFetchEffect.tsx b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceModeFetchEffect.tsx new file mode 100644 index 0000000000..7d96504feb --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceModeFetchEffect.tsx @@ -0,0 +1,30 @@ +import { useQuery } from '@apollo/client/react'; +import { useEffect } from 'react'; +import { isDefined } from 'twenty-shared/utils'; + +import { GET_MAINTENANCE_MODE } from '@/settings/admin-panel/health-status/maintenance-mode/graphql/queries/getMaintenanceMode'; +import { adminPanelMaintenanceModeState } from '@/settings/admin-panel/health-status/maintenance-mode/states/adminPanelMaintenanceModeState'; +import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; +import { type GetMaintenanceModeQuery } from '~/generated-metadata/graphql'; + +export const SettingsAdminMaintenanceModeFetchEffect = () => { + const { data } = useQuery(GET_MAINTENANCE_MODE, { + fetchPolicy: 'network-only', + }); + + const setAdminPanelMaintenanceMode = useSetAtomState( + adminPanelMaintenanceModeState, + ); + + useEffect(() => { + const maintenanceMode = data?.getMaintenanceMode; + + if (!isDefined(data)) { + return; + } + + setAdminPanelMaintenanceMode(maintenanceMode ?? null); + }, [data, setAdminPanelMaintenanceMode]); + + return null; +}; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/clearMaintenanceMode.ts b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/clearMaintenanceMode.ts new file mode 100644 index 0000000000..029c9ce63b --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/clearMaintenanceMode.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const CLEAR_MAINTENANCE_MODE = gql` + mutation ClearMaintenanceMode { + clearMaintenanceMode + } +`; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/setMaintenanceMode.ts b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/setMaintenanceMode.ts new file mode 100644 index 0000000000..fbaebea7af --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/mutations/setMaintenanceMode.ts @@ -0,0 +1,11 @@ +import { gql } from '@apollo/client'; + +export const SET_MAINTENANCE_MODE = gql` + mutation SetMaintenanceMode( + $startAt: DateTime! + $endAt: DateTime! + $link: String + ) { + setMaintenanceMode(startAt: $startAt, endAt: $endAt, link: $link) + } +`; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/queries/getMaintenanceMode.ts b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/queries/getMaintenanceMode.ts new file mode 100644 index 0000000000..119ccc93bb --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/graphql/queries/getMaintenanceMode.ts @@ -0,0 +1,11 @@ +import { gql } from '@apollo/client'; + +export const GET_MAINTENANCE_MODE = gql` + query GetMaintenanceMode { + getMaintenanceMode { + startAt + endAt + link + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/states/adminPanelMaintenanceModeState.ts b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/states/adminPanelMaintenanceModeState.ts new file mode 100644 index 0000000000..8e577fbb7a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/admin-panel/health-status/maintenance-mode/states/adminPanelMaintenanceModeState.ts @@ -0,0 +1,13 @@ +import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState'; + +type AdminPanelMaintenanceMode = { + startAt: string; + endAt: string; + link?: string | null; +}; + +export const adminPanelMaintenanceModeState = + createAtomState({ + key: 'adminPanelMaintenanceModeState', + defaultValue: null, + }); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx b/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx new file mode 100644 index 0000000000..cb3c8b9d2d --- /dev/null +++ b/packages/twenty-front/src/modules/settings/components/SettingsDatePickerInput.tsx @@ -0,0 +1,175 @@ +import { styled } from '@linaria/react'; +import { useLingui } from '@lingui/react/macro'; +import { useRef, useState } from 'react'; +import { Temporal } from 'temporal-polyfill'; +import { + autoUpdate, + FloatingPortal, + offset, + flip, + useFloating, +} from '@floating-ui/react'; + +import { + DateTimePicker, + MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, + MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID, +} from '@/ui/input/components/internal/date/components/DateTimePicker'; +import { OverlayContainer } from '@/ui/layout/overlay/components/OverlayContainer'; +import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; +import { isDefined } from 'twenty-shared/utils'; +import { IconCalendar } from 'twenty-ui/display'; +import { themeCssVariables } from 'twenty-ui/theme-constants'; + +const SETTINGS_DATE_PICKER_CLICK_OUTSIDE_ID = 'settings-date-picker-floating'; + +const StyledInputContainer = styled.div` + position: relative; +`; + +const StyledInput = styled.div<{ hasValue: boolean }>` + align-items: center; + background-color: ${themeCssVariables.background.transparent.lighter}; + border: 1px solid ${themeCssVariables.border.color.medium}; + border-radius: ${themeCssVariables.border.radius.sm}; + box-sizing: border-box; + color: ${({ hasValue }) => + hasValue + ? themeCssVariables.font.color.primary + : themeCssVariables.font.color.light}; + cursor: pointer; + display: flex; + gap: ${themeCssVariables.spacing[2]}; + height: 32px; + padding: 0 ${themeCssVariables.spacing[2]}; + width: 100%; + + &:hover { + border-color: ${themeCssVariables.border.color.strong}; + } +`; + +const StyledLabel = styled.div` + color: ${themeCssVariables.font.color.light}; + font-size: ${themeCssVariables.font.size.xs}; + font-weight: ${themeCssVariables.font.weight.medium}; + margin-bottom: ${themeCssVariables.spacing[1]}; +`; + +const StyledIconContainer = styled.div` + color: ${themeCssVariables.font.color.tertiary}; + display: flex; +`; + +const StyledFloatingContainer = styled.div` + z-index: 1000; +`; + +export type SettingsDatePickerInputProps = { + label: string; + value: Date | undefined; + onChange: (date: Date | undefined) => void; + placeholder?: string; +}; + +export const SettingsDatePickerInput = ({ + label, + value, + onChange, + placeholder, +}: SettingsDatePickerInputProps) => { + const { t } = useLingui(); + const [isOpen, setIsOpen] = useState(false); + const containerRef = useRef(null); + + const { refs, floatingStyles } = useFloating({ + open: isOpen, + placement: 'bottom-start', + middleware: [offset(4), flip()], + whileElementsMounted: autoUpdate, + }); + + const handleClose = () => { + setIsOpen(false); + }; + + useListenClickOutside({ + refs: [containerRef], + listenerId: `settings-date-picker-${label}`, + callback: handleClose, + enabled: isOpen, + excludedClickOutsideIds: [ + SETTINGS_DATE_PICKER_CLICK_OUTSIDE_ID, + MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID, + MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID, + ], + }); + + const handleDateTimeSelect = (newDateTime: Temporal.ZonedDateTime | null) => { + if (isDefined(newDateTime)) { + onChange(new Date(newDateTime.epochMilliseconds)); + } + handleClose(); + }; + + const handleClear = () => { + onChange(undefined); + handleClose(); + }; + + const formatDisplayValue = (date: Date | undefined): string => { + if (!isDefined(date)) { + return placeholder ?? t`Select date & time`; + } + + return date.toLocaleString(undefined, { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }); + }; + + const zonedDateTime = isDefined(value) + ? Temporal.Instant.fromEpochMilliseconds( + value.getTime(), + ).toZonedDateTimeISO(Temporal.Now.timeZoneId()) + : null; + + return ( + + {label} + setIsOpen(true)} + > + + + + {formatDisplayValue(value)} + + {isOpen && ( + + + + + + + + )} + + ); +}; diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx index 30f4f00162..9bbe27c923 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx @@ -2,6 +2,7 @@ import { useDeleteOneFieldMetadataItem } from '@/object-metadata/hooks/useDelete import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem'; import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag'; import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes'; @@ -13,6 +14,7 @@ import { TableRow } from '@/ui/layout/table/components/TableRow'; import { useContext, useMemo } from 'react'; import { styled } from '@linaria/react'; import { useLingui } from '@lingui/react/macro'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState'; import { FieldMetadataType, SettingsPath } from 'twenty-shared/types'; import { getSettingsPath, isDefined } from 'twenty-shared/utils'; @@ -84,9 +86,12 @@ export const SettingsObjectFieldItemTableRow = ({ const { fieldMetadataItem, objectMetadataItem } = settingsObjectDetailTableItem; - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const navigate = useNavigateSettings(); diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx index a6960bb45a..55811a538d 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx @@ -3,6 +3,7 @@ import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataIt import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata'; import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag'; import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes'; @@ -10,6 +11,7 @@ import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; import { styled } from '@linaria/react'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useLingui } from '@lingui/react/macro'; import { useContext, useMemo } from 'react'; import { Link } from 'react-router-dom'; @@ -109,9 +111,12 @@ export const SettingsObjectRelationItemTableRow = ({ [fieldMetadataItem, getRelationMetadata], ) ?? {}; - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const { activateMetadataField } = useFieldMetadataItem(); const { deleteOneFieldMetadataItem } = useDeleteOneFieldMetadataItem(); diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm.tsx index 26f3031d0b..154453b9c5 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm.tsx @@ -1,5 +1,6 @@ import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem'; import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { computeUpdatedNavigationMemorizedUrlAfterObjectNamePluralChange } from '@/settings/data-model/object-details/utils/computeUpdatedNavigationMemorizedUrlAfterObjectNamePluralChange'; import { SettingsDataModelObjectAboutForm } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectAboutForm'; @@ -8,6 +9,7 @@ import { settingsDataModelObjectAboutFormSchema, } from '@/settings/data-model/validation-schemas/settingsDataModelObjectAboutFormSchema'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; import { zodResolver } from '@hookform/resolvers/zod'; import { FormProvider, useForm } from 'react-hook-form'; @@ -23,9 +25,12 @@ type SettingsUpdateDataModelObjectAboutFormProps = { export const SettingsUpdateDataModelObjectAboutForm = ({ objectMetadataItem, }: SettingsUpdateDataModelObjectAboutFormProps) => { - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const navigate = useNavigateSettings(); const setUpdatedObjectNamePlural = useSetAtomState( updatedObjectNamePluralState, diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectFields.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectFields.tsx index e559af212e..efc1b2e600 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectFields.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectFields.tsx @@ -1,8 +1,10 @@ import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem'; import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { SettingsObjectRelationsTable } from '@/settings/data-model/object-details/components/SettingsObjectRelationsTable'; import { styled } from '@linaria/react'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useLingui } from '@lingui/react/macro'; import { FieldMetadataType, SettingsPath } from 'twenty-shared/types'; import { getSettingsPath } from 'twenty-shared/utils'; @@ -25,9 +27,12 @@ type ObjectFieldsProps = { export const ObjectFields = ({ objectMetadataItem }: ObjectFieldsProps) => { const { t } = useLingui(); - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const objectLabelSingular = objectMetadataItem.labelSingular; diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx index c44fa2a9e6..0aa99df638 100644 --- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/tabs/ObjectSettings.tsx @@ -2,6 +2,7 @@ import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/Enriche import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem'; import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { AdvancedSettingsWrapper } from '@/settings/components/AdvancedSettingsWrapper'; import { SettingsUpdateDataModelObjectAboutForm } from '@/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm'; @@ -11,6 +12,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useModal } from '@/ui/layout/modal/hooks/useModal'; import { styled } from '@linaria/react'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useLingui } from '@lingui/react/macro'; import { SettingsPath } from 'twenty-shared/types'; import { H2Title, IconArchive, IconTrash } from 'twenty-ui/display'; @@ -56,7 +58,10 @@ export const ObjectSettings = ({ const { enqueueSuccessSnackBar } = useSnackBar(); const { openModal, closeModal } = useModal(); - const isReadOnly = isObjectMetadataReadOnly({ objectMetadataItem }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const isReadOnly = + isObjectMetadataReadOnly({ objectMetadataItem }) || isDDLLocked; const handleDisable = async () => { const result = await updateOneObjectMetadataItem({ diff --git a/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx b/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx index 5a7874a7ee..1267cda67e 100644 --- a/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx +++ b/packages/twenty-front/src/modules/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm.tsx @@ -2,9 +2,11 @@ import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdat import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem'; import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems'; import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { Select } from '@/ui/input/components/Select'; import { styled } from '@linaria/react'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { zodResolver } from '@hookform/resolvers/zod'; import { t } from '@lingui/core/macro'; import { useMemo } from 'react'; @@ -43,9 +45,12 @@ const StyledContainer = styled.div` export const SettingsDataModelObjectIdentifiersForm = ({ objectMetadataItem, }: SettingsDataModelObjectIdentifiersFormProps) => { - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const formConfig = useForm({ mode: 'onTouched', resolver: zodResolver(settingsDataModelObjectIdentifiersFormSchema), diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx index f9196b2dec..a27133042b 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsNewObject.tsx @@ -9,12 +9,13 @@ import { type SettingsDataModelObjectAboutFormValues, settingsDataModelObjectAboutFormSchema, } from '@/settings/data-model/validation-schemas/settingsDataModelObjectAboutFormSchema'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { zodResolver } from '@hookform/resolvers/zod'; import { useLingui } from '@lingui/react/macro'; import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { SettingsPath } from 'twenty-shared/types'; import { getSettingsPath, isDefined } from 'twenty-shared/utils'; import { H2Title } from 'twenty-ui/display'; @@ -26,6 +27,7 @@ export const SettingsNewObject = () => { const navigate = useNavigateSettings(); const [isLoading, setIsLoading] = useState(false); const { createOneObjectMetadataItem } = useCreateOneObjectMetadataItem(); + const isDDLLocked = useAtomStateValue(isDDLLockedState); const objectMetadataItems = useAtomStateValue(objectMetadataItemsSelector); const formConfig = useForm({ @@ -49,7 +51,7 @@ export const SettingsNewObject = () => { const hasNameConflict = isDefined(conflictingObjectMetadataItem); const { isValid, isSubmitting } = formConfig.formState; - const canSave = isValid && !isSubmitting && !hasNameConflict; + const canSave = isValid && !isSubmitting && !hasNameConflict && !isDDLLocked; const handleSave = async ( formValues: SettingsDataModelObjectAboutFormValues, diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx index 75f2f22bd8..8bb52491ce 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectDetailPage.tsx @@ -20,6 +20,7 @@ import { SettingsPath, } from 'twenty-shared/types'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState'; import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue'; @@ -64,9 +65,12 @@ export const SettingsObjectDetailPage = () => { findObjectMetadataItemByNamePlural(objectNamePlural) ?? findObjectMetadataItemByNamePlural(updatedObjectNamePlural); - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const activeTabId = useAtomComponentStateValue( activeTabIdComponentState, diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx index f9d43486a7..023d3d8293 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx @@ -12,6 +12,7 @@ import { useUpdateOneFieldMetadataItem } from '@/object-metadata/hooks/useUpdate import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural'; import { formatFieldMetadataItemInput } from '@/object-metadata/utils/formatFieldMetadataItemInput'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; @@ -28,6 +29,7 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; import { shouldNavigateBackToMemorizedUrlOnSaveState } from '@/ui/navigation/states/shouldNavigateBackToMemorizedUrlOnSaveState'; import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { styled } from '@linaria/react'; import { useLingui } from '@lingui/react/macro'; import { AppPath, SettingsPath } from 'twenty-shared/types'; @@ -85,9 +87,12 @@ export const SettingsObjectFieldEdit = () => { const objectMetadataItem = findObjectMetadataItemByNamePlural(objectNamePlural); - const readonly = isObjectMetadataReadOnly({ - objectMetadataItem, - }); + const isDDLLocked = useAtomStateValue(isDDLLockedState); + + const readonly = + isObjectMetadataReadOnly({ + objectMetadataItem, + }) || isDDLLocked; const { deactivateMetadataField, diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx index 0e0162892a..410c8008fd 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectTable.tsx @@ -1,4 +1,5 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; +import { isDDLLockedState } from '@/client-config/states/isDDLLockedState'; import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem'; import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem'; import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem'; @@ -71,6 +72,7 @@ export const SettingsObjectTable = ({ const { t } = useLingui(); const isAdvancedModeEnabled = useAtomStateValue(isAdvancedModeEnabledState); + const isDDLLocked = useAtomStateValue(isDDLLockedState); const [searchTerm, setSearchTerm] = useState(''); const [showDeactivated, setShowDeactivated] = useState(true); @@ -246,7 +248,7 @@ export const SettingsObjectTable = ({ stroke={theme.icon.stroke.sm} /> - ) : ( + ) : isDDLLocked ? null : ( { const { t } = useLingui(); const { objectMetadataItems } = useFilteredObjectMetadataItems(); + const isDDLLocked = useAtomStateValue(isDDLLockedState); return ( + isDDLLocked ? (