From a79eba4791f8d95de15841889cbc4a76d53ffe04 Mon Sep 17 00:00:00 2001 From: Vova Kulikov Date: Wed, 6 Jul 2022 12:41:19 -0400 Subject: [PATCH] Code Insights: Reuse series picker in compute insight creation UI page (#38183) * Improve type exports * Refactor form series component (preparation for reusing it in compute insight page) * Update repositories prop comment * Put validators in a separate file * Fix autofocus problem for series form fields * Move insight series picker to the shared components directory * Fix imports for the search-based and capture group insight creation UI pages * Move constants to the top level exports * Reuse form series component on the compute-powered insight page * Simplify useField generics types * Fix visual bug with query input editor * Fix problems with bad imports and outdated mocks --- .../code-insights-page/CodeInsightsPage.tsx | 2 +- .../CodeInsightDashboardsVisibility.tsx | 0 .../CodeInsightTimeStepPicker.module.scss | 0 .../CodeInsightTimeStepPicker.tsx | 0 .../get-interval-description-text.tsx | 0 .../get-interval-description.text.test.ts | 0 .../CreationUiLayout.module.scss | 0 .../creation-ui-layout/CreationUiLayout.tsx | 0 .../form-series/FormSeries.module.scss | 0 .../creation-ui/form-series/FormSeries.tsx | 85 ++++++++++++ .../FormColorInput.module.scss | 0 .../form-color-input/FormColorInput.tsx | 2 +- .../form-series-input/FormSeriesInput.tsx | 71 ++++------ .../get-pattern-type-filter.ts | 0 .../form-series-input/validators.ts | 22 +++ .../series-card/SeriesCard.module.scss | 0 .../components/series-card/SeriesCard.tsx | 2 +- .../creation-ui/form-series/index.ts | 3 + .../creation-ui/form-series/types.ts | 7 + .../form-series}/use-editable-series.ts | 78 ++++++----- .../{creation-ui-kit => creation-ui}/index.ts | 2 + .../live-preview/LivePreviewCard.module.scss | 0 .../live-preview/LivePreviewCard.tsx | 0 .../live-preview/constants.ts | 0 .../live-preview/index.ts | 0 .../live-preview/use-live-preview.ts | 0 .../sanitizers/repositories.test.ts | 0 .../sanitizers/repositories.ts | 0 .../components/form/hooks/useField.ts | 8 +- .../insights/components/form/hooks/useForm.ts | 4 +- .../insights/components/form/index.ts | 4 +- .../query-input/InsightQueryInput.module.scss | 5 + .../form/query-input/InsightQueryInput.tsx | 2 +- .../utils/generate-repo-filters-query.ts | 2 +- .../repositories-field/RepositoryField.tsx | 2 +- .../utils/get-suggestions-search-term.ts | 2 +- .../insights/components/form/validators.ts | 6 +- .../enterprise/insights/components/index.ts | 2 +- .../views/card/InsightCard.story.tsx | 3 +- .../categorical/CategoricalChart.story.tsx | 3 +- .../chart/categorical/CategoricalChart.tsx | 6 +- .../insights/components/views/chart/index.ts | 4 +- .../views/chart/series/SeriesChart.story.tsx | 3 +- .../views/chart/series/SeriesChart.tsx | 5 +- .../insights/components/views/index.ts | 3 +- .../insights/components/views/types.ts | 8 -- .../constants.ts => constants/index.ts} | 0 .../deserializators.ts | 2 +- .../src/enterprise/insights/hooks/index.ts | 1 + .../creation/LineChartLivePreview.tsx | 14 +- .../utils/capture-group-insight-sanitizer.ts | 2 +- .../compute/ComputeInsightCreationPage.tsx | 5 +- .../ComputeInsightCreationContent.tsx | 73 +++++++++- .../creation/compute/components/types.ts | 2 +- .../SearchInsightCreationPage.story.tsx | 2 +- .../components/SearchInsightCreationForm.tsx | 39 +----- .../components/form-series/FormSeries.tsx | 128 ------------------ .../SearchInsightCreationContent.tsx | 22 ++- .../hooks/helpers.ts | 13 -- .../use-insight-creation-form.ts | 21 ++- .../initial-insight-values.ts | 3 +- .../validators.ts | 4 +- .../insights/creation/search-insight/index.ts | 6 +- .../insights/creation/search-insight/types.ts | 31 +---- .../search-insight/utils/insight-sanitizer.ts | 8 +- .../search-insight-url-parsers.test.ts | 24 +++- .../search-insight-url-parsers.ts | 2 +- .../use-url-query-insight.ts | 4 +- .../components/EditCaptureGroupInsight.tsx | 2 +- .../components/EditSearchInsight.tsx | 3 +- .../code-insights-examples/examples.ts | 2 +- .../code-insights-templates/constants.ts | 3 +- .../DynamicCodeInsightExample.tsx | 12 +- .../DynamicInsightPreview.tsx | 13 +- 74 files changed, 401 insertions(+), 386 deletions(-) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/CodeInsightDashboardsVisibility.tsx (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/code-insight-time-step-picker/CodeInsightTimeStepPicker.module.scss (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/code-insight-time-step-picker/CodeInsightTimeStepPicker.tsx (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description-text.tsx (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description.text.test.ts (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/creation-ui-layout/CreationUiLayout.module.scss (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/creation-ui-layout/CreationUiLayout.tsx (100%) rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight/components => components/creation-ui}/form-series/FormSeries.module.scss (100%) create mode 100644 client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.tsx rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight => components/creation-ui/form-series}/components/form-color-input/FormColorInput.module.scss (100%) rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight => components/creation-ui/form-series}/components/form-color-input/FormColorInput.tsx (97%) rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight => components/creation-ui/form-series}/components/form-series-input/FormSeriesInput.tsx (67%) rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight => components/creation-ui/form-series}/components/form-series-input/get-pattern-type-filter.ts (100%) create mode 100644 client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/validators.ts rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight/components => components/creation-ui}/form-series/components/series-card/SeriesCard.module.scss (100%) rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight/components => components/creation-ui}/form-series/components/series-card/SeriesCard.tsx (97%) create mode 100644 client/web/src/enterprise/insights/components/creation-ui/form-series/index.ts create mode 100644 client/web/src/enterprise/insights/components/creation-ui/form-series/types.ts rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight/components/search-insight-creation-content/hooks => components/creation-ui/form-series}/use-editable-series.ts (70%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/index.ts (73%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/live-preview/LivePreviewCard.module.scss (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/live-preview/LivePreviewCard.tsx (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/live-preview/constants.ts (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/live-preview/index.ts (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/live-preview/use-live-preview.ts (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/sanitizers/repositories.test.ts (100%) rename client/web/src/enterprise/insights/components/{creation-ui-kit => creation-ui}/sanitizers/repositories.ts (100%) delete mode 100644 client/web/src/enterprise/insights/components/views/types.ts rename client/web/src/enterprise/insights/{pages/insights/creation/search-insight/constants.ts => constants/index.ts} (100%) delete mode 100644 client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.tsx delete mode 100644 client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/helpers.ts rename client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/{use-insight-creation-form => }/use-insight-creation-form.ts (83%) diff --git a/client/web/src/enterprise/insights/components/code-insights-page/CodeInsightsPage.tsx b/client/web/src/enterprise/insights/components/code-insights-page/CodeInsightsPage.tsx index 6850b615ffd..d00ef380de0 100644 --- a/client/web/src/enterprise/insights/components/code-insights-page/CodeInsightsPage.tsx +++ b/client/web/src/enterprise/insights/components/code-insights-page/CodeInsightsPage.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Page } from '../../../../components/Page' -import { useUiFeatures } from '../../hooks/use-ui-features' +import { useUiFeatures } from '../../hooks' import { CodeInsightsLimitAccessBanner } from './limit-access-banner/CodeInsightsLimitAccessBanner' diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/CodeInsightDashboardsVisibility.tsx b/client/web/src/enterprise/insights/components/creation-ui/CodeInsightDashboardsVisibility.tsx similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/CodeInsightDashboardsVisibility.tsx rename to client/web/src/enterprise/insights/components/creation-ui/CodeInsightDashboardsVisibility.tsx diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/CodeInsightTimeStepPicker.module.scss b/client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/CodeInsightTimeStepPicker.module.scss similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/CodeInsightTimeStepPicker.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/CodeInsightTimeStepPicker.module.scss diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/CodeInsightTimeStepPicker.tsx b/client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/CodeInsightTimeStepPicker.tsx similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/CodeInsightTimeStepPicker.tsx rename to client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/CodeInsightTimeStepPicker.tsx diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description-text.tsx b/client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description-text.tsx similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description-text.tsx rename to client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description-text.tsx diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description.text.test.ts b/client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description.text.test.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description.text.test.ts rename to client/web/src/enterprise/insights/components/creation-ui/code-insight-time-step-picker/get-interval-descrtiption-text/get-interval-description.text.test.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/creation-ui-layout/CreationUiLayout.module.scss b/client/web/src/enterprise/insights/components/creation-ui/creation-ui-layout/CreationUiLayout.module.scss similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/creation-ui-layout/CreationUiLayout.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/creation-ui-layout/CreationUiLayout.module.scss diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/creation-ui-layout/CreationUiLayout.tsx b/client/web/src/enterprise/insights/components/creation-ui/creation-ui-layout/CreationUiLayout.tsx similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/creation-ui-layout/CreationUiLayout.tsx rename to client/web/src/enterprise/insights/components/creation-ui/creation-ui-layout/CreationUiLayout.tsx diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.module.scss b/client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.module.scss similarity index 100% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.module.scss diff --git a/client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.tsx b/client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.tsx new file mode 100644 index 00000000000..8472d19b1c0 --- /dev/null +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/FormSeries.tsx @@ -0,0 +1,85 @@ +import { FC, ReactNode } from 'react' + +import classNames from 'classnames' + +import { Button } from '@sourcegraph/wildcard' + +import { useUiFeatures } from '../../../hooks' +import { LimitedAccessLabel, useFieldAPI } from '../../index' + +import { FormSeriesInput } from './components/form-series-input/FormSeriesInput' +import { SeriesCard } from './components/series-card/SeriesCard' +import { EditableDataSeries } from './types' +import { useEditableSeries } from './use-editable-series' + +import styles from './FormSeries.module.scss' + +export interface FormSeriesProps { + seriesField: useFieldAPI + repositories: string + showValidationErrorsOnMount: boolean + + /** + * This field is only needed for specifying a special compute-specific + * query field description when this component is used on the compute-powered insight. + * This prop should be removed when we will have a better form series management + * solution, see https://github.com/sourcegraph/sourcegraph/issues/38236 + */ + queryFieldDescription?: ReactNode +} + +export const FormSeries: FC = props => { + const { seriesField, showValidationErrorsOnMount, repositories, queryFieldDescription } = props + + const { licensed } = useUiFeatures() + const { series, changeSeries, editRequest, editCommit, cancelEdit, deleteSeries } = useEditableSeries(seriesField) + + return ( +
    + {series.map((line, index) => + line.edit ? ( + 1} + autofocus={line.autofocus} + repositories={repositories} + queryFieldDescription={queryFieldDescription} + className={classNames('p-3', styles.formSeriesItem)} + onSubmit={editCommit} + onCancel={() => cancelEdit(line.id)} + onChange={(seriesValues, valid) => changeSeries(seriesValues, valid, index)} + /> + ) : ( + line && ( + = 10} + onEdit={() => editRequest(line.id)} + onRemove={() => deleteSeries(line.id)} + className={styles.formSeriesItem} + {...line} + /> + ) + ) + )} + + {!licensed && ( + + )} + + +
+ ) +} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-color-input/FormColorInput.module.scss b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-color-input/FormColorInput.module.scss similarity index 100% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-color-input/FormColorInput.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-color-input/FormColorInput.module.scss diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-color-input/FormColorInput.tsx b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-color-input/FormColorInput.tsx similarity index 97% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-color-input/FormColorInput.tsx rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-color-input/FormColorInput.tsx index 61afee9c0ec..a3288436832 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-color-input/FormColorInput.tsx +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-color-input/FormColorInput.tsx @@ -6,7 +6,7 @@ import { noop } from 'rxjs' import { Label } from '@sourcegraph/wildcard' -import { DATA_SERIES_COLORS } from '../../constants' +import { DATA_SERIES_COLORS } from '../../../../../constants' import styles from './FormColorInput.module.scss' diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series-input/FormSeriesInput.tsx b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/FormSeriesInput.tsx similarity index 67% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series-input/FormSeriesInput.tsx rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/FormSeriesInput.tsx index ded7f5ae4a0..14c96a9cee2 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series-input/FormSeriesInput.tsx +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/FormSeriesInput.tsx @@ -1,54 +1,42 @@ -import React from 'react' +import { FC, ReactNode } from 'react' import classNames from 'classnames' import { noop } from 'rxjs' import { Button, Card, Input, Code } from '@sourcegraph/wildcard' -import { getDefaultInputProps } from '../../../../../../components/form/getDefaultInputProps' -import { useField } from '../../../../../../components/form/hooks/useField' -import { useForm, ValidationResult } from '../../../../../../components/form/hooks/useForm' -import { InsightQueryInput } from '../../../../../../components/form/query-input/InsightQueryInput' -import { createRequiredValidator } from '../../../../../../components/form/validators' -import { searchQueryValidator } from '../../../capture-group/utils/search-query-validator' -import { DEFAULT_DATA_SERIES_COLOR } from '../../constants' +import { DEFAULT_DATA_SERIES_COLOR } from '../../../../../constants' +import { getDefaultInputProps, useField, InsightQueryInput, useForm } from '../../../../form' import { EditableDataSeries } from '../../types' import { FormColorInput } from '../form-color-input/FormColorInput' import { getQueryPatternTypeFilter } from './get-pattern-type-filter' - -const requiredNameField = createRequiredValidator('Name is a required field for data series.') -const validQuery = (value: string | undefined, validity: ValidityState | null | undefined): ValidationResult => { - const result = createRequiredValidator('Query is a required field for data series.')(value, validity) - if (result) { - return result - } - const { isNotContext, isNotRepo } = searchQueryValidator(value || '', true) - - if (!isNotContext) { - return 'The `context:` filter is not supported; instead, run over all repositories and use the `context:` on the filter panel after creation' - } - - if (!isNotRepo) { - return 'Do not include a `repo:` filter; add targeted repositories above, or filter repos on the filter panel after creation' - } -} +import { requiredNameField, validQuery } from './validators' interface FormSeriesInputProps { + series: EditableDataSeries + /** Series index. */ index: number - /** - * Show all validation error of all fields within the form. - */ + /** Show all validation error of all fields within the form. */ showValidationErrorsOnMount?: boolean - series: EditableDataSeries - - /** Code Insight repositories field string value - repo1, repo2, ... */ + /** + * Code Insight repositories field string value - repo1, repo2, ... + * This prop is used in order to generate a proper link for the query preview button. + */ repositories: string - /** Enable autofocus behavior of first input of form. */ + /** + * This field is only needed for specifying a special compute-specific + * query field description when this component is used on the compute-powered insight. + * This prop should be removed when we will have a better form series management + * solution, see https://github.com/sourcegraph/sourcegraph/issues/38236 + */ + queryFieldDescription?: ReactNode + + /** Enable autofocus behavior of the first input element of series form. */ autofocus?: boolean /** Enable cancel button. */ @@ -67,7 +55,7 @@ interface FormSeriesInputProps { onChange?: (formValues: EditableDataSeries, valid: boolean) => void } -export const FormSeriesInput: React.FunctionComponent> = props => { +export const FormSeriesInput: FC = props => { const { index, series, @@ -76,6 +64,7 @@ export const FormSeriesInput: React.FunctionComponent} + message={ + queryFieldDescription ?? ( + + Do not include the context: or repo: filter; if needed,{' '} + repo: will be added automatically. + + ) + } className="mt-4" {...getDefaultInputProps(queryField)} /> @@ -179,10 +175,3 @@ export const FormSeriesInput: React.FunctionComponent ) } - -const QueryFieldDescription: React.FunctionComponent> = () => ( - - Do not include the context: or repo: filter; if needed, repo: will be - added automatically. - -) diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series-input/get-pattern-type-filter.ts b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/get-pattern-type-filter.ts similarity index 100% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series-input/get-pattern-type-filter.ts rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/get-pattern-type-filter.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/validators.ts b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/validators.ts new file mode 100644 index 00000000000..ed47e8acd04 --- /dev/null +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/form-series-input/validators.ts @@ -0,0 +1,22 @@ +import { searchQueryValidator } from '../../../../../pages/insights/creation/capture-group/utils/search-query-validator' +import { createRequiredValidator, ValidationResult } from '../../../../form' + +export const requiredNameField = createRequiredValidator('Name is a required field for data series.') + +export const validQuery = (value: string | undefined, validity: ValidityState | null | undefined): ValidationResult => { + const result = createRequiredValidator('Query is a required field for data series.')(value, validity) + + if (result) { + return result + } + + const { isNotContext, isNotRepo } = searchQueryValidator(value || '', true) + + if (!isNotContext) { + return 'The `context:` filter is not supported; instead, run over all repositories and use the `context:` on the filter panel after creation' + } + + if (!isNotRepo) { + return 'Do not include a `repo:` filter; add targeted repositories above, or filter repos on the filter panel after creation' + } +} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/components/series-card/SeriesCard.module.scss b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/series-card/SeriesCard.module.scss similarity index 100% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/components/series-card/SeriesCard.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/series-card/SeriesCard.module.scss diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/components/series-card/SeriesCard.tsx b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/series-card/SeriesCard.tsx similarity index 97% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/components/series-card/SeriesCard.tsx rename to client/web/src/enterprise/insights/components/creation-ui/form-series/components/series-card/SeriesCard.tsx index e5ad8613fab..db9042d384b 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/components/series-card/SeriesCard.tsx +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/components/series-card/SeriesCard.tsx @@ -4,7 +4,7 @@ import classNames from 'classnames' import { Button, Card } from '@sourcegraph/wildcard' -import { DEFAULT_DATA_SERIES_COLOR } from '../../../../constants' +import { DEFAULT_DATA_SERIES_COLOR } from '../../../../../constants' import styles from './SeriesCard.module.scss' diff --git a/client/web/src/enterprise/insights/components/creation-ui/form-series/index.ts b/client/web/src/enterprise/insights/components/creation-ui/form-series/index.ts new file mode 100644 index 00000000000..7eab4b0b829 --- /dev/null +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/index.ts @@ -0,0 +1,3 @@ +export { FormSeries } from './FormSeries' +export { createDefaultEditSeries } from './use-editable-series' +export type { EditableDataSeries } from './types' diff --git a/client/web/src/enterprise/insights/components/creation-ui/form-series/types.ts b/client/web/src/enterprise/insights/components/creation-ui/form-series/types.ts new file mode 100644 index 00000000000..f0bfcb3ff3c --- /dev/null +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/types.ts @@ -0,0 +1,7 @@ +import { SearchBasedInsightSeries } from '../../../core' + +export interface EditableDataSeries extends SearchBasedInsightSeries { + valid: boolean + edit: boolean + autofocus: boolean +} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-editable-series.ts b/client/web/src/enterprise/insights/components/creation-ui/form-series/use-editable-series.ts similarity index 70% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-editable-series.ts rename to client/web/src/enterprise/insights/components/creation-ui/form-series/use-editable-series.ts index 522d5e1e437..93d8f12671e 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-editable-series.ts +++ b/client/web/src/enterprise/insights/components/creation-ui/form-series/use-editable-series.ts @@ -2,61 +2,63 @@ import { useState } from 'react' import * as uuid from 'uuid' -import { useFieldAPI } from '../../../../../../../components/form/hooks/useField' import { DEFAULT_DATA_SERIES_COLOR } from '../../../constants' -import { CreateInsightFormFields, EditableDataSeries } from '../../../types' +import { useFieldAPI } from '../../form' -import { remove, replace } from './helpers' - -const EDIT_SERIES_PREFIX = 'runtime-series' +import { EditableDataSeries } from './types' export const createDefaultEditSeries = (series?: Partial): EditableDataSeries => ({ - id: `${EDIT_SERIES_PREFIX}.${uuid.v4()}`, - ...defaultEditSeries, + id: `runtime-series.${uuid.v4()}`, + ...DEFAULT_EDITABLE_SERIES, ...series, }) -const defaultEditSeries = { +const DEFAULT_EDITABLE_SERIES = { valid: false, edit: false, + autofocus: false, name: '', query: '', stroke: DEFAULT_DATA_SERIES_COLOR, } -export interface UseEditableSeriesProps { - series: useFieldAPI -} - export interface UseEditableSeriesAPI { /** - * Edit series array used below for rendering series edit form. - * In case of some element has undefined value we're showing - * series card with data instead of form. - * */ - editSeries: CreateInsightFormFields['series'] + * A list of editable data series. Basically, this is just a + * sorted/filtered list of original data series but with + * additional logic around create/updated/delete actions for + * series list. + */ + series: EditableDataSeries[] - /** - * Handler to listen latest values of particular sereis form. - * */ - listen: (liveSeries: EditableDataSeries, valid: boolean, index: number) => void + /** Call whenever the user changes any fields (title, query, color) of series */ + changeSeries: (liveSeries: EditableDataSeries, valid: boolean, index: number) => void - /** - * Handlers for CRUD operations over series. - * */ + /** Call whenever the user clicks the edit series button in series preview card. */ editRequest: (seriesId?: string) => void + + /** Call whenever the user clicks the save series button */ editCommit: (editedSeries: EditableDataSeries) => void + + /** + * Call whenever the user cancel series editing by clicking cancel button + * in series form. + */ cancelEdit: (seriesId: string) => void + + /** + * Call whenever the user tries to delete series by clicking delete button + * in series preview card. + */ deleteSeries: (series: string) => void } /** - * Implementation of CRUD operation over insight series. Used in form to manage - * edit, delete, add, and cancel series forms. + * Basically this is just a stateful selector function over series that simplifies work + * with editable series and its special UX actions like delete series through preview card, + * edit series through form, create new series through add more series button. */ -export function useEditableSeries(props: UseEditableSeriesProps): UseEditableSeriesAPI { - const { series } = props - +export function useEditableSeries(series: useFieldAPI): UseEditableSeriesAPI { const [seriesBeforeEdit, setSeriesBeforeEdit] = useState>({}) const handleSeriesLiveChange = (liveSeries: EditableDataSeries, valid: boolean): void => { @@ -79,7 +81,7 @@ export function useEditableSeries(props: UseEditableSeriesProps): UseEditableSer const index = newEditSeries.findIndex(series => series.id === seriesId) if (index !== -1) { - newEditSeries[index] = { ...seriesValue[index], edit: true } + newEditSeries[index] = { ...seriesValue[index], edit: true, autofocus: true } const newSeriesID = newEditSeries[index].id @@ -92,7 +94,7 @@ export function useEditableSeries(props: UseEditableSeriesProps): UseEditableSer }) } } else { - newEditSeries.push(createDefaultEditSeries({ edit: true })) + newEditSeries.push(createDefaultEditSeries({ edit: true, autofocus: true })) } series.meta.setState(state => ({ ...state, value: newEditSeries })) @@ -163,11 +165,21 @@ export function useEditableSeries(props: UseEditableSeriesProps): UseEditableSer } return { - editSeries: series.input.value, - listen: handleSeriesLiveChange, + series: series.input.value, + changeSeries: handleSeriesLiveChange, editRequest: handleEditSeriesRequest, editCommit: handleEditSeriesCommit, cancelEdit: handleEditSeriesCancel, deleteSeries: handleRemoveSeries, } } + +/** Helper replace element in array by index and return new array. */ +function replace(list: Element[], index: number, newElement: Element): Element[] { + return [...list.slice(0, index), newElement, ...list.slice(index + 1)] +} + +/** Helper remove element from array by index. */ +function remove(list: Element[], index: number): Element[] { + return [...list.slice(0, index), ...list.slice(index + 1)] +} diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/index.ts b/client/web/src/enterprise/insights/components/creation-ui/index.ts similarity index 73% rename from client/web/src/enterprise/insights/components/creation-ui-kit/index.ts rename to client/web/src/enterprise/insights/components/creation-ui/index.ts index e749967bed2..a33bf07a31b 100644 --- a/client/web/src/enterprise/insights/components/creation-ui-kit/index.ts +++ b/client/web/src/enterprise/insights/components/creation-ui/index.ts @@ -5,3 +5,5 @@ export { getSanitizedRepositories } from './sanitizers/repositories' export { CodeInsightDashboardsVisibility } from './CodeInsightDashboardsVisibility' export { CodeInsightTimeStepPicker } from './code-insight-time-step-picker/CodeInsightTimeStepPicker' +export { FormSeries, createDefaultEditSeries } from './form-series' +export type { EditableDataSeries } from './form-series' diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/LivePreviewCard.module.scss b/client/web/src/enterprise/insights/components/creation-ui/live-preview/LivePreviewCard.module.scss similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/LivePreviewCard.module.scss rename to client/web/src/enterprise/insights/components/creation-ui/live-preview/LivePreviewCard.module.scss diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/LivePreviewCard.tsx b/client/web/src/enterprise/insights/components/creation-ui/live-preview/LivePreviewCard.tsx similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/LivePreviewCard.tsx rename to client/web/src/enterprise/insights/components/creation-ui/live-preview/LivePreviewCard.tsx diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/constants.ts b/client/web/src/enterprise/insights/components/creation-ui/live-preview/constants.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/constants.ts rename to client/web/src/enterprise/insights/components/creation-ui/live-preview/constants.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/index.ts b/client/web/src/enterprise/insights/components/creation-ui/live-preview/index.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/index.ts rename to client/web/src/enterprise/insights/components/creation-ui/live-preview/index.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/use-live-preview.ts b/client/web/src/enterprise/insights/components/creation-ui/live-preview/use-live-preview.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/live-preview/use-live-preview.ts rename to client/web/src/enterprise/insights/components/creation-ui/live-preview/use-live-preview.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/sanitizers/repositories.test.ts b/client/web/src/enterprise/insights/components/creation-ui/sanitizers/repositories.test.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/sanitizers/repositories.test.ts rename to client/web/src/enterprise/insights/components/creation-ui/sanitizers/repositories.test.ts diff --git a/client/web/src/enterprise/insights/components/creation-ui-kit/sanitizers/repositories.ts b/client/web/src/enterprise/insights/components/creation-ui/sanitizers/repositories.ts similarity index 100% rename from client/web/src/enterprise/insights/components/creation-ui-kit/sanitizers/repositories.ts rename to client/web/src/enterprise/insights/components/creation-ui/sanitizers/repositories.ts diff --git a/client/web/src/enterprise/insights/components/form/hooks/useField.ts b/client/web/src/enterprise/insights/components/form/hooks/useField.ts index 505914381ce..e25bdf54494 100644 --- a/client/web/src/enterprise/insights/components/form/hooks/useField.ts +++ b/client/web/src/enterprise/insights/components/form/hooks/useField.ts @@ -25,7 +25,7 @@ export interface Validators { /** * Subset of native input props that useField can set to the native input element. */ -interface InputProps extends Omit, 'name' | 'value' | 'onChange'> { +export interface InputProps extends Omit, 'name' | 'value' | 'onChange'> { onChange?: (value: Value) => void } @@ -75,7 +75,7 @@ export type UseFieldProps = { * * Should be used with useForm hook to connect field and form component's states. */ -export function useField['initialValues']>( +export function useField( props: UseFieldProps ): useFieldAPI { const { formApi, name, validators, onChange = noop, ...inputProps } = props @@ -130,7 +130,7 @@ export function useField['init } if (async) { - // Due the call of start async validation in useLayoutEffect we have to + // Due to the call of start async validation in useLayoutEffect we have to // schedule the async validation event in the next tick to be able run // observable pipeline validation since useAsyncValidation hook use // useObservable hook internally which calls '.subscribe' in useEffect. @@ -189,7 +189,7 @@ export function useField['init type FieldStateTransformer = (previousState: FieldState) => FieldState -function useFormFieldState['initialValues']>( +function useFormFieldState( name: Key, formAPI: FormAPI ): [FieldState, Dispatch>] { diff --git a/client/web/src/enterprise/insights/components/form/hooks/useForm.ts b/client/web/src/enterprise/insights/components/form/hooks/useForm.ts index 7b5ad42b40f..5d6c140f47e 100644 --- a/client/web/src/enterprise/insights/components/form/hooks/useForm.ts +++ b/client/web/src/enterprise/insights/components/form/hooks/useForm.ts @@ -15,7 +15,7 @@ import { import { debounce, DebouncedFunc, isFunction } from 'lodash' import { noop } from 'rxjs' -import { useDistinctValue } from '../../../hooks/use-distinct-value' +import { useDistinctValue } from '../../../hooks' // Special key for the submit error store. export const FORM_ERROR = 'useForm/submissionErrors' @@ -106,7 +106,7 @@ export interface FormAPI { /** * Mark to understand was there an attempt by user to submit the form? * Used in useField hook to trigger appearance of error message if - * user tried submit the form. + * user tried to submit the form. */ submitted: boolean diff --git a/client/web/src/enterprise/insights/components/form/index.ts b/client/web/src/enterprise/insights/components/form/index.ts index 61fbb2e18e9..ca27145c57a 100644 --- a/client/web/src/enterprise/insights/components/form/index.ts +++ b/client/web/src/enterprise/insights/components/form/index.ts @@ -11,8 +11,10 @@ export { FormGroup } from './form-group/FormGroup' // form hooks export { useForm, FORM_ERROR } from './hooks/useForm' -export type { Form, SubmissionErrors, FormChangeEvent } from './hooks/useForm' +export type { Form, ValidationResult, SubmissionErrors, FormChangeEvent } from './hooks/useForm' + export { useField } from './hooks/useField' export type { useFieldAPI } from './hooks/useField' + export { useCheckboxes } from './hooks/useCheckboxes' export { useAsyncInsightTitleValidator } from './hooks/use-async-insight-title-validator' diff --git a/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.module.scss b/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.module.scss index d2f2ded426e..015bc634426 100644 --- a/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.module.scss +++ b/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.module.scss @@ -5,6 +5,11 @@ } .input-wrapper { + // Spread standard input paddings in order to fix visually problem + // with codemirror editor on the code insight creation UI pages. + // See https://github.com/sourcegraph/sourcegraph/issues/37785 + padding-top: 0.5rem; + padding-bottom: 0.5rem; border-top-right-radius: 0; border-bottom-right-radius: 0; } diff --git a/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.tsx b/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.tsx index c3081b0dc2d..b3b4e514811 100644 --- a/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.tsx +++ b/client/web/src/enterprise/insights/components/form/query-input/InsightQueryInput.tsx @@ -34,7 +34,7 @@ export const InsightQueryInput = forwardRef ) : ( - + )} diff --git a/client/web/src/enterprise/insights/components/form/query-input/utils/generate-repo-filters-query.ts b/client/web/src/enterprise/insights/components/form/query-input/utils/generate-repo-filters-query.ts index 69e266ae592..30271ddf049 100644 --- a/client/web/src/enterprise/insights/components/form/query-input/utils/generate-repo-filters-query.ts +++ b/client/web/src/enterprise/insights/components/form/query-input/utils/generate-repo-filters-query.ts @@ -1,6 +1,6 @@ import escapeRegExp from 'lodash/escapeRegExp' -import { getSanitizedRepositories } from '../../../creation-ui-kit' +import { getSanitizedRepositories } from '../../../creation-ui' export const generateRepoFiltersQuery = (repositoriesString: string): string => { const repositories = getSanitizedRepositories(repositoriesString) diff --git a/client/web/src/enterprise/insights/components/form/repositories-field/RepositoryField.tsx b/client/web/src/enterprise/insights/components/form/repositories-field/RepositoryField.tsx index e4dcd276e44..0e90d2b801b 100644 --- a/client/web/src/enterprise/insights/components/form/repositories-field/RepositoryField.tsx +++ b/client/web/src/enterprise/insights/components/form/repositories-field/RepositoryField.tsx @@ -4,7 +4,7 @@ import { Combobox, ComboboxInput, ComboboxPopover } from '@reach/combobox' import { FlexTextArea } from '@sourcegraph/wildcard' -import { getSanitizedRepositories } from '../../creation-ui-kit' +import { getSanitizedRepositories } from '../../creation-ui' import { SuggestionsPanel } from './components/suggestion-panel/SuggestionPanel' import { useRepoSuggestions } from './hooks/use-repo-suggestions' diff --git a/client/web/src/enterprise/insights/components/form/repositories-field/utils/get-suggestions-search-term.ts b/client/web/src/enterprise/insights/components/form/repositories-field/utils/get-suggestions-search-term.ts index 4272b176251..df306a4614d 100644 --- a/client/web/src/enterprise/insights/components/form/repositories-field/utils/get-suggestions-search-term.ts +++ b/client/web/src/enterprise/insights/components/form/repositories-field/utils/get-suggestions-search-term.ts @@ -1,4 +1,4 @@ -import { getSanitizedRepositories } from '../../../creation-ui-kit' +import { getSanitizedRepositories } from '../../../creation-ui' interface SuggestionsSearchTermInput { value: string diff --git a/client/web/src/enterprise/insights/components/form/validators.ts b/client/web/src/enterprise/insights/components/form/validators.ts index be7f2b6129c..40fc3d8aca7 100644 --- a/client/web/src/enterprise/insights/components/form/validators.ts +++ b/client/web/src/enterprise/insights/components/form/validators.ts @@ -2,9 +2,9 @@ import { Validator } from './hooks/useField' import { ValidationResult } from './hooks/useForm' /** - * Validator for required form field which returns error massage + * Validator for required form field which returns error message * as a sign of invalid state. - * */ + */ export const createRequiredValidator = (errorMessage: string): Validator => (value, validity) => { if (validity?.valueMissing) { return errorMessage @@ -20,6 +20,6 @@ export const createRequiredValidator = (errorMessage: string): Validator< /** * Composes a few validators together and show first error for form field. - * */ + */ export const composeValidators = (...validators: Validator[]): Validator => (value, validity) => validators.reduce((error, validator) => error || validator(value, validity), undefined) diff --git a/client/web/src/enterprise/insights/components/index.ts b/client/web/src/enterprise/insights/components/index.ts index 7489921253c..51460521294 100644 --- a/client/web/src/enterprise/insights/components/index.ts +++ b/client/web/src/enterprise/insights/components/index.ts @@ -3,7 +3,7 @@ export { CodeInsightsIcon } from '../../../insights/Icons' export * from './insights-view-grid' export * from './views' export * from './trancated-text/TruncatedText' -export * from './creation-ui-kit' +export * from './creation-ui' export * from './form' export * from './limited-access-label/LimitedAccessLabel' export * from './code-insights-page/CodeInsightsPage' diff --git a/client/web/src/enterprise/insights/components/views/card/InsightCard.story.tsx b/client/web/src/enterprise/insights/components/views/card/InsightCard.story.tsx index 33919a7ee1e..ee749785e09 100644 --- a/client/web/src/enterprise/insights/components/views/card/InsightCard.story.tsx +++ b/client/web/src/enterprise/insights/components/views/card/InsightCard.story.tsx @@ -9,8 +9,7 @@ import { Button, Menu, MenuButton, MenuItem, MenuList, H2 } from '@sourcegraph/w import { getLineColor, LegendItem, LegendList, ParentSize, Series } from '../../../../../charts' import { WebStory } from '../../../../../components/WebStory' import { useSeriesToggle } from '../../../../../insights/utils/use-series-toggle' -import { SeriesChart } from '../chart' -import { SeriesBasedChartTypes } from '../types' +import { SeriesBasedChartTypes, SeriesChart } from '../chart' import * as Card from './InsightCard' diff --git a/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.story.tsx b/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.story.tsx index b0021746553..ed3df9e6e7f 100644 --- a/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.story.tsx +++ b/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.story.tsx @@ -1,9 +1,8 @@ import { Meta, Story } from '@storybook/react' import { WebStory } from '../../../../../../components/WebStory' -import { CategoricalBasedChartTypes } from '../../types' -import { CategoricalChart } from './CategoricalChart' +import { CategoricalBasedChartTypes, CategoricalChart } from './CategoricalChart' const StoryConfig: Meta = { title: 'web/insights/views/CategoricalChart', diff --git a/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.tsx b/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.tsx index e88fa4d4949..4dbf7a3a5d8 100644 --- a/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.tsx +++ b/client/web/src/enterprise/insights/components/views/chart/categorical/CategoricalChart.tsx @@ -1,9 +1,13 @@ import React, { SVGProps } from 'react' import { CategoricalLikeChart, PieChart } from '../../../../../../charts' -import { CategoricalBasedChartTypes } from '../../types' import { LockedChart } from '../locked/LockedChart' +export enum CategoricalBasedChartTypes { + Pie, + Bar, +} + export interface CategoricalChartProps extends CategoricalLikeChart, Omit, 'type'> { diff --git a/client/web/src/enterprise/insights/components/views/chart/index.ts b/client/web/src/enterprise/insights/components/views/chart/index.ts index 7f13d7653a3..4db650b1870 100644 --- a/client/web/src/enterprise/insights/components/views/chart/index.ts +++ b/client/web/src/enterprise/insights/components/views/chart/index.ts @@ -1,5 +1,5 @@ -export { SeriesChart } from './series/SeriesChart' -export { CategoricalChart } from './categorical/CategoricalChart' +export { SeriesChart, SeriesBasedChartTypes } from './series/SeriesChart' +export { CategoricalChart, CategoricalBasedChartTypes } from './categorical/CategoricalChart' export type { SeriesChartProps } from './series/SeriesChart' export type { CategoricalChartProps } from './categorical/CategoricalChart' diff --git a/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.story.tsx b/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.story.tsx index 7a6a47d9345..a2e34962d1b 100644 --- a/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.story.tsx +++ b/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.story.tsx @@ -3,9 +3,8 @@ import { Meta, Story } from '@storybook/react' import { Series } from '../../../../../../charts' import { WebStory } from '../../../../../../components/WebStory' import { useSeriesToggle } from '../../../../../../insights/utils/use-series-toggle' -import { SeriesBasedChartTypes } from '../../types' -import { SeriesChart } from './SeriesChart' +import { SeriesBasedChartTypes, SeriesChart } from './SeriesChart' const StoryConfig: Meta = { title: 'web/insights/views/SeriesChart', diff --git a/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.tsx b/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.tsx index a746d9edacf..b6e7aa2df03 100644 --- a/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.tsx +++ b/client/web/src/enterprise/insights/components/views/chart/series/SeriesChart.tsx @@ -4,9 +4,12 @@ import { LineChart, SeriesLikeChart } from '../../../../../../charts' import { LineChartProps } from '../../../../../../charts/components/line-chart/LineChart' import { SeriesWithData } from '../../../../../../charts/components/line-chart/utils' import { UseSeriesToggleReturn } from '../../../../../../insights/utils/use-series-toggle' -import { SeriesBasedChartTypes } from '../../types' import { LockedChart } from '../locked/LockedChart' +export enum SeriesBasedChartTypes { + Line, +} + export interface SeriesChartProps extends SeriesLikeChart, Omit, 'type'> { type: SeriesBasedChartTypes width: number diff --git a/client/web/src/enterprise/insights/components/views/index.ts b/client/web/src/enterprise/insights/components/views/index.ts index 86c53001dc3..b465bd5f169 100644 --- a/client/web/src/enterprise/insights/components/views/index.ts +++ b/client/web/src/enterprise/insights/components/views/index.ts @@ -1,6 +1,5 @@ export * from './card/InsightCard' -export { SeriesChart, CategoricalChart } from './chart' -export { CategoricalBasedChartTypes, SeriesBasedChartTypes } from './types' +export { SeriesChart, CategoricalChart, CategoricalBasedChartTypes, SeriesBasedChartTypes } from './chart' export type { SeriesChartProps, CategoricalChartProps } from './chart' diff --git a/client/web/src/enterprise/insights/components/views/types.ts b/client/web/src/enterprise/insights/components/views/types.ts deleted file mode 100644 index e8c25d9c306..00000000000 --- a/client/web/src/enterprise/insights/components/views/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export enum SeriesBasedChartTypes { - Line, -} - -export enum CategoricalBasedChartTypes { - Pie, - Bar, -} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/constants.ts b/client/web/src/enterprise/insights/constants/index.ts similarity index 100% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/constants.ts rename to client/web/src/enterprise/insights/constants/index.ts diff --git a/client/web/src/enterprise/insights/core/backend/gql-backend/methods/get-backend-insight-data/deserializators.ts b/client/web/src/enterprise/insights/core/backend/gql-backend/methods/get-backend-insight-data/deserializators.ts index 2f0568861b4..f9fa547891a 100644 --- a/client/web/src/enterprise/insights/core/backend/gql-backend/methods/get-backend-insight-data/deserializators.ts +++ b/client/web/src/enterprise/insights/core/backend/gql-backend/methods/get-backend-insight-data/deserializators.ts @@ -1,5 +1,5 @@ import { InsightDataNode } from '../../../../../../../graphql-operations' -import { DATA_SERIES_COLORS } from '../../../../../pages/insights/creation/search-insight' +import { DATA_SERIES_COLORS } from '../../../../../constants' import { BackendInsight } from '../../../../types' import { BackendInsightData } from '../../../code-insights-backend-types' import { createLineChartContent } from '../../../utils/create-line-chart-content' diff --git a/client/web/src/enterprise/insights/hooks/index.ts b/client/web/src/enterprise/insights/hooks/index.ts index 683263ae5ce..e75dd424726 100644 --- a/client/web/src/enterprise/insights/hooks/index.ts +++ b/client/web/src/enterprise/insights/hooks/index.ts @@ -1,5 +1,6 @@ export { useLazyParallelRequest } from './use-parallel-requests/use-parallel-request' export type { LazyQueryState, LazyQueryResult } from './use-parallel-requests/use-parallel-request' + export { useApi } from './use-api' export { useCopyURLHandler } from './use-copy-url-handler' export { useDeleteInsight } from './use-delete-insight' diff --git a/client/web/src/enterprise/insights/pages/insights/creation/LineChartLivePreview.tsx b/client/web/src/enterprise/insights/pages/insights/creation/LineChartLivePreview.tsx index 1ccc326c9ce..873a39ac15e 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/LineChartLivePreview.tsx +++ b/client/web/src/enterprise/insights/pages/insights/creation/LineChartLivePreview.tsx @@ -24,6 +24,13 @@ import { CodeInsightsBackendContext, SeriesChartContent } from '../../../core' import { getSanitizedCaptureQuery } from './capture-group/utils/capture-group-insight-sanitizer' import { InsightStep } from './search-insight' +export interface LivePreviewSeries { + query: string + label: string + generatedFromCaptureGroup: boolean + stroke: string +} + interface LineChartLivePreviewProps { disabled: boolean repositories: string @@ -31,12 +38,7 @@ interface LineChartLivePreviewProps { step: InsightStep isAllReposMode: boolean className?: string - series: { - query: string - label: string - generatedFromCaptureGroup: boolean - stroke: string - }[] + series: LivePreviewSeries[] } export const LineChartLivePreview: React.FunctionComponent< diff --git a/client/web/src/enterprise/insights/pages/insights/creation/capture-group/utils/capture-group-insight-sanitizer.ts b/client/web/src/enterprise/insights/pages/insights/creation/capture-group/utils/capture-group-insight-sanitizer.ts index f5056f1ee29..05bff2928a9 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/capture-group/utils/capture-group-insight-sanitizer.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/capture-group/utils/capture-group-insight-sanitizer.ts @@ -2,7 +2,7 @@ import { FilterType, resolveFilter } from '@sourcegraph/shared/src/search/query/ import { scanSearchQuery } from '@sourcegraph/shared/src/search/query/scanner' import { Filter } from '@sourcegraph/shared/src/search/query/token' -import { getSanitizedRepositories } from '../../../../../components/creation-ui-kit' +import { getSanitizedRepositories } from '../../../../../components' import { InsightExecutionType, InsightType, MinimalCaptureGroupInsightData } from '../../../../../core' import { CaptureGroupFormFields } from '../types' diff --git a/client/web/src/enterprise/insights/pages/insights/creation/compute/ComputeInsightCreationPage.tsx b/client/web/src/enterprise/insights/pages/insights/creation/compute/ComputeInsightCreationPage.tsx index f3513406178..65ad469bd8a 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/compute/ComputeInsightCreationPage.tsx +++ b/client/web/src/enterprise/insights/pages/insights/creation/compute/ComputeInsightCreationPage.tsx @@ -6,8 +6,7 @@ import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryServi import { Link, PageHeader, Text, useLocalStorage } from '@sourcegraph/wildcard' import { PageTitle } from '../../../../../../components/PageTitle' -import { CodeInsightsPage } from '../../../../components/code-insights-page/CodeInsightsPage' -import { FormChangeEvent } from '../../../../components/form/hooks/useForm' +import { CodeInsightsPage, FormChangeEvent } from '../../../../components' import { ComputeInsightCreationContent } from './components/ComputeInsightCreationContent' import { CreateComputeInsightFormFields } from './components/types' @@ -42,7 +41,7 @@ export const ComputeInsightCreationPage: FunctionComponent + , 'onSubmit' | 'onChange'> interface ComputeInsightCreationContentProps extends NativeContainerProps { + mode?: 'creation' | 'edit' initialValue?: Partial onChange: (event: FormChangeEvent) => void @@ -16,11 +37,55 @@ interface ComputeInsightCreationContentProps extends NativeContainerProps { } export const ComputeInsightCreationContent: FunctionComponent = props => { - const { initialValue, onChange, onSubmit, onCancel, ...attributes } = props + const { mode = 'creation', initialValue, onChange, onSubmit, onCancel, ...attributes } = props + const { licensed } = useUiFeatures() + + const form = useForm({ + initialValues: { ...INITIAL_INSIGHT_VALUES, ...initialValue }, + onSubmit, + onChange, + touched: mode === 'edit', + }) + + const series = useField({ + name: 'series', + formApi: form.formAPI, + }) return ( - Hello World + + + +
  • + Do not include the repo: filter as it will be added + automatically, if needed{' '} +
  • +
  • + You can use before: and after:{' '} + operators for type:diff and{' '} + type:commit to define the timeframe (example query:{' '} + type:diff author:nick before:"last thursday" SearchTerm) +
  • + + } + /> +
    +
    This is live preview
    diff --git a/client/web/src/enterprise/insights/pages/insights/creation/compute/components/types.ts b/client/web/src/enterprise/insights/pages/insights/creation/compute/components/types.ts index 9273ab636e3..5483e592525 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/compute/components/types.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/compute/components/types.ts @@ -1,4 +1,4 @@ -import { EditableDataSeries } from '../../search-insight' +import { EditableDataSeries } from '../../../../../components' export interface CreateComputeInsightFormFields { /** diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/SearchInsightCreationPage.story.tsx b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/SearchInsightCreationPage.story.tsx index 36fa8b28600..573ee511f5c 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/SearchInsightCreationPage.story.tsx +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/SearchInsightCreationPage.story.tsx @@ -6,7 +6,7 @@ import { NOOP_TELEMETRY_SERVICE } from '@sourcegraph/shared/src/telemetry/teleme import { WebStory } from '../../../../../../components/WebStory' import { CodeInsightsBackendStoryMock } from '../../../../CodeInsightsBackendStoryMock' -import { SERIES_MOCK_CHART } from '../../../../components/creation-ui-kit' +import { SERIES_MOCK_CHART } from '../../../../components' import { SearchInsightCreationPage as SearchInsightCreationPageComponent } from './SearchInsightCreationPage' diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/SearchInsightCreationForm.tsx b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/SearchInsightCreationForm.tsx index 15540924c8f..c9a6db9a368 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/SearchInsightCreationForm.tsx +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/SearchInsightCreationForm.tsx @@ -1,10 +1,11 @@ -import React, { FormEventHandler, RefObject, useMemo } from 'react' +import { FC, FormEventHandler, RefObject, useMemo } from 'react' import { ErrorAlert } from '@sourcegraph/branded/src/components/alerts' import { Button, Checkbox, Input, Link, useObservable } from '@sourcegraph/wildcard' import { LoaderButton } from '../../../../../../../components/LoaderButton' import { + FormSeries, LimitedAccessLabel, CodeInsightDashboardsVisibility, CodeInsightTimeStepPicker, @@ -17,9 +18,7 @@ import { } from '../../../../../components' import { Insight } from '../../../../../core' import { useUiFeatures } from '../../../../../hooks' -import { CreateInsightFormFields, EditableDataSeries } from '../types' - -import { FormSeries } from './form-series/FormSeries' +import { CreateInsightFormFields } from '../types' interface CreationSearchInsightFormProps { /** This component might be used in edit or creation insight case. */ @@ -44,22 +43,6 @@ interface CreationSearchInsightFormProps { insight?: Insight onCancel: () => void - - /** - * Handler to listen latest value form particular series edit form - * Used to get information for live preview chart. - */ - onSeriesLiveChange: (liveSeries: EditableDataSeries, isValid: boolean, index: number) => void - - /** - * Handlers for CRUD operation over series. Add, delete, update and cancel - * series edit form. - */ - onEditSeriesRequest: (seriesId?: string) => void - onEditSeriesCommit: (editedSeries: EditableDataSeries) => void - onEditSeriesCancel: (seriesId: string) => void - onSeriesRemove: (seriesId: string) => void - onFormReset: () => void } @@ -67,9 +50,7 @@ interface CreationSearchInsightFormProps { * Displays creation code insight form (title, visibility, series, etc.) * UI layer only, all controlled data should be managed by consumer of this component. */ -export const SearchInsightCreationForm: React.FunctionComponent< - React.PropsWithChildren -> = props => { +export const SearchInsightCreationForm: FC = props => { const { mode, innerRef, @@ -88,11 +69,6 @@ export const SearchInsightCreationForm: React.FunctionComponent< dashboardReferenceCount, insight, onCancel, - onSeriesLiveChange, - onEditSeriesRequest, - onEditSeriesCommit, - onEditSeriesCancel, - onSeriesRemove, onFormReset, } = props @@ -164,14 +140,9 @@ export const SearchInsightCreationForm: React.FunctionComponent< innerRef={series.input.ref} > diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.tsx b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.tsx deleted file mode 100644 index 7e8859f8e79..00000000000 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/form-series/FormSeries.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react' - -import classNames from 'classnames' - -import { Button } from '@sourcegraph/wildcard' - -import { LimitedAccessLabel } from '../../../../../../components/limited-access-label/LimitedAccessLabel' -import { useUiFeatures } from '../../../../../../hooks/use-ui-features' -import { EditableDataSeries } from '../../types' -import { FormSeriesInput } from '../form-series-input/FormSeriesInput' - -import { SeriesCard } from './components/series-card/SeriesCard' - -import styles from './FormSeries.module.scss' - -export interface FormSeriesProps { - /** - * Show all validation error for all forms and fields within the series forms. - */ - showValidationErrorsOnMount: boolean - - /** - * Controlled value (series - chart lines) for series input component. - */ - series?: EditableDataSeries[] - - /** - * Code Insight repositories field string value - repo1, repo2, ... - */ - repositories: string - - /** - * Live change series handler while user typing in active series form. - * Used by consumers to get latest values from series inputs and pass - * them tp live preview chart. - */ - onLiveChange: (liveSeries: EditableDataSeries, isValid: boolean, index: number) => void - - /** - * Handler that runs every time user clicked edit on particular - * series card. - */ - onEditSeriesRequest: (seriesId?: string) => void - - /** - * Handler that runs every time use clicked commit (done) in - * series edit form. - */ - onEditSeriesCommit: (editedSeries: EditableDataSeries) => void - - /** - * Handler that runs every time use canceled (click cancel) in - * series edit form. - */ - onEditSeriesCancel: (seriesId: string) => void - - /** - * Handler that runs every time use removed (click remove) in - * series card. - */ - onSeriesRemove: (seriesId: string) => void -} - -/** - * Renders form series (sub-form) for series (chart lines) creation code insight form. - */ -export const FormSeries: React.FunctionComponent> = props => { - const { - series = [], - showValidationErrorsOnMount, - repositories, - onEditSeriesRequest, - onEditSeriesCommit, - onEditSeriesCancel, - onSeriesRemove, - onLiveChange, - } = props - - const { licensed } = useUiFeatures() - - return ( -
      - {series.map((line, index) => - line.edit ? ( - 1} - autofocus={series.length > 1} - repositories={repositories} - onSubmit={onEditSeriesCommit} - onCancel={() => onEditSeriesCancel(line.id)} - className={classNames('p-3', styles.formSeriesItem)} - onChange={(seriesValues, valid) => onLiveChange({ ...line, ...seriesValues }, valid, index)} - /> - ) : ( - line && ( - = 10} - onEdit={() => onEditSeriesRequest(line.id)} - onRemove={() => onSeriesRemove(line.id)} - className={styles.formSeriesItem} - {...line} - /> - ) - ) - )} - - {!licensed && ( - - )} - - -
    - ) -} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/SearchInsightCreationContent.tsx b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/SearchInsightCreationContent.tsx index 99713c5d973..3d7fd665628 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/SearchInsightCreationContent.tsx +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/SearchInsightCreationContent.tsx @@ -8,15 +8,16 @@ import { CreationUIPreview, FormChangeEvent, SubmissionErrors, + createDefaultEditSeries, + EditableDataSeries, } from '../../../../../../components' import { Insight } from '../../../../../../core' -import { LineChartLivePreview } from '../../../LineChartLivePreview' -import { CreateInsightFormFields, EditableDataSeries } from '../../types' +import { LineChartLivePreview, LivePreviewSeries } from '../../../LineChartLivePreview' +import { CreateInsightFormFields } from '../../types' import { getSanitizedSeries } from '../../utils/insight-sanitizer' import { SearchInsightCreationForm } from '../SearchInsightCreationForm' -import { useEditableSeries, createDefaultEditSeries } from './hooks/use-editable-series' -import { useInsightCreationForm } from './hooks/use-insight-creation-form/use-insight-creation-form' +import { useInsightCreationForm } from './hooks/use-insight-creation-form' export interface SearchInsightCreationContentProps { /** This component might be used in edit or creation insight case. */ @@ -61,8 +62,6 @@ export const SearchInsightCreationContent: FC onSubmit, }) - const { editSeries, listen, editRequest, editCommit, cancelEdit, deleteSeries } = useEditableSeries({ series }) - const handleFormReset = (): void => { // TODO [VK] Change useForm API in order to implement form.reset method. title.input.onChange('') @@ -78,7 +77,7 @@ export const SearchInsightCreationContent: FC // we should disable live chart preview const allFieldsForPreviewAreValid = repositories.meta.validState === 'VALID' && - (series.meta.validState === 'VALID' || editSeries.some(series => series.valid)) && + (series.meta.validState === 'VALID' || series.input.value.some(series => series.valid)) && stepValue.meta.validState === 'VALID' && // For the "all repositories" mode we are not able to show the live preview chart !allReposMode.input.value @@ -107,12 +106,7 @@ export const SearchInsightCreationContent: FC isFormClearActive={hasFilledValue} dashboardReferenceCount={initialValue?.dashboardReferenceCount} insight={insight} - onSeriesLiveChange={listen} onCancel={onCancel} - onEditSeriesRequest={editRequest} - onEditSeriesCancel={cancelEdit} - onEditSeriesCommit={editCommit} - onSeriesRemove={deleteSeries} onFormReset={handleFormReset} /> @@ -121,7 +115,7 @@ export const SearchInsightCreationContent: FC disabled={!allFieldsForPreviewAreValid} repositories={repositories.meta.value} isAllReposMode={allReposMode.input.value} - series={seriesToPreview(editSeries)} + series={seriesToPreview(series.input.value)} step={step.meta.value} stepValue={stepValue.meta.value} /> @@ -129,7 +123,7 @@ export const SearchInsightCreationContent: FC ) } -function seriesToPreview(currentSeries: EditableDataSeries[]): any { +function seriesToPreview(currentSeries: EditableDataSeries[]): LivePreviewSeries[] { const validSeries = currentSeries.filter(series => series.valid) return getSanitizedSeries(validSeries).map(series => ({ query: series.query, diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/helpers.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/helpers.ts deleted file mode 100644 index 0ba8cb152b9..00000000000 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/helpers.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Helper replace element in array by index and return new array. - * */ -export function replace(list: Element[], index: number, newElement: Element): Element[] { - return [...list.slice(0, index), newElement, ...list.slice(index + 1)] -} - -/** - * Helper remove element from array by index - * */ -export function remove(list: Element[], index: number): Element[] { - return [...list.slice(0, index), ...list.slice(index + 1)] -} diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form/use-insight-creation-form.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form.ts similarity index 83% rename from client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form/use-insight-creation-form.ts rename to client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form.ts index 46d9ccac371..9e4a406840a 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form/use-insight-creation-form.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/hooks/use-insight-creation-form.ts @@ -1,15 +1,22 @@ -import { useAsyncInsightTitleValidator } from '../../../../../../../../components/form/hooks/use-async-insight-title-validator' -import { useField, useFieldAPI } from '../../../../../../../../components/form/hooks/useField' -import { Form, FormChangeEvent, SubmissionErrors, useForm } from '../../../../../../../../components/form/hooks/useForm' -import { createRequiredValidator } from '../../../../../../../../components/form/validators' -import { CreateInsightFormFields, EditableDataSeries, InsightStep } from '../../../../types' -import { INITIAL_INSIGHT_VALUES } from '../../initial-insight-values' +import { + useAsyncInsightTitleValidator, + useField, + useFieldAPI, + Form, + FormChangeEvent, + SubmissionErrors, + useForm, + createRequiredValidator, + EditableDataSeries, +} from '../../../../../../../components' +import { CreateInsightFormFields, InsightStep } from '../../../types' +import { INITIAL_INSIGHT_VALUES } from '../initial-insight-values' import { repositoriesExistValidator, repositoriesFieldValidator, requiredStepValueField, seriesRequired, -} from '../../validators' +} from '../validators' const titleRequiredValidator = createRequiredValidator('Title is a required field.') diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/initial-insight-values.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/initial-insight-values.ts index 489e1ee3091..2e9d6362b45 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/initial-insight-values.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/initial-insight-values.ts @@ -1,7 +1,6 @@ +import { createDefaultEditSeries } from '../../../../../../components' import { CreateInsightFormFields } from '../../types' -import { createDefaultEditSeries } from './hooks/use-editable-series' - export const INITIAL_INSIGHT_VALUES: CreateInsightFormFields = { // If user opens the creation form to create insight // we want to show the series form as soon as possible diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/validators.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/validators.ts index c8c01aa2f13..933d8feacd4 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/validators.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/components/search-insight-creation-content/validators.ts @@ -1,12 +1,10 @@ import { renderError } from '@sourcegraph/branded/src/components/alerts' import { dedupeWhitespace } from '@sourcegraph/common' -import { getSanitizedRepositories } from '../../../../../../components/creation-ui-kit' +import { getSanitizedRepositories, createRequiredValidator, EditableDataSeries } from '../../../../../../components' import { Validator } from '../../../../../../components/form/hooks/useField' import { AsyncValidator } from '../../../../../../components/form/hooks/utils/use-async-validation' -import { createRequiredValidator } from '../../../../../../components/form/validators' import { fetchRepositories } from '../../../../../../core/backend/gql-backend/methods/get-built-in-insight-data/utils/fetch-repositories' -import { EditableDataSeries } from '../../types' export const repositoriesFieldValidator: Validator = value => { if (value !== undefined && dedupeWhitespace(value).trim() === '') { diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/index.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/index.ts index aa688b83a8a..f3c519e5f37 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/index.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/index.ts @@ -1,8 +1,6 @@ -export { DATA_SERIES_COLORS, DEFAULT_DATA_SERIES_COLOR } from './constants' - export { SearchInsightCreationPage } from './SearchInsightCreationPage' export { encodeSearchInsightUrl } from './utils/search-insight-url-parsers/search-insight-url-parsers' -export { getQueryPatternTypeFilter } from './components/form-series-input/get-pattern-type-filter' +export { getQueryPatternTypeFilter } from '../../../../components/creation-ui/form-series/components/form-series-input/get-pattern-type-filter' export type { SearchInsightURLValues } from './utils/search-insight-url-parsers/search-insight-url-parsers' -export type { CreateInsightFormFields, EditableDataSeries, InsightStep } from './types' +export type { CreateInsightFormFields, InsightStep } from './types' diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/types.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/types.ts index 0bed4964684..210081bc6e2 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/types.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/types.ts @@ -1,36 +1,21 @@ -import { SearchBasedInsightSeries } from '../../../../core' +import { EditableDataSeries } from '../../../../components/creation-ui/form-series/types' export type InsightStep = 'hours' | 'days' | 'weeks' | 'months' | 'years' -export interface EditableDataSeries extends SearchBasedInsightSeries { - valid: boolean - edit: boolean -} - export interface CreateInsightFormFields { - /** - * Code Insight series setting (name of line, line query, color) - */ + /** Code Insight series setting (name of line, line query, color) */ series: EditableDataSeries[] - /** - * Title of code insight - */ + /** Title of code insight */ title: string - /** - * Repositories which to be used to get the info for code insights - */ + /** Repositories which to be used to get the info for code insights */ repositories: string - /** - * Setting for set chart step - how often do we collect data. - */ + /** Setting for set chart step - how often do we collect data. */ step: InsightStep - /** - * Value for insight step setting - */ + /** Value for insight step setting */ stepValue: string /** @@ -39,8 +24,6 @@ export interface CreateInsightFormFields { */ allRepos: boolean - /** - * The total number of dashboards on which this insight is referenced. - */ + /** The total number of dashboards on which this insight is referenced. */ dashboardReferenceCount: number } diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/insight-sanitizer.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/insight-sanitizer.ts index 3aa2b8bccf1..adc1bf5e280 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/insight-sanitizer.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/insight-sanitizer.ts @@ -1,13 +1,13 @@ -import { getSanitizedRepositories } from '../../../../../components/creation-ui-kit' +import { getSanitizedRepositories } from '../../../../../components' import { MinimalSearchBasedInsightData, InsightExecutionType, InsightType, SearchBasedInsightSeries, } from '../../../../../core' -import { CreateInsightFormFields, EditableDataSeries } from '../types' +import { CreateInsightFormFields } from '../types' -export function getSanitizedLine(line: EditableDataSeries): SearchBasedInsightSeries { +export function getSanitizedLine(line: SearchBasedInsightSeries): SearchBasedInsightSeries { return { id: line.id, name: line.name.trim(), @@ -20,7 +20,7 @@ export function getSanitizedLine(line: EditableDataSeries): SearchBasedInsightSe } } -export function getSanitizedSeries(rawSeries: EditableDataSeries[]): SearchBasedInsightSeries[] { +export function getSanitizedSeries(rawSeries: SearchBasedInsightSeries[]): SearchBasedInsightSeries[] { return rawSeries.map(getSanitizedLine) } diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.test.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.test.ts index 2fdc1a20559..ebd444b2b96 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.test.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.test.ts @@ -27,8 +27,8 @@ describe('decodeSearchInsightUrl', () => { title: 'Insight title', allRepos: true, series: [ - { id: 1, edit: false, valid: true, name: 'series 1', query: 'test1', stroke: 'red' }, - { id: 2, edit: false, valid: true, name: 'series 2', query: 'test2', stroke: 'blue' }, + { id: 1, edit: false, valid: true, autofocus: false, name: 'series 1', query: 'test1', stroke: 'red' }, + { id: 2, edit: false, valid: true, autofocus: false, name: 'series 2', query: 'test2', stroke: 'blue' }, ], }) }) @@ -51,8 +51,24 @@ describe('encodeSearchInsightUrl', () => { title: 'Insight title', allRepos: true, series: [ - { id: '1', edit: false, valid: true, name: 'series 1', query: 'test1', stroke: 'red' }, - { id: '2', edit: false, valid: true, name: 'series 2', query: 'test2', stroke: 'blue' }, + { + id: '1', + edit: false, + valid: true, + autofocus: false, + name: 'series 1', + query: 'test1', + stroke: 'red', + }, + { + id: '2', + edit: false, + valid: true, + autofocus: false, + name: 'series 2', + query: 'test2', + stroke: 'blue', + }, ], }) }) diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.ts index 0f67d9dd340..7bb46d0842d 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/search-insight-url-parsers/search-insight-url-parsers.ts @@ -1,5 +1,5 @@ +import { createDefaultEditSeries } from '../../../../../../components' import { SearchBasedInsightSeries } from '../../../../../../core' -import { createDefaultEditSeries } from '../../components/search-insight-creation-content/hooks/use-editable-series' import { CreateInsightFormFields } from '../../types' export function decodeSearchInsightUrl(queryParameters: string): Partial | null { diff --git a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/use-url-query-insight/use-url-query-insight.ts b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/use-url-query-insight/use-url-query-insight.ts index d4920a27dca..af98ac259f0 100644 --- a/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/use-url-query-insight/use-url-query-insight.ts +++ b/client/web/src/enterprise/insights/pages/insights/creation/search-insight/utils/use-url-query-insight/use-url-query-insight.ts @@ -6,8 +6,8 @@ import { stringHuman } from '@sourcegraph/shared/src/search/query/printer' import { scanSearchQuery } from '@sourcegraph/shared/src/search/query/scanner' import { isFilterType, isRepoFilter } from '@sourcegraph/shared/src/search/query/validate' -import { CodeInsightsBackendContext } from '../../../../../../core/backend/code-insights-backend-context' -import { createDefaultEditSeries } from '../../components/search-insight-creation-content/hooks/use-editable-series' +import { createDefaultEditSeries } from '../../../../../../components' +import { CodeInsightsBackendContext } from '../../../../../../core' import { INITIAL_INSIGHT_VALUES } from '../../components/search-insight-creation-content/initial-insight-values' import { CreateInsightFormFields } from '../../types' diff --git a/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditCaptureGroupInsight.tsx b/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditCaptureGroupInsight.tsx index ac356b8df2e..21946bfa8c0 100644 --- a/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditCaptureGroupInsight.tsx +++ b/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditCaptureGroupInsight.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from 'react' -import { SubmissionErrors } from '../../../../components/form/hooks/useForm' +import { SubmissionErrors } from '../../../../components' import { MinimalCaptureGroupInsightData, CaptureGroupInsight } from '../../../../core' import { CaptureGroupFormFields } from '../../creation/capture-group' import { CaptureGroupCreationContent } from '../../creation/capture-group/components/CaptureGroupCreationContent' diff --git a/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditSearchInsight.tsx b/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditSearchInsight.tsx index af14df4882d..ee517be529b 100644 --- a/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditSearchInsight.tsx +++ b/client/web/src/enterprise/insights/pages/insights/edit-insight/components/EditSearchInsight.tsx @@ -1,9 +1,8 @@ import React, { useMemo } from 'react' -import { SubmissionErrors } from '../../../../components/form/hooks/useForm' +import { SubmissionErrors, createDefaultEditSeries } from '../../../../components' import { MinimalSearchBasedInsightData, SearchBasedInsight } from '../../../../core' import { CreateInsightFormFields, InsightStep } from '../../creation/search-insight' -import { createDefaultEditSeries } from '../../creation/search-insight/components/search-insight-creation-content/hooks/use-editable-series' import { SearchInsightCreationContent } from '../../creation/search-insight/components/search-insight-creation-content/SearchInsightCreationContent' import { getSanitizedSearchInsight } from '../../creation/search-insight/utils/insight-sanitizer' diff --git a/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-examples/examples.ts b/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-examples/examples.ts index 556523a7295..b670c7eef88 100644 --- a/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-examples/examples.ts +++ b/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-examples/examples.ts @@ -1,4 +1,4 @@ -import { DATA_SERIES_COLORS } from '../../../../insights/creation/search-insight' +import { DATA_SERIES_COLORS } from '../../../../../constants' import { CaptureGroupExampleContent, SearchInsightExampleContent } from './types' diff --git a/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-templates/constants.ts b/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-templates/constants.ts index 6e0337c2054..a7bf167354c 100644 --- a/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-templates/constants.ts +++ b/client/web/src/enterprise/insights/pages/landing/getting-started/components/code-insights-templates/constants.ts @@ -1,8 +1,9 @@ import { SettingsExperimentalFeatures } from '@sourcegraph/shared/src/schema/settings.schema' +import { DATA_SERIES_COLORS } from '../../../../../constants' import { InsightType } from '../../../../../core' import { CaptureInsightUrlValues } from '../../../../insights/creation/capture-group' -import { DATA_SERIES_COLORS, SearchInsightURLValues } from '../../../../insights/creation/search-insight' +import { SearchInsightURLValues } from '../../../../insights/creation/search-insight' export interface TemplateSection { title: string diff --git a/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicCodeInsightExample.tsx b/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicCodeInsightExample.tsx index 54aeadeb6dc..cb3552dc0fd 100644 --- a/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicCodeInsightExample.tsx +++ b/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicCodeInsightExample.tsx @@ -7,11 +7,13 @@ import { noop } from 'rxjs' import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService' import { Button, Card, Link, useObservable, useDebounce, Icon, Input, H2, H3, Text } from '@sourcegraph/wildcard' -import { getDefaultInputProps } from '../../../../../components/form/getDefaultInputProps' -import { useField } from '../../../../../components/form/hooks/useField' -import { useForm } from '../../../../../components/form/hooks/useForm' -import { InsightQueryInput } from '../../../../../components/form/query-input/InsightQueryInput' -import { RepositoriesField } from '../../../../../components/form/repositories-field/RepositoriesField' +import { + getDefaultInputProps, + useField, + useForm, + InsightQueryInput, + RepositoriesField, +} from '../../../../../components' import { CodeInsightsBackendContext } from '../../../../../core' import { getQueryPatternTypeFilter } from '../../../../insights/creation/search-insight' import { diff --git a/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicInsightPreview.tsx b/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicInsightPreview.tsx index e543851f20a..ba129be6b91 100644 --- a/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicInsightPreview.tsx +++ b/client/web/src/enterprise/insights/pages/landing/getting-started/components/dynamic-code-insight-example/DynamicInsightPreview.tsx @@ -5,8 +5,9 @@ import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryServi import { useDeepMemo } from '@sourcegraph/wildcard' import { useSeriesToggle } from '../../../../../../../insights/utils/use-series-toggle' -import { SeriesBasedChartTypes, SeriesChart } from '../../../../../components' import { + SeriesBasedChartTypes, + SeriesChart, getSanitizedRepositories, useLivePreview, StateStatus, @@ -18,16 +19,14 @@ import { LivePreviewBanner, LivePreviewLegend, SERIES_MOCK_CHART, -} from '../../../../../components/creation-ui-kit' -import { CodeInsightsBackendContext, SeriesChartContent } from '../../../../../core' +} from '../../../../../components' +import { DATA_SERIES_COLORS } from '../../../../../constants' +import { CodeInsightsBackendContext, SearchBasedInsightSeries, SeriesChartContent } from '../../../../../core' import { CodeInsightTrackType, useCodeInsightViewPings } from '../../../../../pings' -import { DATA_SERIES_COLORS, EditableDataSeries } from '../../../../insights/creation/search-insight' -const createExampleDataSeries = (query: string): EditableDataSeries[] => [ +const createExampleDataSeries = (query: string): SearchBasedInsightSeries[] => [ { query, - valid: true, - edit: false, id: '1', name: 'TODOs', stroke: DATA_SERIES_COLORS.ORANGE,