mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
parent
d00c874d1b
commit
27f0782fca
6 changed files with 164 additions and 163 deletions
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { SavedObjectProvider } from 'ui/saved_objects/saved_object';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { extractReferences, injectReferences } from './saved_workspace_references';
|
||||
|
||||
export function SavedWorkspaceProvider(Private) {
|
||||
// SavedWorkspace constructor. Usually you'd interact with an instance of this.
|
||||
// ID is option, without it one will be generated on save.
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
class SavedWorkspace extends SavedObject {
|
||||
constructor(id) {
|
||||
// Gives our SavedWorkspace the properties of a SavedObject
|
||||
super({
|
||||
type: SavedWorkspace.type,
|
||||
mapping: SavedWorkspace.mapping,
|
||||
searchSource: SavedWorkspace.searchsource,
|
||||
extractReferences: extractReferences,
|
||||
injectReferences: injectReferences,
|
||||
|
||||
// if this is null/undefined then the SavedObject will be assigned the defaults
|
||||
id: id,
|
||||
|
||||
// default values that will get assigned if the doc is new
|
||||
defaults: {
|
||||
title: i18n.translate('xpack.graph.savedWorkspace.workspaceNameTitle', {
|
||||
defaultMessage: 'New Graph Workspace',
|
||||
}),
|
||||
numLinks: 0,
|
||||
numVertices: 0,
|
||||
wsState: '{}',
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Overwrite the default getDisplayName function which uses type and which is not very
|
||||
// user friendly for this object.
|
||||
this.getDisplayName = function() {
|
||||
return 'graph workspace';
|
||||
};
|
||||
}
|
||||
} //End of class
|
||||
|
||||
SavedWorkspace.type = 'graph-workspace';
|
||||
|
||||
// if type:workspace has no mapping, we push this mapping into ES
|
||||
SavedWorkspace.mapping = {
|
||||
title: 'text',
|
||||
description: 'text',
|
||||
numLinks: 'integer',
|
||||
numVertices: 'integer',
|
||||
version: 'integer',
|
||||
wsState: 'json',
|
||||
};
|
||||
|
||||
SavedWorkspace.searchsource = false;
|
||||
return SavedWorkspace;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types';
|
||||
import { createSavedObjectClass } from 'ui/saved_objects/saved_object';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { extractReferences, injectReferences } from './saved_workspace_references';
|
||||
|
||||
export interface SavedWorkspace extends SavedObject {
|
||||
wsState?: string;
|
||||
}
|
||||
|
||||
export function createSavedWorkspaceClass(services: SavedObjectKibanaServices) {
|
||||
// SavedWorkspace constructor. Usually you'd interact with an instance of this.
|
||||
// ID is option, without it one will be generated on save.
|
||||
const SavedObjectClass = createSavedObjectClass(services);
|
||||
class SavedWorkspaceClass extends SavedObjectClass {
|
||||
public static type: string = 'graph-workspace';
|
||||
// if type:workspace has no mapping, we push this mapping into ES
|
||||
public static mapping: Record<string, string> = {
|
||||
title: 'text',
|
||||
description: 'text',
|
||||
numLinks: 'integer',
|
||||
numVertices: 'integer',
|
||||
version: 'integer',
|
||||
wsState: 'json',
|
||||
};
|
||||
// Order these fields to the top, the rest are alphabetical
|
||||
public static fieldOrder = ['title', 'description'];
|
||||
public static searchSource = false;
|
||||
|
||||
public wsState?: string;
|
||||
|
||||
constructor(id: string) {
|
||||
// Gives our SavedWorkspace the properties of a SavedObject
|
||||
super({
|
||||
type: SavedWorkspaceClass.type,
|
||||
mapping: SavedWorkspaceClass.mapping,
|
||||
searchSource: SavedWorkspaceClass.searchSource,
|
||||
extractReferences,
|
||||
injectReferences,
|
||||
// if this is null/undefined then the SavedObject will be assigned the defaults
|
||||
id,
|
||||
// default values that will get assigned if the doc is new
|
||||
defaults: {
|
||||
title: i18n.translate('xpack.graph.savedWorkspace.workspaceNameTitle', {
|
||||
defaultMessage: 'New Graph Workspace',
|
||||
}),
|
||||
numLinks: 0,
|
||||
numVertices: 0,
|
||||
wsState: '{}',
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
// Overwrite the default getDisplayName function which uses type and which is not very
|
||||
// user friendly for this object.
|
||||
getDisplayName = () => {
|
||||
return 'graph workspace';
|
||||
};
|
||||
}
|
||||
return SavedWorkspaceClass;
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { extractReferences, injectReferences } from './saved_workspace_references';
|
||||
import { SavedWorkspace } from './saved_workspace';
|
||||
|
||||
describe('extractReferences', () => {
|
||||
test('extracts references from wsState', () => {
|
||||
|
@ -19,6 +20,7 @@ describe('extractReferences', () => {
|
|||
})
|
||||
),
|
||||
},
|
||||
references: [],
|
||||
};
|
||||
const updatedDoc = extractReferences(doc);
|
||||
expect(updatedDoc).toMatchInlineSnapshot(`
|
||||
|
@ -48,6 +50,7 @@ Object {
|
|||
})
|
||||
),
|
||||
},
|
||||
references: [],
|
||||
};
|
||||
expect(() => extractReferences(doc)).toThrowErrorMatchingInlineSnapshot(
|
||||
`"indexPattern attribute is missing in \\"wsState\\""`
|
||||
|
@ -59,12 +62,12 @@ describe('injectReferences', () => {
|
|||
test('injects references into context', () => {
|
||||
const context = {
|
||||
id: '1',
|
||||
foo: true,
|
||||
title: 'test',
|
||||
wsState: JSON.stringify({
|
||||
indexPatternRefName: 'indexPattern_0',
|
||||
bar: true,
|
||||
}),
|
||||
};
|
||||
} as SavedWorkspace;
|
||||
const references = [
|
||||
{
|
||||
name: 'indexPattern_0',
|
||||
|
@ -75,8 +78,8 @@ describe('injectReferences', () => {
|
|||
injectReferences(context, references);
|
||||
expect(context).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"foo": true,
|
||||
"id": "1",
|
||||
"title": "test",
|
||||
"wsState": "{\\"bar\\":true,\\"indexPattern\\":\\"pattern*\\"}",
|
||||
}
|
||||
`);
|
||||
|
@ -85,13 +88,13 @@ Object {
|
|||
test('skips when wsState is not a string', () => {
|
||||
const context = {
|
||||
id: '1',
|
||||
foo: true,
|
||||
};
|
||||
title: 'test',
|
||||
} as SavedWorkspace;
|
||||
injectReferences(context, []);
|
||||
expect(context).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"foo": true,
|
||||
"id": "1",
|
||||
"title": "test",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -100,7 +103,7 @@ Object {
|
|||
const context = {
|
||||
id: '1',
|
||||
wsState: JSON.stringify({ bar: true }),
|
||||
};
|
||||
} as SavedWorkspace;
|
||||
injectReferences(context, []);
|
||||
expect(context).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
|
@ -116,7 +119,7 @@ Object {
|
|||
wsState: JSON.stringify({
|
||||
indexPatternRefName: 'indexPattern_0',
|
||||
}),
|
||||
};
|
||||
} as SavedWorkspace;
|
||||
expect(() => injectReferences(context, [])).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Could not find reference \\"indexPattern_0\\""`
|
||||
);
|
|
@ -4,9 +4,18 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export function extractReferences({ attributes, references = [] }) {
|
||||
import { SavedObjectAttributes, SavedObjectReference } from 'kibana/public';
|
||||
import { SavedWorkspace } from './saved_workspace';
|
||||
|
||||
export function extractReferences({
|
||||
attributes,
|
||||
references = [],
|
||||
}: {
|
||||
attributes: SavedObjectAttributes;
|
||||
references: SavedObjectReference[];
|
||||
}) {
|
||||
// For some reason, wsState comes in stringified 2x
|
||||
const state = JSON.parse(JSON.parse(attributes.wsState));
|
||||
const state = JSON.parse(JSON.parse(String(attributes.wsState)));
|
||||
const { indexPattern } = state;
|
||||
if (!indexPattern) {
|
||||
throw new Error('indexPattern attribute is missing in "wsState"');
|
||||
|
@ -29,7 +38,7 @@ export function extractReferences({ attributes, references = [] }) {
|
|||
};
|
||||
}
|
||||
|
||||
export function injectReferences(savedObject, references) {
|
||||
export function injectReferences(savedObject: SavedWorkspace, references: SavedObjectReference[]) {
|
||||
// Skip if wsState is missing, at the time of development of this, there is no guarantee each
|
||||
// saved object has wsState.
|
||||
if (typeof savedObject.wsState !== 'string') {
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import chrome from 'ui/chrome';
|
||||
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
|
||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { SavedWorkspaceProvider } from './saved_workspace';
|
||||
|
||||
export function SavedWorkspacesProvider(kbnUrl, Private, Promise) {
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
const SavedWorkspace = Private(SavedWorkspaceProvider);
|
||||
|
||||
this.type = SavedWorkspace.type;
|
||||
this.Class = SavedWorkspace;
|
||||
|
||||
this.loaderProperties = {
|
||||
name: 'Graph workspace',
|
||||
noun: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspaceLabel', {
|
||||
defaultMessage: 'Graph workspace',
|
||||
}),
|
||||
nouns: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspacesLabel', {
|
||||
defaultMessage: 'Graph workspaces',
|
||||
}),
|
||||
};
|
||||
|
||||
// Returns a single dashboard by ID, should be the name of the workspace
|
||||
this.get = function(id) {
|
||||
// Returns a promise that contains a workspace which is a subclass of docSource
|
||||
return new SavedWorkspace(id).init();
|
||||
};
|
||||
|
||||
this.urlFor = function(id) {
|
||||
return chrome.addBasePath(kbnUrl.eval('/app/graph#/workspace/{{id}}', { id }));
|
||||
};
|
||||
|
||||
this.delete = function(ids) {
|
||||
ids = !_.isArray(ids) ? [ids] : ids;
|
||||
return Promise.map(ids, function(id) {
|
||||
return new SavedWorkspace(id).delete();
|
||||
});
|
||||
};
|
||||
|
||||
this.mapHits = function(hit) {
|
||||
const source = hit.attributes;
|
||||
source.id = hit.id;
|
||||
source.url = this.urlFor(hit.id);
|
||||
source.icon = 'fa-share-alt'; // looks like a graph
|
||||
return source;
|
||||
};
|
||||
|
||||
this.find = function(searchString, size = 100) {
|
||||
let body;
|
||||
if (searchString) {
|
||||
body = {
|
||||
query: {
|
||||
simple_query_string: {
|
||||
query: searchString + '*',
|
||||
fields: ['title^3', 'description'],
|
||||
default_operator: 'AND',
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
body = { query: { match_all: {} } };
|
||||
}
|
||||
|
||||
return savedObjectsClient
|
||||
.find({
|
||||
type: SavedWorkspace.type,
|
||||
search: searchString ? `${searchString}*` : undefined,
|
||||
perPage: size,
|
||||
searchFields: ['title^3', 'description'],
|
||||
})
|
||||
.then(resp => {
|
||||
return {
|
||||
total: resp.total,
|
||||
hits: resp.savedObjects.map(hit => this.mapHits(hit)),
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
SavedObjectRegistryProvider.register(SavedWorkspacesProvider);
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { createSavedWorkspaceClass } from './saved_workspace';
|
||||
|
||||
export function SavedWorkspacesProvider() {
|
||||
const savedObjectsClient = npStart.core.savedObjects.client;
|
||||
const services = {
|
||||
savedObjectsClient,
|
||||
indexPatterns: npStart.plugins.data.indexPatterns,
|
||||
chrome: npStart.core.chrome,
|
||||
overlays: npStart.core.overlays,
|
||||
};
|
||||
|
||||
const SavedWorkspace = createSavedWorkspaceClass(services);
|
||||
const urlFor = (id: string) =>
|
||||
npSetup.core.http.basePath.prepend(`/app/graph#/workspace/${encodeURIComponent(id)}`);
|
||||
const mapHits = (hit: { id: string; attributes: Record<string, unknown> }) => {
|
||||
const source = hit.attributes;
|
||||
source.id = hit.id;
|
||||
source.url = urlFor(hit.id);
|
||||
source.icon = 'fa-share-alt'; // looks like a graph
|
||||
return source;
|
||||
};
|
||||
|
||||
return {
|
||||
type: SavedWorkspace.type,
|
||||
Class: SavedWorkspace,
|
||||
loaderProperties: {
|
||||
name: 'Graph workspace',
|
||||
noun: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspaceLabel', {
|
||||
defaultMessage: 'Graph workspace',
|
||||
}),
|
||||
nouns: i18n.translate('xpack.graph.savedWorkspaces.graphWorkspacesLabel', {
|
||||
defaultMessage: 'Graph workspaces',
|
||||
}),
|
||||
},
|
||||
// Returns a single dashboard by ID, should be the name of the workspace
|
||||
get: (id: string) => {
|
||||
// Returns a promise that contains a workspace which is a subclass of docSource
|
||||
// @ts-ignore
|
||||
return new SavedWorkspace(id).init();
|
||||
},
|
||||
urlFor,
|
||||
delete: (ids: string | string[]) => {
|
||||
const idArr = Array.isArray(ids) ? ids : [ids];
|
||||
return Promise.all(
|
||||
idArr.map((id: string) => savedObjectsClient.delete(SavedWorkspace.type, id))
|
||||
);
|
||||
},
|
||||
find: (searchString: string, size: number = 100) => {
|
||||
return savedObjectsClient
|
||||
.find({
|
||||
type: SavedWorkspace.type,
|
||||
search: searchString ? `${searchString}*` : undefined,
|
||||
perPage: size,
|
||||
searchFields: ['title^3', 'description'],
|
||||
})
|
||||
.then(resp => {
|
||||
return {
|
||||
total: resp.total,
|
||||
hits: resp.savedObjects.map(hit => mapHits(hit)),
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
SavedObjectRegistryProvider.register(SavedWorkspacesProvider);
|
Loading…
Add table
Add a link
Reference in a new issue