[Discover] Fix 'auto' collapsing of documents (#89712) (#90120)

This commit is contained in:
Matthias Wilhelm 2021-02-03 09:53:11 +01:00 committed by GitHub
parent fbd503c5fa
commit 18e4f05a1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 88 deletions

View file

@ -14,69 +14,6 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { getServices, IIndexPattern } from '../../../kibana_services';
import { IndexPatternField } from '../../../../../data/common/index_patterns';
export type AngularScope = IScope;
export interface AngularDirective {
template: string;
}
/**
* Compiles and injects the give angular template into the given dom node
* returns a function to cleanup the injected angular element
*/
export async function injectAngularElement(
domNode: Element,
template: string,
scopeProps: any,
getInjector: () => Promise<auto.IInjectorService>
): Promise<() => void> {
const $injector = await getInjector();
const rootScope: AngularScope = $injector.get('$rootScope');
const $compile: ICompileService = $injector.get('$compile');
const newScope = Object.assign(rootScope.$new(), scopeProps);
const $target = angular.element(domNode);
const $element = angular.element(template);
newScope.$apply(() => {
const linkFn = $compile($element);
$target.empty().append($element);
linkFn(newScope);
});
return () => {
newScope.$destroy();
};
}
/**
* Converts a given legacy angular directive to a render function
* for usage in a react component. Note that the rendering is async
*/
export function convertDirectiveToRenderFn(
directive: AngularDirective,
getInjector: () => Promise<auto.IInjectorService>
) {
return (domNode: Element, props: any) => {
let rejected = false;
const cleanupFnPromise = injectAngularElement(domNode, directive.template, props, getInjector);
cleanupFnPromise.catch(() => {
rejected = true;
render(<div>error</div>, domNode);
});
return () => {
if (!rejected) {
// for cleanup
// http://roubenmeschian.com/rubo/?p=51
cleanupFnPromise.then((cleanup) => cleanup());
}
};
};
}
export interface DocTableLegacyProps {
columns: string[];
searchDescription?: string;
@ -94,37 +31,91 @@ export interface DocTableLegacyProps {
sort?: string[][];
useNewFieldsApi?: boolean;
}
export interface AngularDirective {
template: string;
}
export type AngularScope = IScope & { renderProps?: DocTableLegacyProps };
export function DocTableLegacy(renderProps: DocTableLegacyProps) {
const renderFn = convertDirectiveToRenderFn(
{
template: `<doc-table
columns="columns"
data-description="{{searchDescription}}"
/**
* Compiles and injects the give angular template into the given dom node
* returns a function to cleanup the injected angular element
*/
export async function injectAngularElement(
domNode: Element,
template: string,
renderProps: any,
injector: auto.IInjectorService
) {
const rootScope: IScope = injector.get('$rootScope');
const $compile: ICompileService = injector.get('$compile');
const newScope = Object.assign(rootScope.$new(), { renderProps });
const $target = angular.element(domNode);
const $element = angular.element(template);
newScope.$apply(() => {
const linkFn = $compile($element);
$target.empty().append($element);
linkFn(newScope);
});
return newScope;
}
function getRenderFn(domNode: Element, props: any) {
const directive = {
template: `<doc-table
columns="renderProps.columns"
data-description="{{renderProps.searchDescription}}"
data-shared-item
data-test-subj="discoverDocTable"
data-title="{{searchTitle}}"
filter="onFilter"
hits="rows"
index-pattern="indexPattern"
data-title="{{renderProps.searchTitle}}"
filter="renderProps.onFilter"
hits="renderProps.rows"
index-pattern="renderProps.indexPattern"
infinite-scroll="true"
minimum-visible-rows="minimumVisibleRows"
on-add-column="onAddColumn"
on-change-sort-order="onSort"
on-move-column="onMoveColumn"
on-remove-column="onRemoveColumn"
minimum-visible-rows="renderProps.minimumVisibleRows"
on-add-column="renderProps.onAddColumn"
on-change-sort-order="renderProps.onSort"
on-move-column="renderProps.onMoveColumn"
on-remove-column="renderProps.onRemoveColumn"
render-complete
use-new-fields-api="useNewFieldsApi"
sorting="sort"></doc_table>`,
},
() => getServices().getEmbeddableInjector()
);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (ref && ref.current) {
return renderFn(ref.current, renderProps);
use-new-fields-api="renderProps.useNewFieldsApi"
sorting="renderProps.sort"></doc_table>`,
};
return async () => {
try {
const injector = await getServices().getEmbeddableInjector();
return await injectAngularElement(domNode, directive.template, props, injector);
} catch (e) {
render(<div>error</div>, domNode);
}
}, [renderFn, renderProps]);
};
}
export function DocTableLegacy(renderProps: DocTableLegacyProps) {
const ref = useRef<HTMLDivElement>(null);
const scope = useRef<AngularScope | undefined>();
useEffect(() => {
if (ref && ref.current && !scope.current) {
const fn = getRenderFn(ref.current, renderProps);
fn().then((newScope) => {
scope.current = newScope;
});
} else if (scope && scope.current) {
scope.current.renderProps = renderProps;
scope.current.$apply();
}
}, [renderProps]);
useEffect(() => {
return () => {
if (scope.current) {
scope.current.$destroy();
}
};
}, []);
return (
<div>
<div ref={ref} />

View file

@ -59,6 +59,10 @@ export function createDocTableDirective(pagerFactory: any, $filter: any) {
$scope.limit += 50;
};
$scope.$watch('minimumVisibleRows', (minimumVisibleRows: number) => {
$scope.limit = Math.max(minimumVisibleRows || 50, $scope.limit || 50);
});
$scope.$watch('hits', (hits: any) => {
if (!hits) return;

View file

@ -15,6 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const docTable = getService('docTable');
const queryBar = getService('queryBar');
const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
const defaultSettings = {
defaultIndex: 'logstash-*',
@ -107,6 +108,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
// TODO: test something more meaninful here?
});
});
it('should not close the detail panel actions when data is re-requested', async function () {
await retry.try(async function () {
const nrOfFetches = await PageObjects.discover.getNrOfFetches();
await docTable.clickRowToggle({ isAnchorRow: false, rowIndex: rowToInspect - 1 });
const detailsEl = await docTable.getDetailsRows();
const defaultMessageEl = await detailsEl[0].findByTestSubject('docTableRowDetailsTitle');
expect(defaultMessageEl).to.be.ok();
await queryBar.submitQuery();
const nrOfFetchesResubmit = await PageObjects.discover.getNrOfFetches();
expect(nrOfFetchesResubmit).to.be.above(nrOfFetches);
const defaultMessageElResubmit = await detailsEl[0].findByTestSubject(
'docTableRowDetailsTitle'
);
expect(defaultMessageElResubmit).to.be.ok();
});
});
});
describe('add and remove columns', function () {