Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
403a32b
replace useEffect with observables as much as possible
mattkime Oct 1, 2022
27c1b86
Merge branch 'main' into refactor_data_view_create
mattkime Oct 1, 2022
1476c84
cleanup, fix timestamp field / allow hidden bug
mattkime Oct 2, 2022
ab39b4e
cleanup
mattkime Oct 2, 2022
cf2fcc1
Merge branch 'main' into refactor_data_view_create
mattkime Oct 2, 2022
c734834
fix highlighting for comma separated index patterns
mattkime Oct 2, 2022
dbc7d2e
fix jest test
mattkime Oct 2, 2022
32ee139
fix tests
mattkime Oct 2, 2022
3d2890b
getIsRollupIndex cleanup
mattkime Oct 7, 2022
6f771ea
revert showHidden flag for field caps
mattkime Oct 7, 2022
2a12a3e
type fix
mattkime Oct 7, 2022
e2814b4
cleanup, fix timestamp selection
mattkime Oct 7, 2022
989d652
add comments
mattkime Oct 7, 2022
159440e
Merge branch 'main' into refactor_data_view_create
mattkime Oct 7, 2022
c3d7c0f
transition business logic to service
mattkime Oct 7, 2022
30763f8
type fix
mattkime Oct 8, 2022
2d7544b
update limits
mattkime Oct 8, 2022
d8c5bdd
Merge branch 'main' into refactor_data_view_create
mattkime Oct 8, 2022
fc32839
remove comment
mattkime Oct 8, 2022
e350211
Merge branch 'main' into refactor_data_view_create
mattkime Oct 10, 2022
8bd2cd0
Merge branch 'main' into refactor_data_view_create
flash1293 Oct 10, 2022
d612886
reduce limits entry
mattkime Oct 10, 2022
21a5da5
Merge branch 'main' into refactor_data_view_create
mattkime Oct 10, 2022
7059c53
Merge branch 'main' into refactor_data_view_create
mattkime Oct 10, 2022
833ca22
async load service, no stale state, fix timestamp field default
mattkime Oct 10, 2022
5f3ee43
Merge branch 'refactor_data_view_create' of github.com:mattkime/kiban…
mattkime Oct 10, 2022
ae32bf2
debounce network requests
mattkime Oct 11, 2022
418a438
Merge branch 'main' into refactor_data_view_create
mattkime Oct 11, 2022
1015195
remove unneeded use of dedupe
mattkime Oct 12, 2022
06318bc
Merge branch 'refactor_data_view_create' of github.com:mattkime/kiban…
mattkime Oct 12, 2022
180008c
Merge branch 'main' into refactor_data_view_create
mattkime Oct 12, 2022
1a44ee1
account for failed requests, improve async code
mattkime Oct 12, 2022
245559d
Merge branch 'main' into refactor_data_view_create
mattkime Oct 14, 2022
0625a98
Merge branch 'main' into refactor_data_view_create
mattkime Oct 17, 2022
ec81f4b
fix edit data view
mattkime Oct 17, 2022
6f1ef8c
Merge branch 'refactor_data_view_create' of github.com:mattkime/kiban…
mattkime Oct 17, 2022
f109e9e
fix functional test
mattkime Oct 17, 2022
c00ef54
Merge branch 'main' into refactor_data_view_create
mattkime Oct 17, 2022
c1d4964
Merge branch 'main' into refactor_data_view_create
mattkime Oct 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import { EuiLoadingSpinner } from '@elastic/eui';

import { DataViewEditorProps } from '../types';

const IndexPatternFlyoutContentContainer = lazy(
() => import('./data_view_flyout_content_container')
);
const DataViewFlyoutContentContainer = lazy(() => import('./data_view_flyout_content_container'));

export const DataViewEditorLazy = (props: DataViewEditorProps) => (
<Suspense fallback={<EuiLoadingSpinner size="xl" />}>
<IndexPatternFlyoutContentContainer {...props} />
<DataViewFlyoutContentContainer {...props} />
</Suspense>
);
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ import { i18n } from '@kbn/i18n';
import { DataViewSpec, useKibana } from '../shared_imports';
import { IndexPatternEditorFlyoutContent } from './data_view_editor_flyout_content';
import { DataViewEditorContext, DataViewEditorProps } from '../types';
import { DataViewEditorService } from '../data_view_editor_service';

const IndexPatternFlyoutContentContainer = ({
// @ts-ignore
export const DataViewEditorServiceContext = React.createContext<{
dataViewEditorService: DataViewEditorService;
}>();

const DataViewFlyoutContentContainer = ({
onSave,
onCancel = () => {},
defaultTypeIsRollup,
Expand All @@ -23,7 +29,7 @@ const IndexPatternFlyoutContentContainer = ({
showManagementLink,
}: DataViewEditorProps) => {
const {
services: { dataViews, notifications },
services: { dataViews, notifications, http },
} = useKibana<DataViewEditorContext>();

const onSaveClick = async (dataViewSpec: DataViewSpec, persist: boolean = true) => {
Expand Down Expand Up @@ -63,17 +69,21 @@ const IndexPatternFlyoutContentContainer = ({
};

return (
<IndexPatternEditorFlyoutContent
onSave={onSaveClick}
onCancel={onCancel}
defaultTypeIsRollup={defaultTypeIsRollup}
requireTimestampField={requireTimestampField}
editData={editData}
showManagementLink={showManagementLink}
allowAdHoc={allowAdHocDataView || false}
/>
<DataViewEditorServiceContext.Provider
value={{ dataViewEditorService: new DataViewEditorService(http, dataViews) }}
>
<IndexPatternEditorFlyoutContent
onSave={onSaveClick}
onCancel={onCancel}
defaultTypeIsRollup={defaultTypeIsRollup}
requireTimestampField={requireTimestampField}
editData={editData}
showManagementLink={showManagementLink}
allowAdHoc={allowAdHocDataView || false}
/>
</DataViewEditorServiceContext.Provider>
);
};

/* eslint-disable import/no-default-export */
export default IndexPatternFlyoutContentContainer;
export default DataViewFlyoutContentContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
import React, { ChangeEvent, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { BehaviorSubject } from 'rxjs';
import useObservable from 'react-use/lib/useObservable';
import {
DataView,
UseField,
ValidationConfig,
FieldConfig,
Expand All @@ -20,8 +21,7 @@ import { IndexPatternConfig } from '../../types';
import { schema } from '../form_schema';

interface NameFieldProps {
editData?: DataView;
existingDataViewNames: string[];
existingDataViewNames$: BehaviorSubject<string[]>;
}

interface GetNameConfigArgs {
Expand Down Expand Up @@ -53,13 +53,14 @@ const getNameConfig = ({ namesNotAllowed }: GetNameConfigArgs): FieldConfig<stri
};
};

export const NameField = ({ editData, existingDataViewNames }: NameFieldProps) => {
export const NameField = ({ existingDataViewNames$ }: NameFieldProps) => {
const namesNotAllowed = useObservable(existingDataViewNames$, []);
const config = useMemo(
() =>
getNameConfig({
namesNotAllowed: existingDataViewNames,
namesNotAllowed,
}),
[existingDataViewNames]
[namesNotAllowed]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';

import useObservable from 'react-use/lib/useObservable';
import { BehaviorSubject, Subject } from 'rxjs';
import { EuiFormRow, EuiComboBox, EuiFormHelpText, EuiComboBoxOptionOption } from '@elastic/eui';
import { matchedIndiciesDefault } from '../data_view_editor_flyout_content';

import {
UseField,
Expand All @@ -18,17 +20,17 @@ import {
getFieldValidityAndErrorMessage,
} from '../../shared_imports';

import { TimestampOption } from '../../types';
import { TimestampOption, MatchedIndicesSet } from '../../types';
import { schema } from '../form_schema';

interface Props {
options: TimestampOption[];
isLoadingOptions: boolean;
isLoadingMatchedIndices: boolean;
hasMatchedIndices: boolean;
options$: Subject<TimestampOption[]>;
isLoadingOptions$: BehaviorSubject<boolean>;
isLoadingMatchedIndices$: BehaviorSubject<boolean>;
matchedIndices$: Subject<MatchedIndicesSet>;
}

const requireTimestampOptionValidator = (options: Props['options']): ValidationConfig => ({
const requireTimestampOptionValidator = (options: TimestampOption[]): ValidationConfig => ({
validator: async ({ value }) => {
const isValueRequired = !!options.length;
if (isValueRequired && !value) {
Expand All @@ -45,7 +47,7 @@ const requireTimestampOptionValidator = (options: Props['options']): ValidationC
});

const getTimestampConfig = (
options: Props['options']
options: TimestampOption[]
): FieldConfig<EuiComboBoxOptionOption<string>> => {
const timestampFieldConfig = schema.timestampField;

Expand All @@ -70,15 +72,22 @@ const timestampFieldHelp = i18n.translate('indexPatternEditor.editor.form.timeFi
});

export const TimestampField = ({
options = [],
isLoadingOptions = false,
isLoadingMatchedIndices,
hasMatchedIndices,
options$,
isLoadingOptions$,
isLoadingMatchedIndices$,
matchedIndices$,
}: Props) => {
const options = useObservable<TimestampOption[]>(options$, []);
const isLoadingOptions = useObservable<boolean>(isLoadingOptions$, false);
const isLoadingMatchedIndices = useObservable<boolean>(isLoadingMatchedIndices$, false);
const hasMatchedIndices = !!useObservable(matchedIndices$, matchedIndiciesDefault)
.exactMatchedIndices.length;

const optionsAsComboBoxOptions = options.map(({ display, fieldName }) => ({
label: display,
value: fieldName,
}));

const timestampConfig = useMemo(() => getTimestampConfig(options), [options]);
const selectTimestampHelp = options.length ? timestampFieldHelp : '';

Expand All @@ -98,8 +107,12 @@ export const TimestampField = ({

const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field);
const isDisabled = !optionsAsComboBoxOptions.length;
// if the value isn't in the list then don't use it.
const valueInList = !!optionsAsComboBoxOptions.find(
(option) => option.value === value.value
);

if (!value && !isDisabled) {
if ((!value || !valueInList) && !isDisabled) {
const val = optionsAsComboBoxOptions.filter((el) => el.value === '@timestamp');
if (val.length) {
setValue(val[0]);
Expand All @@ -124,7 +137,7 @@ export const TimestampField = ({
)}
singleSelection={{ asPlainText: true }}
options={optionsAsComboBoxOptions}
selectedOptions={value ? [value] : undefined}
selectedOptions={value && valueInList ? [value] : undefined}
onChange={(newValue) => {
if (newValue.length === 0) {
// Don't allow clearing the type. One must always be selected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import React, { ChangeEvent, useState, useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { Subject } from 'rxjs';
import useObservable from 'react-use/lib/useObservable';
import { MatchedItem } from '@kbn/data-views-plugin/public';
import {
UseField,
Expand All @@ -19,6 +21,7 @@ import {
import { canAppendWildcard, removeSpaces } from '../../lib';
import { schema } from '../form_schema';
import { RollupIndicesCapsResponse, IndexPatternConfig, MatchedIndicesSet } from '../../types';
import { matchedIndiciesDefault } from '../data_view_editor_flyout_content';

interface RefreshMatchedIndicesResult {
matchedIndicesResult: MatchedIndicesSet;
Expand All @@ -27,7 +30,7 @@ interface RefreshMatchedIndicesResult {

interface TitleFieldProps {
isRollup: boolean;
matchedIndices: MatchedItem[];
matchedIndices$: Subject<MatchedIndicesSet>;
rollupIndicesCapabilities: RollupIndicesCapsResponse;
refreshMatchedIndices: (title: string) => Promise<RefreshMatchedIndicesResult>;
}
Expand Down Expand Up @@ -134,11 +137,12 @@ const getTitleConfig = ({

export const TitleField = ({
isRollup,
matchedIndices,
matchedIndices$,
rollupIndicesCapabilities,
refreshMatchedIndices,
}: TitleFieldProps) => {
const [appendedWildcard, setAppendedWildcard] = useState<boolean>(false);
const matchedIndices = useObservable(matchedIndices$, matchedIndiciesDefault).exactMatchedIndices;

const fieldConfig = useMemo(
() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,35 @@ export class IndicesList extends React.Component<IndicesListProps, IndicesListSt
}

highlightIndexName(indexName: string, query: string) {
const queryIdx = indexName.indexOf(query);
if (!query || queryIdx === -1) {
if (!query) {
return indexName;
}

const preStr = indexName.substr(0, queryIdx);
const postStr = indexName.substr(queryIdx + query.length);
const queryAsArray = query.split(',').map((q) => q.trim());
let queryIdx = -1;
let queryWithoutWildcard = '';
for (let i = 0; i < queryAsArray.length; i++) {
const queryComponent = queryAsArray[i];
queryWithoutWildcard = queryComponent.endsWith('*')
? queryComponent.substring(0, queryComponent.length - 1)
: queryComponent;
queryIdx = indexName.indexOf(queryWithoutWildcard);

if (queryIdx !== -1) {
break;
}
}
if (queryIdx === -1) {
return indexName;
}

const preStr = indexName.substring(0, queryIdx);
const postStr = indexName.substr(queryIdx + queryWithoutWildcard.length);

return (
<span>
{preStr}
<strong>{query}</strong>
<strong>{queryWithoutWildcard}</strong>
{postStr}
</span>
);
Expand All @@ -164,15 +181,11 @@ export class IndicesList extends React.Component<IndicesListProps, IndicesListSt
render() {
const { indices, query, ...rest } = this.props;

const queryWithoutWildcard = query.endsWith('*') ? query.substr(0, query.length - 1) : query;

const paginatedIndices = indices.slice(this.pager.firstItemIndex, this.pager.lastItemIndex + 1);
const rows = paginatedIndices.map((index, key) => {
return (
<EuiTableRow key={key}>
<EuiTableRowCell>
{this.highlightIndexName(index.name, queryWithoutWildcard)}
</EuiTableRowCell>
<EuiTableRowCell>{this.highlightIndexName(index.name, query)}</EuiTableRowCell>
<EuiTableRowCell>
{index.tags.map((tag: Tag) => {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@

import React from 'react';
import { EuiSpacer } from '@elastic/eui';
import useObservable from 'react-use/lib/useObservable';
import { Subject } from 'rxjs';
import { INDEX_PATTERN_TYPE } from '@kbn/data-views-plugin/public';
import { StatusMessage } from './status_message';
import { IndicesList } from './indices_list';
import { matchedIndiciesDefault } from '../data_view_editor_flyout_content';

import { MatchedIndicesSet } from '../../types';

interface Props {
type: INDEX_PATTERN_TYPE;
allowHidden: boolean;
title: string;
matched: MatchedIndicesSet;
matchedIndices$: Subject<MatchedIndicesSet>;
}

export const PreviewPanel = ({ type, allowHidden, title = '', matched }: Props) => {
export const PreviewPanel = ({ type, allowHidden, title = '', matchedIndices$ }: Props) => {
const matched = useObservable(matchedIndices$, matchedIndiciesDefault);
const indicesListContent =
matched.visibleIndices.length || matched.allIndices.length ? (
<>
Expand Down
Loading