forked from opensearch-project/OpenSearch-Dashboards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Data Explorer] Migrate surrounding doc viewer to Flyout
In this PR: * separate context application and discover state. * allow view to register multiple redux slices * add surrounding flyout * restore original context application to surrounding flyout * restore and simplify the fetch logic from context application Issue Resolve opensearch-project#4231 opensearch-project#4230 Signed-off-by: ananzh <[email protected]>
- Loading branch information
Showing
35 changed files
with
1,937 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
src/plugins/discover/public/application/components/context/api/anchor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Any modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { i18n } from '@osd/i18n'; | ||
|
||
import { | ||
ISearchSource, | ||
OpenSearchQuerySortValue, | ||
IndexPattern, | ||
} from '../../../../../../data/public'; | ||
import { OpenSearchHitRecord } from './context'; | ||
|
||
export async function fetchAnchor( | ||
anchorId: string, | ||
indexPattern: IndexPattern, | ||
searchSource: ISearchSource, | ||
sort: OpenSearchQuerySortValue[] | ||
): Promise<OpenSearchHitRecord> { | ||
updateSearchSource(searchSource, anchorId, sort, indexPattern); | ||
|
||
const response = await searchSource.fetch(); | ||
const doc = response.hits?.hits?.[0]; | ||
|
||
if (!doc) { | ||
throw new Error( | ||
i18n.translate('discover.context.failedToLoadAnchorDocumentErrorDescription', { | ||
defaultMessage: 'Failed to load anchor document.', | ||
}) | ||
); | ||
} | ||
|
||
return { | ||
...doc, | ||
isAnchor: true, | ||
} as OpenSearchHitRecord; | ||
} | ||
|
||
export function updateSearchSource( | ||
searchSource: ISearchSource, | ||
anchorId: string, | ||
sort: OpenSearchQuerySortValue[], | ||
indexPattern: IndexPattern | ||
) { | ||
searchSource | ||
.setParent(undefined) | ||
.setField('index', indexPattern) | ||
.setField('version', true) | ||
.setField('size', 1) | ||
.setField('query', { | ||
query: { | ||
constant_score: { | ||
filter: { | ||
ids: { | ||
values: [anchorId], | ||
}, | ||
}, | ||
}, | ||
}, | ||
language: 'lucene', | ||
}) | ||
.setField('sort', sort); | ||
|
||
return searchSource; | ||
} |
133 changes: 133 additions & 0 deletions
133
src/plugins/discover/public/application/components/context/api/context.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Any modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { Filter, IndexPattern } from 'src/plugins/data/public'; | ||
import { reverseSortDir, SortDirection } from './utils/sorting'; | ||
import { extractNanos, convertIsoToMillis } from './utils/date_conversion'; | ||
import { fetchHitsInInterval } from './utils/fetch_hits_in_interval'; | ||
import { generateIntervals } from './utils/generate_intervals'; | ||
import { getOpenSearchQuerySearchAfter } from './utils/get_opensearch_query_search_after'; | ||
import { getOpenSearchQuerySort } from './utils/get_opensearch_query_sort'; | ||
import { getServices } from '../../../../opensearch_dashboards_services'; | ||
|
||
export enum SurrDocType { | ||
SUCCESSORS = 'successors', | ||
PREDECESSORS = 'predecessors', | ||
} | ||
export interface OpenSearchHitRecord { | ||
fields: Record<string, any>; | ||
sort: number[]; | ||
_source: Record<string, any>; | ||
_id: string; | ||
isAnchor?: boolean; | ||
} | ||
export type OpenSearchHitRecordList = OpenSearchHitRecord[]; | ||
|
||
const DAY_MILLIS = 24 * 60 * 60 * 1000; | ||
|
||
// look from 1 day up to 10000 days into the past and future | ||
const LOOKUP_OFFSETS = [0, 1, 7, 30, 365, 10000].map((days) => days * DAY_MILLIS); | ||
|
||
/** | ||
* Fetch successor or predecessor documents of a given anchor document | ||
* | ||
* @param {SurrDocType} type - `successors` or `predecessors` | ||
* @param {string} indexPatternId | ||
* @param {OpenSearchHitRecord} anchor - anchor record | ||
* @param {string} timeField - name of the timefield, that's sorted on | ||
* @param {string} tieBreakerField - name of the tie breaker, the 2nd sort field | ||
* @param {SortDirection} sortDir - direction of sorting | ||
* @param {number} size - number of records to retrieve | ||
* @param {Filter[]} filters - to apply in the query | ||
* @returns {Promise<object[]>} | ||
*/ | ||
|
||
export async function fetchSurroundingDocs( | ||
type: SurrDocType, | ||
indexPattern: IndexPattern, | ||
anchor: OpenSearchHitRecord, | ||
tieBreakerField: string, | ||
sortDir: SortDirection, | ||
size: number, | ||
filters: Filter[] | ||
) { | ||
if (typeof anchor !== 'object' || anchor === null || !size) { | ||
return []; | ||
} | ||
const timeField = indexPattern.timeFieldName!; | ||
const searchSource = await createSearchSource(indexPattern, filters); | ||
const sortDirToApply = type === 'successors' ? sortDir : reverseSortDir(sortDir); | ||
|
||
const nanos = indexPattern.isTimeNanosBased() ? extractNanos(anchor._source[timeField]) : ''; | ||
const timeValueMillis = | ||
nanos !== '' ? convertIsoToMillis(anchor._source[timeField]) : anchor.sort[0]; | ||
|
||
const intervals = generateIntervals(LOOKUP_OFFSETS, timeValueMillis, type, sortDir); | ||
let documents: OpenSearchHitRecordList = []; | ||
|
||
for (const interval of intervals) { | ||
const remainingSize = size - documents.length; | ||
|
||
if (remainingSize <= 0) { | ||
break; | ||
} | ||
|
||
const searchAfter = getOpenSearchQuerySearchAfter(type, documents, timeField, anchor, nanos); | ||
|
||
const sort = getOpenSearchQuerySort(timeField, tieBreakerField, sortDirToApply); | ||
|
||
const hits = await fetchHitsInInterval( | ||
searchSource, | ||
timeField, | ||
sort, | ||
sortDirToApply, | ||
interval, | ||
searchAfter, | ||
remainingSize, | ||
nanos, | ||
anchor._id | ||
); | ||
|
||
documents = | ||
type === 'successors' ? [...documents, ...hits] : [...hits.slice().reverse(), ...documents]; | ||
} | ||
|
||
return documents; | ||
} | ||
|
||
export async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) { | ||
const { data } = getServices(); | ||
|
||
const searchSource = await data.search.searchSource.create(); | ||
return searchSource | ||
.setParent(undefined) | ||
.setField('index', indexPattern) | ||
.setField('filter', filters); | ||
} |
43 changes: 43 additions & 0 deletions
43
src/plugins/discover/public/application/components/context/api/utils/date_conversion.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Any modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { extractNanos } from './date_conversion'; | ||
|
||
describe('function extractNanos', function () { | ||
test('extract nanos of 2014-01-01', function () { | ||
expect(extractNanos('2014-01-01')).toBe('000000000'); | ||
}); | ||
test('extract nanos of 2014-01-01T12:12:12.234Z', function () { | ||
expect(extractNanos('2014-01-01T12:12:12.234Z')).toBe('234000000'); | ||
}); | ||
test('extract nanos of 2014-01-01T12:12:12.234123321Z', function () { | ||
expect(extractNanos('2014-01-01T12:12:12.234123321Z')).toBe('234123321'); | ||
}); | ||
}); |
76 changes: 76 additions & 0 deletions
76
src/plugins/discover/public/application/components/context/api/utils/date_conversion.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
* | ||
* Any modifications Copyright OpenSearch Contributors. See | ||
* GitHub history for details. | ||
*/ | ||
|
||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import moment from 'moment'; | ||
/** | ||
* extract nanoseconds if available in ISO timestamp | ||
* returns the nanos as string like this: | ||
* 9ns -> 000000009 | ||
* 10000ns -> 0000010000 | ||
* returns 000000000 for invalid timestamps or timestamps with just date | ||
**/ | ||
export function extractNanos(timeFieldValue: string = ''): string { | ||
const fieldParts = timeFieldValue.split('.'); | ||
const fractionSeconds = fieldParts.length === 2 ? fieldParts[1].replace('Z', '') : ''; | ||
return fractionSeconds.length !== 9 ? fractionSeconds.padEnd(9, '0') : fractionSeconds; | ||
} | ||
|
||
/** | ||
* convert an iso formatted string to number of milliseconds since | ||
* 1970-01-01T00:00:00.000Z | ||
* @param {string} isoValue | ||
* @returns {number} | ||
*/ | ||
export function convertIsoToMillis(isoValue: string): number { | ||
const date = new Date(isoValue); | ||
return date.getTime(); | ||
} | ||
/** | ||
* the given time value in milliseconds is converted to a ISO formatted string | ||
* if nanosValue is provided, the given value replaces the fractional seconds part | ||
* of the formated string since moment.js doesn't support formatting timestamps | ||
* with a higher precision then microseconds | ||
* The browser rounds date nanos values: | ||
* 2019-09-18T06:50:12.999999999 -> browser rounds to 1568789413000000000 | ||
* 2019-09-18T06:50:59.999999999 -> browser rounds to 1568789460000000000 | ||
* 2017-12-31T23:59:59.999999999 -> browser rounds 1514761199999999999 to 1514761200000000000 | ||
*/ | ||
export function convertTimeValueToIso(timeValueMillis: number, nanosValue: string): string | null { | ||
if (!timeValueMillis) { | ||
return null; | ||
} | ||
const isoString = moment(timeValueMillis).toISOString(); | ||
if (!isoString) { | ||
return null; | ||
} else if (nanosValue !== '') { | ||
return `${isoString.substring(0, isoString.length - 4)}${nanosValue}Z`; | ||
} | ||
return isoString; | ||
} |
Oops, something went wrong.