Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c68ffaf
Draft scheduled report flyout UI
umbopepato May 31, 2025
ff4f897
Implement scheduled reports flyout
umbopepato Jun 17, 2025
dc4c074
Fix type errors
umbopepato Jun 18, 2025
0ddb6ea
Fix translations, reduce page load bundle size
umbopepato Jun 18, 2025
5914e61
Switch back to form in flyout content, add tests
umbopepato Jun 18, 2025
d4b6cde
Fix form validity check, flyout sizing, license check
umbopepato Jun 18, 2025
1af5c5f
Use loading state from rq instead of buggy form.isSubmitting
umbopepato Jun 18, 2025
3dbdd71
Add time to recurrence form textual summary
umbopepato Jun 18, 2025
c24eaf5
Attempt to fix functional Discover tests
umbopepato Jun 18, 2025
aa3154f
Add pdf print option toggle
umbopepato Jun 19, 2025
f0a92a2
Add health check before registering button, fix type error
umbopepato Jun 19, 2025
07725d1
Disable yearly frequency
umbopepato Jun 19, 2025
acdd24a
Fix Discover functional tests
umbopepato Jun 19, 2025
ea2dc7d
Revert test change causing type error
umbopepato Jun 19, 2025
a492c73
Implement scheduled report transform util, update recurrence form
umbopepato Jun 19, 2025
65dea18
Fix type error
umbopepato Jun 19, 2025
04cc893
Catch schedule report errors
umbopepato Jun 19, 2025
9673dbf
Fix last Dashboard and Discover functional tests
umbopepato Jun 19, 2025
4b87914
Fix wrong page object method call
umbopepato Jun 19, 2025
7ff7bdb
More functional test fixes
umbopepato Jun 19, 2025
ff6ff75
Even more functional test fixes
umbopepato Jun 20, 2025
95c706a
Filter share items by ones that support scheduling
umbopepato Jun 20, 2025
e9bf5cd
Change csv export icon type
umbopepato Jun 20, 2025
77e387a
Log schedule errors to console
umbopepato Jun 20, 2025
aab40a3
Check license against allowlist
umbopepato Jun 20, 2025
03d14c9
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jun 20, 2025
03d256f
Fix circular TS proj dependency
umbopepato Jun 23, 2025
0981e53
Combine import and export of useShareTypeContext into a single statement
umbopepato Jun 23, 2025
bc6aa0c
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Jun 23, 2025
bc68511
Fix type error
umbopepato Jun 23, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
LENS_APP_LOCATOR,
VISUALIZE_APP_LOCATOR,
} from '@kbn/deeplinks-analytics';
import { LicenseType } from '@kbn/licensing-plugin/common/types';

export const ALLOWED_JOB_CONTENT_TYPES = [
'application/json',
Expand Down Expand Up @@ -40,6 +41,13 @@ export const LICENSE_TYPE_CLOUD_STANDARD = 'standard' as const;
export const LICENSE_TYPE_GOLD = 'gold' as const;
export const LICENSE_TYPE_PLATINUM = 'platinum' as const;
export const LICENSE_TYPE_ENTERPRISE = 'enterprise' as const;
export const SCHEDULED_REPORT_VALID_LICENSES: LicenseType[] = [
LICENSE_TYPE_TRIAL,
LICENSE_TYPE_CLOUD_STANDARD,
LICENSE_TYPE_GOLD,
LICENSE_TYPE_PLATINUM,
LICENSE_TYPE_ENTERPRISE,
];

/*
* Notifications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
"@kbn/i18n",
"@kbn/task-manager-plugin",
"@kbn/deeplinks-analytics",
"@kbn/licensing-plugin",
]
}
23 changes: 22 additions & 1 deletion src/platform/packages/private/kbn-reporting/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
LayoutParams,
PerformanceMetrics as ScreenshotMetrics,
} from '@kbn/screenshotting-plugin/common';
import type { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server';
import type { ConcreteTaskInstance, RruleSchedule } from '@kbn/task-manager-plugin/server';
import { JOB_STATUS } from './constants';
import type { LocatorParams } from './url';

Expand Down Expand Up @@ -211,3 +211,24 @@ export interface LicenseCheckResults {
showLinks: boolean;
message: string;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picked from #224354 just to provide a utility to integrate our PRs together

export interface ScheduledReportApiJSON {
id: string;
created_at: string;
created_by: string;
enabled: boolean;
jobtype: string;
last_run: string | undefined;
next_run: string | undefined;
notification?: {
email?: {
to?: string[];
cc?: string[];
bcc?: string[];
};
};
payload?: ReportApiJSON['payload'];
schedule: RruleSchedule;
space_id: string;
title: string;
}
7 changes: 6 additions & 1 deletion src/platform/packages/private/kbn-reporting/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { ActionsPublicPluginSetup } from '@kbn/actions-plugin/public';

export type { ClientConfigType } from './types';
export { Job } from './job';
export * from './job_completion_notifications';
Expand All @@ -15,7 +17,7 @@ export { useCheckIlmPolicyStatus } from './hooks';
export { ReportingAPIClient } from './reporting_api_client';
export { checkLicense } from './license_check';

import type { CoreSetup, CoreStart } from '@kbn/core/public';
import type { CoreSetup, CoreStart, NotificationsStart } from '@kbn/core/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { useKibana as _useKibana } from '@kbn/kibana-react-plugin/public';
import type { SharePluginStart } from '@kbn/share-plugin/public';
Expand All @@ -26,10 +28,13 @@ import type { SharePluginStart } from '@kbn/share-plugin/public';
export interface KibanaContext {
http: CoreSetup['http'];
application: CoreStart['application'];
settings: CoreStart['settings'];
uiSettings: CoreStart['uiSettings'];
docLinks: CoreStart['docLinks'];
data: DataPublicPluginStart;
share: SharePluginStart;
actions: ActionsPublicPluginSetup;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the actions plugin to get the validateEmailAddresses utility (not ideal, but in the future we could export that to a more generic place)

notifications: NotificationsStart;
}

export const useKibana = () => _useKibana<KibanaContext>();
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,42 @@ import type { SerializedSearchSourceFields } from '@kbn/data-plugin/common';
import { FormattedMessage, InjectedIntl } from '@kbn/i18n-react';
import { ShareContext, type ExportShare } from '@kbn/share-plugin/public';
import { LocatorParams } from '@kbn/reporting-common/types';
import { ReportParamsGetter, ReportParamsGetterOptions } from '../../types';
import { getSearchCsvJobParams, CsvSearchModeParams } from '../shared/get_search_csv_job_params';
import type { ExportModalShareOpts } from '.';
import { checkLicense } from '../..';

export const getCsvReportParams: ReportParamsGetter<
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I exported the params getters for all types of exports since I need to generate params in the scheduled report flyout too

ReportParamsGetterOptions & { forShareUrl?: boolean },
CsvSearchModeParams
> = ({ sharingData, forShareUrl = false }) => {
const getSearchSource = sharingData.getSearchSource as ({
addGlobalTimeFilter,
absoluteTime,
}: {
addGlobalTimeFilter?: boolean;
absoluteTime?: boolean;
}) => SerializedSearchSourceFields;

if (sharingData.isTextBased) {
// csv v2 uses locator params
return {
isEsqlMode: true,
locatorParams: sharingData.locatorParams as LocatorParams[],
};
}

// csv v1 uses search source and columns
return {
isEsqlMode: false,
columns: sharingData.columns as string[] | undefined,
searchSource: getSearchSource({
addGlobalTimeFilter: true,
absoluteTime: !forShareUrl,
}),
};
};

export const reportingCsvExportProvider = ({
apiClient,
startServices$,
Expand All @@ -27,33 +59,8 @@ export const reportingCsvExportProvider = ({
objectType,
sharingData,
}: ShareContext): ReturnType<ExportShare['config']> => {
const getSearchSource = sharingData.getSearchSource as ({
addGlobalTimeFilter,
absoluteTime,
}: {
addGlobalTimeFilter?: boolean;
absoluteTime?: boolean;
}) => SerializedSearchSourceFields;

const getSearchModeParams = (forShareUrl?: boolean): CsvSearchModeParams => {
if (sharingData.isTextBased) {
// csv v2 uses locator params
return {
isEsqlMode: true,
locatorParams: sharingData.locatorParams as LocatorParams[],
};
}

// csv v1 uses search source and columns
return {
isEsqlMode: false,
columns: sharingData.columns as string[] | undefined,
searchSource: getSearchSource({
addGlobalTimeFilter: true,
absoluteTime: !forShareUrl,
}),
};
};
const getSearchModeParams = (forShareUrl?: boolean): CsvSearchModeParams =>
getCsvReportParams({ sharingData, forShareUrl });

const generateReportingJobCSV = ({ intl }: { intl: InjectedIntl }) => {
const { reportType, decoratedJobParams } = getSearchCsvJobParams({
Expand Down Expand Up @@ -132,7 +139,7 @@ export const reportingCsvExportProvider = ({
name: panelTitle,
exportType: reportType,
label: 'CSV',
icon: 'documents',
icon: 'tableDensityNormal',
generateAssetExport: generateReportingJobCSV,
helpText: (
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,69 @@ import { ShareContext } from '@kbn/share-plugin/public';
import React from 'react';
import { firstValueFrom } from 'rxjs';
import { ExportGenerationOpts, ExportShare } from '@kbn/share-plugin/public/types';
import { ReportParamsGetter, ReportParamsGetterOptions } from '../../types';
import { ExportModalShareOpts, JobParamsProviderOptions, ReportingSharingData } from '.';
import { checkLicense } from '../../license_check';

const getJobParams = (opts: JobParamsProviderOptions, type: 'pngV2' | 'printablePdfV2') => () => {
const {
objectType,
sharingData: { title, locatorParams },
optimizedForPrinting,
} = opts;

const getBaseParams = (objectType: string) => {
const el = document.querySelector('[data-shared-items-container]');
const { height, width } = el ? el.getBoundingClientRect() : { height: 768, width: 1024 };
const dimensions = { height, width };
const layoutId = optimizedForPrinting ? ('print' as const) : ('preserve_layout' as const);
const layout = { id: layoutId, dimensions };
const baseParams = { objectType, layout, title };
return {
objectType,
layout: {
id: 'preserve_layout' as 'preserve_layout' | 'print',
dimensions,
},
};
};

interface PngPdfReportBaseParams {
layout: { dimensions: { height: number; width: number }; id: 'preserve_layout' | 'print' };
objectType: string;
locatorParams: any;
}

export const getPngReportParams: ReportParamsGetter<
ReportParamsGetterOptions,
PngPdfReportBaseParams
> = ({ sharingData }): PngPdfReportBaseParams => {
return {
...getBaseParams('pngV2'),
locatorParams: sharingData.locatorParams,
};
};

if (type === 'printablePdfV2') {
// multi locator for PDF V2
return { ...baseParams, locatorParams: [locatorParams] };
export const getPdfReportParams: ReportParamsGetter<
ReportParamsGetterOptions & { optimizedForPrinting?: boolean },
PngPdfReportBaseParams
> = ({ sharingData, optimizedForPrinting = false }) => {
const params = {
...getBaseParams('printablePdfV2'),
locatorParams: [sharingData.locatorParams],
};
if (optimizedForPrinting) {
params.layout.id = 'print';
}
// single locator for PNG V2
return { ...baseParams, locatorParams };
return params;
};

const getJobParams = (opts: JobParamsProviderOptions, type: 'pngV2' | 'printablePdfV2') => () => {
const { objectType, sharingData, optimizedForPrinting } = opts;
let baseParams: PngPdfReportBaseParams;
if (type === 'pngV2') {
baseParams = getPngReportParams({ sharingData });
} else {
baseParams = getPdfReportParams({
sharingData,
optimizedForPrinting,
});
}
return {
...baseParams,
objectType,
title: sharingData.title,
};
};

export const reportingPDFExportProvider = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
"@kbn/home-plugin",
"@kbn/management-plugin",
"@kbn/ui-actions-plugin",
"@kbn/actions-plugin",
]
}
10 changes: 10 additions & 0 deletions src/platform/packages/private/kbn-reporting/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@ export interface ClientConfigType {
};
statefulSettings: { enabled: boolean };
}

export interface ReportParamsGetterOptions {
objectType?: string;
sharingData: any;
}

export type ReportParamsGetter<
O extends ReportParamsGetterOptions = ReportParamsGetterOptions,
T = unknown
> = (options: O) => T;
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { ILicense, LicenseType } from '@kbn/licensing-plugin/server';
import {
LICENSE_TYPE_CLOUD_STANDARD,
LICENSE_TYPE_ENTERPRISE,
LICENSE_TYPE_GOLD,
LICENSE_TYPE_PLATINUM,
LICENSE_TYPE_TRIAL,
} from '@kbn/reporting-common';
import { ILicense } from '@kbn/licensing-plugin/server';
import { SCHEDULED_REPORT_VALID_LICENSES } from '@kbn/reporting-common';
import type { ExportType } from '.';
import { ExportTypesRegistry } from './export_types_registry';

Expand All @@ -25,14 +19,6 @@ export interface LicenseCheckResult {
jobTypes?: string[];
}

const scheduledReportValidLicenses: LicenseType[] = [
LICENSE_TYPE_TRIAL,
LICENSE_TYPE_CLOUD_STANDARD,
LICENSE_TYPE_GOLD,
LICENSE_TYPE_PLATINUM,
LICENSE_TYPE_ENTERPRISE,
];

const messages = {
getUnavailable: () => {
return 'You cannot use Reporting because license information is not available at this time.';
Expand Down Expand Up @@ -95,7 +81,7 @@ const makeScheduledReportsFeature = () => {
};
}

if (!scheduledReportValidLicenses.includes(license.type)) {
if (!SCHEDULED_REPORT_VALID_LICENSES.includes(license.type)) {
return {
showLinks: false,
enableLinks: false,
Expand Down
Loading