mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Reporting/fix csv download with scroll duration auto (#178047)
A bugfix/refactoring part of https://github.com/elastic/kibana/issues/164104 ## Summary This PR prevents an exception that happens with CSV download when the `xpack.reporting.csv.scroll.duration: auto` configuration is set. Steps to reproduce: 1. Use `xpack.reporting.csv.scroll.duration: auto` in kibana.yml 2. Attempt CSV download from a dashboard search panel. **Before**  **After**  ## Other changes * Move `get_panel_action` to the `kbn-reporting/public` package. * Update unit test ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b051cc163d
commit
152423691a
13 changed files with 200 additions and 60 deletions
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CsvGenerator } from '@kbn/generate-csv';
|
||||
|
||||
jest.mock('@kbn/generate-csv', () => {
|
||||
return {
|
||||
CsvGenerator: jest.fn().mockImplementation(() => {
|
||||
return { generateData: jest.fn() };
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
import { httpServerMock } from '@kbn/core-http-server-mocks';
|
||||
import type { CoreStart, KibanaRequest } from '@kbn/core/server';
|
||||
import { coreMock, elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import { dataPluginMock } from '@kbn/data-plugin/server/mocks';
|
||||
import { discoverPluginMock } from '@kbn/discover-plugin/server/mocks';
|
||||
import { createFieldFormatsStartMock } from '@kbn/field-formats-plugin/server/mocks';
|
||||
import { createMockConfigSchema } from '@kbn/reporting-mocks-server';
|
||||
import { setFieldFormats } from '@kbn/reporting-server';
|
||||
import type { Writable } from 'stream';
|
||||
|
||||
import { CsvSearchSourceImmediateExportType } from '.';
|
||||
import { ReportingRequestHandlerContext } from './types';
|
||||
|
||||
const mockLogger = loggingSystemMock.createLogger();
|
||||
const encryptionKey = 'tetkey';
|
||||
let stream: jest.Mocked<Writable>;
|
||||
let mockCsvSearchSourceImmediateExportType: CsvSearchSourceImmediateExportType;
|
||||
let mockCoreStart: CoreStart;
|
||||
let mockRequest: KibanaRequest<any, any, any, any>;
|
||||
let mockRequestHandlerContext: ReportingRequestHandlerContext;
|
||||
|
||||
beforeEach(async () => {
|
||||
// use fieldFormats plugin for csv formats
|
||||
// normally, this is done in the Reporting plugin
|
||||
setFieldFormats(createFieldFormatsStartMock());
|
||||
stream = {} as typeof stream;
|
||||
|
||||
const configType = createMockConfigSchema({
|
||||
encryptionKey,
|
||||
csv: {
|
||||
checkForFormulas: true,
|
||||
escapeFormulaValues: true,
|
||||
maxSizeBytes: 180000,
|
||||
scroll: { size: 500, duration: 'auto' },
|
||||
},
|
||||
});
|
||||
const mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
const context = coreMock.createPluginInitializerContext(configType);
|
||||
mockRequest = httpServerMock.createKibanaRequest();
|
||||
|
||||
mockCsvSearchSourceImmediateExportType = new CsvSearchSourceImmediateExportType(
|
||||
mockCoreSetup,
|
||||
configType,
|
||||
mockLogger,
|
||||
context
|
||||
);
|
||||
|
||||
mockRequestHandlerContext = {
|
||||
core: Promise.resolve(mockCoreStart),
|
||||
} as unknown as ReportingRequestHandlerContext;
|
||||
|
||||
mockCsvSearchSourceImmediateExportType.setup({
|
||||
basePath: { set: jest.fn() },
|
||||
});
|
||||
|
||||
mockCsvSearchSourceImmediateExportType.start({
|
||||
esClient: elasticsearchServiceMock.createClusterClient(),
|
||||
savedObjects: mockCoreStart.savedObjects,
|
||||
uiSettings: mockCoreStart.uiSettings,
|
||||
discover: discoverPluginMock.createStartContract(),
|
||||
data: dataPluginMock.createStartContract(),
|
||||
});
|
||||
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(1630526670000);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('allows csv.scroll.duration to be "auto"', async () => {
|
||||
const mockGenerateData = jest.fn().mockResolvedValue(() => ({ csv_contains_formulas: false }));
|
||||
(CsvGenerator as jest.Mock).mockImplementationOnce(() => {
|
||||
return { generateData: mockGenerateData };
|
||||
});
|
||||
|
||||
await mockCsvSearchSourceImmediateExportType.runTask(
|
||||
'cool-job-id',
|
||||
{ browserTimezone: 'US/Alaska', searchSource: {}, title: 'Test Search' },
|
||||
mockRequestHandlerContext,
|
||||
stream,
|
||||
mockRequest
|
||||
);
|
||||
|
||||
expect(CsvGenerator).toBeCalledWith(
|
||||
{
|
||||
browserTimezone: 'US/Alaska',
|
||||
objectType: 'immediate-search',
|
||||
searchSource: {},
|
||||
title: 'Test Search',
|
||||
},
|
||||
{
|
||||
checkForFormulas: true,
|
||||
escapeFormulaValues: true,
|
||||
maxSizeBytes: 180000,
|
||||
scroll: { duration: 'auto', size: 500 },
|
||||
},
|
||||
{
|
||||
retryAt: new Date('2021-09-01T20:06:30.000Z'),
|
||||
startedAt: new Date('2021-09-01T20:04:30.000Z'),
|
||||
},
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(mockGenerateData).toBeCalled();
|
||||
});
|
|
@ -20,6 +20,7 @@ import {
|
|||
LICENSE_TYPE_GOLD,
|
||||
LICENSE_TYPE_PLATINUM,
|
||||
LICENSE_TYPE_TRIAL,
|
||||
durationToNumber,
|
||||
} from '@kbn/reporting-common';
|
||||
import type { TaskRunResult } from '@kbn/reporting-common/types';
|
||||
import {
|
||||
|
@ -108,7 +109,17 @@ export class CsvSearchSourceImmediateExportType extends ExportType<
|
|||
};
|
||||
const cancellationToken = new CancellationToken();
|
||||
const csvConfig = this.config.csv;
|
||||
const taskInstanceFields = { startedAt: null, retryAt: null };
|
||||
const taskInstanceFields =
|
||||
csvConfig.scroll.duration === 'auto'
|
||||
? {
|
||||
startedAt: new Date(),
|
||||
retryAt: new Date(Date.now() + durationToNumber(this.config.queue.timeout)),
|
||||
}
|
||||
: {
|
||||
startedAt: null,
|
||||
retryAt: null,
|
||||
};
|
||||
|
||||
const csv = new CsvGenerator(
|
||||
job,
|
||||
csvConfig,
|
||||
|
|
|
@ -27,5 +27,6 @@
|
|||
"@kbn/reporting-mocks-server",
|
||||
"@kbn/core-http-request-handler-context-server",
|
||||
"@kbn/field-formats-plugin",
|
||||
"@kbn/core-http-server-mocks",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,4 +9,5 @@
|
|||
export { getSharedComponents } from './shared';
|
||||
export { reportingScreenshotShareProvider } from './share_context_menu/register_pdf_png_reporting';
|
||||
export { reportingCsvShareProvider } from './share_context_menu/register_csv_reporting';
|
||||
export { ReportingCsvPanelAction } from './panel_actions/get_csv_panel_action';
|
||||
export type { ReportingPublicComponents } from './shared/get_shared_components';
|
||||
|
|
|
@ -1,24 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import * as Rx from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import type { SearchSource } from '@kbn/data-plugin/common';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import { LicenseCheckState } from '@kbn/licensing-plugin/public';
|
||||
import { coreMock } from '@kbn/core/public/mocks';
|
||||
import type { SearchSource } from '@kbn/data-plugin/common';
|
||||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
|
||||
import type { ReportingPublicPluginStartDependencies } from '../plugin';
|
||||
import type { ActionContext } from './get_csv_panel_action';
|
||||
import { ReportingCsvPanelAction } from './get_csv_panel_action';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { ReportingAPIClient } from '@kbn/reporting-public';
|
||||
import { LicenseCheckState } from '@kbn/licensing-plugin/public';
|
||||
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import { ReportingAPIClient } from '../..';
|
||||
import {
|
||||
ActionContext,
|
||||
type PanelActionDependencies,
|
||||
ReportingCsvPanelAction,
|
||||
} from './get_csv_panel_action';
|
||||
|
||||
const core = coreMock.createSetup();
|
||||
let apiClient: ReportingAPIClient;
|
||||
|
@ -27,7 +30,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
let context: ActionContext;
|
||||
let mockLicenseState: LicenseCheckState;
|
||||
let mockSearchSource: SearchSource;
|
||||
let mockStartServicesPayload: [CoreStart, ReportingPublicPluginStartDependencies, unknown];
|
||||
let mockStartServicesPayload: [CoreStart, PanelActionDependencies, unknown];
|
||||
let mockStartServices$: Rx.Observable<typeof mockStartServicesPayload>;
|
||||
|
||||
const mockLicense$ = () => {
|
||||
|
@ -65,7 +68,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
{
|
||||
data: dataPluginMock.createStartContract(),
|
||||
licensing: { ...licensingMock.createStart(), license$: mockLicense$() },
|
||||
} as unknown as ReportingPublicPluginStartDependencies,
|
||||
} as unknown as PanelActionDependencies,
|
||||
null,
|
||||
];
|
||||
mockStartServices$ = Rx.from(Promise.resolve(mockStartServicesPayload));
|
||||
|
@ -106,7 +109,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
await panel.execute(context);
|
||||
|
||||
|
@ -142,7 +145,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
await panel.execute(context);
|
||||
|
||||
|
@ -164,7 +167,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
await panel.execute(context);
|
||||
|
||||
|
@ -179,7 +182,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
await panel.execute(context);
|
||||
|
||||
|
@ -196,7 +199,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
await panel.execute(context);
|
||||
|
||||
|
@ -213,7 +216,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
expect(await plugin.isCompatible(context)).toEqual(false);
|
||||
});
|
||||
|
||||
|
@ -225,10 +228,10 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
expect(panel.getIconType()).toMatchInlineSnapshot(`"document"`);
|
||||
expect(panel.getDisplayName()).toMatchInlineSnapshot(`"Download CSV"`);
|
||||
expect(panel.getIconType()).toBe('document');
|
||||
expect(panel.getDisplayName()).toBe('Download CSV');
|
||||
});
|
||||
|
||||
describe('Application UI Capabilities', () => {
|
||||
|
@ -241,7 +244,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
expect(await plugin.isCompatible(context)).toEqual(false);
|
||||
});
|
||||
|
@ -254,7 +257,7 @@ describe('GetCsvReportPanelAction', () => {
|
|||
usesUiCapabilities: true,
|
||||
});
|
||||
|
||||
await mockStartServices$.pipe(first()).toPromise();
|
||||
await Rx.firstValueFrom(mockStartServices$);
|
||||
|
||||
expect(await plugin.isCompatible(context)).toEqual(true);
|
||||
});
|
|
@ -1,26 +1,28 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, NotificationsSetup } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
|
||||
import type { CoreSetup, NotificationsSetup } from '@kbn/core/public';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { ISearchEmbeddable } from '@kbn/discover-plugin/public';
|
||||
import { loadSharingDataHelpers, SEARCH_EMBEDDABLE_TYPE } from '@kbn/discover-plugin/public';
|
||||
import type { IEmbeddable } from '@kbn/embeddable-plugin/public';
|
||||
import { ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { CSV_REPORTING_ACTION } from '@kbn/reporting-export-types-csv-common';
|
||||
import { LicensingPluginStart } from '@kbn/licensing-plugin/public';
|
||||
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import type { UiActionsActionDefinition as ActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
import { ReportingAPIClient, checkLicense } from '@kbn/reporting-public';
|
||||
import type { ReportingPublicPluginStartDependencies } from '../plugin';
|
||||
import { CSV_REPORTING_ACTION } from '@kbn/reporting-export-types-csv-common';
|
||||
import { checkLicense } from '../../license_check';
|
||||
import { ReportingAPIClient } from '../../reporting_api_client';
|
||||
|
||||
function isSavedSearchEmbeddable(
|
||||
embeddable: IEmbeddable | ISearchEmbeddable
|
||||
|
@ -32,10 +34,15 @@ export interface ActionContext {
|
|||
embeddable: ISearchEmbeddable;
|
||||
}
|
||||
|
||||
export interface PanelActionDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
licensing: LicensingPluginStart;
|
||||
}
|
||||
|
||||
interface Params {
|
||||
apiClient: ReportingAPIClient;
|
||||
core: CoreSetup;
|
||||
startServices$: Observable<[CoreStart, ReportingPublicPluginStartDependencies, unknown]>;
|
||||
startServices$: Observable<[CoreStart, PanelActionDependencies, unknown]>;
|
||||
usesUiCapabilities: boolean;
|
||||
}
|
||||
|
||||
|
@ -63,7 +70,7 @@ export class ReportingCsvPanelAction implements ActionDefinition<ActionContext>
|
|||
}
|
||||
|
||||
public getDisplayName() {
|
||||
return i18n.translate('xpack.reporting.dashboard.downloadCsvPanelTitle', {
|
||||
return i18n.translate('reporting.share.panelAction.generateCsvPanelTitle', {
|
||||
defaultMessage: 'Download CSV',
|
||||
});
|
||||
}
|
||||
|
@ -131,10 +138,10 @@ export class ReportingCsvPanelAction implements ActionDefinition<ActionContext>
|
|||
this.isDownloading = true;
|
||||
|
||||
this.notifications.toasts.addSuccess({
|
||||
title: i18n.translate('xpack.reporting.dashboard.csvDownloadStartedTitle', {
|
||||
title: i18n.translate('reporting.share.panelAction.csvDownloadStartedTitle', {
|
||||
defaultMessage: `CSV Download Started`,
|
||||
}),
|
||||
text: i18n.translate('xpack.reporting.dashboard.csvDownloadStartedMessage', {
|
||||
text: i18n.translate('reporting.share.panelAction.csvDownloadStartedMessage', {
|
||||
defaultMessage: `Your CSV will download momentarily.`,
|
||||
}),
|
||||
'data-test-subj': 'csvDownloadStarted',
|
||||
|
@ -173,10 +180,10 @@ export class ReportingCsvPanelAction implements ActionDefinition<ActionContext>
|
|||
private onGenerationFail(_error: Error) {
|
||||
this.isDownloading = false;
|
||||
this.notifications.toasts.addDanger({
|
||||
title: i18n.translate('xpack.reporting.dashboard.failedCsvDownloadTitle', {
|
||||
title: i18n.translate('reporting.share.panelAction.failedCsvReportTitle', {
|
||||
defaultMessage: `CSV download failed`,
|
||||
}),
|
||||
text: i18n.translate('xpack.reporting.dashboard.failedCsvDownloadMessage', {
|
||||
text: i18n.translate('reporting.share.panelAction.failedCsvReportMessage', {
|
||||
defaultMessage: `We couldn't generate your CSV at this time.`,
|
||||
}),
|
||||
'data-test-subj': 'downloadCsvFail',
|
|
@ -30,5 +30,10 @@
|
|||
"@kbn/screenshotting-plugin",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/test-jest-helpers",
|
||||
"@kbn/discover-utils",
|
||||
"@kbn/saved-search-plugin",
|
||||
"@kbn/discover-plugin",
|
||||
"@kbn/embeddable-plugin",
|
||||
"@kbn/ui-actions-plugin",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
"screenshotting"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"discover",
|
||||
"embeddable",
|
||||
"esUiShared",
|
||||
"kibanaReact"
|
||||
|
|
|
@ -22,21 +22,21 @@ import { i18n } from '@kbn/i18n';
|
|||
import type { LicensingPluginStart } from '@kbn/licensing-plugin/public';
|
||||
import type { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
|
||||
import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public';
|
||||
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
import { durationToNumber } from '@kbn/reporting-common';
|
||||
import type { ClientConfigType } from '@kbn/reporting-public';
|
||||
import { ReportingAPIClient } from '@kbn/reporting-public';
|
||||
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
|
||||
import {
|
||||
ReportingCsvPanelAction,
|
||||
getSharedComponents,
|
||||
reportingCsvShareProvider,
|
||||
reportingScreenshotShareProvider,
|
||||
} from '@kbn/reporting-public/share';
|
||||
import type { ReportingSetup, ReportingStart } from '.';
|
||||
import { ReportingNotifierStreamHandler as StreamHandler } from './lib/stream_handler';
|
||||
import { ReportingCsvPanelAction } from './panel_actions/get_csv_panel_action';
|
||||
|
||||
export interface ReportingPublicPluginSetupDependencies {
|
||||
home: HomePublicPluginSetup;
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
"@kbn/core-test-helpers-test-utils",
|
||||
"@kbn/safer-lodash-set",
|
||||
"@kbn/reporting-common",
|
||||
"@kbn/saved-search-plugin",
|
||||
"@kbn/core-http-router-server-internal",
|
||||
"@kbn/reporting-public",
|
||||
"@kbn/reporting-server",
|
||||
|
@ -50,7 +49,6 @@
|
|||
"@kbn/reporting-mocks-server",
|
||||
"@kbn/core-http-request-handler-context-server",
|
||||
"@kbn/reporting-public",
|
||||
"@kbn/discover-utils",
|
||||
"@kbn/analytics-client",
|
||||
],
|
||||
"exclude": [
|
||||
|
|
|
@ -29748,11 +29748,6 @@
|
|||
"xpack.reporting.statusIndicator.processingMaxAttemptsLabel": "En cours de traitement, tentative {attempt} sur {of}",
|
||||
"xpack.reporting.userAccessError.message": "Demandez à votre administrateur un accès aux fonctionnalités de reporting. {grantUserAccessDocs}.",
|
||||
"xpack.reporting.breadcrumb": "Reporting",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedMessage": "Votre CSV sera téléchargé dans un instant.",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedTitle": "Téléchargement du CSV démarré",
|
||||
"xpack.reporting.dashboard.downloadCsvPanelTitle": "Télécharger CSV",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadMessage": "Nous n'avons pas pu générer votre CSV pour le moment.",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadTitle": "Le téléchargement du CSV a échoué",
|
||||
"xpack.reporting.deprecations.migrateIndexIlmPolicyActionTitle": "Des index de reporting gérés par une politique ILM personnalisée ont été détectés.",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorCorrectiveAction": "Assurez-vous de disposer du privilège de cluster \"manage_security\".",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorMessage": "Vous n’avez pas les autorisations requises pour remédier à ce déclassement.",
|
||||
|
|
|
@ -29749,11 +29749,6 @@
|
|||
"xpack.reporting.statusIndicator.processingMaxAttemptsLabel": "処理中。{attempt}/{of}回試行",
|
||||
"xpack.reporting.userAccessError.message": "レポート機能にアクセスするには、管理者に問い合わせてください。{grantUserAccessDocs}。",
|
||||
"xpack.reporting.breadcrumb": "レポート",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedMessage": "間もなく CSV がダウンロードされます。",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedTitle": "CSV のダウンロードが開始しました",
|
||||
"xpack.reporting.dashboard.downloadCsvPanelTitle": "CSV をダウンロード",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadMessage": "現在 CSV を生成できません。",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadTitle": "CSV のダウンロードに失敗",
|
||||
"xpack.reporting.deprecations.migrateIndexIlmPolicyActionTitle": "カスタムILMポリシーで管理されたレポートインデックスが見つかりました。",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorCorrectiveAction": "「manage_security」クラスター権限が割り当てられていることを確認してください。",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorMessage": "この廃止予定を修正する十分な権限がありません。",
|
||||
|
|
|
@ -29733,11 +29733,6 @@
|
|||
"xpack.reporting.statusIndicator.processingMaxAttemptsLabel": "正在处理,尝试 {attempt} {of}",
|
||||
"xpack.reporting.userAccessError.message": "请联系管理员以访问报告功能。{grantUserAccessDocs}.",
|
||||
"xpack.reporting.breadcrumb": "Reporting",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedMessage": "您的 CSV 将很快下载。",
|
||||
"xpack.reporting.dashboard.csvDownloadStartedTitle": "CSV 下载已开始",
|
||||
"xpack.reporting.dashboard.downloadCsvPanelTitle": "下载 CSV",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadMessage": "我们此次无法生成 CSV。",
|
||||
"xpack.reporting.dashboard.failedCsvDownloadTitle": "CSV 下载失败。",
|
||||
"xpack.reporting.deprecations.migrateIndexIlmPolicyActionTitle": "找到由定制 ILM 策略管理的报告索引。",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorCorrectiveAction": "请确保您分配有“manage_security”集群权限。",
|
||||
"xpack.reporting.deprecations.reportingRole.forbiddenErrorMessage": "您没有足够的权限来修复此弃用。",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue