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 <laura.hacker@sourcegraph.com>

* Update client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx

Co-authored-by: Laura Hacker <laura.hacker@sourcegraph.com>

* Update client/web/src/enterprise/batches/batch-spec/edit/workspaces-preview/ImportingChangesetsPreviewList.story.tsx

Co-authored-by: Laura Hacker <laura.hacker@sourcegraph.com>

* Update client/web/src/components/diff/DiffStat.story.tsx

Co-authored-by: Laura Hacker <laura.hacker@sourcegraph.com>

* Update client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx

Co-authored-by: Laura Hacker <laura.hacker@sourcegraph.com>

* code review updates

* continued code review updates

* format fix

* buildkite fix

* Additional minor updates

Co-authored-by: Tom Ross <tom@umpox.com>
Co-authored-by: Laura Hacker <laura.hacker@sourcegraph.com>
This commit is contained in:
Lauren Melendez 2022-08-17 10:52:15 -04:00 committed by GitHub
parent 7b7e784671
commit 0568790ed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 1276 additions and 804 deletions

View File

@ -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 (
<>
<H1>Meter</H1>
<Text>
The HTML{' '}
<Link
to="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter"
target="_blank"
rel="noopener noreferrer"
>
<Code>{'<meter>'}</Code>
</Link>{' '}
element represents either a scalar value within a known range or a fractional value.
</Text>
<H2>Examples</H2>
<hr />
<div className="pb-3">
<H3>Optimum</H3>
<meter min={0} max={1} optimum={1} value={1} />
</div>
<hr />
<div className="pb-3">
<H3>Sub optimum</H3>
<meter min={0} max={1} high={0.8} low={0.2} optimum={1} value={0.6} />
</div>
<hr />
<div className="pb-3">
<H3>Sub sub optimum</H3>
<meter min={0} max={1} high={0.8} low={0.2} optimum={1} value={0.1} />
</div>
<hr />
<div className="pb-3">
<H3>Customize with knobs</H3>
<meter min={min} max={max} high={high} low={low} optimum={optimum} value={value} />
</div>
</>
)
export const Meter: Story = args => (
<>
<H1>Meter</H1>
<Text>
The HTML{' '}
<Link
to="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter"
target="_blank"
rel="noopener noreferrer"
>
<Code>{'<meter>'}</Code>
</Link>{' '}
element represents either a scalar value within a known range or a fractional value.
</Text>
<H2>Examples</H2>
<hr />
<div className="pb-3">
<H3>Optimum</H3>
<meter min={0} max={1} optimum={1} value={1} />
</div>
<hr />
<div className="pb-3">
<H3>Sub optimum</H3>
<meter min={0} max={1} high={0.8} low={0.2} optimum={1} value={0.6} />
</div>
<hr />
<div className="pb-3">
<H3>Sub sub optimum</H3>
<meter min={0} max={1} high={0.8} low={0.2} optimum={1} value={0.1} />
</div>
<hr />
<div className="pb-3">
<H3>Customize with controls</H3>
<meter {...args} />
</div>
</>
)
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,
},
}

View File

@ -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<React.PropsWithChildren<Partia
{ key: 'experimentalLinkPreviews', label: 'Experimental link previews', value: false },
]}
onChangeOptionFlag={action('onChangeOptionFlag')}
version={text('version', '0.0.0')}
sourcegraphUrl={text('sourcegraphUrl', 'https://sourcegraph.com')}
version=""
sourcegraphUrl=""
validateSourcegraphUrl={validateSourcegraphUrl}
onChangeSourcegraphUrl={action('onChangeSourcegraphUrl')}
showSourcegraphCloudAlert={boolean('showSourcegraphCloudAlert', false)}
suggestedSourcegraphUrls={['https://k8s.sgdev.org', 'https://sourcegraph.com']}
{...props}
/>
)
const Interactive: Story = () => {
const Interactive: Story = args => {
const [isActivated, setIsActivated] = useState(false)
return <OptionsPageWrapper isActivated={isActivated} onToggleActivated={setIsActivated} />
return <OptionsPageWrapper isActivated={isActivated} onToggleActivated={setIsActivated} {...args} />
}
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 = {}) => (
<div>
<H1 className="text-center mb-3">All Options Pages</H1>
<div>
<div className="d-flex justify-content-center">
<div className="mx-4">
<H3 className="text-center">Interactive</H3>
<Interactive />
<Interactive {...args} />
</div>
<div className="mx-4">
<H3 className="text-center">URL validation error</H3>
<OptionsPageWrapper
validateSourcegraphUrl={invalidSourcegraphUrl}
sourcegraphUrl={text('sourcegraphUrl', 'https://not-sourcegraph.com')}
/>
<OptionsPageWrapper validateSourcegraphUrl={invalidSourcegraphUrl} {...args} />
</div>
<div className="mx-4">
<H3 className="text-center">With advanced settings</H3>
<WithAdvancedSettings />
<WithAdvancedSettings {...args} />
</div>
</div>
@ -98,6 +94,8 @@ export const AllOptionsPages: Story = () => (
<OptionsPageWrapper
requestPermissionsHandler={requestPermissionsHandler}
showSourcegraphCloudAlert={true}
sourcegraphUrl={args.sourcegraphUrl}
version={args.version}
/>
</div>
<div className="mx-4">
@ -105,6 +103,7 @@ export const AllOptionsPages: Story = () => (
<OptionsPageWrapper
permissionAlert={{ name: 'GitHub', icon: GithubIcon }}
requestPermissionsHandler={requestPermissionsHandler}
{...args}
/>
</div>
</div>
@ -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}
/>
</div>
<div className="mx-4">
<H3 className="text-center">Self-hosted</H3>
<OptionsPageWrapper
sourcegraphUrl={text('sourcegraphUrl', 'https://k8s.sgdev.org')}
currentUser={{ settingsURL: '/users/john-doe/settings', siteAdmin: false }}
hasRepoSyncError={true}
requestPermissionsHandler={requestPermissionsHandler}
{...args}
/>
</div>
<div className="mx-4">
<H3 className="text-center">Self-hosted instance, user is admin</H3>
<OptionsPageWrapper
sourcegraphUrl={text('sourcegraphUrl', 'https://k8s.sgdev.org')}
currentUser={{ settingsURL: '/users/john-doe/settings', siteAdmin: true }}
hasRepoSyncError={true}
requestPermissionsHandler={requestPermissionsHandler}
{...args}
/>
</div>
</div>
</div>
</div>
)
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: {

View File

@ -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<keyof typeof NotificationType, NotificationTypeType>,
},
},
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<NotificationTypeType>(
'Type',
NotificationType as Record<keyof typeof NotificationType, NotificationTypeType>,
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 (
<NotificationItem
notification={{ message, type, source }}
@ -47,17 +61,17 @@ export const WithoutProgress: Story = () => {
/>
)
}
export const WithProgress: Story = () => {
const message = text('Message', 'My *custom* message')
const type = select<NotificationTypeType>(
'Type',
NotificationType as Record<keyof typeof NotificationType, NotificationTypeType>,
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 (
<NotificationItem
notification={{
@ -74,6 +88,21 @@ export const WithProgress: Story = () => {
/>
)
}
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 = {

View File

@ -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: {

View File

@ -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 => (
<WebStory>
{() => <RepoBatchChangesButton repoName="Awesome Repo" queryRepoChangesetsStats={queryRepoChangesetsStats} />}
{() => {
openValue = args.open
mergedValue = args.merged
return (
<RepoBatchChangesButton repoName="Awesome Repo" queryRepoChangesetsStats={queryRepoChangesetsStats} />
)
}}
</WebStory>
)
RepoButton.argTypes = {
open: {
control: { type: 'number' },
defaultValue: 2,
},
merged: {
control: { type: 'number' },
defaultValue: 47,
},
}
RepoButton.storyName = 'RepoButton'

View File

@ -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 = () => <ActivationDropdown {...commonProps} activation={baseActivation()} />
export const _04Completed: Story = () => (
export const _04Completed: Story = args => (
<ActivationDropdown
{...commonProps}
activation={{
...baseActivation(),
completed: {
ConnectedCodeHost: boolean('ConnectedCodeHost', false),
DidSearch: boolean('DidSearch', false),
FoundReferences: boolean('FoundReferences', false),
EnabledRepository: boolean('EnabledRepository', false),
...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 => (
<ActivationDropdown
{...commonProps}
activation={{
...baseActivation(),
completed: {
ConnectedCodeHost: boolean('ConnectedCodeHost', true),
DidSearch: boolean('DidSearch', false),
FoundReferences: boolean('FoundReferences', false),
EnabledRepository: boolean('EnabledRepository', false),
...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 = {

View File

@ -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 => <div className="p-3 container">{story()}</div>
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 <WebStory>{() => <DiffStat {...stats} />}</WebStory>
}
export const CollapsedCounts: Story<React.ComponentProps<typeof DiffStat>> = args => (
<WebStory>{() => <DiffStat {...args} />}</WebStory>
)
CollapsedCounts.storyName = 'Collapsed counts'
export const ExpandedCounts: Story = () => {
const stats = getSharedKnobs()
return <WebStory>{() => <DiffStat {...stats} expandedCounts={true} />}</WebStory>
}
export const ExpandedCounts: Story<React.ComponentProps<typeof DiffStat>> = args => (
<WebStory>{() => <DiffStat {...args} expandedCounts={true} />}</WebStory>
)
ExpandedCounts.storyName = 'Expanded counts'
export const DiffStatSquaresStory: Story = () => {
const stats = getSharedKnobs()
return <WebStory>{() => <DiffStatSquares {...stats} />}</WebStory>
}
export const DiffStatSquaresStory: Story<React.ComponentProps<typeof DiffStatSquares>> = args => (
<WebStory>{() => <DiffStatSquares {...args} />}</WebStory>
)
DiffStatSquaresStory.storyName = 'DiffStatSquares'
export const DiffStatStackStory: Story = () => {
const stats = getSharedKnobs()
return <WebStory>{() => <DiffStatStack {...stats} />}</WebStory>
}
export const DiffStatStackStory: Story<React.ComponentProps<typeof DiffStatStack>> = args => (
<WebStory>{() => <DiffStatStack {...args} />}</WebStory>
)
DiffStatStackStory.storyName = 'DiffStatStack'

View File

@ -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 => (
<WebStory>
{webProps => (
<FileDiffHunks
diffMode="unified"
{...webProps}
persistLines={boolean('persistLines', true)}
persistLines={args.persistLines}
fileDiffAnchor="abc"
lineNumbers={boolean('lineNumbers', true)}
lineNumbers={args.lineNumbers}
hunks={DEMO_HUNKS}
className="abcdef"
/>
@ -80,15 +89,15 @@ export const OneDiffUnifiedHunk: Story = () => (
OneDiffUnifiedHunk.storyName = 'One diff unified hunk'
export const OneDiffSplitHunk: Story = () => (
export const OneDiffSplitHunk: Story = args => (
<WebStory>
{webProps => (
<FileDiffHunks
diffMode="split"
{...webProps}
persistLines={boolean('persistLines', true)}
persistLines={args.persistLines}
fileDiffAnchor="abc"
lineNumbers={boolean('lineNumbers', true)}
lineNumbers={args.lineNumbers}
hunks={DEMO_HUNKS}
className="abcdef"
/>

View File

@ -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 => (
<WebStory>
{webProps => (
<ul className="list-unstyled">
@ -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 => (
<WebStory>
{webProps => (
<ul className="list-unstyled">
@ -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"
/>

View File

@ -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 => <div className="p-3 container">{story()}</div>
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 = () => (
<WebStory>
{props => (
<Duration {...props} start={new Date(date('start', subDays(now, 1)))} end={new Date(date('end', now))} />
)}
</WebStory>
export const Fixed: Story = args => (
<WebStory>{props => <Duration {...props} start={new Date(args.start)} end={new Date(args.end)} />}</WebStory>
)
Fixed.argTypes = {
end: {
control: { type: 'date' },
defaultValue: now,
},
}
export const Active: Story = () => (
export const Active: Story = args => (
<WebStory>
{props => (
<>
<H3>Borders demonstrate how the time changing does not cause layout shift.</H3>
<div className="d-flex">
<span style={{ backgroundColor: 'red', width: 100 }} />
<Duration {...props} start={new Date(date('start', subDays(now, 1)))} />
<Duration {...props} start={new Date(args.start)} />
<span style={{ backgroundColor: 'red', width: 100 }} />
</div>
<H3 className="mt-4">
@ -42,7 +49,7 @@ export const Active: Story = () => (
</H3>
<div className="d-flex">
<span style={{ backgroundColor: 'red', width: 100 }} />
<Duration {...props} start={new Date(date('start', subDays(now, 1)))} stableWidth={false} />
<Duration {...props} start={new Date(args.start)} stableWidth={false} />
<span style={{ backgroundColor: 'red', width: 100 }} />
</div>
</>

View File

@ -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<Props, 'disabled' | 'dropdownMenuPosition'> = () => ({
disabled: boolean('Disabled', false),
dropdownMenuPosition: select(
'Dropdown menu position',
{
None: undefined,
Left: 'left',
Right: 'right',
},
undefined
),
})
const decorator: DecoratorFn = story => <div className="p-3 container">{story()}</div>
const config: Meta = {
title: 'web/batches/DropdownButton',
decorators: [decorator],
argTypes: {
disabled: {
control: { type: 'boolean' },
defaultValue: false,
},
},
}
export default config
export const NoActions: Story = () => <WebStory>{() => <DropdownButton actions={[]} {...commonKnobs()} />}</WebStory>
export const NoActions: Story = args => <WebStory>{() => <DropdownButton actions={[]} {...args} />}</WebStory>
NoActions.argTypes = {
disabled: {
table: {
disable: true,
},
},
}
NoActions.storyName = 'No actions'
export const SingleAction: Story = () => (
<WebStory>{() => <DropdownButton actions={[action]} {...commonKnobs()} />}</WebStory>
)
export const SingleAction: Story = args => <WebStory>{() => <DropdownButton actions={[action]} {...args} />}</WebStory>
SingleAction.storyName = 'Single action'
export const MultipleActionsWithoutDefault: Story = () => (
<WebStory>
{() => <DropdownButton actions={[action, disabledAction, experimentalAction]} {...commonKnobs()} />}
</WebStory>
export const MultipleActionsWithoutDefault: Story = args => (
<WebStory>{() => <DropdownButton actions={[action, disabledAction, experimentalAction]} {...args} />}</WebStory>
)
MultipleActionsWithoutDefault.storyName = 'Multiple actions without default'
export const MultipleActionsWithDefault: Story = () => (
export const MultipleActionsWithDefault: Story = args => (
<WebStory>
{() => (
<DropdownButton
actions={[action, disabledAction, experimentalAction]}
defaultAction={0}
{...commonKnobs()}
/>
)}
{() => <DropdownButton actions={[action, disabledAction, experimentalAction]} defaultAction={0} {...args} />}
</WebStory>
)

View File

@ -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

View File

@ -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 = () => (
<WebStory>
{props => (
<TabBar
{...props}
tabsConfig={EXECUTING_TABS}
activeTabKey={select('Active tab', ['configuration', 'spec', 'execution'], 'execution')}
/>
)}
</WebStory>
export const ExecuteBatchSpec: Story = args => (
<WebStory>{props => <TabBar {...props} tabsConfig={EXECUTING_TABS} activeTabKey={args.activeTabKey} />}</WebStory>
)
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 = () => (
<WebStory>
{props => (
<TabBar
{...props}
tabsConfig={PREVIEWING_TABS}
activeTabKey={select('Active tab', ['configuration', 'spec', 'execution', 'preview'], 'preview')}
/>
)}
</WebStory>
export const PreviewExecutionResult: Story = args => (
<WebStory>{props => <TabBar {...props} tabsConfig={PREVIEWING_TABS} activeTabKey={args.activeTabKey} />}</WebStory>
)
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 = () => (
<WebStory>
{props => (
<TabBar
{...props}
tabsConfig={LOCAL_TABS}
activeTabKey={select('Active tab', ['configuration', 'spec', 'preview'], 'preview')}
/>
)}
</WebStory>
export const LocallyExecutedSpec: Story = args => (
<WebStory>{props => <TabBar {...props} tabsConfig={LOCAL_TABS} activeTabKey={args.activeTabKey} />}</WebStory>
)
LocallyExecutedSpec.argTypes = {
activeTabKey: {
control: { type: 'select', options: ['configuration', 'spec', 'preview'] },
defaultValue: 'preview',
},
}
LocallyExecutedSpec.storyName = 'for a locally-executed spec'

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<EditorFeedbackPanel
errors={{
actions: text('Actions', ''),
execute: text('Execute', ''),
preview: text('Preview', ''),
codeUpdate: text('Code Update', ''),
codeValidation: text(
'Validation',
'The entered spec is invalid:\n * name must match pattern "^my-batch-change$"'
),
actions: args.actions,
execute: args.execute,
preview: args.preview,
codeUpdate: args.codeUpdate,
codeValidation: args.codeValidation,
}}
{...props}
/>

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<MonacoBatchSpecEditor
batchChangeName="hello-world"
value={sample}
readOnly={boolean('Read Only', false)}
autoFocus={boolean('Auto Focus', false)}
readOnly={args.readOnly}
autoFocus={args.autoFocus}
onChange={action('On Change')}
{...props}
/>

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<ReplaceSpecModal
libraryItemName={text('Name', 'my-batch-change')}
libraryItemName={args.libraryItemName}
onCancel={action('On Cancel')}
onConfirm={action('On Confirm')}
{...props}

View File

@ -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,13 +10,35 @@ const decorator: DecoratorFn = story => <div className="p-3 container">{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 (
<WebStory>
{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}
/>
)}

View File

@ -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 => (
<WebStory>
{() => (
<MockedTestProvider link={new WildcardMockLink(UNSTARTED_CONNECTION_MOCKS)}>
<BatchSpecContextProvider
batchChange={mockBatchChange()}
batchSpec={
boolean('Valid batch spec?', true)
? mockBatchSpec()
: mockBatchSpec({ originalInput: 'not-valid' })
}
batchSpec={args.batchSpec ? mockBatchSpec() : mockBatchSpec({ originalInput: 'not-valid' })}
refetchBatchChange={() => Promise.resolve()}
>
<WorkspacesPreview />
@ -54,18 +49,21 @@ export const Unstarted: Story = () => (
)}
</WebStory>
)
Unstarted.argTypes = {
batchSpec: {
name: 'Valid batch spec?',
control: { type: 'boolean' },
defaultValue: true,
},
}
export const UnstartedWithCachedConnectionResult: Story = () => (
export const UnstartedWithCachedConnectionResult: Story = args => (
<WebStory>
{() => (
<MockedTestProvider link={new WildcardMockLink(UNSTARTED_WITH_CACHE_CONNECTION_MOCKS)}>
<BatchSpecContextProvider
batchChange={mockBatchChange()}
batchSpec={
boolean('Valid batch spec?', true)
? mockBatchSpec()
: mockBatchSpec({ originalInput: 'not-valid' })
}
batchSpec={args.batchSpec ? mockBatchSpec() : mockBatchSpec({ originalInput: 'not-valid' })}
refetchBatchChange={() => Promise.resolve()}
>
<WorkspacesPreview />
@ -74,17 +72,18 @@ export const UnstartedWithCachedConnectionResult: Story = () => (
)}
</WebStory>
)
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 = () => {
<MockedTestProvider link={inProgressConnectionMocks}>
<BatchSpecContextProvider
batchChange={mockBatchChange()}
batchSpec={
boolean('Valid batch spec?', true)
? mockBatchSpec()
: mockBatchSpec({ originalInput: 'not-valid' })
}
batchSpec={args.batchSpec ? mockBatchSpec() : mockBatchSpec({ originalInput: 'not-valid' })}
refetchBatchChange={() => Promise.resolve()}
>
<WorkspacesPreview />
@ -133,17 +128,25 @@ export const QueuedInProgress: Story = () => {
</WebStory>
)
}
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 = () => {
</WebStory>
)
}
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 = () => {
</WebStory>
)
}
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 = () => {
</WebStory>
)
}
FailedErroredWithCachedConnectionResult.argTypes = {
inProgressResolution: {
name: 'Status',
control: {
type: 'select',
options: [BatchSpecWorkspaceResolutionState.FAILED, BatchSpecWorkspaceResolutionState.ERRORED],
},
defaultValue: BatchSpecWorkspaceResolutionState.FAILED,
},
}
FailedErroredWithCachedConnectionResult.storyName = 'failed/errored, with cached connection result'

View File

@ -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 => <div className="p-3 container">{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 (
<WebStory>
{props => (
<WorkspacesPreviewList
isStale={boolean('Stale', false)}
isStale={args.isStale}
showCached={false}
error={undefined}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
@ -36,7 +35,7 @@ export const DefaultStory: Story = () => {
endCursor: null,
},
},
hasNextPage: boolean('Has Next Page', false),
hasNextPage: args.hasNextPage,
fetchMore: action('Fetch More'),
}}
{...props}
@ -45,6 +44,23 @@ export const DefaultStory: Story = () => {
</WebStory>
)
}
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'

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<CancelExecutionModal
{...props}
modalBody={<Text>Are you sure you want to cancel the current execution?</Text>}
isOpen={true}
isLoading={boolean('isLoading', false)}
isLoading={args.isLoading}
onCancel={noop}
onConfirm={noop}
/>

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<ExecutionStatsBar
{...props}
errored={number('errored', 0)}
ignored={number('ignored', 0)}
queued={number('queued', 14)}
processing={number('processing', 4)}
completed={number('completed', 7)}
errored={args.errored}
completed={args.completed}
processing={args.processing}
queued={args.queued}
ignored={args.ignored}
/>
)}
</WebStory>

View File

@ -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 => (
<WebStory>
{props => (
<BatchSpecContextProvider
batchChange={mockBatchChange()}
batchSpec={mockFullBatchSpec({
state: select(
'batch spec state',
[BatchSpecState.PROCESSING, BatchSpecState.QUEUED],
BatchSpecState.PROCESSING
),
state: args.state,
})}
>
<ReadOnlyBatchSpecForm {...props} />
@ -40,26 +35,23 @@ export const Executing: Story = () => (
)}
</WebStory>
)
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 => (
<WebStory>
{props => (
<BatchSpecContextProvider
batchChange={mockBatchChange()}
batchSpec={mockFullBatchSpec({
state: select(
'batch spec state',
[
BatchSpecState.CANCELED,
BatchSpecState.CANCELING,
BatchSpecState.COMPLETED,
BatchSpecState.FAILED,
BatchSpecState.PENDING,
],
BatchSpecState.COMPLETED
),
state: args.state,
})}
>
<ReadOnlyBatchSpecForm {...props} />
@ -67,6 +59,22 @@ export const ExecutionFinished: Story = () => (
)}
</WebStory>
)
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'

View File

@ -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 => <div className="p-3">{story()}</div>
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 => (
<WebStory>
{props => (
<>
@ -25,11 +31,7 @@ export const WorkspaceStateIconStory: Story = () => (
.map(value => (
<div key={value} className="p-1">
{value}:{' '}
<WorkspaceStateIcon
state={value}
cachedResultFound={boolean('Cache Found', false)}
{...props}
/>
<WorkspaceStateIcon state={value} cachedResultFound={args.cachedResultFound} {...props} />
</div>
))}
</>

View File

@ -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 (
<WebStory>
{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()}
/>
)}
</WebStory>
)
}
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 (
<WebStory>
@ -55,7 +65,7 @@ export const NoOpenChangesets: Story = () => {
totalCount={0}
closeChangesets={closeChangesets}
setCloseChangesets={setCloseChangesets}
viewerCanAdminister={boolean('viewerCanAdminister', true)}
viewerCanAdminister={args.viewerCanAdminister}
closeBatchChange={() => Promise.resolve()}
/>
)}

View File

@ -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 = () => {
</WebStory>
)
}
Overview.argTypes = {
viewerCanAdminister: {
control: { type: 'boolean' },
defaultValue: true,
},
}
export const NoOpenChangesets: Story = () => {
const batchChange: BatchChangeFields = useMemo(() => batchChangeDefaults, [])

View File

@ -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 => <div className="p-3 container">{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(
() => [

View File

@ -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}
/>
</MockedTestProvider>
)}
</WebStory>
)
}
EmptyChangesets.parameters = {
controls: { hideNoControlsWarning: true, exclude: ['supersedingBatchSpec', 'viewerCanAdminister', 'isClosed'] },
}
EmptyChangesets.storyName = 'Empty changesets'

View File

@ -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 => <div className="p-3 container">{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 => (
<WebStory>
{props => (
<MockedTestProvider link={mocks}>
@ -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 => (
<WebStory>
{props => (
<MockedTestProvider link={mocks}>
@ -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 (
<WebStory>
@ -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}
/>
</MockedTestProvider>
)}
</WebStory>
)
}
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'

View File

@ -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 => <div className="p-3 container">{story()}</div>
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<string>(100).fill('fake-id').map((id, index) => `${id}-${index}`)
const CHANGESET_IDS = new Array<string>(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)

View File

@ -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 (
<WebStory>
@ -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 (
<WebStory>
@ -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 (
<WebStory>
@ -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 (
<WebStory>
@ -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 (
<WebStory>
@ -350,7 +355,7 @@ export const SyncFailed: Story = () => {
reviewState: null,
currentSpec: null,
}}
viewerCanAdminister={boolean('viewerCanAdminister', true)}
viewerCanAdminister={args.viewerCanAdminister}
queryExternalChangesetWithFileDiffs={() =>
of({
diff: null,

View File

@ -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 (
<WebStory>
{props => (
<MockedTestProvider link={buildMocks()}>
<BatchChangeListPage
{...props}
headingElement="h1"
canCreate={canCreate}
settingsCascade={EMPTY_SETTINGS_CASCADE}
/>
</MockedTestProvider>
)}
</WebStory>
)
export const ListOfBatchChanges: Story = args => (
<WebStory>
{props => (
<MockedTestProvider link={buildMocks()}>
<BatchChangeListPage
{...props}
headingElement="h1"
canCreate={args.canCreate}
settingsCascade={EMPTY_SETTINGS_CASCADE}
/>
</MockedTestProvider>
)}
</WebStory>
)
ListOfBatchChanges.argTypes = {
canCreate: {
name: 'can create batch changes',
control: { type: 'boolean' },
defaultValue: true,
},
}
ListOfBatchChanges.storyName = 'List of batch changes'

View File

@ -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 }) => (
<WebStory>
{props => (
<BatchChangeNode
{...props}
node={node}
displayNamespace={boolean('Display namespace', true)}
displayNamespace={args.displayNamespace}
now={isChromatic() ? () => subDays(now, 5) : undefined}
isExecutionEnabled={false}
/>

View File

@ -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 => <div className="p-3 container">{story()}</div>
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 }) => (
<WebStory>
{() => <BatchChangesListIntro isLicensed={stateToInput(radios('licensed', LicensingState, state))} />}
</WebStory>
const Template: Story = ({ state, ...args }) => (
<WebStory>{() => <BatchChangesListIntro isLicensed={stateToInput(args.licensed)} />}</WebStory>
)
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 },
}

View File

@ -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<BatchSpecApplyPreviewConn
const queryEmptyFileDiffs = () => 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 (
<WebStory>
{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 (
<WebStory>
{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 (
<WebStory>
{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 (
<WebStory initialEntries={['/users/alice/batch-changes/awesome-batch-change?tab=spec']}>
{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 (
<WebStory>
{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 (
<WebStory>
{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 (
<WebStory>
{props => (

View File

@ -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 => (
<WebStory>
{props => (
<CreateUpdateBatchChangeAlert
@ -28,13 +33,13 @@ export const Create: Story = () => (
specID="123"
toBeArchived={18}
batchChange={null}
viewerCanAdminister={boolean('viewerCanAdminister', true)}
viewerCanAdminister={args.viewerCanAdminister}
/>
)}
</WebStory>
)
export const Update: Story = () => (
export const Update: Story = args => (
<WebStory>
{props => (
<CreateUpdateBatchChangeAlert
@ -42,13 +47,13 @@ export const Update: Story = () => (
specID="123"
toBeArchived={199}
batchChange={{ id: '123', name: 'awesome-batch-change', url: 'http://test.test/awesome' }}
viewerCanAdminister={boolean('viewerCanAdminister', true)}
viewerCanAdminister={args.viewerCanAdminister}
/>
)}
</WebStory>
)
export const Disabled: Story = () => (
export const Disabled: Story = args => (
<WebStory>
{props => (
<MultiSelectContextProvider initialSelected={['id1', 'id2']}>
@ -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}
/>
</MultiSelectContextProvider>
)}

View File

@ -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 => <div className="p-3 container">{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)),

View File

@ -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 => (
<WebStory>
{props => (
<MockedTestProvider
@ -56,11 +55,7 @@ export const RequiresSSHstep1: Story = () => (
<AddCredentialModal
{...props}
userID="user-id-1"
externalServiceKind={select(
'External service kind',
Object.values(ExternalServiceKind),
ExternalServiceKind.GITHUB
)}
externalServiceKind={args.externalServiceKind}
externalServiceURL="https://github.com/"
requiresSSH={true}
requiresUsername={false}
@ -71,20 +66,23 @@ export const RequiresSSHstep1: Story = () => (
)}
</WebStory>
)
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 => (
<WebStory>
{props => (
<AddCredentialModal
{...props}
userID="user-id-1"
externalServiceKind={select(
'External service kind',
Object.values(ExternalServiceKind),
ExternalServiceKind.GITHUB
)}
externalServiceKind={args.externalServiceKind}
externalServiceURL="https://github.com/"
requiresSSH={true}
requiresUsername={false}
@ -95,6 +93,13 @@ export const RequiresSSHstep2: Story = () => (
)}
</WebStory>
)
RequiresSSHstep2.argTypes = {
externalServiceKind: {
name: 'External service kind',
control: { type: 'select', options: Object.values(ExternalServiceKind) },
defaultValue: ExternalServiceKind.GITHUB,
},
}
RequiresSSHstep2.storyName = 'Requires SSH - step 2'

View File

@ -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<InferredIndexConfig
const story: Meta = {
title: 'web/codeintel/configuration/CodeIntelConfigurationPage',
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
decorators: [story => <div className="p-3 container">{story()}</div>, withKnobs],
decorators: [story => <div className="p-3 container">{story()}</div>],
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<CodeIntelConfigurationPageProps> = args => (
inferredRepositoryConfigurationRequest, // For Infer index configuration from HEAD
]}
>
{props => (
<CodeIntelConfigurationPage {...props} indexingEnabled={boolean('indexingEnabled', true)} {...args} />
)}
{props => <CodeIntelConfigurationPage {...props} {...args} />}
</WebStory>
)

View File

@ -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 => <div className="p-3 container">{story()}</div>, withKnobs],
decorators: [story => <div className="p-3 container">{story()}</div>],
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<CodeIntelConfigurationPolicyPageProps> = args => (
previewRepositoryFilterRequest,
]}
>
{props => (
<CodeIntelConfigurationPolicyPage {...props} indexingEnabled={boolean('indexingEnabled', true)} {...args} />
)}
{props => <CodeIntelConfigurationPolicyPage {...props} {...args} />}
</WebStory>
)

View File

@ -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 => <div className="p-3 container">{story()}</div>, withKnobs],
decorators: [story => <div className="p-3 container">{story()}</div>],
parameters: {
component: CodeIntelRepositoryIndexConfigurationPage,
chromatic: {
viewports: [320, 576, 978, 1440],
},
},
argTypes: {
repo: {
table: {
disable: true,
},
},
},
}
export default story

View File

@ -106,6 +106,10 @@ const story: Meta = {
chromatic: {
viewports: [320, 576, 978, 1440],
},
controls: {
hideNoControlsWarning: true,
exclude: ['now', 'queryLsifUploadsList', 'queryLisfUploadFields', 'queryRetentionMatches'],
},
},
}
export default story

View File

@ -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<CodeIntelUploadsPageProps> = 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 = {

View File

@ -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 (
<OpenByDefaultWrapper>
{({ 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 (
<OpenByDefaultWrapper>
{({ menuButtonRef }) => (

View File

@ -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 => (
<WebStory>
{() => (
<Card>
<GitCommitNode
node={gitCommitNode}
compact={boolean('compact', false)}
expandCommitMessageBody={boolean('expandCommitMessageBody', false)}
showSHAAndParentsRow={boolean('showSHAAndParentsRow', false)}
hideExpandCommitMessageBody={boolean('hideExpandCommitMessageBody', false)}
preferAbsoluteTimestamps={boolean('preferAbsoluteTimestamps', false)}
compact={args.compact}
expandCommitMessageBody={args.expandCommitMessageBody}
showSHAAndParentsRow={args.showSHAAndParentsRow}
hideExpandCommitMessageBody={args.hideExpandCommitMessageBody}
preferAbsoluteTimestamps={args.preferAbsoluteTimestamps}
/>
</Card>
)}
</WebStory>
)
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'

View File

@ -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 => (
<WebStory>
{() => (
<MessagePanel
@ -52,14 +51,17 @@ export const JSONResponse: Story = () => (
headers: messagePanelObject.JSON.headers,
body: messagePanelObject.JSON.body,
}}
requestOrStatusCode={number('status code', 200, {
min: 100,
max: 599,
})}
requestOrStatusCode={args.requestOrStatusCode}
/>
)}
</WebStory>
)
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 => (
<WebStory>
{() => (
<MessagePanel
@ -91,13 +93,16 @@ export const PlainResponse: Story = () => (
headers: messagePanelObject.plain.headers,
body: messagePanelObject.plain.body,
}}
requestOrStatusCode={number('status code', 200, {
min: 100,
max: 599,
})}
requestOrStatusCode={args.requestOrStatusCode}
/>
)}
</WebStory>
)
PlainResponse.argTypes = {
requestOrStatusCode: {
control: { type: 'number', min: 100, max: 599 },
defaultValue: 200,
},
}
PlainResponse.storyName = 'plain response'

View File

@ -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 = () => (
<WebStory>{() => <StatusCode code={number('code', 204, { min: 100, max: 399 })} />}</WebStory>
)
export const Success: Story = args => <WebStory>{() => <StatusCode code={args.code} />}</WebStory>
Success.argTypes = {
code: {
control: { type: 'number', min: 100, max: 399 },
defaultValue: 204,
},
}
export const Failure: Story = () => (
<WebStory>{() => <StatusCode code={number('code', 418, { min: 400, max: 599 })} />}</WebStory>
)
export const Failure: Story = args => <WebStory>{() => <StatusCode code={args.code} />}</WebStory>
Failure.argTypes = {
code: {
control: { type: 'number', min: 400, max: 599 },
defaultValue: 418,
},
}

View File

@ -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<WebhookLogFields, 'receivedAt' | 'statusCode'>
export const Collapsed: Story<StoryArguments> = args => (
<WebStory>
{() => (
<WebhookLogNode
node={webhookLogNode({
node={webhookLogNode(args, {
externalService: {
displayName: 'GitLab',
},
@ -50,14 +65,16 @@ export const Collapsed: Story = () => (
</WebStory>
)
export const ExpandedRequest: Story = () => (
<WebStory>{() => <WebhookLogNode node={webhookLogNode()} initiallyExpanded={true} />}</WebStory>
export const ExpandedRequest: Story<StoryArguments> = args => (
<WebStory>{() => <WebhookLogNode node={webhookLogNode(args)} initiallyExpanded={true} />}</WebStory>
)
ExpandedRequest.storyName = 'expanded request'
export const ExpandedResponse: Story = () => (
<WebStory>{() => <WebhookLogNode node={webhookLogNode()} initiallyExpanded={true} initialTabIndex={1} />}</WebStory>
export const ExpandedResponse: Story<StoryArguments> = args => (
<WebStory>
{() => <WebhookLogNode node={webhookLogNode(args)} initiallyExpanded={true} initialTabIndex={1} />}
</WebStory>
)
ExpandedResponse.storyName = 'expanded response'

View File

@ -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 => (
<WebStory>
{props => (
<MockedTestProvider mocks={buildHeaderMock(2, 2)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPage {...props} queryWebhookLogs={buildQueryWebhookLogs([])} />
</MockedTestProvider>
)}
@ -116,10 +128,10 @@ export const NoLogs: Story = () => (
NoLogs.storyName = 'no logs'
export const OnePageOfLogs: Story = () => (
export const OnePageOfLogs: Story = args => (
<WebStory>
{props => (
<MockedTestProvider mocks={buildHeaderMock(2, 2)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPage {...props} queryWebhookLogs={buildQueryWebhookLogs(buildWebhookLogs(20, 2))} />
</MockedTestProvider>
)}
@ -128,10 +140,10 @@ export const OnePageOfLogs: Story = () => (
OnePageOfLogs.storyName = 'one page of logs'
export const TwoPagesOfLogs: Story = () => (
export const TwoPagesOfLogs: Story = args => (
<WebStory>
{props => (
<MockedTestProvider mocks={buildHeaderMock(2, 2)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPage {...props} queryWebhookLogs={buildQueryWebhookLogs(buildWebhookLogs(40, 2))} />
</MockedTestProvider>
)}

View File

@ -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 => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(0, 0)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer />
</MockedTestProvider>
)}
</WebStory>
)
AllZeroes.argTypes = {
externalServiceCount: {
defaultValue: 0,
},
erroredWebhookCount: {
defaultValue: 0,
},
}
AllZeroes.storyName = 'all zeroes'
export const ExternalServices: Story = () => (
export const ExternalServices: Story = args => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(10, 0)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer />
</MockedTestProvider>
)}
</WebStory>
)
ExternalServices.argTypes = {
externalServiceCount: {
defaultValue: 10,
},
erroredWebhookCount: {
defaultValue: 0,
},
}
ExternalServices.storyName = 'external services'
export const ExternalServicesAndErrors: Story = () => (
export const ExternalServicesAndErrors: Story = args => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(20, 500)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer />
</MockedTestProvider>
)}
</WebStory>
)
ExternalServicesAndErrors.argTypes = {
externalServiceCount: {
defaultValue: 20,
},
erroredWebhookCount: {
defaultValue: 500,
},
}
ExternalServicesAndErrors.storyName = 'external services and errors'
export const OnlyErrorsTurnedOn: Story = () => (
export const OnlyErrorsTurnedOn: Story = args => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(20, 500)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer initialOnlyErrors={true} />
</MockedTestProvider>
)}
</WebStory>
)
OnlyErrorsTurnedOn.argTypes = {
externalServiceCount: {
defaultValue: 20,
},
erroredWebhookCount: {
defaultValue: 500,
},
}
OnlyErrorsTurnedOn.storyName = 'only errors turned on'
export const SpecificExternalServiceSelected: Story = () => (
export const SpecificExternalServiceSelected: Story = args => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(20, 500)}>
<WebhookLogPageHeaderContainer
initialExternalService={number('selected external service', 2, { min: 0, max: 19 }).toString()}
/>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer initialExternalService={args.initialExternalService.toString()} />
</MockedTestProvider>
)}
</WebStory>
)
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 => (
<WebStory>
{() => (
<MockedTestProvider mocks={buildHeaderMock(20, 500)}>
<MockedTestProvider mocks={buildHeaderMock(args.externalServiceCount, args.erroredWebhookCount)}>
<WebhookLogPageHeaderContainer initialExternalService="unmatched" />
</MockedTestProvider>
)}
</WebStory>
)
UnmatchedExternalServiceSelected.argTypes = {
externalServiceCount: {
defaultValue: 20,
},
erroredWebhookCount: {
defaultValue: 500,
},
}
UnmatchedExternalServiceSelected.storyName = 'unmatched external service selected'

View File

@ -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>): WebhookLogFields => ({
export const webhookLogNode = (
defaultArguments: Pick<WebhookLogFields, 'receivedAt' | 'statusCode'>,
overrides?: Partial<WebhookLogFields>
): 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<WebhookLogFields>): 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,
},
},
},

View File

@ -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 = () => (
<Button
variant={select('Variant', BUTTON_VARIANTS, 'primary')}
size={select('Size', BUTTON_SIZES, undefined)}
disabled={boolean('Disabled', false)}
outline={boolean('Outline', false)}
>
export const Simple: Story = (args = {}) => (
<Button variant={args.variant} size={args.size} disabled={args.disabled} outline={args.outline}>
Click me!
</Button>
)
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 = () => (
<div className="pb-3">

View File

@ -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 = () => <LoadingSpinner inline={boolean('inline', true)} />
export const Simple: Story = (args = {}) => <LoadingSpinner inline={args.inline} />

View File

@ -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 <PageSelector currentPage={page} onPageChange={setPage} totalPages={number('maxPages', 5)} />
return <PageSelector currentPage={page} onPageChange={setPage} totalPages={args.totalPages} />
}
Simple.argTypes = {
totalPages: {
name: 'maxPages',
control: { type: 'number' },
defaultValue: 5,
},
}
export const AllPageSelectors: Story = () => (

View File

@ -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 (
<ScrollCenterBox title="Root scroll block" className={styles.root}>
<div className={styles.spreadContentBlock}>
<ScrollCenterBox
title="Sub scroll block (see knobs panel for rendering tooltip outside of the scroll container"
title="Sub scroll block (see controls panel for rendering tooltip outside of the scroll container"
className={classNames(styles.container, styles.containerAsSubRoot)}
>
<div className={styles.content}>
@ -440,6 +439,12 @@ export const WithNestedScrollParents: Story = () => {
</ScrollCenterBox>
)
}
WithNestedScrollParents.argTypes = {
constrainToScrollParents: {
control: { type: 'boolean' },
defaultValue: true,
},
}
export const WithVirtualTarget: Story = () => {
const [virtualElement, setVirtualElement] = useState<Point | null>(null)

View File

@ -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 = {}) => (
<>
<H2>Headings</H2>
<table className="table">
@ -50,10 +49,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H1
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H1 mode={args.mode} alignment={args.alignment}>
This is H1
</H1>
</td>
@ -67,10 +63,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H2
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H2 mode={args.mode} alignment={args.alignment}>
This is H2
</H2>
</td>
@ -84,10 +77,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H3
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H3 mode={args.mode} alignment={args.alignment}>
This is H3
</H3>
</td>
@ -101,10 +91,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H4
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H4 mode={args.mode} alignment={args.alignment}>
This is H4
</H4>
</td>
@ -118,10 +105,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H5
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H5 mode={args.mode} alignment={args.alignment}>
This is H5
</H5>
</td>
@ -135,10 +119,7 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<H6
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
>
<H6 mode={args.mode} alignment={args.alignment}>
This is H6
</H6>
</td>
@ -196,59 +177,32 @@ export const Simple: Story = () => (
</td>
<td>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="base"
>
<Label mode={args.mode} alignment={args.alignment} size="base">
This is Label / Base
</Label>
</div>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="base"
isUnderline={true}
>
<Label mode={args.mode} alignment={args.alignment} size="base" isUnderline={true}>
This is Label / Base - underline
</Label>
</div>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
>
<Label mode={args.mode} alignment={args.alignment} size="small">
This is Label / Small
</Label>
</div>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
isUnderline={true}
>
<Label mode={args.mode} alignment={args.alignment} size="small" isUnderline={true}>
This is Label / Small - underline
</Label>
</div>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
isUppercase={true}
>
<Label mode={args.mode} alignment={args.alignment} isUppercase={true}>
This is Label / Uppercase / Base
</Label>
</div>
<div>
<Label
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
isUppercase={true}
>
<Label mode={args.mode} alignment={args.alignment} size="small" isUppercase={true}>
This is Label / Uppercase / Small
</Label>
</div>
@ -269,52 +223,22 @@ export const Simple: Story = () => (
</Code>
</td>
<td>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="base"
weight="regular"
>
<Text mode={args.mode} alignment={args.alignment} size="base" weight="regular">
This is Body / Base / Regular
</Text>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="base"
weight="medium"
>
<Text mode={args.mode} alignment={args.alignment} size="base" weight="medium">
This is Body / Base / Medium
</Text>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="base"
weight="bold"
>
<Text mode={args.mode} alignment={args.alignment} size="base" weight="bold">
This is Body / Base / Bold
</Text>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
weight="regular"
>
<Text mode={args.mode} alignment={args.alignment} size="small" weight="regular">
This is Body / Small / Regular
</Text>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
weight="medium"
>
<Text mode={args.mode} alignment={args.alignment} size="small" weight="medium">
This is Body / Small / Medium
</Text>
<Text
mode={select('mode', TYPOGRAPHY_MODES, undefined)}
alignment={select('alignment', TYPOGRAPHY_ALIGNMENTS, undefined)}
size="small"
weight="bold"
>
<Text mode={args.mode} alignment={args.alignment} size="small" weight="bold">
This is Body / Small / Bold
</Text>
</td>
@ -323,6 +247,16 @@ export const Simple: Story = () => (
</table>
</>
)
Simple.argTypes = {
mode: {
control: { type: 'select', options: TYPOGRAPHY_MODES },
defaultValue: 'default',
},
alignment: {
control: { type: 'select', options: TYPOGRAPHY_ALIGNMENTS },
defaultValue: 'left',
},
}
export const CrossingStyles: Story = () => (
<>

File diff suppressed because one or more lines are too long

View File

@ -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",

161
yarn.lock
View File

@ -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"