Skip to content

Commit

Permalink
Merge branch 'main' into versioned-router/cleanup-types
Browse files Browse the repository at this point in the history
  • Loading branch information
jloleysens committed May 5, 2023
2 parents b54059f + 14f5b9e commit f9a9428
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 49 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@
"@turf/distance": "6.0.1",
"@turf/helpers": "6.0.1",
"@turf/length": "^6.0.2",
"@xstate/react": "^3.2.1",
"@xstate/react": "^3.2.2",
"JSONStream": "1.3.5",
"abort-controller": "^3.0.0",
"adm-zip": "^0.5.9",
Expand Down Expand Up @@ -965,7 +965,7 @@
"vinyl": "^2.2.0",
"whatwg-fetch": "^3.0.0",
"xml2js": "^0.4.22",
"xstate": "^4.37.1",
"xstate": "^4.37.2",
"xterm": "^5.1.0",
"yauzl": "^2.10.0",
"yazl": "^2.5.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ import { IEmbeddable, ViewMode } from '@kbn/embeddable-plugin/public';
import { Action } from '@kbn/ui-actions-plugin/public';
import { VisualizeEmbeddable } from '../embeddable';
import { DASHBOARD_VISUALIZATION_PANEL_TRIGGER } from '../triggers';
import { getUiActions, getApplication, getEmbeddable, getUsageCollection } from '../services';
import {
getUiActions,
getApplication,
getEmbeddable,
getUsageCollection,
getCapabilities,
} from '../services';

export const ACTION_EDIT_IN_LENS = 'ACTION_EDIT_IN_LENS';

Expand Down Expand Up @@ -116,7 +122,8 @@ export class EditInLensAction implements Action<EditInLensContext> {

async isCompatible(context: ActionExecutionContext<EditInLensContext>) {
const { embeddable } = context;
if (!isVisualizeEmbeddable(embeddable)) {
const { visualize } = getCapabilities();
if (!isVisualizeEmbeddable(embeddable) || !visualize.show) {
return false;
}
const vis = embeddable.getVis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const createVisEmbeddableFromObject =
const capabilities = {
visualizeSave: Boolean(getCapabilities().visualize.save),
dashboardSave: Boolean(getCapabilities().dashboard?.showWriteControls),
visualizeOpen: Boolean(getCapabilities().visualize?.show),
};

return createVisualizeEmbeddableAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export interface VisualizeEmbeddableConfiguration {
indexPatterns?: DataView[];
editPath: string;
editUrl: string;
capabilities: { visualizeSave: boolean; dashboardSave: boolean };
capabilities: { visualizeSave: boolean; dashboardSave: boolean; visualizeOpen: boolean };
deps: VisualizeEmbeddableFactoryDeps;
}

Expand Down Expand Up @@ -171,7 +171,9 @@ export class VisualizeEmbeddable

if (this.attributeService) {
const isByValue = !this.inputIsRefType(initialInput);
const editable = capabilities.visualizeSave || (isByValue && capabilities.dashboardSave);
const editable =
capabilities.visualizeSave ||
(isByValue && capabilities.dashboardSave && capabilities.visualizeOpen);
this.updateOutput({ ...this.getOutput(), editable });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,26 @@ const SearchResult = ({ hit }) => {
const clickHandler = () => {
trackSearchClick({
document: { id: hit.id, index: "products" },
page: {
url: "http://my-website.com/products/123"
},
search: {
query: "search term",
filters: [],
filters: {},
page: { current: 1, size: 10 },
results: {
results: {
items: [
{ id: "123", index: "products" }
{
document: {
id: "123",
index: "products",
},
page: {
url: "http://my-website.com/products/123",
},
},
],
total_results: 10
total_results: 10
},
sort: {
name: "relevance",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ window.elasticAnalytics.createTracker({
{`window.elasticAnalytics.trackSearch({
search: {
query: "laptop",
filters: [
{ field: "brand", value: ["apple"] },
{ field: "price", value: ["1000-2000"] },
],
filters: {
brand: ["apple"],
price: ["1000-2000"],
},
page: {
current: 1,
size: 10,
Expand Down
27 changes: 27 additions & 0 deletions x-pack/plugins/lens/public/embeddable/embeddable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -361,6 +362,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -413,6 +415,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -940,6 +943,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -1039,6 +1043,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -1135,6 +1140,7 @@ describe('embeddable', () => {
capabilities: {
canSaveDashboards: true,
canSaveVisualizations: true,
canOpenVisualizations: true,
discover: {},
navLinks: {},
},
Expand Down Expand Up @@ -1186,4 +1192,25 @@ describe('embeddable', () => {
})
);
});

it('should not be editable for no visualize library privileges', async () => {
const embeddable = new Embeddable(
getEmbeddableProps({
capabilities: {
canSaveDashboards: false,
canSaveVisualizations: true,
canOpenVisualizations: false,
discover: {},
navLinks: {},
},
}),
{
timeRange: {
from: 'now-15m',
to: 'now',
},
} as LensEmbeddableInput
);
expect(embeddable.getOutput().editable).toBeUndefined();
});
});
5 changes: 4 additions & 1 deletion x-pack/plugins/lens/public/embeddable/embeddable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export interface LensEmbeddableDeps {
getTriggerCompatibleActions?: UiActionsStart['getTriggerCompatibleActions'];
capabilities: {
canSaveVisualizations: boolean;
canOpenVisualizations: boolean;
canSaveDashboards: boolean;
navLinks: Capabilities['navLinks'];
discover: Capabilities['discover'];
Expand Down Expand Up @@ -1353,7 +1354,9 @@ export class Embeddable
private getIsEditable() {
return (
this.deps.capabilities.canSaveVisualizations ||
(!this.inputIsRefType(this.getInput()) && this.deps.capabilities.canSaveDashboards)
(!this.inputIsRefType(this.getInput()) &&
this.deps.capabilities.canSaveDashboards &&
this.deps.capabilities.canOpenVisualizations)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export class EmbeddableFactory implements EmbeddableFactoryDefinition {
capabilities: {
canSaveDashboards: Boolean(capabilities.dashboard?.showWriteControls),
canSaveVisualizations: Boolean(capabilities.visualize.save),
canOpenVisualizations: Boolean(capabilities.visualize.show),
navLinks: capabilities.navLinks,
discover: capabilities.discover,
},
Expand Down
18 changes: 14 additions & 4 deletions x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { toMountPoint, wrapWithTheme } from '@kbn/kibana-react-plugin/public';
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { StorageContextProvider } from '@kbn/ml-local-storage';

import { firstValueFrom } from 'rxjs';
import { mlCapabilities } from './capabilities/check_capabilities';
import { ML_STORAGE_KEYS } from '../../common/types/storage';
import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator';
Expand Down Expand Up @@ -74,10 +75,19 @@ export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;

const App: FC<AppProps> = ({ coreStart, deps, appMountParams }) => {
const redirectToMlAccessDeniedPage = async () => {
const accessDeniedPageUrl = await deps.share.url.locators.get(ML_APP_LOCATOR)!.getUrl({
page: ML_PAGES.ACCESS_DENIED,
});
await coreStart.application.navigateToUrl(accessDeniedPageUrl);
// access maybe be denied due to an expired license, so check the license status first
// if the license has expired, redirect to the license management page
const license = await firstValueFrom(deps.licensing.license$);
const redirectPage =
license.status === 'expired'
? deps.share.url.locators.get('LICENSE_MANAGEMENT_LOCATOR')!.getUrl({
page: 'dashboard',
})
: deps.share.url.locators.get(ML_APP_LOCATOR)!.getUrl({
page: ML_PAGES.ACCESS_DENIED,
});

await coreStart.application.navigateToUrl(await redirectPage);
};

const pageDeps = {
Expand Down
38 changes: 13 additions & 25 deletions x-pack/plugins/ml/server/saved_objects/checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import type {
MlSavedObjectType,
} from '../../common/types/saved_objects';

import type { DataFrameAnalyticsConfig } from '../../common/types/data_frame_analytics';
import type { ResolveMlCapabilities } from '../../common/types/capabilities';
import { getJobDetailsFromTrainedModel } from './util';
import { getJobDetailsFromTrainedModel, getJobsAndModels } from './util';

export interface JobSavedObjectStatus {
jobId: string;
Expand Down Expand Up @@ -79,7 +78,7 @@ export function checksFactory(
mlSavedObjectService: MLSavedObjectService
) {
async function checkStatus(): Promise<StatusResponse> {
const [
const {
jobObjects,
allJobObjects,
modelObjects,
Expand All @@ -88,18 +87,7 @@ export function checksFactory(
datafeeds,
dfaJobs,
models,
] = await Promise.all([
mlSavedObjectService.getAllJobObjects(undefined, false),
mlSavedObjectService.getAllJobObjectsForAllSpaces(),
mlSavedObjectService.getAllTrainedModelObjects(false),
mlSavedObjectService.getAllTrainedModelObjectsForAllSpaces(),
client.asInternalUser.ml.getJobs(),
client.asInternalUser.ml.getDatafeeds(),
client.asInternalUser.ml.getDataFrameAnalytics() as unknown as {
data_frame_analytics: DataFrameAnalyticsConfig[];
},
client.asInternalUser.ml.getTrainedModels(),
]);
} = await getJobsAndModels(client, mlSavedObjectService);

const jobSavedObjectsStatus: JobSavedObjectStatus[] = jobObjects.map(
({ attributes, namespaces }) => {
Expand All @@ -111,10 +99,10 @@ export function checksFactory(
let datafeedExists: boolean | undefined;

if (type === 'anomaly-detector') {
jobExists = adJobs.jobs.some((j) => j.job_id === jobId);
datafeedExists = datafeeds.datafeeds.some((d) => d.job_id === jobId);
jobExists = adJobs.some((j) => j.job_id === jobId);
datafeedExists = datafeeds.some((d) => d.job_id === jobId);
} else {
jobExists = dfaJobs.data_frame_analytics.some((j) => j.id === jobId);
jobExists = dfaJobs.some((j) => j.id === jobId);
}

return {
Expand All @@ -130,12 +118,12 @@ export function checksFactory(
}
);

const dfaJobsCreateTimeMap = dfaJobs.data_frame_analytics.reduce((acc, cur) => {
const dfaJobsCreateTimeMap = dfaJobs.reduce((acc, cur) => {
acc.set(cur.id, cur.create_time!);
return acc;
}, new Map<string, number>());

const modelJobExits = models.trained_model_configs.reduce((acc, cur) => {
const modelJobExits = models.reduce((acc, cur) => {
const job = getJobDetailsFromTrainedModel(cur);
if (job === null) {
return acc;
Expand All @@ -152,7 +140,7 @@ export function checksFactory(

const modelSavedObjectsStatus: TrainedModelSavedObjectStatus[] = modelObjects.map(
({ attributes: { job, model_id: modelId }, namespaces }) => {
const trainedModelExists = models.trained_model_configs.some((m) => m.model_id === modelId);
const trainedModelExists = models.some((m) => m.model_id === modelId);
const dfaJobExists = modelJobExits.get(modelId) ?? null;

return {
Expand Down Expand Up @@ -194,14 +182,14 @@ export function checksFactory(
);
const modelObjectIds = new Set(modelSavedObjectsStatus.map(({ modelId }) => modelId));

const anomalyDetectorsStatus = adJobs.jobs
const anomalyDetectorsStatus = adJobs
.filter(({ job_id: jobId }) => {
// only list jobs which are in the current space (adObjectIds)
// or are not in any spaces (nonSpaceADObjectIds)
return adObjectIds.has(jobId) === true || nonSpaceADObjectIds.has(jobId) === false;
})
.map(({ job_id: jobId }) => {
const datafeedId = datafeeds.datafeeds.find((df) => df.job_id === jobId)?.datafeed_id;
const datafeedId = datafeeds.find((df) => df.job_id === jobId)?.datafeed_id;
return {
jobId,
datafeedId: datafeedId ?? null,
Expand All @@ -211,7 +199,7 @@ export function checksFactory(
};
});

const dataFrameAnalyticsStatus = dfaJobs.data_frame_analytics
const dataFrameAnalyticsStatus = dfaJobs
.filter(({ id: jobId }) => {
// only list jobs which are in the current space (dfaObjectIds)
// or are not in any spaces (nonSpaceDFAObjectIds)
Expand All @@ -227,7 +215,7 @@ export function checksFactory(
};
});

const modelsStatus = models.trained_model_configs
const modelsStatus = models
.filter(({ model_id: modelId }) => {
// only list jobs which are in the current space (adObjectIds)
// or are not in any spaces (nonSpaceADObjectIds)
Expand Down
Loading

0 comments on commit f9a9428

Please sign in to comment.