diff --git a/client/web/BUILD.bazel b/client/web/BUILD.bazel index cbbdfc1d113e9..1acc0289f1ae7 100644 --- a/client/web/BUILD.bazel +++ b/client/web/BUILD.bazel @@ -1789,8 +1789,8 @@ ts_project( "src/enterprise/batches/batch-spec/yaml-util.test.ts", "src/enterprise/batches/detail/BatchChangeDetailsPage.mock.ts", "src/enterprise/batches/detail/changesets/BatchChangeChangesets.mock.ts", + "src/enterprise/batches/mocks.ts", "src/enterprise/batches/settings/format.test.ts", - "src/enterprise/batches/settings/mocks.ts", "src/enterprise/code-monitoring/CodeMonitoringPage.test.tsx", "src/enterprise/code-monitoring/CreateCodeMonitorPage.test.tsx", "src/enterprise/code-monitoring/ManageCodeMonitorPage.test.tsx", diff --git a/client/web/dev/utils/create-js-context.ts b/client/web/dev/utils/create-js-context.ts index efbe39bd03ae3..1d52cf0cf6973 100644 --- a/client/web/dev/utils/create-js-context.ts +++ b/client/web/dev/utils/create-js-context.ts @@ -75,7 +75,6 @@ export const createJsContext = ({ sourcegraphBaseUrl }: { sourcegraphBaseUrl: st }, embeddingsEnabled: false, primaryLoginProvidersCount: 5, - batchChangesRolloutWindows: null, // Site-config overrides default JS context ...siteConfig, } diff --git a/client/web/src/enterprise/batches/DropdownButton.story.tsx b/client/web/src/enterprise/batches/DropdownButton.story.tsx index 5d759a3f1c72b..2f3da0d718c01 100644 --- a/client/web/src/enterprise/batches/DropdownButton.story.tsx +++ b/client/web/src/enterprise/batches/DropdownButton.story.tsx @@ -1,8 +1,13 @@ import { DecoratorFn, Meta, Story } from '@storybook/react' +import { getDocumentNode } from '@sourcegraph/http-client' +import { MockedTestProvider } from '@sourcegraph/shared/src/testing/apollo' + import { WebStory } from '../../components/WebStory' +import { BATCH_CHANGES_SITE_CONFIGURATION } from './backend' import { Action, DropdownButton } from './DropdownButton' +import { rolloutWindowConfigMockResult, noRolloutWindowMockResult } from './mocks' // eslint-disable-next-line @typescript-eslint/require-await const onTrigger = async (onDone: () => void) => onDone() @@ -33,6 +38,15 @@ const experimentalAction: Action = { experimental: true, } +const publishAction: Action = { + type: 'publish', + buttonLabel: 'Publish Changeset', + dropdownTitle: 'Publish Changeset', + dropdownDescription: 'Attempt to publish all changesets to the code hosts.', + onTrigger, + experimental: false, +} + const decorator: DecoratorFn = story =>
{story()}
const config: Meta = { @@ -64,15 +78,64 @@ export const SingleAction: Story = args => {() => ( - {() => } + + {() => ( + + + + )} + ) MultipleActionsWithoutDefault.storyName = 'Multiple actions without default' export const MultipleActionsWithDefault: Story = args => ( - {() => } + {() => ( + + + + )} ) MultipleActionsWithDefault.storyName = 'Multiple actions with default' + +export const PublishActionWithRolloutWindowConfigured: Story = args => ( + + {() => ( + + + + )} + +) + +PublishActionWithRolloutWindowConfigured.storyName = 'Publish Action with rollout window configured' diff --git a/client/web/src/enterprise/batches/DropdownButton.tsx b/client/web/src/enterprise/batches/DropdownButton.tsx index d64e91974fc5f..fe81562b813eb 100644 --- a/client/web/src/enterprise/batches/DropdownButton.tsx +++ b/client/web/src/enterprise/batches/DropdownButton.tsx @@ -18,6 +18,8 @@ import { Icon, } from '@sourcegraph/wildcard' +import { useBatchChangesRolloutWindowConfig } from './backend' + import styles from './DropdownButton.module.scss' export interface Action { @@ -169,11 +171,11 @@ const DropdownItem: React.FunctionComponent { + const { rolloutWindowConfig, loading } = useBatchChangesRolloutWindowConfig() const onSelect = useCallback(() => { setSelectedType(action.type) }, [setSelectedType, action.type]) - - const { batchChangesRolloutWindows } = window.context + const shouldDisplayRolloutInfo = action.type === 'publish' && rolloutWindowConfig && rolloutWindowConfig.length > 0 return ( @@ -187,17 +189,18 @@ const DropdownItem: React.FunctionComponent - {action.type === 'publish' && batchChangesRolloutWindows && batchChangesRolloutWindows.length > 0 ? ( - - {action.dropdownDescription}
- - Note: Rollout windows have been set up by the admin. This means that some of the selected - changesets won't be processed until a time in the future. - {' '} -
- ) : ( - {action.dropdownDescription} - )} + + {action.dropdownDescription} + {!loading && shouldDisplayRolloutInfo && ( + <> +
+ + Note: Rollout windows have been set up by the admin. This means that some of the + selected changesets won't be processed until a time in the future. + + + )} +
) diff --git a/client/web/src/enterprise/batches/backend.ts b/client/web/src/enterprise/batches/backend.ts index 661fca24b1c58..5e790617cb31c 100644 --- a/client/web/src/enterprise/batches/backend.ts +++ b/client/web/src/enterprise/batches/backend.ts @@ -1,8 +1,12 @@ -import { QueryResult } from '@apollo/client' +import { useMemo } from 'react' + +import { ApolloError } from '@apollo/client' +import * as jsonc from 'jsonc-parser' import { Observable } from 'rxjs' import { map } from 'rxjs/operators' import { dataOrThrowErrors, gql, useQuery } from '@sourcegraph/http-client' +import { BatchChangeRolloutWindow, SiteConfiguration } from '@sourcegraph/shared/src/schema/site.schema' import { requestGraphQL } from '../../backend/graphql' import { @@ -212,10 +216,27 @@ export const BATCH_CHANGES_SITE_CONFIGURATION = gql` } ` -export const useGetBatchChangesSiteConfiguration = (): QueryResult< - BatchChangesSiteConfigurationResult, - BatchChangesSiteConfigurationVariables -> => - useQuery(BATCH_CHANGES_SITE_CONFIGURATION, { +interface useGetBatchChangesSiteConfigurationResult { + loading: boolean + error: ApolloError | undefined + rolloutWindowConfig: BatchChangeRolloutWindow[] +} + +export const useBatchChangesRolloutWindowConfig = (): useGetBatchChangesSiteConfigurationResult => { + const { loading, error, data } = useQuery< + BatchChangesSiteConfigurationResult, + BatchChangesSiteConfigurationVariables + >(BATCH_CHANGES_SITE_CONFIGURATION, { fetchPolicy: 'cache-first', }) + + const rolloutWindowConfig: BatchChangeRolloutWindow[] = useMemo(() => { + if (!data) { + return [] + } + const siteConfig = jsonc.parse(data.site.configuration.effectiveContents) as SiteConfiguration + return siteConfig['batchChanges.rolloutWindows'] || [] + }, [data]) + + return { loading, error, rolloutWindowConfig } +} diff --git a/client/web/src/enterprise/batches/settings/mocks.ts b/client/web/src/enterprise/batches/mocks.ts similarity index 100% rename from client/web/src/enterprise/batches/settings/mocks.ts rename to client/web/src/enterprise/batches/mocks.ts diff --git a/client/web/src/enterprise/batches/settings/BatchChangesSettingsArea.story.tsx b/client/web/src/enterprise/batches/settings/BatchChangesSettingsArea.story.tsx index 34d1d93156b97..eb8db2559a589 100644 --- a/client/web/src/enterprise/batches/settings/BatchChangesSettingsArea.story.tsx +++ b/client/web/src/enterprise/batches/settings/BatchChangesSettingsArea.story.tsx @@ -11,10 +11,10 @@ import { UserBatchChangesCodeHostsResult, } from '../../../graphql-operations' import { BATCH_CHANGES_SITE_CONFIGURATION } from '../backend' +import { noRolloutWindowMockResult, rolloutWindowConfigMockResult } from '../mocks' import { USER_CODE_HOSTS } from './backend' import { BatchChangesSettingsArea } from './BatchChangesSettingsArea' -import { noRolloutWindowMockResult, rolloutWindowConfigMockResult } from './mocks' const decorator: DecoratorFn = story =>
{story()}
diff --git a/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.story.tsx b/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.story.tsx index f5a8827a37341..81fae402823ed 100644 --- a/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.story.tsx +++ b/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.story.tsx @@ -5,8 +5,8 @@ import { MockedTestProvider } from '@sourcegraph/shared/src/testing/apollo' import { WebStory } from '../../../components/WebStory' import { BATCH_CHANGES_SITE_CONFIGURATION } from '../backend' +import { noRolloutWindowMockResult, rolloutWindowConfigMockResult } from '../mocks' -import { noRolloutWindowMockResult, rolloutWindowConfigMockResult } from './mocks' import { RolloutWindowsConfiguration } from './RolloutWindowsConfiguration' const decorator: DecoratorFn = story =>
{story()}
diff --git a/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.tsx b/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.tsx index dc5b1470c5c98..31a53a4b5cc1f 100644 --- a/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.tsx +++ b/client/web/src/enterprise/batches/settings/RolloutWindowsConfiguration.tsx @@ -1,12 +1,10 @@ -import React, { useEffect, useState } from 'react' +import React from 'react' import { mdiPulse } from '@mdi/js' -import * as jsonc from 'jsonc-parser' -import { BatchChangeRolloutWindow } from '@sourcegraph/shared/src/schema/site.schema' import { Text, H3, Container, Icon, LoadingSpinner, ErrorAlert, Link } from '@sourcegraph/wildcard' -import { useGetBatchChangesSiteConfiguration } from '../backend' +import { useBatchChangesRolloutWindowConfig } from '../backend' import { formatRate, formatDays } from './format' @@ -14,22 +12,15 @@ import styles from './RolloutWindowsConfiguration.module.scss' // Displays the rollout window configuration. export const RolloutWindowsConfiguration: React.FunctionComponent = () => { - const [rolloutWindows, setRolloutWindows] = useState([]) - const { loading, error, data } = useGetBatchChangesSiteConfiguration() - useEffect(() => { - if (data) { - const siteConfig = jsonc.parse(data.site.configuration.effectiveContents) - setRolloutWindows(siteConfig['batchChanges.rolloutWindows'] || []) - } - }, [data]) + const { loading, error, rolloutWindowConfig } = useBatchChangesRolloutWindowConfig() return (

Rollout Windows

{loading && } {error && } {!loading && - data && - (rolloutWindows.length === 0 ? ( + rolloutWindowConfig && + (rolloutWindowConfig.length === 0 ? ( No rollout windows configured for changesets. Learn how to configure them in{' '} @@ -48,7 +39,7 @@ export const RolloutWindowsConfiguration: React.FunctionComponent = () => {
    - {rolloutWindows.map((rolloutWindow, index) => ( + {rolloutWindowConfig.map((rolloutWindow, index) => (
  • , 'e batchChangesWebhookLogsEnabled: boolean - batchChangesRolloutWindows: BatchChangeRolloutWindow[] | null - /** Whether cody is enabled for the user. */ codyEnabled: boolean diff --git a/cmd/frontend/internal/app/jscontext/jscontext.go b/cmd/frontend/internal/app/jscontext/jscontext.go index 9fe00003df0b3..b0de6e5dfc322 100644 --- a/cmd/frontend/internal/app/jscontext/jscontext.go +++ b/cmd/frontend/internal/app/jscontext/jscontext.go @@ -176,10 +176,9 @@ type JSContext struct { // the request is an admin and thus can access batch changes // It does NOT reflect whether or not the site license has batch changes available. // Use LicenseInfo for that. - BatchChangesEnabled bool `json:"batchChangesEnabled"` - BatchChangesDisableWebhooksWarning bool `json:"batchChangesDisableWebhooksWarning"` - BatchChangesWebhookLogsEnabled bool `json:"batchChangesWebhookLogsEnabled"` - BatchChangesRolloutWindows *[]*schema.BatchChangeRolloutWindow `json:"batchChangesRolloutWindows"` + BatchChangesEnabled bool `json:"batchChangesEnabled"` + BatchChangesDisableWebhooksWarning bool `json:"batchChangesDisableWebhooksWarning"` + BatchChangesWebhookLogsEnabled bool `json:"batchChangesWebhookLogsEnabled"` CodyEnabled bool `json:"codyEnabled"` @@ -360,7 +359,6 @@ func NewJSContextFromRequest(req *http.Request, db database.DB) JSContext { BatchChangesEnabled: enterprise.BatchChangesEnabledForUser(ctx, db) == nil, BatchChangesDisableWebhooksWarning: conf.Get().BatchChangesDisableWebhooksWarning, BatchChangesWebhookLogsEnabled: webhooks.LoggingEnabled(conf.Get()), - BatchChangesRolloutWindows: conf.Get().BatchChangesRolloutWindows, CodyEnabled: cody.IsCodyEnabled(ctx),