From 0568790ed258922326ca25d7f9013aa9350d7b82 Mon Sep 17 00:00:00 2001 From: Lauren Melendez <79547367+lmelende20@users.noreply.github.com> Date: Wed, 17 Aug 2022 10:52:15 -0400 Subject: [PATCH] Storybook Knobs to Control Migration (#39720) * Start of Knobs to Control Migration * last migration of the remaining knobs * small fix * testing fixes * fixed comments containing knobs * merge conflict resolution * yarn duplicate fix * possible merge conflict fix * fix * Update yarn.lock * batch change preview page fix * removal of additional knobs * removing knobs addon * fix ui visual changes * fix ui visual changes with additional fix * visual changes fix update * BatchChangeDetailsPage visual change fix * BatchChangeDetailsPage visual change fix update * Update client/web/src/batches/RepoBatchChangesButton.story.tsx Co-authored-by: Laura Hacker * Update client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx Co-authored-by: Laura Hacker * Update client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/ImportingChangesetsPreviewList.story.tsx Co-authored-by: Laura Hacker * Update client/web/src/components/diff/DiffStat.story.tsx Co-authored-by: Laura Hacker * Update client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx Co-authored-by: Laura Hacker * code review updates * continued code review updates * format fix * buildkite fix * Additional minor updates Co-authored-by: Tom Ross Co-authored-by: Laura Hacker --- .../GlobalStylesStory/GlobalStyles.story.tsx | 108 +++++++----- .../options-menu/OptionsPage.story.tsx | 47 +++-- .../notifications/NotificationItem.story.tsx | 69 +++++--- client/storybook/src/main.ts | 2 +- .../batches/RepoBatchChangesButton.story.tsx | 29 +++- .../ActivationDropdown.story.tsx | 51 ++++-- .../src/components/diff/DiffStat.story.tsx | 49 +++--- .../components/diff/FileDiffHunks.story.tsx | 23 ++- .../components/diff/FileDiffNode.story.tsx | 23 ++- .../src/components/time/Duration.story.tsx | 31 ++-- .../batches/DropdownButton.story.tsx | 51 +++--- .../src/enterprise/batches/DropdownButton.tsx | 1 - .../batches/batch-spec/TabBar.story.tsx | 55 +++--- .../edit/editor/EditorFeedbackPanel.story.tsx | 45 +++-- .../editor/MonacoBatchSpecEditor.story.tsx | 21 ++- .../edit/library/ReplaceSpecModal.story.tsx | 14 +- .../ImportingChangesetsPreviewList.story.tsx | 35 +++- .../WorkspacesPreview.story.tsx | 117 ++++++++----- .../WorkspacesPreviewList.story.tsx | 28 ++- .../execute/CancelExecutionModal.story.tsx | 13 +- .../execute/ExecutionStatsBar.story.tsx | 36 +++- .../execute/ReadOnlyBatchSpecForm.story.tsx | 46 ++--- .../workspaces/WorkspaceStateIcon.story.tsx | 18 +- .../close/BatchChangeCloseAlert.story.tsx | 24 ++- .../close/BatchChangeClosePage.story.tsx | 11 +- .../detail/ActiveExecutionNotice.story.tsx | 21 ++- .../detail/BatchChangeDetailsPage.story.tsx | 62 ++++++- .../BatchChangeChangesets.story.tsx | 37 +++- .../changesets/ChangesetSelectRow.story.tsx | 36 ++-- .../ExternalChangesetNode.story.tsx | 27 +-- .../list/BatchChangeListPage.story.tsx | 38 +++-- .../batches/list/BatchChangeNode.story.tsx | 18 +- .../list/BatchChangesListIntro.story.tsx | 39 +++-- .../preview/BatchChangePreviewPage.story.tsx | 63 ++++--- .../CreateUpdateBatchChangeAlert.story.tsx | 21 ++- .../preview/list/PreviewList.story.tsx | 12 +- .../settings/AddCredentialModal.story.tsx | 31 ++-- .../CodeIntelConfigurationPage.story.tsx | 18 +- ...CodeIntelConfigurationPolicyPage.story.tsx | 18 +- ...RepositoryIndexConfigurationPage.story.tsx | 10 +- .../pages/CodeIntelUploadPage.story.tsx | 4 + .../pages/CodeIntelUploadsPage.story.tsx | 45 ++++- client/web/src/nav/UserNavItem.story.tsx | 31 ++-- .../src/repo/commits/GitCommitNode.story.tsx | 35 +++- .../webhooks/MessagePanel.story.tsx | 27 +-- .../site-admin/webhooks/StatusCode.story.tsx | 21 ++- .../webhooks/WebhookLogNode.story.tsx | 31 +++- .../webhooks/WebhookLogPage.story.tsx | 24 ++- .../webhooks/WebhookLogPageHeader.story.tsx | 94 ++++++++-- .../src/site-admin/webhooks/story/fixtures.ts | 13 +- .../components/Button/story/Button.story.tsx | 32 +++- .../LoadingSpinner/LoadingSpinner.story.tsx | 9 +- .../PageSelector/PageSelector.story.tsx | 12 +- .../Popover/story/Popover.story.tsx | 13 +- .../Typography/Typography.story.tsx | 124 ++++---------- .../cmd/tracking-issue/testdata/fixtures.json | 4 +- package.json | 2 +- yarn.lock | 161 +++--------------- 58 files changed, 1276 insertions(+), 804 deletions(-) diff --git a/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx b/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx index df33a7cd598..84ed2a8f656 100644 --- a/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx +++ b/client/branded/src/global-styles/GlobalStylesStory/GlobalStyles.story.tsx @@ -5,7 +5,6 @@ import { useState } from 'react' import { action } from '@storybook/addon-actions' -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import classNames from 'classnames' import 'storybook-addon-designs' @@ -577,49 +576,66 @@ export const ListGroups: Story = () => ( ListGroups.storyName = 'List groups' -export const Meter: Story = () => { - const min = number('min', 0) - const max = number('max', 1) - const high = number('high', 0.8) - const low = number('low', 0.2) - const optimum = number('optimum', 1) - const value = number('value', 0.1) - - return ( - <> -

Meter

- - The HTML{' '} - - {''} - {' '} - element represents either a scalar value within a known range or a fractional value. - -

Examples

-
-
-

Optimum

- -
-
-
-

Sub optimum

- -
-
-
-

Sub sub optimum

- -
-
-
-

Customize with knobs

- -
- - ) +export const Meter: Story = args => ( + <> +

Meter

+ + The HTML{' '} + + {''} + {' '} + element represents either a scalar value within a known range or a fractional value. + +

Examples

+
+
+

Optimum

+ +
+
+
+

Sub optimum

+ +
+
+
+

Sub sub optimum

+ +
+
+
+

Customize with controls

+ +
+ +) +Meter.argTypes = { + min: { + type: 'number', + defaultValue: 0, + }, + max: { + type: 'number', + defaultValue: 1, + }, + high: { + type: 'number', + defaultValue: 0.8, + }, + low: { + type: 'number', + defaultValue: 0.2, + }, + optimum: { + type: 'number', + defaultValue: 1, + }, + value: { + type: 'number', + defaultValue: 0.1, + }, } diff --git a/client/browser/src/browser-extension/options-menu/OptionsPage.story.tsx b/client/browser/src/browser-extension/options-menu/OptionsPage.story.tsx index 0ad3447ee60..74755d6cb2d 100644 --- a/client/browser/src/browser-extension/options-menu/OptionsPage.story.tsx +++ b/client/browser/src/browser-extension/options-menu/OptionsPage.story.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react' import { action } from '@storybook/addon-actions' -import { boolean, text } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import GithubIcon from 'mdi-react/GithubIcon' import { Observable, of } from 'rxjs' @@ -37,22 +36,21 @@ const OptionsPageWrapper: React.FunctionComponent ) -const Interactive: Story = () => { +const Interactive: Story = args => { const [isActivated, setIsActivated] = useState(false) - return + return } -const WithAdvancedSettings: Story = () => { +const WithAdvancedSettings: Story = args => { const [optionFlagValues, setOptionFlagValues] = useState([ { key: 'allowErrorReporting', label: 'Allow error reporting', value: false }, { key: 'experimentalLinkPreviews', label: 'Experimental link previews', value: true }, @@ -66,29 +64,27 @@ const WithAdvancedSettings: Story = () => { initialShowAdvancedSettings={true} optionFlags={optionFlagValues} onChangeOptionFlag={setOptionFlag} + {...args} /> ) } -export const AllOptionsPages: Story = () => ( +export const AllOptionsPages: Story = (args = {}) => (

All Options Pages

Interactive

- +

URL validation error

- +

With advanced settings

- +
@@ -98,6 +94,8 @@ export const AllOptionsPages: Story = () => (
@@ -105,6 +103,7 @@ export const AllOptionsPages: Story = () => (
@@ -118,30 +117,46 @@ export const AllOptionsPages: Story = () => ( currentUser={{ settingsURL: '/users/john-doe/settings', siteAdmin: false }} hasRepoSyncError={true} requestPermissionsHandler={requestPermissionsHandler} + showSourcegraphCloudAlert={args.showSourcegraphCloudAlert} + version={args.version} />

Self-hosted

Self-hosted instance, user is admin

) +AllOptionsPages.argTypes = { + sourcegraphUrl: { + control: { type: 'text' }, + defaultValue: 'https://not-sourcegraph.com', + }, + version: { + control: { type: 'text' }, + defaultValue: '0.0.0', + }, + showSourcegraphCloudAlert: { + control: { type: 'boolean' }, + defaultValue: false, + }, +} AllOptionsPages.parameters = { chromatic: { diff --git a/client/shared/src/notifications/NotificationItem.story.tsx b/client/shared/src/notifications/NotificationItem.story.tsx index be960797196..99cfdbdf828 100644 --- a/client/shared/src/notifications/NotificationItem.story.tsx +++ b/client/shared/src/notifications/NotificationItem.story.tsx @@ -1,5 +1,4 @@ import { action } from '@storybook/addon-actions' -import { number, select, text } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { of } from 'rxjs' import { NotificationType as NotificationTypeType } from 'sourcegraph' @@ -28,17 +27,32 @@ const decorator: DecoratorFn = story => ( const config: Meta = { title: 'shared/NotificationItem', decorators: [decorator], + argTypes: { + message: { + name: 'Message', + control: { type: 'text' }, + defaultValue: 'My *custom* message', + }, + type: { + name: 'type', + control: { + type: 'select', + options: NotificationType as Record, + }, + }, + source: { + name: 'Source', + control: { type: 'text' }, + defaultValue: 'some source', + }, + }, } export default config -export const WithoutProgress: Story = () => { - const message = text('Message', 'My *custom* message') - const type = select( - 'Type', - NotificationType as Record, - NotificationType.Error - ) - const source = text('Source', 'some source') +export const WithoutProgress: Story = args => { + const message = args.message + const type = args.type + const source = args.source return ( { /> ) } - -export const WithProgress: Story = () => { - const message = text('Message', 'My *custom* message') - const type = select( - 'Type', - NotificationType as Record, - NotificationType.Info - ) - const source = text('Source', 'some source') - const progressMessage = text('Progress message', 'My *custom* progress message') - const progressPercentage = number('Progress % (0-100)', 50) +WithoutProgress.argTypes = { + type: { + defaultValue: NotificationType.Error, + }, +} +export const WithProgress: Story = args => { + const message = args.message + const type = args.type + const source = args.source + const progressMessage = args.progressMessage + const progressPercentage = args.progressPercentage return ( { /> ) } +WithProgress.argTypes = { + progressMessage: { + name: 'Progress message', + control: { type: 'text' }, + defaultValue: 'My *custom* progress message', + }, + progressPercentage: { + name: 'Progress % (0-100)', + control: { type: 'number', min: 0, max: 100 }, + defaultValue: 50, + }, + type: { + defaultValue: NotificationType.Info, + }, +} WithProgress.storyName = 'With progress' WithProgress.parameters = { diff --git a/client/storybook/src/main.ts b/client/storybook/src/main.ts index c0684952633..fe8aa6b37bc 100644 --- a/client/storybook/src/main.ts +++ b/client/storybook/src/main.ts @@ -74,13 +74,13 @@ const config: Config = { staticDirs: [path.resolve(__dirname, '../assets'), STATIC_ASSETS_PATH], stories: getStoriesGlob(), addons: [ - '@storybook/addon-knobs', '@storybook/addon-actions', 'storybook-addon-designs', 'storybook-dark-mode', '@storybook/addon-a11y', '@storybook/addon-toolbars', '@storybook/addon-docs', + '@storybook/addon-controls', { name: '@storybook/addon-storysource', options: { diff --git a/client/web/src/batches/RepoBatchChangesButton.story.tsx b/client/web/src/batches/RepoBatchChangesButton.story.tsx index ca276ae5357..dedf89876d6 100644 --- a/client/web/src/batches/RepoBatchChangesButton.story.tsx +++ b/client/web/src/batches/RepoBatchChangesButton.story.tsx @@ -1,4 +1,3 @@ -import { number } from '@storybook/addon-knobs' import { Meta, Story, DecoratorFn } from '@storybook/react' import { of } from 'rxjs' @@ -15,19 +14,37 @@ const config: Meta = { } export default config - +let openValue = 0 +let mergedValue = 0 const queryRepoChangesetsStats: typeof _queryRepoChangesetsStats = () => of({ changesetsStats: { - open: number('Open', 2), - merged: number('Merged', 47), + open: openValue, + merged: mergedValue, }, }) -export const RepoButton: Story = () => ( +export const RepoButton: Story = args => ( - {() => } + {() => { + openValue = args.open + mergedValue = args.merged + + return ( + + ) + }} ) +RepoButton.argTypes = { + open: { + control: { type: 'number' }, + defaultValue: 2, + }, + merged: { + control: { type: 'number' }, + defaultValue: 47, + }, +} RepoButton.storyName = 'RepoButton' diff --git a/client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx b/client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx index c1846d36d78..747e46a7208 100644 --- a/client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx +++ b/client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx @@ -1,5 +1,4 @@ import { action } from '@storybook/addon-actions' -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import * as H from 'history' @@ -64,20 +63,35 @@ export default config export const Loading: Story = () => -export const _04Completed: Story = () => ( +export const _04Completed: Story = args => ( ) +_04Completed.argTypes = { + ConnectedCodeHost: { + control: { type: 'boolean' }, + defaultValue: false, + }, + DidSearch: { + control: { type: 'boolean' }, + defaultValue: false, + }, + FoundReferences: { + control: { type: 'boolean' }, + defaultValue: false, + }, + EnabledSharing: { + control: { type: 'boolean' }, + defaultValue: false, + }, +} _04Completed.storyName = 'Progress 0/4 completed' _04Completed.parameters = { @@ -88,20 +102,35 @@ _04Completed.parameters = { }, } -export const _14Completed: Story = () => ( +export const _14Completed: Story = args => ( ) +_14Completed.argTypes = { + ConnectedCodeHost: { + control: { type: 'boolean' }, + defaultValue: true, + }, + DidSearch: { + control: { type: 'boolean' }, + defaultValue: false, + }, + FoundReferences: { + control: { type: 'boolean' }, + defaultValue: false, + }, + EnabledSharing: { + control: { type: 'boolean' }, + defaultValue: false, + }, +} _14Completed.storyName = 'Progress 1/4 completed' _14Completed.parameters = { diff --git a/client/web/src/components/diff/DiffStat.story.tsx b/client/web/src/components/diff/DiffStat.story.tsx index fab82269dfa..403a9c8aa6a 100644 --- a/client/web/src/components/diff/DiffStat.story.tsx +++ b/client/web/src/components/diff/DiffStat.story.tsx @@ -1,49 +1,52 @@ -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../WebStory' import { DiffStat, DiffStatSquares, DiffStatStack } from './DiffStat' -const getSharedKnobs = () => ({ - added: number('Added', 10), - changed: number('Changed', 4), - deleted: number('Deleted', 8), -}) - const decorator: DecoratorFn = story =>
{story()}
const config: Meta = { title: 'web/diffs/DiffStat', decorators: [decorator], + argTypes: { + added: { + type: 'number', + defaultValue: 10, + }, + changed: { + type: 'number', + defaultValue: 4, + }, + deleted: { + type: 'number', + defaultValue: 8, + }, + }, } export default config -export const CollapsedCounts: Story = () => { - const stats = getSharedKnobs() - return {() => } -} +export const CollapsedCounts: Story> = args => ( + {() => } +) CollapsedCounts.storyName = 'Collapsed counts' -export const ExpandedCounts: Story = () => { - const stats = getSharedKnobs() - return {() => } -} +export const ExpandedCounts: Story> = args => ( + {() => } +) ExpandedCounts.storyName = 'Expanded counts' -export const DiffStatSquaresStory: Story = () => { - const stats = getSharedKnobs() - return {() => } -} +export const DiffStatSquaresStory: Story> = args => ( + {() => } +) DiffStatSquaresStory.storyName = 'DiffStatSquares' -export const DiffStatStackStory: Story = () => { - const stats = getSharedKnobs() - return {() => } -} +export const DiffStatStackStory: Story> = args => ( + {() => } +) DiffStatStackStory.storyName = 'DiffStatStack' diff --git a/client/web/src/components/diff/FileDiffHunks.story.tsx b/client/web/src/components/diff/FileDiffHunks.story.tsx index c81db634b2c..0ca61daf862 100644 --- a/client/web/src/components/diff/FileDiffHunks.story.tsx +++ b/client/web/src/components/diff/FileDiffHunks.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { FileDiffHunkFields, DiffHunkLineType } from '../../graphql-operations' @@ -58,19 +57,29 @@ const config: Meta = { title: 'web/diffs/FileDiffHunks', decorators: [decorator], includeStories: ['OneDiffUnifiedHunk', 'OneDiffSplitHunk'], + argTypes: { + persistLines: { + control: { type: 'boolean' }, + defaultValue: true, + }, + lineNumbers: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const OneDiffUnifiedHunk: Story = () => ( +export const OneDiffUnifiedHunk: Story = args => ( {webProps => ( @@ -80,15 +89,15 @@ export const OneDiffUnifiedHunk: Story = () => ( OneDiffUnifiedHunk.storyName = 'One diff unified hunk' -export const OneDiffSplitHunk: Story = () => ( +export const OneDiffSplitHunk: Story = args => ( {webProps => ( diff --git a/client/web/src/components/diff/FileDiffNode.story.tsx b/client/web/src/components/diff/FileDiffNode.story.tsx index a1d57326bd6..2e207081aab 100644 --- a/client/web/src/components/diff/FileDiffNode.story.tsx +++ b/client/web/src/components/diff/FileDiffNode.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { FileDiffFields } from '../../graphql-operations' @@ -189,11 +188,21 @@ const config: Meta = { title: 'web/diffs/FileDiffNode', decorators: [decorator], includeStories: ['AllUnifiedFileNode', 'AllSplitFileNode'], + argTypes: { + persistLines: { + control: { type: 'boolean' }, + defaultValue: true, + }, + lineNumbers: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const AllUnifiedFileNode: Story = () => ( +export const AllUnifiedFileNode: Story = args => ( {webProps => (
    @@ -202,8 +211,8 @@ export const AllUnifiedFileNode: Story = () => ( {...webProps} diffMode="unified" key={index} - persistLines={boolean('persistLines', true)} - lineNumbers={boolean('lineNumbers', true)} + persistLines={args.persistLines} + lineNumbers={args.lineNumbers} node={node} className="abcdef" /> @@ -215,7 +224,7 @@ export const AllUnifiedFileNode: Story = () => ( AllUnifiedFileNode.storyName = 'All unified file node states overview' -export const AllSplitFileNode: Story = () => ( +export const AllSplitFileNode: Story = args => ( {webProps => (
      @@ -224,8 +233,8 @@ export const AllSplitFileNode: Story = () => ( {...webProps} diffMode="split" key={index} - persistLines={boolean('persistLines', true)} - lineNumbers={boolean('lineNumbers', true)} + persistLines={args.persistLines} + lineNumbers={args.lineNumbers} node={node} className="abcdef" /> diff --git a/client/web/src/components/time/Duration.story.tsx b/client/web/src/components/time/Duration.story.tsx index 73cc7383c0e..69b70ac8ce9 100644 --- a/client/web/src/components/time/Duration.story.tsx +++ b/client/web/src/components/time/Duration.story.tsx @@ -1,4 +1,3 @@ -import { date } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { subDays } from 'date-fns' @@ -10,31 +9,39 @@ import { Duration } from './Duration' const decorator: DecoratorFn = story =>
      {story()}
      +const now = new Date() + const config: Meta = { title: 'web/Duration', decorators: [decorator], + argTypes: { + start: { + control: { type: 'date' }, + defaultValue: subDays(now, 1), + }, + }, } export default config -const now = new Date() - -export const Fixed: Story = () => ( - - {props => ( - - )} - +export const Fixed: Story = args => ( + {props => } ) +Fixed.argTypes = { + end: { + control: { type: 'date' }, + defaultValue: now, + }, +} -export const Active: Story = () => ( +export const Active: Story = args => ( {props => ( <>

      Borders demonstrate how the time changing does not cause layout shift.

      - +

      @@ -42,7 +49,7 @@ export const Active: Story = () => (

      - +
      diff --git a/client/web/src/enterprise/batches/DropdownButton.story.tsx b/client/web/src/enterprise/batches/DropdownButton.story.tsx index bc39a07acf5..5d759a3f1c7 100644 --- a/client/web/src/enterprise/batches/DropdownButton.story.tsx +++ b/client/web/src/enterprise/batches/DropdownButton.story.tsx @@ -1,9 +1,8 @@ -import { boolean, select } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../components/WebStory' -import { Action, DropdownButton, Props } from './DropdownButton' +import { Action, DropdownButton } from './DropdownButton' // eslint-disable-next-line @typescript-eslint/require-await const onTrigger = async (onDone: () => void) => onDone() @@ -34,55 +33,45 @@ const experimentalAction: Action = { experimental: true, } -const commonKnobs: () => Pick = () => ({ - disabled: boolean('Disabled', false), - dropdownMenuPosition: select( - 'Dropdown menu position', - { - None: undefined, - Left: 'left', - Right: 'right', - }, - undefined - ), -}) - const decorator: DecoratorFn = story =>
      {story()}
      const config: Meta = { title: 'web/batches/DropdownButton', decorators: [decorator], + argTypes: { + disabled: { + control: { type: 'boolean' }, + defaultValue: false, + }, + }, } export default config -export const NoActions: Story = () => {() => } +export const NoActions: Story = args => {() => } +NoActions.argTypes = { + disabled: { + table: { + disable: true, + }, + }, +} NoActions.storyName = 'No actions' -export const SingleAction: Story = () => ( - {() => } -) +export const SingleAction: Story = args => {() => } SingleAction.storyName = 'Single action' -export const MultipleActionsWithoutDefault: Story = () => ( - - {() => } - +export const MultipleActionsWithoutDefault: Story = args => ( + {() => } ) MultipleActionsWithoutDefault.storyName = 'Multiple actions without default' -export const MultipleActionsWithDefault: Story = () => ( +export const MultipleActionsWithDefault: Story = args => ( - {() => ( - - )} + {() => } ) diff --git a/client/web/src/enterprise/batches/DropdownButton.tsx b/client/web/src/enterprise/batches/DropdownButton.tsx index dce17a567de..4ec521db7ce 100644 --- a/client/web/src/enterprise/batches/DropdownButton.tsx +++ b/client/web/src/enterprise/batches/DropdownButton.tsx @@ -46,7 +46,6 @@ export interface Props { actions: Action[] defaultAction?: number disabled?: boolean - dropdownMenuPosition?: 'left' | 'right' onLabel?: (label: string | undefined) => void placeholder?: string tooltip?: string diff --git a/client/web/src/enterprise/batches/batch-spec/TabBar.story.tsx b/client/web/src/enterprise/batches/batch-spec/TabBar.story.tsx index cae5bea7080..60c5d943082 100644 --- a/client/web/src/enterprise/batches/batch-spec/TabBar.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/TabBar.story.tsx @@ -1,6 +1,5 @@ import { useState } from 'react' -import { select } from '@storybook/addon-knobs' import { DecoratorFn, Story, Meta } from '@storybook/react' import { WebStory } from '../../../components/WebStory' @@ -57,17 +56,15 @@ const EXECUTING_TABS: TabsConfig[] = [ { key: 'execution', isEnabled: true, handler: { type: 'link' } }, ] -export const ExecuteBatchSpec: Story = () => ( - - {props => ( - - )} - +export const ExecuteBatchSpec: Story = args => ( + {props => } ) +ExecuteBatchSpec.argTypes = { + activeTabKey: { + control: { type: 'select', options: ['configuration', 'spec', 'execution'] }, + defaultValue: 'execution', + }, +} ExecuteBatchSpec.storyName = 'executing a batch spec' @@ -78,17 +75,15 @@ const PREVIEWING_TABS: TabsConfig[] = [ { key: 'preview', isEnabled: true, handler: { type: 'link' } }, ] -export const PreviewExecutionResult: Story = () => ( - - {props => ( - - )} - +export const PreviewExecutionResult: Story = args => ( + {props => } ) +PreviewExecutionResult.argTypes = { + activeTabKey: { + control: { type: 'select', options: ['configuration', 'spec', 'execution', 'preview'] }, + defaultValue: 'preview', + }, +} PreviewExecutionResult.storyName = 'previewing an execution result' @@ -99,16 +94,14 @@ const LOCAL_TABS: TabsConfig[] = [ { key: 'preview', isEnabled: true, handler: { type: 'link' } }, ] -export const LocallyExecutedSpec: Story = () => ( - - {props => ( - - )} - +export const LocallyExecutedSpec: Story = args => ( + {props => } ) +LocallyExecutedSpec.argTypes = { + activeTabKey: { + control: { type: 'select', options: ['configuration', 'spec', 'preview'] }, + defaultValue: 'preview', + }, +} LocallyExecutedSpec.storyName = 'for a locally-executed spec' diff --git a/client/web/src/enterprise/batches/batch-spec/edit/editor/EditorFeedbackPanel.story.tsx b/client/web/src/enterprise/batches/batch-spec/edit/editor/EditorFeedbackPanel.story.tsx index 45bb2cc99d3..5e0da19e60d 100644 --- a/client/web/src/enterprise/batches/batch-spec/edit/editor/EditorFeedbackPanel.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/edit/editor/EditorFeedbackPanel.story.tsx @@ -1,4 +1,3 @@ -import { text, withKnobs } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../../../../components/WebStory' @@ -9,24 +8,48 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/edit/editor/EditorFeedbackPanel', - decorators: [decorator, withKnobs], + decorators: [decorator], + argTypes: { + actions: { + name: 'Actions', + control: { type: 'text' }, + defaultValue: '', + }, + execute: { + name: 'Execute', + control: { type: 'text' }, + defaultValue: '', + }, + preview: { + name: 'Preview', + control: { type: 'text' }, + defaultValue: '', + }, + codeUpdate: { + name: 'Code Update', + control: { type: 'text' }, + defaultValue: '', + }, + codeValidation: { + name: 'codeValidation', + control: { type: 'text' }, + defaultValue: 'The entered spec is invalid:\n * name must match pattern "^my-batch-change$"', + }, + }, } export default config -export const EditorFeedbackPanelStory: Story = () => ( +export const EditorFeedbackPanelStory: Story = args => ( {props => ( diff --git a/client/web/src/enterprise/batches/batch-spec/edit/editor/MonacoBatchSpecEditor.story.tsx b/client/web/src/enterprise/batches/batch-spec/edit/editor/MonacoBatchSpecEditor.story.tsx index 094bc5e80f6..1761d8434cf 100644 --- a/client/web/src/enterprise/batches/batch-spec/edit/editor/MonacoBatchSpecEditor.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/edit/editor/MonacoBatchSpecEditor.story.tsx @@ -1,5 +1,4 @@ import { action } from '@storybook/addon-actions' -import { boolean, withKnobs } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../../../../components/WebStory' @@ -11,19 +10,31 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/edit/editor/MonacoBatchSpecEditor', - decorators: [decorator, withKnobs], + decorators: [decorator], + argTypes: { + readOnly: { + name: 'Read Only', + control: { type: 'boolean' }, + defaultValue: false, + }, + autoFocus: { + name: 'Auto Focus', + control: { type: 'boolean' }, + defaultValue: false, + }, + }, } export default config -export const MonacoBatchSpecEditorStory: Story = () => ( +export const MonacoBatchSpecEditorStory: Story = args => ( {props => ( diff --git a/client/web/src/enterprise/batches/batch-spec/edit/library/ReplaceSpecModal.story.tsx b/client/web/src/enterprise/batches/batch-spec/edit/library/ReplaceSpecModal.story.tsx index 6cfe0b95fa1..d43728df48f 100644 --- a/client/web/src/enterprise/batches/batch-spec/edit/library/ReplaceSpecModal.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/edit/library/ReplaceSpecModal.story.tsx @@ -1,5 +1,4 @@ import { action } from '@storybook/addon-actions' -import { text, withKnobs } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../../../../components/WebStory' @@ -10,16 +9,23 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/edit/library/ReplaceSpecModal', - decorators: [decorator, withKnobs], + decorators: [decorator], + argTypes: { + libraryItemName: { + name: 'Name', + control: { type: 'text' }, + defaultValue: 'my-batch-change', + }, + }, } export default config -export const ReplaceSpecModalStory: Story = () => ( +export const ReplaceSpecModalStory: Story = args => ( {props => (
      {story()} const config: Meta = { title: 'web/batches/batch-spec/edit/workspaces-preview/ImportingChangesetsPreviewList', - decorators: [decorator, withKnobs], + decorators: [decorator], + argTypes: { + count: { + name: 'Count', + control: { type: 'number' }, + defaultValue: 1, + }, + isStale: { + name: 'Stale', + control: { type: 'boolean' }, + defaultValue: false, + }, + hasNextPage: { + name: 'Has Next Page', + control: { type: 'boolean' }, + defaultValue: false, + }, + loading: { + name: 'Loading', + control: { type: 'boolean' }, + defaultValue: false, + }, + }, } export default config -export const ImportingChangesetsPreviewListStory: Story = () => { - const count = number('Count', 1) +export const ImportingChangesetsPreviewListStory: Story = args => { + const count = args.count return ( {props => ( @@ -34,11 +55,11 @@ export const ImportingChangesetsPreviewListStory: Story = () => { endCursor: null, }, }, - hasNextPage: boolean('Has Next Page', false), + hasNextPage: args.hasNextPage, fetchMore: action('Fetch More'), - loading: boolean('Loading', false), + loading: args.loading, }} - isStale={boolean('Is Stale', false)} + isStale={args.isStale} {...props} /> )} diff --git a/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreview.story.tsx b/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreview.story.tsx index 18a5e5bbe52..ed1fe8d9397 100644 --- a/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreview.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreview.story.tsx @@ -1,4 +1,3 @@ -import { boolean, select } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { noop } from 'lodash' import { MATCH_ANY_PARAMETERS, WildcardMockLink } from 'wildcard-mock-link' @@ -35,17 +34,13 @@ const config: Meta = { export default config -export const Unstarted: Story = () => ( +export const Unstarted: Story = args => ( {() => ( Promise.resolve()} > @@ -54,18 +49,21 @@ export const Unstarted: Story = () => ( )} ) +Unstarted.argTypes = { + batchSpec: { + name: 'Valid batch spec?', + control: { type: 'boolean' }, + defaultValue: true, + }, +} -export const UnstartedWithCachedConnectionResult: Story = () => ( +export const UnstartedWithCachedConnectionResult: Story = args => ( {() => ( Promise.resolve()} > @@ -74,17 +72,18 @@ export const UnstartedWithCachedConnectionResult: Story = () => ( )} ) +UnstartedWithCachedConnectionResult.argTypes = { + batchSpec: { + name: 'Valid batch spec?', + control: { type: 'boolean' }, + defaultValue: true, + }, +} UnstartedWithCachedConnectionResult.storyName = 'unstarted, with cached connection result' -export const QueuedInProgress: Story = () => { - const inProgressResolution = mockWorkspaceResolutionStatus( - select( - 'Status', - [BatchSpecWorkspaceResolutionState.QUEUED, BatchSpecWorkspaceResolutionState.PROCESSING], - BatchSpecWorkspaceResolutionState.QUEUED - ) - ) +export const QueuedInProgress: Story = args => { + const inProgressResolution = mockWorkspaceResolutionStatus(args.inProgressResolution) const inProgressConnectionMocks = new WildcardMockLink([ { @@ -119,11 +118,7 @@ export const QueuedInProgress: Story = () => { Promise.resolve()} > @@ -133,17 +128,25 @@ export const QueuedInProgress: Story = () => { ) } +QueuedInProgress.argTypes = { + inProgressResolution: { + name: 'Status', + control: { + type: 'select', + options: [BatchSpecWorkspaceResolutionState.QUEUED, BatchSpecWorkspaceResolutionState.PROCESSING], + }, + defaultValue: BatchSpecWorkspaceResolutionState.QUEUED, + }, + batchSpec: { + control: { type: 'boolean' }, + defaultValue: true, + }, +} QueuedInProgress.storyName = 'queued/in progress' -export const QueuedInProgressWithCachedConnectionResult: Story = () => { - const inProgressResolution = mockWorkspaceResolutionStatus( - select( - 'Status', - [BatchSpecWorkspaceResolutionState.QUEUED, BatchSpecWorkspaceResolutionState.PROCESSING], - BatchSpecWorkspaceResolutionState.QUEUED - ) - ) +export const QueuedInProgressWithCachedConnectionResult: Story = args => { + const inProgressResolution = mockWorkspaceResolutionStatus(args.inProgressResolution) const inProgressConnectionMocks = new WildcardMockLink([ { @@ -188,16 +191,22 @@ export const QueuedInProgressWithCachedConnectionResult: Story = () => { ) } +QueuedInProgressWithCachedConnectionResult.argTypes = { + inProgressResolution: { + name: 'Status', + control: { + type: 'select', + options: [BatchSpecWorkspaceResolutionState.QUEUED, BatchSpecWorkspaceResolutionState.PROCESSING], + }, + defaultValue: BatchSpecWorkspaceResolutionState.QUEUED, + }, +} QueuedInProgressWithCachedConnectionResult.storyName = 'queued/in progress, with cached connection result' -export const FailedErrored: Story = () => { +export const FailedErrored: Story = args => { const failedResolution = mockWorkspaceResolutionStatus( - select( - 'Status', - [BatchSpecWorkspaceResolutionState.FAILED, BatchSpecWorkspaceResolutionState.ERRORED], - BatchSpecWorkspaceResolutionState.FAILED - ), + args.inProgressResolution, "Oh no something went wrong. This is a longer error message to demonstrate how this might take up a decent portion of screen real estate but hopefully it's still helpful information so it's worth the cost. Here's a long error message with some bullets:\n * This is a bullet\n * This is another bullet\n * This is a third bullet and it's also the most important one so it's longer than all the others wow look at that." ) @@ -244,16 +253,22 @@ export const FailedErrored: Story = () => { ) } +FailedErrored.argTypes = { + inProgressResolution: { + name: 'Status', + control: { + type: 'select', + options: [BatchSpecWorkspaceResolutionState.FAILED, BatchSpecWorkspaceResolutionState.ERRORED], + }, + defaultValue: BatchSpecWorkspaceResolutionState.FAILED, + }, +} FailedErrored.storyName = 'failed/errored' -export const FailedErroredWithCachedConnectionResult: Story = () => { +export const FailedErroredWithCachedConnectionResult: Story = args => { const failedResolution = mockWorkspaceResolutionStatus( - select( - 'Status', - [BatchSpecWorkspaceResolutionState.FAILED, BatchSpecWorkspaceResolutionState.ERRORED], - BatchSpecWorkspaceResolutionState.FAILED - ), + args.inProgressResolution, "Oh no something went wrong. This is a longer error message to demonstrate how this might take up a decent portion of screen real estate but hopefully it's still helpful information so it's worth the cost. Here's a long error message with some bullets:\n * This is a bullet\n * This is another bullet\n * This is a third bullet and it's also the most important one so it's longer than all the others wow look at that." ) @@ -300,6 +315,16 @@ export const FailedErroredWithCachedConnectionResult: Story = () => { ) } +FailedErroredWithCachedConnectionResult.argTypes = { + inProgressResolution: { + name: 'Status', + control: { + type: 'select', + options: [BatchSpecWorkspaceResolutionState.FAILED, BatchSpecWorkspaceResolutionState.ERRORED], + }, + defaultValue: BatchSpecWorkspaceResolutionState.FAILED, + }, +} FailedErroredWithCachedConnectionResult.storyName = 'failed/errored, with cached connection result' diff --git a/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreviewList.story.tsx b/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreviewList.story.tsx index 45393621be7..898a1dcbcb5 100644 --- a/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreviewList.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/WorkspacesPreviewList.story.tsx @@ -1,5 +1,4 @@ import { action } from '@storybook/addon-actions' -import { boolean, number, withKnobs } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../../../../components/WebStory' @@ -11,18 +10,18 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/edit/workspaces-preview/WorkspacesPreviewList', - decorators: [decorator, withKnobs], + decorators: [decorator], } export default config -export const DefaultStory: Story = () => { - const count = number('Count', 1) +export const DefaultStory: Story = args => { + const count = args.count return ( {props => ( { endCursor: null, }, }, - hasNextPage: boolean('Has Next Page', false), + hasNextPage: args.hasNextPage, fetchMore: action('Fetch More'), }} {...props} @@ -45,6 +44,23 @@ export const DefaultStory: Story = () => { ) } +DefaultStory.argTypes = { + count: { + name: 'name', + control: { type: 'number' }, + defaultValue: 1, + }, + isStale: { + name: 'Stale', + control: { type: 'boolean' }, + defaultValue: false, + }, + hasNextPage: { + name: 'Has Next Page', + control: { type: 'boolean' }, + defaultValue: false, + }, +} DefaultStory.storyName = 'default' diff --git a/client/web/src/enterprise/batches/batch-spec/execute/CancelExecutionModal.story.tsx b/client/web/src/enterprise/batches/batch-spec/execute/CancelExecutionModal.story.tsx index db1344b1380..a4e8d2c9073 100644 --- a/client/web/src/enterprise/batches/batch-spec/execute/CancelExecutionModal.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/execute/CancelExecutionModal.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { noop } from 'lodash' @@ -13,18 +12,26 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/execute', decorators: [decorator], + argTypes: { + isLoading: { + control: { + type: 'boolean', + }, + defaultValue: false, + }, + }, } export default config -export const CancelExecutionModalStory: Story = () => ( +export const CancelExecutionModalStory: Story = args => ( {props => ( Are you sure you want to cancel the current execution?} isOpen={true} - isLoading={boolean('isLoading', false)} + isLoading={args.isLoading} onCancel={noop} onConfirm={noop} /> diff --git a/client/web/src/enterprise/batches/batch-spec/execute/ExecutionStatsBar.story.tsx b/client/web/src/enterprise/batches/batch-spec/execute/ExecutionStatsBar.story.tsx index df349fe62f3..4e7a79dd40f 100644 --- a/client/web/src/enterprise/batches/batch-spec/execute/ExecutionStatsBar.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/execute/ExecutionStatsBar.story.tsx @@ -1,4 +1,3 @@ -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../../../components/WebStory' @@ -10,20 +9,43 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/batch-spec/execute', decorators: [decorator], + argTypes: { + errored: { + control: { type: 'number' }, + defaultValue: 0, + }, + completed: { + control: { type: 'number' }, + defaultValue: 7, + }, + processing: { + control: { type: 'number' }, + defaultValue: 4, + }, + + queued: { + control: { type: 'number' }, + defaultValue: 14, + }, + ignored: { + control: { type: 'number' }, + defaultValue: 0, + }, + }, } export default config -export const ExecutionStatsBarStory: Story = () => ( +export const ExecutionStatsBarStory: Story = args => ( {props => ( )} diff --git a/client/web/src/enterprise/batches/batch-spec/execute/ReadOnlyBatchSpecForm.story.tsx b/client/web/src/enterprise/batches/batch-spec/execute/ReadOnlyBatchSpecForm.story.tsx index c1be96da92b..228bc716db2 100644 --- a/client/web/src/enterprise/batches/batch-spec/execute/ReadOnlyBatchSpecForm.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/execute/ReadOnlyBatchSpecForm.story.tsx @@ -1,4 +1,3 @@ -import { select } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { BatchSpecSource } from '@sourcegraph/shared/src/schema' @@ -22,17 +21,13 @@ const config: Meta = { export default config -export const Executing: Story = () => ( +export const Executing: Story = args => ( {props => ( @@ -40,26 +35,23 @@ export const Executing: Story = () => ( )} ) +Executing.argTypes = { + state: { + name: 'batch spec state', + control: { type: 'select', options: [BatchSpecState.PROCESSING, BatchSpecState.QUEUED] }, + defaultValue: BatchSpecState.PROCESSING, + }, +} Executing.storyName = 'while executing' -export const ExecutionFinished: Story = () => ( +export const ExecutionFinished: Story = args => ( {props => ( @@ -67,6 +59,22 @@ export const ExecutionFinished: Story = () => ( )} ) +ExecutionFinished.argTypes = { + state: { + name: 'batch spec state', + control: { + type: 'select', + options: [ + BatchSpecState.CANCELED, + BatchSpecState.CANCELING, + BatchSpecState.COMPLETED, + BatchSpecState.FAILED, + BatchSpecState.PENDING, + ], + }, + defaultValue: BatchSpecState.COMPLETED, + }, +} ExecutionFinished.storyName = 'after execution finishes' diff --git a/client/web/src/enterprise/batches/batch-spec/execute/workspaces/WorkspaceStateIcon.story.tsx b/client/web/src/enterprise/batches/batch-spec/execute/workspaces/WorkspaceStateIcon.story.tsx index d8068872093..b239a60b509 100644 --- a/client/web/src/enterprise/batches/batch-spec/execute/workspaces/WorkspaceStateIcon.story.tsx +++ b/client/web/src/enterprise/batches/batch-spec/execute/workspaces/WorkspaceStateIcon.story.tsx @@ -1,4 +1,3 @@ -import { boolean, withKnobs } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { BatchSpecWorkspaceState } from '@sourcegraph/shared/src/graphql-operations' @@ -11,12 +10,19 @@ const decorator: DecoratorFn = story =>
      {story()}
      const config: Meta = { title: 'web/batches/batch-spec/execute/workspaces/WorkspaceStateIcon', - decorators: [decorator, withKnobs], + decorators: [decorator], + argTypes: { + cachedResultFound: { + name: 'Cache Found', + control: { type: 'boolean' }, + defaultValue: false, + }, + }, } export default config -export const WorkspaceStateIconStory: Story = () => ( +export const WorkspaceStateIconStory: Story = args => ( {props => ( <> @@ -25,11 +31,7 @@ export const WorkspaceStateIconStory: Story = () => ( .map(value => (
      {value}:{' '} - +
      ))} diff --git a/client/web/src/enterprise/batches/close/BatchChangeCloseAlert.story.tsx b/client/web/src/enterprise/batches/close/BatchChangeCloseAlert.story.tsx index b9da46038ae..2220d5a462e 100644 --- a/client/web/src/enterprise/batches/close/BatchChangeCloseAlert.story.tsx +++ b/client/web/src/enterprise/batches/close/BatchChangeCloseAlert.story.tsx @@ -1,4 +1,3 @@ -import { boolean, number } from '@storybook/addon-knobs' import { useState } from '@storybook/addons' import { Meta, Story, DecoratorFn } from '@storybook/react' @@ -16,13 +15,18 @@ const config: Meta = { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const HasOpenChangesets: Story = () => { +export const HasOpenChangesets: Story = args => { const [closeChangesets, setCloseChangesets] = useState(false) - const totalCount = number('totalCount', 10) return ( {props => ( @@ -30,20 +34,26 @@ export const HasOpenChangesets: Story = () => { {...props} batchChangeID="change123" batchChangeURL="/users/john/batch-changes/change123" - totalCount={totalCount} + totalCount={args.totalCount} closeChangesets={closeChangesets} setCloseChangesets={setCloseChangesets} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} closeBatchChange={() => Promise.resolve()} /> )} ) } +HasOpenChangesets.argTypes = { + totalCount: { + control: { type: 'number' }, + defaultValue: 10, + }, +} HasOpenChangesets.storyName = 'Has open changesets' -export const NoOpenChangesets: Story = () => { +export const NoOpenChangesets: Story = args => { const [closeChangesets, setCloseChangesets] = useState(false) return ( @@ -55,7 +65,7 @@ export const NoOpenChangesets: Story = () => { totalCount={0} closeChangesets={closeChangesets} setCloseChangesets={setCloseChangesets} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} closeBatchChange={() => Promise.resolve()} /> )} diff --git a/client/web/src/enterprise/batches/close/BatchChangeClosePage.story.tsx b/client/web/src/enterprise/batches/close/BatchChangeClosePage.story.tsx index 6d017947ae8..065b839c653 100644 --- a/client/web/src/enterprise/batches/close/BatchChangeClosePage.story.tsx +++ b/client/web/src/enterprise/batches/close/BatchChangeClosePage.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { useMemo, useCallback } from '@storybook/addons' import { Meta, Story, DecoratorFn } from '@storybook/react' import { subDays } from 'date-fns' @@ -254,8 +253,8 @@ const queryEmptyExternalChangesetWithFileDiffs: typeof queryExternalChangesetWit }, }) -export const Overview: Story = () => { - const viewerCanAdminister = boolean('viewerCanAdminister', true) +export const Overview: Story = args => { + const viewerCanAdminister = args.viewerCanAdminister const batchChange: BatchChangeFields = useMemo( () => ({ ...batchChangeDefaults, @@ -282,6 +281,12 @@ export const Overview: Story = () => { ) } +Overview.argTypes = { + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, +} export const NoOpenChangesets: Story = () => { const batchChange: BatchChangeFields = useMemo(() => batchChangeDefaults, []) diff --git a/client/web/src/enterprise/batches/detail/ActiveExecutionNotice.story.tsx b/client/web/src/enterprise/batches/detail/ActiveExecutionNotice.story.tsx index 69324b554b5..7187378831f 100644 --- a/client/web/src/enterprise/batches/detail/ActiveExecutionNotice.story.tsx +++ b/client/web/src/enterprise/batches/detail/ActiveExecutionNotice.story.tsx @@ -1,6 +1,5 @@ import { useMemo } from 'react' -import { number } from '@storybook/addon-knobs' import { Meta, Story, DecoratorFn } from '@storybook/react' import { WebStory } from '../../../components/WebStory' @@ -12,6 +11,20 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/details', decorators: [decorator], + argTypes: { + numberActive: { + name: 'number of specs executing', + control: { type: 'number' }, + defaultValue: 1, + min: 0, + }, + numberComplete: { + name: 'number of specs completed', + control: { type: 'number' }, + defaultValue: 1, + min: 0, + }, + }, } export default config @@ -19,9 +32,9 @@ export default config const PROCESSING_BATCH_SPEC = { state: BatchSpecState.PROCESSING } const COMPLETE_BATCH_SPEC = { state: BatchSpecState.COMPLETED } -export const ActiveExecutionNoticeStory: Story = () => { - const numberActive = number('number of specs executing', 1, { min: 0 }) - const numberComplete = number('number of specs complete', 1, { min: 0 }) +export const ActiveExecutionNoticeStory: Story = args => { + const numberActive = args.numberActive + const numberComplete = args.numberComplete const specs = useMemo( () => [ diff --git a/client/web/src/enterprise/batches/detail/BatchChangeDetailsPage.story.tsx b/client/web/src/enterprise/batches/detail/BatchChangeDetailsPage.story.tsx index 6f4bcca6732..643381176f5 100644 --- a/client/web/src/enterprise/batches/detail/BatchChangeDetailsPage.story.tsx +++ b/client/web/src/enterprise/batches/detail/BatchChangeDetailsPage.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { useMemo } from '@storybook/addons' import { DecoratorFn, Meta, Story } from '@storybook/react' import { subDays } from 'date-fns' @@ -37,6 +36,22 @@ const config: Meta = { viewports: [320, 576, 978, 1440], disableSnapshot: false, }, + controls: { + exclude: ['url', 'supersededBatchSpec'], + }, + }, + argTypes: { + supersedingBatchSpec: { + control: { type: 'boolean' }, + }, + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + isClosed: { + control: { type: 'boolean' }, + defaultValue: false, + }, }, } @@ -127,10 +142,11 @@ const queryChangesetCountsOverTime: typeof _queryChangesetCountsOverTime = () => const deleteBatchChange = () => Promise.resolve(undefined) -const Template: Story<{ url: string; supersededBatchSpec?: boolean }> = ({ url, supersededBatchSpec }) => { - const supersedingBatchSpec = boolean('supersedingBatchSpec', !!supersededBatchSpec) - const viewerCanAdminister = boolean('viewerCanAdminister', true) - const isClosed = boolean('isClosed', false) +const Template: Story = ({ url, supersededBatchSpec, ...args }) => { + const supersedingBatchSpec = args.supersedingBatchSpec + const viewerCanAdminister = args.viewerCanAdminister + const isClosed = args.isClosed + const batchChange: BatchChangeFields = useMemo( () => ({ ...MOCK_BATCH_CHANGE, @@ -203,27 +219,57 @@ const Template: Story<{ url: string; supersededBatchSpec?: boolean }> = ({ url, export const Overview = Template.bind({}) Overview.args = { url: '/users/alice/batch-changes/awesome-batch-change' } +Overview.argTypes = { + supersedingBatchSpec: { + defaultValue: false, + }, +} export const BurndownChart = Template.bind({}) BurndownChart.args = { url: '/users/alice/batch-changes/awesome-batch-change?tab=chart' } BurndownChart.storyName = 'Burndown chart' +BurndownChart.argTypes = { + supersedingBatchSpec: { + defaultValue: false, + }, +} export const SpecFile = Template.bind({}) SpecFile.args = { url: '/users/alice/batch-changes/awesome-batch-change?tab=spec' } SpecFile.storyName = 'Spec file' +SpecFile.argTypes = { + supersedingBatchSpec: { + defaultValue: false, + }, +} export const Archived = Template.bind({}) Archived.args = { url: '/users/alice/batch-changes/awesome-batch-change?tab=archived' } +Archived.argTypes = { + supersedingBatchSpec: { + defaultValue: false, + }, +} export const BulkOperations = Template.bind({}) BulkOperations.args = { url: '/users/alice/batch-changes/awesome-batch-change?tab=bulkoperations' } BulkOperations.storyName = 'Bulk operations' +BulkOperations.argTypes = { + supersedingBatchSpec: { + defaultValue: false, + }, +} export const SupersededBatchSpec = Template.bind({}) SupersededBatchSpec.args = { url: '/users/alice/batch-changes/awesome-batch-change', supersededBatchSpec: true } SupersededBatchSpec.storyName = 'Superseded batch-spec' +SupersededBatchSpec.argTypes = { + supersedingBatchSpec: { + defaultValue: true, + }, +} -export const EmptyChangesets: Story = () => { +export const EmptyChangesets: Story = args => { const mocks = new WildcardMockLink([ { request: { @@ -257,11 +303,15 @@ export const EmptyChangesets: Story = () => { extensionsController={{} as any} platformContext={{} as any} settingsCascade={EMPTY_SETTINGS_CASCADE} + {...args} /> )} ) } +EmptyChangesets.parameters = { + controls: { hideNoControlsWarning: true, exclude: ['supersedingBatchSpec', 'viewerCanAdminister', 'isClosed'] }, +} EmptyChangesets.storyName = 'Empty changesets' diff --git a/client/web/src/enterprise/batches/detail/changesets/BatchChangeChangesets.story.tsx b/client/web/src/enterprise/batches/detail/changesets/BatchChangeChangesets.story.tsx index d4308fba995..128c7b09f6a 100644 --- a/client/web/src/enterprise/batches/detail/changesets/BatchChangeChangesets.story.tsx +++ b/client/web/src/enterprise/batches/detail/changesets/BatchChangeChangesets.story.tsx @@ -1,4 +1,3 @@ -import { boolean, select } from '@storybook/addon-knobs' import { Story, Meta, DecoratorFn } from '@storybook/react' import { noop } from 'lodash' import { of } from 'rxjs' @@ -20,6 +19,12 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/BatchChangeChangesets', decorators: [decorator], + argTypes: { + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config @@ -67,7 +72,7 @@ const queryEmptyExternalChangesetWithFileDiffs: typeof queryExternalChangesetWit } } -export const ListOfChangesets: Story = () => ( +export const ListOfChangesets: Story = args => ( {props => ( @@ -78,7 +83,7 @@ export const ListOfChangesets: Story = () => ( extensionsController={undefined as any} platformContext={undefined as any} batchChangeID="batchid" - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} settingsCascade={EMPTY_SETTINGS_CASCADE} batchChangeState={BatchChangeState.OPEN} isExecutionEnabled={false} @@ -90,7 +95,7 @@ export const ListOfChangesets: Story = () => ( ListOfChangesets.storyName = 'List of changesets' -export const ListOfExpandedChangesets: Story = () => ( +export const ListOfExpandedChangesets: Story = args => ( {props => ( @@ -101,7 +106,7 @@ export const ListOfExpandedChangesets: Story = () => ( extensionsController={undefined as any} platformContext={undefined as any} batchChangeID="batchid" - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} expandByDefault={true} settingsCascade={EMPTY_SETTINGS_CASCADE} batchChangeState={BatchChangeState.OPEN} @@ -114,9 +119,8 @@ export const ListOfExpandedChangesets: Story = () => ( ListOfExpandedChangesets.storyName = 'List of expanded changesets' -export const DraftWithoutChangesets: Story = () => { - const options = Object.keys(BatchChangeState) - const batchChangeState = select('batchChangeState', options, BatchChangeState.DRAFT) +export const DraftWithoutChangesets: Story = args => { + const batchChangeState = args.batchChangeState return ( @@ -133,12 +137,27 @@ export const DraftWithoutChangesets: Story = () => { expandByDefault={true} settingsCascade={EMPTY_SETTINGS_CASCADE} batchChangeState={batchChangeState as BatchChangeState} - isExecutionEnabled={boolean('isExecutionEnabled', true)} + isExecutionEnabled={args.isExecutionEnabled} /> )} ) } +DraftWithoutChangesets.argTypes = { + batchChangeState: { + control: { type: 'select', options: Object.keys(BatchChangeState) }, + defaultValue: BatchChangeState.DRAFT, + }, + isExecutionEnabled: { + control: { type: 'boolean' }, + defaultValue: true, + }, + viewerCanAdminister: { + table: { + disable: true, + }, + }, +} DraftWithoutChangesets.storyName = 'Draft without changesets' diff --git a/client/web/src/enterprise/batches/detail/changesets/ChangesetSelectRow.story.tsx b/client/web/src/enterprise/batches/detail/changesets/ChangesetSelectRow.story.tsx index 51b32ed525a..d9ca907544c 100644 --- a/client/web/src/enterprise/batches/detail/changesets/ChangesetSelectRow.story.tsx +++ b/client/web/src/enterprise/batches/detail/changesets/ChangesetSelectRow.story.tsx @@ -1,4 +1,3 @@ -import { number } from '@storybook/addon-knobs' import { Meta, Story, DecoratorFn } from '@storybook/react' import { of } from 'rxjs' @@ -16,31 +15,46 @@ import { ChangesetSelectRow } from './ChangesetSelectRow' const decorator: DecoratorFn = story =>
      {story()}
      +const MAX_CHANGESETS = 100 + const config: Meta = { title: 'web/batches/ChangesetSelectRow', decorators: [decorator], + argTypes: { + visibleChangesets: { + name: 'Visible changesets', + control: { type: 'range', min: 0, max: MAX_CHANGESETS }, + defaultValue: 10, + }, + selectableChangesets: { + name: 'Selectable changesets', + control: { type: 'range', min: 0, max: MAX_CHANGESETS }, + defaultValue: 100, + }, + selectedChangesets: { + name: 'Selected changesets', + control: { type: 'range', min: 0, max: MAX_CHANGESETS }, + defaultValue: 0, + }, + }, } export default config const onSubmit = (): void => {} -const CHANGESET_IDS = new Array(100).fill('fake-id').map((id, index) => `${id}-${index}`) +const CHANGESET_IDS = new Array(MAX_CHANGESETS).fill('fake-id').map((id, index) => `${id}-${index}`) const HALF_CHANGESET_IDS = CHANGESET_IDS.slice(0, 50) const queryAll100ChangesetIDs: typeof _queryAllChangesetIDs = () => of(CHANGESET_IDS) const queryAll50ChangesetIDs: typeof _queryAllChangesetIDs = () => of(CHANGESET_IDS.slice(0, 50)) const allBulkOperations = Object.keys(BulkOperationType) as BulkOperationType[] -export const AllStates: Story = () => { - const totalChangesets = number('Total changesets', 100) - const visibleChangesets = number('Visible changesets', 10, { range: true, min: 0, max: totalChangesets }) - const selectableChangesets = number('Selectable changesets', 100, { range: true, min: 0, max: totalChangesets }) - const selectedChangesets = number('Selected changesets', 0, { range: true, min: 0, max: selectableChangesets }) - - const queryAllChangesetIDs: typeof _queryAllChangesetIDs = () => of(CHANGESET_IDS.slice(0, selectableChangesets)) - const initialSelected = CHANGESET_IDS.slice(0, selectedChangesets) - const initialVisible = CHANGESET_IDS.slice(0, visibleChangesets) +export const AllStates: Story = args => { + const queryAllChangesetIDs: typeof _queryAllChangesetIDs = () => + of(CHANGESET_IDS.slice(0, args.selectableChangesets)) + const initialSelected = CHANGESET_IDS.slice(0, args.selectedChangesets) + const initialVisible = CHANGESET_IDS.slice(0, args.visibleChangesets) const queryAvailableBulkOperations: typeof _queryAvailableBulkOperations = () => of(allBulkOperations) diff --git a/client/web/src/enterprise/batches/detail/changesets/ExternalChangesetNode.story.tsx b/client/web/src/enterprise/batches/detail/changesets/ExternalChangesetNode.story.tsx index cf5dddbbb77..c3cf2ad1009 100644 --- a/client/web/src/enterprise/batches/detail/changesets/ExternalChangesetNode.story.tsx +++ b/client/web/src/enterprise/batches/detail/changesets/ExternalChangesetNode.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { Story, Meta, DecoratorFn } from '@storybook/react' import classNames from 'classnames' import { addHours } from 'date-fns' @@ -23,11 +22,17 @@ const decorator: DecoratorFn = story => ( const config: Meta = { title: 'web/batches/ExternalChangesetNode', decorators: [decorator], + argTypes: { + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const AllStates: Story = () => { +export const AllStates: Story = args => { const now = new Date() return ( @@ -93,7 +98,7 @@ export const AllStates: Story = () => { : { pushUser: false, namespace: null }, }, }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} queryExternalChangesetWithFileDiffs={() => of({ diff: { @@ -119,7 +124,7 @@ export const AllStates: Story = () => { AllStates.storyName = 'All states' -export const Unpublished: Story = () => { +export const Unpublished: Story = args => { const now = new Date() return ( @@ -172,7 +177,7 @@ export const Unpublished: Story = () => { forkTarget: null, }, }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} queryExternalChangesetWithFileDiffs={() => of({ diff: { @@ -194,7 +199,7 @@ export const Unpublished: Story = () => { ) } -export const Importing: Story = () => { +export const Importing: Story = args => { const now = new Date() return ( @@ -234,7 +239,7 @@ export const Importing: Story = () => { reviewState: null, currentSpec: null, }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} queryExternalChangesetWithFileDiffs={() => of({ diff: { @@ -256,7 +261,7 @@ export const Importing: Story = () => { ) } -export const ImportingFailed: Story = () => { +export const ImportingFailed: Story = args => { const now = new Date() return ( @@ -296,7 +301,7 @@ export const ImportingFailed: Story = () => { reviewState: null, currentSpec: null, }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} queryExternalChangesetWithFileDiffs={() => of({ diff: null, @@ -310,7 +315,7 @@ export const ImportingFailed: Story = () => { ImportingFailed.storyName = 'Importing failed' -export const SyncFailed: Story = () => { +export const SyncFailed: Story = args => { const now = new Date() return ( @@ -350,7 +355,7 @@ export const SyncFailed: Story = () => { reviewState: null, currentSpec: null, }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} queryExternalChangesetWithFileDiffs={() => of({ diff: null, diff --git a/client/web/src/enterprise/batches/list/BatchChangeListPage.story.tsx b/client/web/src/enterprise/batches/list/BatchChangeListPage.story.tsx index 711844b343d..235993035b4 100644 --- a/client/web/src/enterprise/batches/list/BatchChangeListPage.story.tsx +++ b/client/web/src/enterprise/batches/list/BatchChangeListPage.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Story, Meta } from '@storybook/react' import { WildcardMockLink, MATCH_ANY_PARAMETERS } from 'wildcard-mock-link' @@ -62,23 +61,26 @@ const MOCKS_FOR_NAMESPACE = new WildcardMockLink([ }, ]) -export const ListOfBatchChanges: Story = () => { - const canCreate = boolean('can create batch changes', true) - - return ( - - {props => ( - - - - )} - - ) +export const ListOfBatchChanges: Story = args => ( + + {props => ( + + + + )} + +) +ListOfBatchChanges.argTypes = { + canCreate: { + name: 'can create batch changes', + control: { type: 'boolean' }, + defaultValue: true, + }, } ListOfBatchChanges.storyName = 'List of batch changes' diff --git a/client/web/src/enterprise/batches/list/BatchChangeNode.story.tsx b/client/web/src/enterprise/batches/list/BatchChangeNode.story.tsx index 60fa02bc303..d8431057deb 100644 --- a/client/web/src/enterprise/batches/list/BatchChangeNode.story.tsx +++ b/client/web/src/enterprise/batches/list/BatchChangeNode.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { Meta, DecoratorFn, Story } from '@storybook/react' import classNames from 'classnames' import { subDays } from 'date-fns' @@ -6,7 +5,6 @@ import { subDays } from 'date-fns' import { isChromatic } from '@sourcegraph/storybook' import { WebStory } from '../../../components/WebStory' -import { ListBatchChange } from '../../../graphql-operations' import { BatchChangeNode } from './BatchChangeNode' import { nodes, now } from './testData' @@ -20,17 +18,29 @@ const decorator: DecoratorFn = story => ( const config: Meta = { title: 'web/batches/list/BatchChangeNode', decorators: [decorator], + argTypes: { + displayNamespace: { + name: 'Display namespace', + control: { type: 'boolean' }, + defaultValue: true, + }, + node: { + table: { + disable: true, + }, + }, + }, } export default config -const Template: Story<{ node: ListBatchChange }> = ({ node }) => ( +const Template: Story /* <{ node: ListBatchChange }>*/ = ({ node, ...args }) => ( {props => ( subDays(now, 5) : undefined} isExecutionEnabled={false} /> diff --git a/client/web/src/enterprise/batches/list/BatchChangesListIntro.story.tsx b/client/web/src/enterprise/batches/list/BatchChangesListIntro.story.tsx index 6992d9e0448..8146df99131 100644 --- a/client/web/src/enterprise/batches/list/BatchChangesListIntro.story.tsx +++ b/client/web/src/enterprise/batches/list/BatchChangesListIntro.story.tsx @@ -1,4 +1,3 @@ -import { radios } from '@storybook/addon-knobs' import { Meta, DecoratorFn, Story } from '@storybook/react' import { WebStory } from '../../../components/WebStory' @@ -6,12 +5,6 @@ import { WebStory } from '../../../components/WebStory' import { BatchChangesListIntro } from './BatchChangesListIntro' const decorator: DecoratorFn = story =>
      {story()}
      -const config: Meta = { - title: 'web/batches/list/BatchChangesListIntro', - decorators: [decorator], -} - -export default config enum LicensingState { Licensed = 'Licensed', @@ -19,6 +12,23 @@ enum LicensingState { Loading = 'Loading', } +const config: Meta = { + title: 'web/batches/list/BatchChangesListIntro', + decorators: [decorator], + argTypes: { + licensed: { + control: { type: 'radio', options: LicensingState }, + }, + state: { + table: { + disable: true, + }, + }, + }, +} + +export default config + function stateToInput(state: LicensingState): boolean | undefined { switch (state) { case LicensingState.Licensed: @@ -30,17 +40,24 @@ function stateToInput(state: LicensingState): boolean | undefined { } } -const Template: Story<{ state: LicensingState }> = ({ state }) => ( - - {() => } - +const Template: Story = ({ state, ...args }) => ( + {() => } ) export const Licensed = Template.bind({}) Licensed.args = { state: LicensingState.Licensed } +Licensed.argTypes = { + licensed: { defaultValue: LicensingState.Licensed }, +} export const Unlicensed = Template.bind({}) Unlicensed.args = { state: LicensingState.Unlicensed } +Unlicensed.argTypes = { + licensed: { defaultValue: LicensingState.Unlicensed }, +} export const Loading = Template.bind({}) Loading.args = { state: LicensingState.Loading } +Loading.argTypes = { + licensed: { defaultValue: LicensingState.Loading }, +} diff --git a/client/web/src/enterprise/batches/preview/BatchChangePreviewPage.story.tsx b/client/web/src/enterprise/batches/preview/BatchChangePreviewPage.story.tsx index 11153816daa..fbf2c87eb60 100644 --- a/client/web/src/enterprise/batches/preview/BatchChangePreviewPage.story.tsx +++ b/client/web/src/enterprise/batches/preview/BatchChangePreviewPage.story.tsx @@ -1,6 +1,5 @@ -import { boolean } from '@storybook/addon-knobs' -import { useMemo } from '@storybook/addons' -import { DecoratorFn, Meta, Story } from '@storybook/react' +import { Args, useMemo } from '@storybook/addons' +import { DecoratorFn, Story, Meta } from '@storybook/react' import { addDays, subDays } from 'date-fns' import { Observable, of } from 'rxjs' import { MATCH_ANY_PARAMETERS, WildcardMockLink } from 'wildcard-mock-link' @@ -35,6 +34,16 @@ const config: Meta = { disableSnapshot: false, }, }, + argTypes: { + supersedingBatchSpec: { + control: { type: 'boolean' }, + defaultValue: false, + }, + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config @@ -44,7 +53,7 @@ const nodes: ChangesetApplyPreviewFields[] = [ ...Object.values(hiddenChangesetApplyPreviewStories), ] -const batchSpec = (): BatchSpecFields => ({ +const batchSpec = (props: Args): BatchSpecFields => ({ appliesToBatchChange: null, createdAt: subDays(new Date(), 5).toISOString(), creator: { @@ -70,14 +79,14 @@ const batchSpec = (): BatchSpecFields => ({ namespaceName: 'alice', url: '/users/alice', }, - supersedingBatchSpec: boolean('supersedingBatchSpec', false) + supersedingBatchSpec: props.supersedingBatchSpec ? { __typename: 'BatchSpec', createdAt: subDays(new Date(), 1).toISOString(), applyURL: '/users/alice/batch-changes/apply/newspecid', } : null, - viewerCanAdminister: boolean('viewerCanAdminister', true), + viewerCanAdminister: props.viewerCanAdminister, viewerBatchChangesCodeHosts: { __typename: 'BatchChangesCodeHostConnection', totalCount: 0, @@ -116,11 +125,11 @@ const batchSpecByIDLink = (spec: BatchSpecFields): WildcardMockLink => }, ]) -const fetchBatchSpecCreate = () => batchSpecByIDLink(batchSpec()) +const fetchBatchSpecCreate = (props: Args) => batchSpecByIDLink(batchSpec(props)) -const fetchBatchSpecMissingCredentials = () => +const fetchBatchSpecMissingCredentials = (props: Args) => batchSpecByIDLink({ - ...batchSpec(), + ...batchSpec(props), viewerBatchChangesCodeHosts: { __typename: 'BatchChangesCodeHostConnection', totalCount: 2, @@ -137,9 +146,9 @@ const fetchBatchSpecMissingCredentials = () => }, }) -const fetchBatchSpecUpdate = () => +const fetchBatchSpecUpdate = (props: Args) => batchSpecByIDLink({ - ...batchSpec(), + ...batchSpec(props), appliesToBatchChange: { id: 'somebatch', name: 'awesome-batch-change', @@ -147,7 +156,7 @@ const fetchBatchSpecUpdate = () => }, }) -const fetchExceedsLicense = () => +const fetchExceedsLicense = (props: Args) => new WildcardMockLink([ { request: { @@ -160,7 +169,7 @@ const fetchExceedsLicense = () => data: { node: { __typename: 'BatchSpec', - ...batchSpec(), + ...batchSpec(props), }, }, }, @@ -216,8 +225,8 @@ const queryEmptyChangesetApplyPreview = (): Observable of({ totalCount: 0, pageInfo: { endCursor: null, hasNextPage: false }, nodes: [] }) -export const Create: Story = () => { - const link = useMemo(() => fetchBatchSpecCreate(), []) +export const Create: Story = args => { + const link = useMemo(() => fetchBatchSpecCreate(args), [args]) return ( {props => ( @@ -242,8 +251,8 @@ export const Create: Story = () => { ) } -export const Update: Story = () => { - const link = useMemo(() => fetchBatchSpecUpdate(), []) +export const Update: Story = args => { + const link = useMemo(() => fetchBatchSpecUpdate(args), [args]) return ( {props => ( @@ -268,8 +277,8 @@ export const Update: Story = () => { ) } -export const MissingCredentials: Story = () => { - const link = useMemo(() => fetchBatchSpecMissingCredentials(), []) +export const MissingCredentials: Story = args => { + const link = useMemo(() => fetchBatchSpecMissingCredentials(args), [args]) return ( {props => ( @@ -296,8 +305,8 @@ export const MissingCredentials: Story = () => { MissingCredentials.storyName = 'Missing credentials' -export const SpecFile: Story = () => { - const link = useMemo(() => fetchBatchSpecCreate(), []) +export const SpecFile: Story = args => { + const link = useMemo(() => fetchBatchSpecCreate(args), [args]) return ( {props => ( @@ -324,8 +333,8 @@ export const SpecFile: Story = () => { SpecFile.storyName = 'Spec file' -export const NoChangesets: Story = () => { - const link = useMemo(() => fetchBatchSpecCreate(), []) +export const NoChangesets: Story = args => { + const link = useMemo(() => fetchBatchSpecCreate(args), [args]) return ( {props => ( @@ -352,8 +361,8 @@ export const NoChangesets: Story = () => { NoChangesets.storyName = 'No changesets' -export const CreateNewStory: Story = () => { - const link = useMemo(() => fetchBatchSpecCreate(), []) +export const CreateNewStory: Story = args => { + const link = useMemo(() => fetchBatchSpecCreate(args), [args]) return ( {props => ( @@ -380,8 +389,8 @@ export const CreateNewStory: Story = () => { CreateNewStory.storyName = 'Create (New)' -export const ExceedsLicenseStory: Story = () => { - const link = useMemo(() => fetchExceedsLicense(), []) +export const ExceedsLicenseStory: Story = args => { + const link = useMemo(() => fetchExceedsLicense(args), [args]) return ( {props => ( diff --git a/client/web/src/enterprise/batches/preview/CreateUpdateBatchChangeAlert.story.tsx b/client/web/src/enterprise/batches/preview/CreateUpdateBatchChangeAlert.story.tsx index ef67a3aa212..a46c2823288 100644 --- a/client/web/src/enterprise/batches/preview/CreateUpdateBatchChangeAlert.story.tsx +++ b/client/web/src/enterprise/batches/preview/CreateUpdateBatchChangeAlert.story.tsx @@ -1,5 +1,4 @@ -import { boolean } from '@storybook/addon-knobs' -import { DecoratorFn, Meta, Story } from '@storybook/react' +import { DecoratorFn, Story, Meta } from '@storybook/react' import { WebStory } from '../../../components/WebStory' import { MultiSelectContextProvider } from '../MultiSelectContext' @@ -16,11 +15,17 @@ const config: Meta = { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + viewerCanAdminister: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const Create: Story = () => ( +export const Create: Story = args => ( {props => ( ( specID="123" toBeArchived={18} batchChange={null} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} /> )} ) -export const Update: Story = () => ( +export const Update: Story = args => ( {props => ( ( specID="123" toBeArchived={199} batchChange={{ id: '123', name: 'awesome-batch-change', url: 'http://test.test/awesome' }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} /> )} ) -export const Disabled: Story = () => ( +export const Disabled: Story = args => ( {props => ( @@ -57,7 +62,7 @@ export const Disabled: Story = () => ( specID="123" toBeArchived={199} batchChange={{ id: '123', name: 'awesome-batch-change', url: 'http://test.test/awesome' }} - viewerCanAdminister={boolean('viewerCanAdminister', true)} + viewerCanAdminister={args.viewerCanAdminister} /> )} diff --git a/client/web/src/enterprise/batches/preview/list/PreviewList.story.tsx b/client/web/src/enterprise/batches/preview/list/PreviewList.story.tsx index ebe2df6e9a8..2168ea0146e 100644 --- a/client/web/src/enterprise/batches/preview/list/PreviewList.story.tsx +++ b/client/web/src/enterprise/batches/preview/list/PreviewList.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { Observable, of } from 'rxjs' @@ -15,14 +14,21 @@ const decorator: DecoratorFn = story =>
      {story()} const config: Meta = { title: 'web/batches/preview/PreviewList', decorators: [decorator], + argTypes: { + publicationStateSet: { + name: 'publication state set by spec file', + control: { type: 'boolean' }, + defaultValue: false, + }, + }, } export default config const queryEmptyFileDiffs = () => of({ totalCount: 0, pageInfo: { endCursor: null, hasNextPage: false }, nodes: [] }) -export const DefaultStory: Story = () => { - const publicationStateSet = boolean('publication state set by spec file', false) +export const DefaultStory: Story = args => { + const publicationStateSet = args.publicationStateSet const nodes: ChangesetApplyPreviewFields[] = [ ...Object.values(visibleChangesetApplyPreviewNodeStories(publicationStateSet)), diff --git a/client/web/src/enterprise/batches/settings/AddCredentialModal.story.tsx b/client/web/src/enterprise/batches/settings/AddCredentialModal.story.tsx index 2170e312cb4..635e1f51255 100644 --- a/client/web/src/enterprise/batches/settings/AddCredentialModal.story.tsx +++ b/client/web/src/enterprise/batches/settings/AddCredentialModal.story.tsx @@ -1,4 +1,3 @@ -import { select } from '@storybook/addon-knobs' import { DecoratorFn, Story, Meta } from '@storybook/react' import { noop } from 'lodash' import { MATCH_ANY_PARAMETERS, WildcardMockLink } from 'wildcard-mock-link' @@ -27,7 +26,7 @@ const config: Meta = { export default config -export const RequiresSSHstep1: Story = () => ( +export const RequiresSSHstep1: Story = args => ( {props => ( ( ( )} ) +RequiresSSHstep1.argTypes = { + externalServiceKind: { + name: 'External service kind', + control: { type: 'select', options: Object.values(ExternalServiceKind) }, + defaultValue: ExternalServiceKind.GITHUB, + }, +} RequiresSSHstep1.storyName = 'Requires SSH - step 1' -export const RequiresSSHstep2: Story = () => ( +export const RequiresSSHstep2: Story = args => ( {props => ( ( )} ) +RequiresSSHstep2.argTypes = { + externalServiceKind: { + name: 'External service kind', + control: { type: 'select', options: Object.values(ExternalServiceKind) }, + defaultValue: ExternalServiceKind.GITHUB, + }, +} RequiresSSHstep2.storyName = 'Requires SSH - step 2' diff --git a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPage.story.tsx b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPage.story.tsx index 18c7320157c..a8dfb9ea7a5 100644 --- a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPage.story.tsx +++ b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPage.story.tsx @@ -1,5 +1,4 @@ import { MockedResponse } from '@apollo/client/testing' -import { boolean, withKnobs } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import { getDocumentNode } from '@sourcegraph/http-client' @@ -234,13 +233,24 @@ const inferredRepositoryConfigurationRequest: MockedResponse
      {story()}
      , withKnobs], + decorators: [story =>
      {story()}
      ], parameters: { component: CodeIntelConfigurationPage, chromatic: { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + indexingEnabled: { + control: { type: 'boolean' }, + defaultValue: true, + }, + authenticatedUser: { + table: { + disable: true, + }, + }, + }, } export default story @@ -254,9 +264,7 @@ const Template: Story = args => ( inferredRepositoryConfigurationRequest, // For Infer index configuration from HEAD ]} > - {props => ( - - )} + {props => } ) diff --git a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPolicyPage.story.tsx b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPolicyPage.story.tsx index e5b4d6d9baa..21be4f1da2c 100644 --- a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPolicyPage.story.tsx +++ b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelConfigurationPolicyPage.story.tsx @@ -1,4 +1,3 @@ -import { boolean, withKnobs } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import { getDocumentNode } from '@sourcegraph/http-client' @@ -127,13 +126,24 @@ const previewRepositoryFilterRequest = { const story: Meta = { title: 'web/codeintel/configuration/CodeIntelConfigurationPolicyPage', - decorators: [story =>
      {story()}
      , withKnobs], + decorators: [story =>
      {story()}
      ], parameters: { component: CodeIntelConfigurationPolicyPage, chromatic: { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + indexingEnabled: { + control: { type: 'boolean' }, + defaultValue: true, + }, + repo: { + table: { + disable: true, + }, + }, + }, } export default story @@ -150,9 +160,7 @@ const Template: Story = args => ( previewRepositoryFilterRequest, ]} > - {props => ( - - )} + {props => } ) diff --git a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelRepositoryIndexConfigurationPage.story.tsx b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelRepositoryIndexConfigurationPage.story.tsx index 3363b73fc79..ac8adf1bf55 100644 --- a/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelRepositoryIndexConfigurationPage.story.tsx +++ b/client/web/src/enterprise/codeintel/configuration/pages/CodeIntelRepositoryIndexConfigurationPage.story.tsx @@ -1,4 +1,3 @@ -import { withKnobs } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import { WebStory } from '../../../../components/WebStory' @@ -10,13 +9,20 @@ import { const story: Meta = { title: 'web/codeintel/configuration/CodeIntelRepositoryIndexConfigurationPage', - decorators: [story =>
      {story()}
      , withKnobs], + decorators: [story =>
      {story()}
      ], parameters: { component: CodeIntelRepositoryIndexConfigurationPage, chromatic: { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + repo: { + table: { + disable: true, + }, + }, + }, } export default story diff --git a/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadPage.story.tsx b/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadPage.story.tsx index 6af68ebb1fd..190123d1011 100644 --- a/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadPage.story.tsx +++ b/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadPage.story.tsx @@ -106,6 +106,10 @@ const story: Meta = { chromatic: { viewports: [320, 576, 978, 1440], }, + controls: { + hideNoControlsWarning: true, + exclude: ['now', 'queryLsifUploadsList', 'queryLisfUploadFields', 'queryRetentionMatches'], + }, }, } export default story diff --git a/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadsPage.story.tsx b/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadsPage.story.tsx index 671d478e043..e32c83cfa0e 100644 --- a/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadsPage.story.tsx +++ b/client/web/src/enterprise/codeintel/uploads/pages/CodeIntelUploadsPage.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import { of } from 'rxjs' @@ -109,14 +108,46 @@ const story: Meta = { viewports: [320, 576, 978, 1440], }, }, + argTypes: { + now: { + table: { + disable: true, + }, + }, + repo: { + table: { + disable: true, + }, + }, + queryLsifUploadsByRepository: { + table: { + disable: true, + }, + }, + queryLsifUploadsList: { + table: { + disable: true, + }, + }, + stale: { + name: 'staleCommitGraph', + control: { type: 'boolean' }, + defaultValue: false, + }, + updatedAt: { + name: 'previouslyUpdatedCommitGraph', + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default story -const Template: Story = args => { +const Template: Story = args => { const queryCommitGraphMetadata = () => of({ - stale: boolean('staleCommitGraph', false), - updatedAt: boolean('previouslyUpdatedCommitGraph', true) ? now() : null, + stale: args.stale, + updatedAt: args.updatedAt ? now() : null, }) return ( @@ -136,12 +167,18 @@ EmptyGlobalPage.args = { ...defaults, queryLsifUploadsList: () => of(makeResponse([])), } +EmptyGlobalPage.parameters = { + controls: { hideNoControlsWarning: true, exclude: ['staleCommitGraph', 'previouslyUpdatedCommitGraph'] }, +} export const GlobalPage = Template.bind({}) GlobalPage.args = { ...defaults, queryLsifUploadsList: () => of(makeResponse(testUploads)), } +GlobalPage.parameters = { + controls: { hideNoControlsWarning: true, exclude: ['staleCommitGraph', 'previouslyUpdatedCommitGraph'] }, +} export const EmptyRepositoryPage = Template.bind({}) EmptyRepositoryPage.args = { diff --git a/client/web/src/nav/UserNavItem.story.tsx b/client/web/src/nav/UserNavItem.story.tsx index bd213c1c08f..77abbe708d6 100644 --- a/client/web/src/nav/UserNavItem.story.tsx +++ b/client/web/src/nav/UserNavItem.story.tsx @@ -1,8 +1,7 @@ import React, { useEffect, useRef } from 'react' import { action } from '@storybook/addon-actions' -import { boolean, select } from '@storybook/addon-knobs' -import { useMemo } from '@storybook/addons' +import { Args, useMemo } from '@storybook/addons' import { Meta, Story } from '@storybook/react' import { Position } from '@sourcegraph/wildcard' @@ -27,6 +26,16 @@ const config: Meta = { viewports: [600], }, }, + argTypes: { + showDotComMarketing: { + control: { type: 'boolean' }, + defaultValue: true, + }, + codeHostIntegrationMessaging: { + control: { type: 'select', options: ['browser-extension', 'native-integration'] as const }, + defaultValue: 'browser-extension', + }, + }, } export default config @@ -58,16 +67,12 @@ const authenticatedUser: UserNavItemProps['authenticatedUser'] = { }, } -const commonProps = (): UserNavItemProps => ({ +const commonProps = (props: Args): UserNavItemProps => ({ themePreference: ThemePreference.Light, isLightTheme: true, onThemePreferenceChange, - showDotComMarketing: boolean('showDotComMarketing', true), - codeHostIntegrationMessaging: select( - 'codeHostIntegrationMessaging', - ['browser-extension', 'native-integration'] as const, - 'browser-extension' - ), + showDotComMarketing: props.showDotComMarketing, + codeHostIntegrationMessaging: props.codeHostIntegrationMessaging, showRepositorySection: true, authenticatedUser, position: Position.bottomStart, @@ -86,8 +91,8 @@ const OpenByDefaultWrapper: React.FunctionComponent<{ return children({ menuButtonRef: menuButtonReference }) } -export const SiteAdmin: Story = () => { - const props = useMemo(() => commonProps(), []) +export const SiteAdmin: Story = args => { + const props = useMemo(() => commonProps(args), [args]) return ( {({ menuButtonRef }) => ( @@ -106,8 +111,8 @@ export const SiteAdmin: Story = () => { ) } -export const WithAvatar: Story = () => { - const props = useMemo(() => commonProps(), []) +export const WithAvatar: Story = args => { + const props = useMemo(() => commonProps(args), [args]) return ( {({ menuButtonRef }) => ( diff --git a/client/web/src/repo/commits/GitCommitNode.story.tsx b/client/web/src/repo/commits/GitCommitNode.story.tsx index cc7623fc3a2..87c7faaa8e2 100644 --- a/client/web/src/repo/commits/GitCommitNode.story.tsx +++ b/client/web/src/repo/commits/GitCommitNode.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { subDays } from 'date-fns' @@ -71,22 +70,44 @@ const gitCommitNode: GitCommitFields = { 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore.', } -export const FullCustomizable: Story = () => ( +export const FullCustomizable: Story = args => ( {() => ( )} ) +FullCustomizable.argTypes = { + compact: { + control: { type: 'boolean' }, + defaultValue: false, + }, + expandCommitMessageBody: { + control: { type: 'boolean' }, + defaultValue: false, + }, + showSHAAndParentsRow: { + control: { type: 'boolean' }, + defaultValue: false, + }, + hideExpandCommitMessageBody: { + control: { type: 'boolean' }, + defaultValue: false, + }, + preferAbsoluteTimestamps: { + control: { type: 'boolean' }, + defaultValue: false, + }, +} FullCustomizable.storyName = 'Full customizable' diff --git a/client/web/src/site-admin/webhooks/MessagePanel.story.tsx b/client/web/src/site-admin/webhooks/MessagePanel.story.tsx index 82dd8b1098f..2faa2368121 100644 --- a/client/web/src/site-admin/webhooks/MessagePanel.story.tsx +++ b/client/web/src/site-admin/webhooks/MessagePanel.story.tsx @@ -1,4 +1,3 @@ -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../components/WebStory' @@ -44,7 +43,7 @@ export const JSONRequest: Story = () => ( JSONRequest.storyName = 'JSON request' -export const JSONResponse: Story = () => ( +export const JSONResponse: Story = args => ( {() => ( ( headers: messagePanelObject.JSON.headers, body: messagePanelObject.JSON.body, }} - requestOrStatusCode={number('status code', 200, { - min: 100, - max: 599, - })} + requestOrStatusCode={args.requestOrStatusCode} /> )} ) +JSONResponse.argTypes = { + requestOrStatusCode: { + control: { type: 'number', min: 100, max: 599 }, + defaultValue: 200, + }, +} JSONResponse.storyName = 'JSON response' @@ -83,7 +85,7 @@ export const PlainRequest: Story = () => ( PlainRequest.storyName = 'plain request' -export const PlainResponse: Story = () => ( +export const PlainResponse: Story = args => ( {() => ( ( headers: messagePanelObject.plain.headers, body: messagePanelObject.plain.body, }} - requestOrStatusCode={number('status code', 200, { - min: 100, - max: 599, - })} + requestOrStatusCode={args.requestOrStatusCode} /> )} ) +PlainResponse.argTypes = { + requestOrStatusCode: { + control: { type: 'number', min: 100, max: 599 }, + defaultValue: 200, + }, +} PlainResponse.storyName = 'plain response' diff --git a/client/web/src/site-admin/webhooks/StatusCode.story.tsx b/client/web/src/site-admin/webhooks/StatusCode.story.tsx index 4519fdc7656..a7508ec2da9 100644 --- a/client/web/src/site-admin/webhooks/StatusCode.story.tsx +++ b/client/web/src/site-admin/webhooks/StatusCode.story.tsx @@ -1,4 +1,3 @@ -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { WebStory } from '../../components/WebStory' @@ -19,10 +18,18 @@ const config: Meta = { export default config -export const Success: Story = () => ( - {() => } -) +export const Success: Story = args => {() => } +Success.argTypes = { + code: { + control: { type: 'number', min: 100, max: 399 }, + defaultValue: 204, + }, +} -export const Failure: Story = () => ( - {() => } -) +export const Failure: Story = args => {() => } +Failure.argTypes = { + code: { + control: { type: 'number', min: 400, max: 599 }, + defaultValue: 418, + }, +} diff --git a/client/web/src/site-admin/webhooks/WebhookLogNode.story.tsx b/client/web/src/site-admin/webhooks/WebhookLogNode.story.tsx index 3d995fa6921..1c5adf49242 100644 --- a/client/web/src/site-admin/webhooks/WebhookLogNode.story.tsx +++ b/client/web/src/site-admin/webhooks/WebhookLogNode.story.tsx @@ -4,6 +4,7 @@ import classNames from 'classnames' import { Container } from '@sourcegraph/wildcard' import { WebStory } from '../../components/WebStory' +import { WebhookLogFields } from '../../graphql-operations' import { webhookLogNode } from './story/fixtures' import { WebhookLogNode } from './WebhookLogNode' @@ -24,6 +25,18 @@ const config: Meta = { }, }, decorators: [decorator], + argTypes: { + receivedAt: { + name: 'received at', + control: { type: 'text' }, + defaultValue: 'Sun Nov 07 2021 14:31:00 GMT-0500 (Eastern Standard Time)', + }, + statusCode: { + name: 'status code', + control: { type: 'number', min: 100, max: 599 }, + defaultValue: 204, + }, + }, } export default config @@ -34,13 +47,15 @@ export default config // the external service name is handled properly when there isn't an external // service. // -// Some bonus knobs are provided for the tinkerers. +// Some bonus controls are provided for the tinkerers. -export const Collapsed: Story = () => ( +type StoryArguments = Pick + +export const Collapsed: Story = args => ( {() => ( ( ) -export const ExpandedRequest: Story = () => ( - {() => } +export const ExpandedRequest: Story = args => ( + {() => } ) ExpandedRequest.storyName = 'expanded request' -export const ExpandedResponse: Story = () => ( - {() => } +export const ExpandedResponse: Story = args => ( + + {() => } + ) ExpandedResponse.storyName = 'expanded response' diff --git a/client/web/src/site-admin/webhooks/WebhookLogPage.story.tsx b/client/web/src/site-admin/webhooks/WebhookLogPage.story.tsx index 9c02fb2e26e..5829844b00f 100644 --- a/client/web/src/site-admin/webhooks/WebhookLogPage.story.tsx +++ b/client/web/src/site-admin/webhooks/WebhookLogPage.story.tsx @@ -21,6 +21,18 @@ const config: Meta = { }, }, decorators: [decorator], + argTypes: { + externalServiceCount: { + name: 'external service count', + control: { type: 'number' }, + defaultValue: 2, + }, + erroredWebhookCount: { + name: 'errored webhook count', + control: { type: 'number' }, + defaultValue: 2, + }, + }, } export default config @@ -104,10 +116,10 @@ const buildWebhookLogs = (count: number, externalServiceCount: number): WebhookL return logs } -export const NoLogs: Story = () => ( +export const NoLogs: Story = args => ( {props => ( - + )} @@ -116,10 +128,10 @@ export const NoLogs: Story = () => ( NoLogs.storyName = 'no logs' -export const OnePageOfLogs: Story = () => ( +export const OnePageOfLogs: Story = args => ( {props => ( - + )} @@ -128,10 +140,10 @@ export const OnePageOfLogs: Story = () => ( OnePageOfLogs.storyName = 'one page of logs' -export const TwoPagesOfLogs: Story = () => ( +export const TwoPagesOfLogs: Story = args => ( {props => ( - + )} diff --git a/client/web/src/site-admin/webhooks/WebhookLogPageHeader.story.tsx b/client/web/src/site-admin/webhooks/WebhookLogPageHeader.story.tsx index 816d3a60155..0111c75ce62 100644 --- a/client/web/src/site-admin/webhooks/WebhookLogPageHeader.story.tsx +++ b/client/web/src/site-admin/webhooks/WebhookLogPageHeader.story.tsx @@ -1,6 +1,5 @@ import React, { useState } from 'react' -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { MockedTestProvider } from '@sourcegraph/shared/src/testing/apollo' @@ -26,6 +25,16 @@ const config: Meta = { }, }, decorators: [decorator], + argTypes: { + externalServiceCount: { + name: 'external service count', + control: { type: 'number' }, + }, + erroredWebhookCount: { + name: 'errored webhook count', + control: { type: 'number' }, + }, + }, } export default config @@ -51,76 +60,129 @@ const WebhookLogPageHeaderContainer: React.FunctionComponent< ) } -export const AllZeroes: Story = () => ( +export const AllZeroes: Story = args => ( {() => ( - + )} ) +AllZeroes.argTypes = { + externalServiceCount: { + defaultValue: 0, + }, + erroredWebhookCount: { + defaultValue: 0, + }, +} AllZeroes.storyName = 'all zeroes' -export const ExternalServices: Story = () => ( +export const ExternalServices: Story = args => ( {() => ( - + )} ) +ExternalServices.argTypes = { + externalServiceCount: { + defaultValue: 10, + }, + erroredWebhookCount: { + defaultValue: 0, + }, +} + ExternalServices.storyName = 'external services' -export const ExternalServicesAndErrors: Story = () => ( +export const ExternalServicesAndErrors: Story = args => ( {() => ( - + )} ) +ExternalServicesAndErrors.argTypes = { + externalServiceCount: { + defaultValue: 20, + }, + erroredWebhookCount: { + defaultValue: 500, + }, +} + ExternalServicesAndErrors.storyName = 'external services and errors' -export const OnlyErrorsTurnedOn: Story = () => ( +export const OnlyErrorsTurnedOn: Story = args => ( {() => ( - + )} ) +OnlyErrorsTurnedOn.argTypes = { + externalServiceCount: { + defaultValue: 20, + }, + erroredWebhookCount: { + defaultValue: 500, + }, +} OnlyErrorsTurnedOn.storyName = 'only errors turned on' -export const SpecificExternalServiceSelected: Story = () => ( +export const SpecificExternalServiceSelected: Story = args => ( {() => ( - - + + )} ) +SpecificExternalServiceSelected.argTypes = { + initialExternalService: { + control: { type: 'number', min: 0, max: 19 }, + defaultValue: 2, + }, + externalServiceCount: { + defaultValue: 20, + }, + erroredWebhookCount: { + defaultValue: 500, + }, +} SpecificExternalServiceSelected.storyName = 'specific external service selected' -export const UnmatchedExternalServiceSelected: Story = () => ( +export const UnmatchedExternalServiceSelected: Story = args => ( {() => ( - + )} ) +UnmatchedExternalServiceSelected.argTypes = { + externalServiceCount: { + defaultValue: 20, + }, + erroredWebhookCount: { + defaultValue: 500, + }, +} + UnmatchedExternalServiceSelected.storyName = 'unmatched external service selected' diff --git a/client/web/src/site-admin/webhooks/story/fixtures.ts b/client/web/src/site-admin/webhooks/story/fixtures.ts index 7f06da2b18d..ada039263b2 100644 --- a/client/web/src/site-admin/webhooks/story/fixtures.ts +++ b/client/web/src/site-admin/webhooks/story/fixtures.ts @@ -1,5 +1,4 @@ import { MockedResponse } from '@apollo/client/testing' -import { number, text } from '@storybook/addon-knobs' import { getDocumentNode } from '@sourcegraph/http-client' @@ -43,10 +42,13 @@ export const HEADERS_PLAIN = [ }, ] -export const webhookLogNode = (overrides?: Partial): WebhookLogFields => ({ +export const webhookLogNode = ( + defaultArguments: Pick, + overrides?: Partial +): WebhookLogFields => ({ id: overrides?.id ?? 'ID', - receivedAt: overrides?.receivedAt ?? text('received at', '2021-11-07T19:31:00Z'), - statusCode: overrides?.statusCode ?? number('status code', 204, { min: 100, max: 599 }), + receivedAt: overrides?.receivedAt ?? defaultArguments.receivedAt, + statusCode: overrides?.statusCode ?? defaultArguments.statusCode, externalService: overrides?.externalService ?? null, request: overrides?.request ?? { headers: HEADERS_JSON, @@ -63,7 +65,6 @@ export const webhookLogNode = (overrides?: Partial): WebhookLo export const buildExternalServices = (count: number): WebhookLogPageHeaderExternalService[] => { const services: WebhookLogPageHeaderExternalService[] = [] - count = number('external service count', count) for (let index = 0; index < count; index++) { const name = `External service ${index}` @@ -90,7 +91,7 @@ export const buildHeaderMock = ( nodes: buildExternalServices(externalServiceCount), }, webhookLogs: { - totalCount: number('errored webhook count', webhookLogCount), + totalCount: webhookLogCount, }, }, }, diff --git a/client/wildcard/src/components/Button/story/Button.story.tsx b/client/wildcard/src/components/Button/story/Button.story.tsx index 5b4582d9058..ceb7a789a3f 100644 --- a/client/wildcard/src/components/Button/story/Button.story.tsx +++ b/client/wildcard/src/components/Button/story/Button.story.tsx @@ -1,4 +1,3 @@ -import { boolean, select } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import SearchIcon from 'mdi-react/SearchIcon' @@ -41,16 +40,33 @@ const config: Meta = { export default config -export const Simple: Story = () => ( - ) +Simple.argTypes = { + variant: { + name: 'Variant', + control: { type: 'select', options: BUTTON_VARIANTS }, + defaultValue: 'primary', + }, + size: { + name: 'Name', + control: { type: 'select', options: BUTTON_SIZES }, + defaultValue: 'sm', + }, + disabled: { + name: 'Disabled', + control: { type: 'boolean' }, + defaultValue: false, + }, + outline: { + name: 'Outline', + control: { type: 'boolean' }, + defaultValue: false, + }, +} export const AllButtons: Story = () => (
      diff --git a/client/wildcard/src/components/LoadingSpinner/LoadingSpinner.story.tsx b/client/wildcard/src/components/LoadingSpinner/LoadingSpinner.story.tsx index 098b1048668..067024b30bb 100644 --- a/client/wildcard/src/components/LoadingSpinner/LoadingSpinner.story.tsx +++ b/client/wildcard/src/components/LoadingSpinner/LoadingSpinner.story.tsx @@ -1,4 +1,3 @@ -import { boolean } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import { BrandedStory } from '@sourcegraph/branded/src/components/BrandedStory' @@ -23,8 +22,14 @@ const config: Meta = { disableSnapshot: false, }, }, + argTypes: { + inline: { + control: { type: 'boolean' }, + defaultValue: true, + }, + }, } export default config -export const Simple: Story = () => +export const Simple: Story = (args = {}) => diff --git a/client/wildcard/src/components/PageSelector/PageSelector.story.tsx b/client/wildcard/src/components/PageSelector/PageSelector.story.tsx index dd88207a850..a1cfe7dbda6 100644 --- a/client/wildcard/src/components/PageSelector/PageSelector.story.tsx +++ b/client/wildcard/src/components/PageSelector/PageSelector.story.tsx @@ -1,6 +1,5 @@ import { useState } from 'react' -import { number } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { BrandedStory } from '@sourcegraph/branded/src/components/BrandedStory' @@ -22,9 +21,16 @@ const config: Meta = { export default config -export const Simple: Story = () => { +export const Simple: Story = (args = {}) => { const [page, setPage] = useState(1) - return + return +} +Simple.argTypes = { + totalPages: { + name: 'maxPages', + control: { type: 'number' }, + defaultValue: 5, + }, } export const AllPageSelectors: Story = () => ( diff --git a/client/wildcard/src/components/Popover/story/Popover.story.tsx b/client/wildcard/src/components/Popover/story/Popover.story.tsx index 2e1d4b8d67d..c28fcbae176 100644 --- a/client/wildcard/src/components/Popover/story/Popover.story.tsx +++ b/client/wildcard/src/components/Popover/story/Popover.story.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react' -import { boolean } from '@storybook/addon-knobs' import { Meta, Story } from '@storybook/react' import classNames from 'classnames' import { noop } from 'rxjs' @@ -400,14 +399,14 @@ export const WithControlledState: Story = () => { ) } -export const WithNestedScrollParents: Story = () => { - const constrainToScrollParents = boolean('constrainToScrollParents', true) +export const WithNestedScrollParents: Story = (args = {}) => { + const constrainToScrollParents = args.constrainToScrollParents return (
      @@ -440,6 +439,12 @@ export const WithNestedScrollParents: Story = () => { ) } +WithNestedScrollParents.argTypes = { + constrainToScrollParents: { + control: { type: 'boolean' }, + defaultValue: true, + }, +} export const WithVirtualTarget: Story = () => { const [virtualElement, setVirtualElement] = useState(null) diff --git a/client/wildcard/src/components/Typography/Typography.story.tsx b/client/wildcard/src/components/Typography/Typography.story.tsx index 7faa74361f3..94f39615447 100644 --- a/client/wildcard/src/components/Typography/Typography.story.tsx +++ b/client/wildcard/src/components/Typography/Typography.story.tsx @@ -1,4 +1,3 @@ -import { select } from '@storybook/addon-knobs' import { DecoratorFn, Meta, Story } from '@storybook/react' import { BrandedStory } from '@sourcegraph/branded/src/components/BrandedStory' @@ -36,7 +35,7 @@ const config: Meta = { export default config -export const Simple: Story = () => ( +export const Simple: Story = (args = {}) => ( <>

      Headings

      @@ -50,10 +49,7 @@ export const Simple: Story = () => ( @@ -67,10 +63,7 @@ export const Simple: Story = () => ( @@ -84,10 +77,7 @@ export const Simple: Story = () => ( @@ -101,10 +91,7 @@ export const Simple: Story = () => ( @@ -118,10 +105,7 @@ export const Simple: Story = () => ( @@ -135,10 +119,7 @@ export const Simple: Story = () => ( @@ -196,59 +177,32 @@ export const Simple: Story = () => ( @@ -323,6 +247,16 @@ export const Simple: Story = () => (
      -

      +

      This is H1

      -

      +

      This is H2

      -

      +

      This is H3

      -

      +

      This is H4

      -
      +
      This is H5
      -
      +
      This is H6
      -
      -
      -
      -
      -
      -
      @@ -269,52 +223,22 @@ export const Simple: Story = () => (
      - + This is Body / Base / Regular - + This is Body / Base / Medium - + This is Body / Base / Bold - + This is Body / Small / Regular - + This is Body / Small / Medium - + This is Body / Small / Bold
      ) +Simple.argTypes = { + mode: { + control: { type: 'select', options: TYPOGRAPHY_MODES }, + defaultValue: 'default', + }, + alignment: { + control: { type: 'select', options: TYPOGRAPHY_ALIGNMENTS }, + defaultValue: 'left', + }, +} export const CrossingStyles: Story = () => ( <> diff --git a/internal/cmd/tracking-issue/testdata/fixtures.json b/internal/cmd/tracking-issue/testdata/fixtures.json index 7ea910cd41c..4155bf46c0d 100755 --- a/internal/cmd/tracking-issue/testdata/fixtures.json +++ b/internal/cmd/tracking-issue/testdata/fixtures.json @@ -7287,7 +7287,7 @@ { "ID": "MDU6SXNzdWU2OTIxMzI1NzI=", "Title": "blackbox exporter \u0026 site 24/7 next steps", - "Body": "**Summary**\r\nHistorically we have used [site24x7](https://www.site24x7.com/) to monitor [sourcegraph.com](https://sourcegraph.com), however it has also been the source of some ephemeral alerts that has been cause for concern and reduced faith in its reliability see [here](https://github.com/sourcegraph/sourcegraph/issues/10742). In an effort to reduce our dependency on site24x7 and improve our on call experience and our monitoring reliability, [blackbox exporter](https://github.com/prometheus/blackbox_exporter) was deployed. At the time of raising this issue, each endpoint configured in site24x7 is replicated in blackbox exporter, all of which are configured to alert if a non 200 http status code is not received for 5 minutes. \r\n\r\n**Site 24x7**\r\nThe good:\r\n- Be default we get a bunch of useful metrics out of the box, without having to configure anything specific, aside from the endpoint itself (response time broken down into dns resolution, download, ssl etc)\r\n- The ui is relatively simple to use\r\n- Summary of outages and the RCA image is sometimes handy to see where things are breaking down. \r\n- Testing from multiple locations\r\n- Cost?\r\n\r\nThe bad: \r\n- We get monitoring up until cloudflare, which is to say that there's no visibility of external vs internal issues in the same platform. As a result, it's hard to know if the issue is with cloudflare or with the sourcegraph frontend and where to look next. \r\n\r\n**Blackbox exporter**\r\nThe good:\r\n- There's a lot of knobs we can turn and tune here to gather exactly the information we find most useful.\r\n- We can easily see on the same grafana dashboard all of the endpoints we have configured per metric\r\n- We get internal and external monitoring of endpoints out of the same service (that is to say we can configure a ping to hit an exernal service as well as the services themselves)\r\n- Free\r\n\r\nThe bad: \r\n- There is some intitial setup required in order to determine what metrics we want, on which endpoints, all of which need to be configured manually in the various config files (blackbox exporter and prometheus, as well as any further alertmanager config that may be required). \r\n- We essentially only get one source of truth here, as we are testing from inside our own cluster, out to the world then back again. We do not get multiple locations like site24x7\r\n- There will be ongoing maintenance, which at this stage is hard to say what that will be, however one could assume the more metrics we gather, the more we need to maintain it and ensure they're up to date. \r\n\r\n**What's next**\r\n\r\nDetermine what we consider to be missing from blackbox exporter that we currently have in site24x7, considering the metrics out of the box that are displayed on site24x7 vs what we can and need to configure in blackbox exporter. \r\n\r\nEnsure that alerting is actually working from blackbox exporter, and that it's a trustworthy source. For example, a comparison in the most recent outage reported by site24x7 is [here](https://www.site24x7.com/app/client#/home/monitors/187445000000070268/OutageTroubleAlerts) and [here](https://sourcegraph.com/-/debug/grafana/explore?orgId=1\u0026left=%5B%221598367600000%22,%221598410800000%22,%22Prometheus%22,%7B%22expr%22:%22probe_http_status_code%7Binstance%3D%5C%22https:%2F%2Fsourcegraph.com%2F%5C%22%7D%22%7D,%7B%22expr%22:%22probe_http_status_code%7Binstance%3D%5C%22http:%2F%2Fsourcegraph-frontend.prod.svc.cluster.local:30080%5C%22%7D%22%7D,%7B%22ui%22:%5Btrue,true,true,%22none%22%5D%7D%5D) the same graph time period from blackbox exporter for both the external endpoint as well as the frontend service.\r\n\r\n", + "Body": "**Summary**\r\nHistorically we have used [site24x7](https://www.site24x7.com/) to monitor [sourcegraph.com](https://sourcegraph.com), however it has also been the source of some ephemeral alerts that has been cause for concern and reduced faith in its reliability see [here](https://github.com/sourcegraph/sourcegraph/issues/10742). In an effort to reduce our dependency on site24x7 and improve our on call experience and our monitoring reliability, [blackbox exporter](https://github.com/prometheus/blackbox_exporter) was deployed. At the time of raising this issue, each endpoint configured in site24x7 is replicated in blackbox exporter, all of which are configured to alert if a non 200 http status code is not received for 5 minutes. \r\n\r\n**Site 24x7**\r\nThe good:\r\n- Be default we get a bunch of useful metrics out of the box, without having to configure anything specific, aside from the endpoint itself (response time broken down into dns resolution, download, ssl etc)\r\n- The ui is relatively simple to use\r\n- Summary of outages and the RCA image is sometimes handy to see where things are breaking down. \r\n- Testing from multiple locations\r\n- Cost?\r\n\r\nThe bad: \r\n- We get monitoring up until cloudflare, which is to say that there's no visibility of external vs internal issues in the same platform. As a result, it's hard to know if the issue is with cloudflare or with the sourcegraph frontend and where to look next. \r\n\r\n**Blackbox exporter**\r\nThe good:\r\n- There's a lot of controls we can turn and tune here to gather exactly the information we find most useful.\r\n- We can easily see on the same grafana dashboard all of the endpoints we have configured per metric\r\n- We get internal and external monitoring of endpoints out of the same service (that is to say we can configure a ping to hit an exernal service as well as the services themselves)\r\n- Free\r\n\r\nThe bad: \r\n- There is some intitial setup required in order to determine what metrics we want, on which endpoints, all of which need to be configured manually in the various config files (blackbox exporter and prometheus, as well as any further alertmanager config that may be required). \r\n- We essentially only get one source of truth here, as we are testing from inside our own cluster, out to the world then back again. We do not get multiple locations like site24x7\r\n- There will be ongoing maintenance, which at this stage is hard to say what that will be, however one could assume the more metrics we gather, the more we need to maintain it and ensure they're up to date. \r\n\r\n**What's next**\r\n\r\nDetermine what we consider to be missing from blackbox exporter that we currently have in site24x7, considering the metrics out of the box that are displayed on site24x7 vs what we can and need to configure in blackbox exporter. \r\n\r\nEnsure that alerting is actually working from blackbox exporter, and that it's a trustworthy source. For example, a comparison in the most recent outage reported by site24x7 is [here](https://www.site24x7.com/app/client#/home/monitors/187445000000070268/OutageTroubleAlerts) and [here](https://sourcegraph.com/-/debug/grafana/explore?orgId=1\u0026left=%5B%221598367600000%22,%221598410800000%22,%22Prometheus%22,%7B%22expr%22:%22probe_http_status_code%7Binstance%3D%5C%22https:%2F%2Fsourcegraph.com%2F%5C%22%7D%22%7D,%7B%22expr%22:%22probe_http_status_code%7Binstance%3D%5C%22http:%2F%2Fsourcegraph-frontend.prod.svc.cluster.local:30080%5C%22%7D%22%7D,%7B%22ui%22:%5Btrue,true,true,%22none%22%5D%7D%5D) the same graph time period from blackbox exporter for both the external endpoint as well as the frontend service.\r\n\r\n", "Number": 13627, "URL": "https://github.com/sourcegraph/sourcegraph/issues/13627", "State": "CLOSED", @@ -8763,7 +8763,7 @@ { "ID": "MDExOlB1bGxSZXF1ZXN0NTAwODM3OTc4", "Title": "codeintel: Determine nearest upload efficiently in query path", - "Body": "This PR should significantly reduce the cost of the find nearest upload operation during the prologue of every code intelligence request. This PR closes #14486.\r\n\r\n## What does the current version do?\r\n\r\nOn each definitions, references, hover, and diagnostics request, the precise code intelligence has to figure out which processed uploads can service the request. The set of uploads that can be used are the _closest_ (by commit distance) upload with an overlapping root and the requested indexer (if supplied).\r\n\r\nOn each processed upload, we mark the repository as \"dirty\", which communicates to a periodic routine that that repository's commit graph should be pulled, and the set of visible uploads from each commit should be updated and stored in postgres for fast lookup.\r\n\r\nIn the query path, we can get a very fast lookup _if we know about the requested commit_. This means that a user can browse the current head before the CI has uploaded an index for it - and we don't have the indexed information to be able to determine the closest upload for this commit. As it is now, we mark the repository as dirty and block until its commit graph has been re-decorated.\r\n\r\nThis is an expensive operation in a latency-sensitive path which necessarily obtains a global lock. We need to do much better here.\r\n\r\n## What does the new version do?\r\n\r\nInstead of blocking on refreshing the entire commit graph, we can solve a smaller problem more efficiently, and simply mark the repository as dirty to refresh it for subsequent requests.\r\n\r\nInstead of pulling the entire commit graph back, we only pull a set of _n_ commits on the ancestor of the currently requested commit. This is _likely_ (but not guaranteed) to contain a commit we have already seen. Then, we can use the upload visibility information we have indexed for those commits, and propagate them forward through the commit graph rooted at the target commit.\r\n\r\nThis is an approximation that has a lot of arbitrarily-chosen defaults for some settings knobs. This change contains a few todos that should be done sooner than later, but are not blockers (make settings knobs more easily tunable).\r\n\r\n## How to review\r\n\r\nBy commit, as follows:\r\n\r\n**Add migration** adds a migration to add the columns `ancestor_visible` and `overwritten` to the `lsif_nearests_uploads` table. These columns represent, respectively, whether or not the commit is visible by looking at ancestors (rather than descendants only), and whether or not the commit _was_ visible during the graph traversal, but there is a closer upload in the opposite direction.\r\n\r\n**Add new fields to uploadMeta** adds the new columns to the `UploadMeta` struct in the codeintel store. Adds the condition that `overwritten = false` to all existing queries of that table.\r\n\r\n**Add FindClosestDumpsFromGraphFragment** adds the method `FindClosestDumpsFromGraphFragment` to the codeintel store. This is similar to `FindClosestDumps`, which uses the contents of `lsif_nearest_uploads` to determine the set of visible uploads for a given commit. The latter method only works if the commit has been indexed; otherwise the method will always return an empty list as it's disconnected from any known commit. The new method tries to solve a simpler problem more efficiently. Given a graph containing your target commit, we determine which of the commits in that graph has visibility information. Then, we propagate the visibility information down the graph, which is rooted at the target commit. This can be done much faster than updating the graph graph, which requires taking a global lock and an expensive postgres write.\r\n\r\nTests in this change are updated so that every graph that works for `FindClosestDumps` will also work for `FindClosestDumpsFromGraphFragment`. An additional test for determining the nearest upload from a partial graph is also added.\r\n\r\nThis change also heavily changes `calculateVisibleUploads` to retain additional information used to update the nearest uploads table. This method should be read on its own rather than comparing it to the previous version - it's been cleaned up so its logic flows clearly and linearly.\r\n\r\n**Add options to CommitGraph** adds an options field to the `CommitGraph` method of the codeintel gitserver package. This allows us to optionally specify a root commit and a limit. Exiting callers in the commits package are updated. An additional test is added for parseParent sanity to ensure the documented behavior is what it does.\r\n\r\n**Update API to take a gitserver client instead of a commit updater** removes a (soon to be) unused commitUpdater field and adds a (soon to be used) gitserver client field. This change was extracted so the noise is separately reviewable.\r\n\r\n**Update FindClosestDumps in API layer** updates how the nearest upload is determined in the query path. Instead of waiting on the repository to be updated, we call the new methods updated in the codeintel gitserver package and the codeintel store. See the inline documentation for details.\r\n\r\n**drive-by: Fix assertion** Replace a `fmt.Printf` with a `t.Fatal` in a test.", + "Body": "This PR should significantly reduce the cost of the find nearest upload operation during the prologue of every code intelligence request. This PR closes #14486.\r\n\r\n## What does the current version do?\r\n\r\nOn each definitions, references, hover, and diagnostics request, the precise code intelligence has to figure out which processed uploads can service the request. The set of uploads that can be used are the _closest_ (by commit distance) upload with an overlapping root and the requested indexer (if supplied).\r\n\r\nOn each processed upload, we mark the repository as \"dirty\", which communicates to a periodic routine that that repository's commit graph should be pulled, and the set of visible uploads from each commit should be updated and stored in postgres for fast lookup.\r\n\r\nIn the query path, we can get a very fast lookup _if we know about the requested commit_. This means that a user can browse the current head before the CI has uploaded an index for it - and we don't have the indexed information to be able to determine the closest upload for this commit. As it is now, we mark the repository as dirty and block until its commit graph has been re-decorated.\r\n\r\nThis is an expensive operation in a latency-sensitive path which necessarily obtains a global lock. We need to do much better here.\r\n\r\n## What does the new version do?\r\n\r\nInstead of blocking on refreshing the entire commit graph, we can solve a smaller problem more efficiently, and simply mark the repository as dirty to refresh it for subsequent requests.\r\n\r\nInstead of pulling the entire commit graph back, we only pull a set of _n_ commits on the ancestor of the currently requested commit. This is _likely_ (but not guaranteed) to contain a commit we have already seen. Then, we can use the upload visibility information we have indexed for those commits, and propagate them forward through the commit graph rooted at the target commit.\r\n\r\nThis is an approximation that has a lot of arbitrarily-chosen defaults for some settings controls. This change contains a few todos that should be done sooner than later, but are not blockers (make settings controls more easily tunable).\r\n\r\n## How to review\r\n\r\nBy commit, as follows:\r\n\r\n**Add migration** adds a migration to add the columns `ancestor_visible` and `overwritten` to the `lsif_nearests_uploads` table. These columns represent, respectively, whether or not the commit is visible by looking at ancestors (rather than descendants only), and whether or not the commit _was_ visible during the graph traversal, but there is a closer upload in the opposite direction.\r\n\r\n**Add new fields to uploadMeta** adds the new columns to the `UploadMeta` struct in the codeintel store. Adds the condition that `overwritten = false` to all existing queries of that table.\r\n\r\n**Add FindClosestDumpsFromGraphFragment** adds the method `FindClosestDumpsFromGraphFragment` to the codeintel store. This is similar to `FindClosestDumps`, which uses the contents of `lsif_nearest_uploads` to determine the set of visible uploads for a given commit. The latter method only works if the commit has been indexed; otherwise the method will always return an empty list as it's disconnected from any known commit. The new method tries to solve a simpler problem more efficiently. Given a graph containing your target commit, we determine which of the commits in that graph has visibility information. Then, we propagate the visibility information down the graph, which is rooted at the target commit. This can be done much faster than updating the graph graph, which requires taking a global lock and an expensive postgres write.\r\n\r\nTests in this change are updated so that every graph that works for `FindClosestDumps` will also work for `FindClosestDumpsFromGraphFragment`. An additional test for determining the nearest upload from a partial graph is also added.\r\n\r\nThis change also heavily changes `calculateVisibleUploads` to retain additional information used to update the nearest uploads table. This method should be read on its own rather than comparing it to the previous version - it's been cleaned up so its logic flows clearly and linearly.\r\n\r\n**Add options to CommitGraph** adds an options field to the `CommitGraph` method of the codeintel gitserver package. This allows us to optionally specify a root commit and a limit. Exiting callers in the commits package are updated. An additional test is added for parseParent sanity to ensure the documented behavior is what it does.\r\n\r\n**Update API to take a gitserver client instead of a commit updater** removes a (soon to be) unused commitUpdater field and adds a (soon to be used) gitserver client field. This change was extracted so the noise is separately reviewable.\r\n\r\n**Update FindClosestDumps in API layer** updates how the nearest upload is determined in the query path. Instead of waiting on the repository to be updated, we call the new methods updated in the codeintel gitserver package and the codeintel store. See the inline documentation for details.\r\n\r\n**drive-by: Fix assertion** Replace a `fmt.Printf` with a `t.Fatal` in a test.", "Number": 14581, "URL": "https://github.com/sourcegraph/sourcegraph/pull/14581", "State": "MERGED", diff --git a/package.json b/package.json index d510b0d5746..b2188b8a803 100644 --- a/package.json +++ b/package.json @@ -134,7 +134,6 @@ "@storybook/addon-actions": "^6.5.9", "@storybook/addon-console": "^1.2.3", "@storybook/addon-docs": "^6.5.9", - "@storybook/addon-knobs": "^6.4.0", "@storybook/addon-links": "^6.5.9", "@storybook/addon-storyshots": "^6.5.9", "@storybook/addon-storyshots-puppeteer": "^6.5.9", @@ -385,6 +384,7 @@ "@sentry/browser": "^7.8.1", "@slimsag/react-shortcuts": "^1.2.1", "@sourcegraph/extension-api-classes": "^1.1.0", + "@storybook/addon-controls": "^6.5.9", "@stripe/react-stripe-js": "^1.8.0-0", "@stripe/stripe-js": "^1.29.0", "@visx/annotation": "^2.10.0", diff --git a/yarn.lock b/yarn.lock index e4d1088370e..6e9e74ccbd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -292,7 +292,7 @@ dependencies: "@babel/types" "^7.17.0" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.16.7": +"@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.16.7": version "7.16.7" resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== @@ -1349,7 +1349,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@7.18.6", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.3", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@^7.9.6": +"@babel/runtime@7.18.6", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.3", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@^7.9.6": version "7.18.6" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== @@ -1718,16 +1718,6 @@ source-map "^0.5.7" stylis "4.0.13" -"@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": - version "10.0.29" - resolved "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" - integrity sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ== - dependencies: - "@emotion/sheet" "0.9.4" - "@emotion/stylis" "0.8.5" - "@emotion/utils" "0.11.3" - "@emotion/weak-memoize" "0.2.5" - "@emotion/cache@^11.4.0", "@emotion/cache@^11.7.1": version "11.7.1" resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.7.1.tgz#08d080e396a42e0037848214e8aa7bf879065539" @@ -1739,37 +1729,11 @@ "@emotion/weak-memoize" "^0.2.5" stylis "4.0.13" -"@emotion/core@^10.0.9": - version "10.1.1" - resolved "https://registry.npmjs.org/@emotion/core/-/core-10.1.1.tgz#c956c1365f2f2481960064bcb8c4732e5fb612c3" - integrity sha512-ZMLG6qpXR8x031NXD8HJqugy/AZSkAuMxxqB46pmAR7ze47MhNJ56cdoX243QPZdGctrdfo+s08yZTiwaUcRKA== - dependencies: - "@babel/runtime" "^7.5.5" - "@emotion/cache" "^10.0.27" - "@emotion/css" "^10.0.27" - "@emotion/serialize" "^0.11.15" - "@emotion/sheet" "0.9.4" - "@emotion/utils" "0.11.3" - -"@emotion/css@^10.0.27", "@emotion/css@^10.0.9": - version "10.0.27" - resolved "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz#3a7458198fbbebb53b01b2b87f64e5e21241e14c" - integrity sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw== - dependencies: - "@emotion/serialize" "^0.11.15" - "@emotion/utils" "0.11.3" - babel-plugin-emotion "^10.0.27" - -"@emotion/hash@0.8.0", "@emotion/hash@^0.8.0": +"@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@emotion/memoize@0.7.4": - version "0.7.4" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== - "@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": version "0.7.5" resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" @@ -1789,17 +1753,6 @@ "@emotion/weak-memoize" "^0.2.5" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": - version "0.11.16" - resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" - integrity sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg== - dependencies: - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/unitless" "0.7.5" - "@emotion/utils" "0.11.3" - csstype "^2.5.7" - "@emotion/serialize@^1.0.2": version "1.0.2" resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" @@ -1811,37 +1764,22 @@ "@emotion/utils" "^1.0.0" csstype "^3.0.2" -"@emotion/sheet@0.9.4": - version "0.9.4" - resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" - integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== - "@emotion/sheet@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.0.tgz#56d99c41f0a1cda2726a05aa6a20afd4c63e58d2" integrity sha512-u0AX4aSo25sMAygCuQTzS+HsImZFuS8llY8O7b9MDRzbJM0kVJlAz6KNDqcG7pOuQZJmj/8X/rAW+66kMnMW+g== -"@emotion/stylis@0.8.5": - version "0.8.5" - resolved "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" - integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== - -"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.5": +"@emotion/unitless@^0.7.5": version "0.7.5" resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== -"@emotion/utils@0.11.3": - version "0.11.3" - resolved "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" - integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== - "@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== -"@emotion/weak-memoize@0.2.5", "@emotion/weak-memoize@^0.2.5": +"@emotion/weak-memoize@^0.2.5": version "0.2.5" resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== @@ -4404,6 +4342,24 @@ dependencies: global "^4.3.2" +"@storybook/addon-controls@^6.5.9": + version "6.5.9" + resolved "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.5.9.tgz#8f6ef939c87b3dbad98f8bda7e124f0b34f668d2" + integrity sha512-VvjkgK32bGURKyWU2No6Q2B0RQZjLZk8D3neVNCnrWxwrl1G82StegxjRPn/UZm9+MZVPvTvI46nj1VdgOktnw== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/node-logger" "6.5.9" + "@storybook/store" "6.5.9" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + lodash "^4.17.21" + ts-dedent "^2.0.0" + "@storybook/addon-docs@^6.5.9": version "6.5.9" resolved "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.5.9.tgz#32b27fb298624afd738c1371a764d7ff4831fe6d" @@ -4438,23 +4394,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-knobs@^6.4.0": - version "6.4.0" - resolved "https://registry.npmjs.org/@storybook/addon-knobs/-/addon-knobs-6.4.0.tgz#fa5943ef21826cdc2e20ded74edfdf5a6dc71dcf" - integrity sha512-DiH1/5e2AFHoHrncl1qLu18ZHPHzRMMPvOLFz8AWvvmc+VCqTdIaE+tdxKr3e8rYylKllibgvDOzrLjfTNjF+Q== - dependencies: - copy-to-clipboard "^3.3.1" - core-js "^3.8.2" - escape-html "^1.0.3" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.20" - prop-types "^15.7.2" - qs "^6.10.0" - react-colorful "^5.1.2" - react-lifecycles-compat "^3.0.4" - react-select "^3.2.0" - "@storybook/addon-links@^6.5.9": version "6.5.9" resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.5.9.tgz#91cbca0c044796badf2498723fdd10dacea5748b" @@ -7959,22 +7898,6 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-emotion@^10.0.27: - version "10.0.29" - resolved "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.29.tgz#89d8e497091fcd3d10331f097f1471e4cc3f35b4" - integrity sha512-7Jpi1OCxjyz0k163lKtqP+LHMg5z3S6A7vMBfHnF06l2unmtsOmFDzZBpGf0CWo1G4m8UACfVcDJiSiRuu/cSw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@emotion/hash" "0.8.0" - "@emotion/memoize" "0.7.4" - "@emotion/serialize" "^0.11.16" - babel-plugin-macros "^2.0.0" - babel-plugin-syntax-jsx "^6.18.0" - convert-source-map "^1.5.0" - escape-string-regexp "^1.0.5" - find-root "^1.1.0" - source-map "^0.5.7" - babel-plugin-extract-import-names@1.6.22: version "1.6.22" resolved "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" @@ -8023,7 +7946,7 @@ babel-plugin-lodash@^3.3.4: lodash "^4.17.10" require-package-name "^2.0.1" -babel-plugin-macros@2.8.0, babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.6.1: +babel-plugin-macros@2.8.0, babel-plugin-macros@^2.6.1: version "2.8.0" resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -8087,11 +8010,6 @@ babel-plugin-react-docgen@^4.2.1: lodash "^4.17.15" react-docgen "^5.0.0" -babel-plugin-syntax-jsx@^6.18.0: - version "6.18.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= - babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: version "7.0.0-beta.0" resolved "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" @@ -10391,11 +10309,6 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^2.5.7: - version "2.6.4" - resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz#d585a6062096e324e7187f80e04f92bd0f00e37f" - integrity sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg== - csstype@^3.0.2, csstype@^3.0.4: version "3.1.0" resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" @@ -20962,11 +20875,6 @@ react-clientside-effect@^1.2.5: dependencies: "@babel/runtime" "^7.12.13" -react-colorful@^5.1.2: - version "5.2.2" - resolved "https://registry.npmjs.org/react-colorful/-/react-colorful-5.2.2.tgz#0a69d0648db47e51359d343854d83d250a742243" - integrity sha512-Xdb1Rl6lZ5SMdNBH59eE0lGqR1g2LVD8IgPlw0WeMDrOC65lYI8fgMEwj/0dDpVRVMh5qp73ciISDst/t2O2iQ== - react-docgen-typescript@^2.1.1: version "2.2.2" resolved "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz#4611055e569edc071204aadb20e1c93e1ab1659c" @@ -21055,13 +20963,6 @@ react-grid-layout@1.3.0: react-draggable "^4.0.0" react-resizable "^3.0.4" -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== - dependencies: - prop-types "^15.5.8" - react-inspector@^5.1.0: version "5.1.1" resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz#58476c78fde05d5055646ed8ec02030af42953c8" @@ -21197,20 +21098,6 @@ react-scroll-manager@^1.0.3: dependencies: prop-types "^15.7.2" -react-select@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/react-select/-/react-select-3.2.0.tgz#de9284700196f5f9b5277c5d850a9ce85f5c72fe" - integrity sha512-B/q3TnCZXEKItO0fFN/I0tWOX3WJvi/X2wtdffmwSQVRwg5BpValScTO1vdic9AxlUgmeSzib2hAZAwIUQUZGQ== - dependencies: - "@babel/runtime" "^7.4.4" - "@emotion/cache" "^10.0.9" - "@emotion/core" "^10.0.9" - "@emotion/css" "^10.0.9" - memoize-one "^5.0.0" - prop-types "^15.6.0" - react-input-autosize "^3.0.0" - react-transition-group "^4.3.0" - react-select@^5.2.2: version "5.2.2" resolved "https://registry.npmjs.org/react-select/-/react-select-5.2.2.tgz#3d5edf0a60f1276fd5f29f9f90a305f0a25a5189"