[ContentEditor] Replace "Inspector" with "ContentEditor" (#147606)

This commit is contained in:
Sébastien Loix 2022-12-16 12:20:08 +00:00 committed by GitHub
parent d14bf59730
commit b052917e31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 155 additions and 163 deletions

2
.github/CODEOWNERS vendored
View file

@ -695,7 +695,7 @@ packages/analytics/shippers/elastic_v3/common @elastic/kibana-core
packages/analytics/shippers/elastic_v3/server @elastic/kibana-core
packages/analytics/shippers/fullstory @elastic/kibana-core
packages/analytics/shippers/gainsight @elastic/kibana-core
packages/content-management/inspector @elastic/kibana-global-experience
packages/content-management/content_editor @elastic/kibana-global-experience
packages/content-management/table_list @elastic/kibana-global-experience
packages/core/analytics/core-analytics-browser @elastic/kibana-core
packages/core/analytics/core-analytics-browser-internal @elastic/kibana-core

View file

@ -147,7 +147,7 @@
"@kbn/config": "link:bazel-bin/packages/kbn-config",
"@kbn/config-mocks": "link:bazel-bin/packages/kbn-config-mocks",
"@kbn/config-schema": "link:bazel-bin/packages/kbn-config-schema",
"@kbn/content-management-inspector": "link:bazel-bin/packages/content-management/inspector",
"@kbn/content-management-content-editor": "link:bazel-bin/packages/content-management/content_editor",
"@kbn/content-management-table-list": "link:bazel-bin/packages/content-management/table_list",
"@kbn/core-analytics-browser": "link:bazel-bin/packages/core/analytics/core-analytics-browser",
"@kbn/core-analytics-browser-internal": "link:bazel-bin/packages/core/analytics/core-analytics-browser-internal",

View file

@ -15,7 +15,7 @@ filegroup(
"//packages/analytics/shippers/elastic_v3/server:build",
"//packages/analytics/shippers/fullstory:build",
"//packages/analytics/shippers/gainsight:build",
"//packages/content-management/inspector:build",
"//packages/content-management/content_editor:build",
"//packages/content-management/table_list:build",
"//packages/core/analytics/core-analytics-browser:build",
"//packages/core/analytics/core-analytics-browser-internal:build",
@ -392,7 +392,7 @@ filegroup(
"//packages/analytics/shippers/elastic_v3/server:build_types",
"//packages/analytics/shippers/fullstory:build_types",
"//packages/analytics/shippers/gainsight:build_types",
"//packages/content-management/inspector:build_types",
"//packages/content-management/content_editor:build_types",
"//packages/content-management/table_list:build_types",
"//packages/core/analytics/core-analytics-browser:build_types",
"//packages/core/analytics/core-analytics-browser-internal:build_types",

View file

@ -2,8 +2,8 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project")
PKG_DIRNAME = "inspector"
PKG_REQUIRE_NAME = "@kbn/content-management-inspector"
PKG_DIRNAME = "content_editor"
PKG_REQUIRE_NAME = "@kbn/content-management-content-editor"
SOURCE_FILES = glob(
[

View file

@ -0,0 +1,7 @@
# @kbn/content-management-content-editor
# Content editor component
## API
TODO: https://github.com/elastic/kibana/issues/144402

View file

@ -6,5 +6,5 @@
* Side Public License, v 1.
*/
export { InspectorProvider, InspectorKibanaProvider, useOpenInspector } from './src';
export type { OpenInspectorParams } from './src';
export { ContentEditorProvider, ContentEditorKibanaProvider, useOpenContentEditor } from './src';
export type { OpenContentEditorParams } from './src';

View file

@ -9,5 +9,5 @@
module.exports = {
preset: '@kbn/test',
rootDir: '../../..',
roots: ['<rootDir>/packages/content-management/inspector'],
roots: ['<rootDir>/packages/content-management/content_editor'],
};

View file

@ -1,6 +1,6 @@
{
"type": "shared-common",
"id": "@kbn/content-management-inspector",
"id": "@kbn/content-management-content-editor",
"owner": "@elastic/kibana-global-experience",
"runtimeDeps": [],
"typeDeps": [],

View file

@ -1,5 +1,5 @@
{
"name": "@kbn/content-management-inspector",
"name": "@kbn/content-management-content-editor",
"private": true,
"version": "1.0.0",
"main": "./target_node/index.js",

View file

@ -9,7 +9,7 @@ import React from 'react';
import type { ComponentType } from 'react';
import { TagSelector, TagList } from '../mocks';
import { InspectorProvider } from '../services';
import { ContentEditorProvider } from '../services';
import type { Services } from '../services';
export const getMockServices = (overrides?: Partial<Services>) => {
@ -31,9 +31,9 @@ export function WithServices<P>(Comp: ComponentType<P>, overrides: Partial<Servi
return (props: P) => {
const services = getMockServices(overrides);
return (
<InspectorProvider {...services}>
<ContentEditorProvider {...services}>
<Comp {...props} />
</InspectorProvider>
</ContentEditorProvider>
);
};
}

View file

@ -30,16 +30,13 @@ import { useMetadataForm } from './use_metadata_form';
import type { CustomValidators } from './use_metadata_form';
const getI18nTexts = ({ entityName }: { entityName: string }) => ({
title: i18n.translate('contentManagement.inspector.flyoutTitle', {
defaultMessage: 'Inspector',
}),
saveButtonLabel: i18n.translate('contentManagement.inspector.saveButtonLabel', {
saveButtonLabel: i18n.translate('contentManagement.contentEditor.saveButtonLabel', {
defaultMessage: 'Update {entityName}',
values: {
entityName,
},
}),
cancelButtonLabel: i18n.translate('contentManagement.inspector.cancelButtonLabel', {
cancelButtonLabel: i18n.translate('contentManagement.contentEditor.cancelButtonLabel', {
defaultMessage: 'Cancel',
}),
});
@ -59,7 +56,9 @@ export interface Props {
onCancel: () => void;
}
export const InspectorFlyoutContent: FC<Props> = ({
const capitalize = (str: string) => `${str.charAt(0).toLocaleUpperCase()}${str.substring(1)}`;
export const ContentEditorFlyoutContent: FC<Props> = ({
item,
entityName,
isReadonly = true,
@ -113,13 +112,22 @@ export const InspectorFlyoutContent: FC<Props> = ({
margin-right: ${euiTheme.size.m};
`;
const title = capitalize(
i18n.translate('contentManagement.contentEditor.flyoutTitle', {
defaultMessage: '{entityName} details',
values: {
entityName,
},
})
);
return (
<>
<EuiFlyoutHeader>
<EuiTitle data-test-subj="flyoutTitle">
<h2>
<EuiIcon type="inspect" css={iconCSS} size="l" />
<span>{i18nTexts.title}</span>
<span>{title}</span>
</h2>
</EuiTitle>
</EuiFlyoutHeader>

View file

@ -8,16 +8,16 @@
import React from 'react';
import type { FC } from 'react';
import { InspectorFlyoutContent } from './inspector_flyout_content';
import type { Props as InspectorFlyoutContentProps } from './inspector_flyout_content';
import { ContentEditorFlyoutContent } from './editor_flyout_content';
import type { Props as ContentEditorFlyoutContentProps } from './editor_flyout_content';
type CommonProps = Pick<
InspectorFlyoutContentProps,
ContentEditorFlyoutContentProps,
'item' | 'isReadonly' | 'services' | 'onSave' | 'onCancel' | 'entityName' | 'customValidators'
>;
export type Props = CommonProps;
export const InspectorFlyoutContentContainer: FC<Props> = (props) => {
return <InspectorFlyoutContent {...props} />;
export const ContentEditorFlyoutContentContainer: FC<Props> = (props) => {
return <ContentEditorFlyoutContent {...props} />;
};

View file

@ -11,12 +11,12 @@ import { EuiCallOut, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
const getI18nTexts = () => ({
title: i18n.translate('contentManagement.inspector.flyoutWarningsTitle', {
title: i18n.translate('contentManagement.contentEditor.flyoutWarningsTitle', {
defaultMessage: 'Proceed with caution!',
}),
});
export const InspectorFlyoutWarningsCallOut = ({
export const ContentEditorFlyoutWarningsCallOut = ({
warningMessages,
}: {
warningMessages?: string[];

View file

@ -9,16 +9,16 @@
import React, { useState, useCallback, useEffect } from 'react';
import { EuiFlyoutHeader, EuiFlyoutBody, EuiFlyoutFooter } from '@elastic/eui';
import type { Props } from './inspector_flyout_content_container';
import type { Props } from './editor_flyout_content_container';
export const InspectorLoader: React.FC<Props> = (props) => {
export const ContentEditorLoader: React.FC<Props> = (props) => {
const [Editor, setEditor] = useState<React.ComponentType<Props> | null>(null);
const loadEditor = useCallback(async () => {
const { InspectorFlyoutContentContainer } = await import(
'./inspector_flyout_content_container'
const { ContentEditorFlyoutContentContainer } = await import(
'./editor_flyout_content_container'
);
setEditor(() => InspectorFlyoutContentContainer);
setEditor(() => ContentEditorFlyoutContentContainer);
}, []);
useEffect(() => {

View file

@ -6,5 +6,5 @@
* Side Public License, v 1.
*/
export { InspectorLoader } from './inspector_loader';
export type { Props as InspectorFlyoutContentContainerProps } from './inspector_flyout_content_container';
export { ContentEditorLoader } from './editor_loader';
export type { Props as ContentEditorFlyoutContentContainerProps } from './editor_flyout_content_container';

View file

@ -11,10 +11,10 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { registerTestBed } from '@kbn/test-jest-helpers';
import type { TestBed } from '@kbn/test-jest-helpers';
import { getMockServices } from '../__jest__';
import { InspectorFlyoutContent } from './inspector_flyout_content';
import type { Props as InspectorFlyoutContentProps } from './inspector_flyout_content';
import { ContentEditorFlyoutContent } from './editor_flyout_content';
import type { Props as ContentEditorFlyoutContentProps } from './editor_flyout_content';
describe('<InspectorFlyoutContent />', () => {
describe('<ContentEditorFlyoutContent />', () => {
beforeAll(() => {
jest.useFakeTimers();
});
@ -26,7 +26,7 @@ describe('<InspectorFlyoutContent />', () => {
describe('metadata', () => {
let testBed: TestBed;
const savedObjectItem: InspectorFlyoutContentProps['item'] = {
const savedObjectItem: ContentEditorFlyoutContentProps['item'] = {
id: '123',
title: 'Foo',
description: 'Some description',
@ -38,29 +38,33 @@ describe('<InspectorFlyoutContent />', () => {
const mockedServices = getMockServices();
const defaultProps: InspectorFlyoutContentProps = {
const defaultProps: ContentEditorFlyoutContentProps = {
item: savedObjectItem,
entityName: 'foo',
services: mockedServices,
onCancel: jest.fn(),
};
const setup = registerTestBed<string, InspectorFlyoutContentProps>(InspectorFlyoutContent, {
memoryRouter: { wrapComponent: false },
defaultProps,
});
const setup = registerTestBed<string, ContentEditorFlyoutContentProps>(
ContentEditorFlyoutContent,
{
memoryRouter: { wrapComponent: false },
defaultProps,
}
);
const waitForValidationResults = async () =>
await act(() => {
const waitForValidationResults = async () => {
await act(async () => {
jest.advanceTimersByTime(550); // There is a 500ms delay to display input errors + async validation
});
};
test('should set the correct flyout title', async () => {
await act(async () => {
testBed = await setup();
});
const { find } = testBed!;
expect(find('flyoutTitle').text()).toBe('Inspector');
expect(find('flyoutTitle').text()).toBe('Foo details');
});
test('should render the form with the provided item', async () => {

View file

@ -11,7 +11,7 @@ import type { FC } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiForm, EuiFormRow, EuiFieldText, EuiTextArea, EuiSpacer } from '@elastic/eui';
import { InspectorFlyoutWarningsCallOut } from './inspector_flyout_warnings';
import { ContentEditorFlyoutWarningsCallOut } from './editor_flyout_warnings';
import type { MetadataFormState, Field } from './use_metadata_form';
import type { SavedObjectsReference, Services } from '../services';
@ -49,10 +49,10 @@ export const MetadataForm: FC<Props> = ({
return (
<EuiForm isInvalid={isSubmitted && !isValid} error={getErrors()} data-test-subj="metadataForm">
<InspectorFlyoutWarningsCallOut warningMessages={getWarnings()} />
<ContentEditorFlyoutWarningsCallOut warningMessages={getWarnings()} />
<EuiFormRow
label={i18n.translate('contentManagement.inspector.metadataForm.nameInputLabel', {
label={i18n.translate('contentManagement.contentEditor.metadataForm.nameInputLabel', {
defaultMessage: 'Name',
})}
error={title.errors}
@ -74,9 +74,12 @@ export const MetadataForm: FC<Props> = ({
<EuiSpacer />
<EuiFormRow
label={i18n.translate('contentManagement.inspector.metadataForm.descriptionInputLabel', {
defaultMessage: 'Description',
})}
label={i18n.translate(
'contentManagement.contentEditor.metadataForm.descriptionInputLabel',
{
defaultMessage: 'Description',
}
)}
error={description.errors}
isInvalid={!isFormFieldValid(description)}
fullWidth
@ -97,7 +100,7 @@ export const MetadataForm: FC<Props> = ({
<>
<EuiSpacer />
<EuiFormRow
label={i18n.translate('contentManagement.inspector.metadataForm.tagsLabel', {
label={i18n.translate('contentManagement.contentEditor.metadataForm.tagsLabel', {
defaultMessage: 'Tags',
})}
fullWidth

View file

@ -47,7 +47,7 @@ const basicValidators: BasicValidators = {
type: 'error',
fn: (value) => {
if (!value || !value.trim()) {
return i18n.translate('contentManagement.inspector.metadataForm.nameIsEmptyError', {
return i18n.translate('contentManagement.contentEditor.metadataForm.nameIsEmptyError', {
defaultMessage: 'A name is required.',
});
}

View file

@ -6,6 +6,6 @@
* Side Public License, v 1.
*/
export { InspectorProvider, InspectorKibanaProvider } from './services';
export { useOpenInspector } from './open_inspector';
export type { OpenInspectorParams } from './open_inspector';
export { ContentEditorProvider, ContentEditorKibanaProvider } from './services';
export { useOpenContentEditor } from './open_content_editor';
export type { OpenContentEditorParams } from './open_content_editor';

View file

@ -11,20 +11,20 @@ import { registerTestBed } from '@kbn/test-jest-helpers';
import { WithServices, getMockServices } from './__jest__';
import type { Services } from './services';
import type { Item } from './types';
import { InspectorLoader } from './components';
import { useOpenInspector } from './open_inspector';
import { ContentEditorLoader } from './components';
import { useOpenContentEditor } from './open_content_editor';
describe('useOpenInspector() hook', () => {
describe('useOpenContentEditor() hook', () => {
const savedObjectItem: Item = { id: 'id', title: 'Foo', tags: [] };
const TestComp = () => {
const openInspector = useOpenInspector();
const openContentEditor = useOpenContentEditor();
return (
<button
onClick={() => {
openInspector({ item: savedObjectItem, entityName: 'Foo' });
openContentEditor({ item: savedObjectItem, entityName: 'Foo' });
}}
data-test-subj="openInspectorButton"
data-test-subj="openContentEditorButton"
>
Open inspector
</button>
@ -41,11 +41,11 @@ describe('useOpenInspector() hook', () => {
test('should call the "openFlyout" provided', () => {
const { find } = setup();
find('openInspectorButton').simulate('click');
find('openContentEditorButton').simulate('click');
expect(openFlyout).toHaveBeenCalled();
const args = openFlyout.mock.calls[0][0] as any;
expect(args?.type).toBe(InspectorLoader);
expect(args?.type).toBe(ContentEditorLoader);
expect(args?.props.item).toBe(savedObjectItem);
expect(args?.props.services).toEqual(mockedServices);
});

View file

@ -10,21 +10,21 @@ import type { OverlayRef } from '@kbn/core-mount-utils-browser';
import { useServices } from './services';
import { InspectorLoader } from './components';
import type { InspectorFlyoutContentContainerProps } from './components';
import { ContentEditorLoader } from './components';
import type { ContentEditorFlyoutContentContainerProps } from './components';
export type OpenInspectorParams = Pick<
InspectorFlyoutContentContainerProps,
export type OpenContentEditorParams = Pick<
ContentEditorFlyoutContentContainerProps,
'item' | 'onSave' | 'isReadonly' | 'entityName' | 'customValidators'
>;
export function useOpenInspector() {
export function useOpenContentEditor() {
const services = useServices();
const { openFlyout } = services;
const flyout = useRef<OverlayRef | null>(null);
return useCallback(
(args: OpenInspectorParams) => {
(args: OpenContentEditorParams) => {
// Validate arguments
if (args.isReadonly === false && args.onSave === undefined) {
throw new Error(`A value for [onSave()] must be provided when [isReadonly] is false.`);
@ -35,7 +35,7 @@ export function useOpenInspector() {
};
flyout.current = openFlyout(
<InspectorLoader {...args} onCancel={closeFlyout} services={services} />,
<ContentEditorLoader {...args} onCancel={closeFlyout} services={services} />,
{
maxWidth: 600,
size: 'm',

View file

@ -36,19 +36,19 @@ export interface Services {
TagSelector?: React.FC<TagSelectorProps>;
}
const InspectorContext = React.createContext<Services | null>(null);
const ContentEditorContext = React.createContext<Services | null>(null);
/**
* Abstract external service Provider.
*/
export const InspectorProvider: FC<Services> = ({ children, ...services }) => {
return <InspectorContext.Provider value={services}>{children}</InspectorContext.Provider>;
export const ContentEditorProvider: FC<Services> = ({ children, ...services }) => {
return <ContentEditorContext.Provider value={services}>{children}</ContentEditorContext.Provider>;
};
/**
* Kibana-specific service types.
*/
export interface InspectorKibanaDependencies {
export interface ContentEditorKibanaDependencies {
/** CoreStart contract */
core: {
overlays: {
@ -97,7 +97,7 @@ export interface InspectorKibanaDependencies {
/**
* Kibana-specific Provider that maps to known dependency types.
*/
export const InspectorKibanaProvider: FC<InspectorKibanaDependencies> = ({
export const ContentEditorKibanaProvider: FC<ContentEditorKibanaDependencies> = ({
children,
...services
}) => {
@ -124,7 +124,7 @@ export const InspectorKibanaProvider: FC<InspectorKibanaDependencies> = ({
);
return (
<InspectorProvider
<ContentEditorProvider
openFlyout={openFlyout}
notifyError={(title, text) => {
core.notifications.toasts.addDanger({ title: toMountPoint(title), text });
@ -133,7 +133,7 @@ export const InspectorKibanaProvider: FC<InspectorKibanaDependencies> = ({
TagSelector={savedObjectsTagging?.ui.components.SavedObjectSaveModalTagSelector}
>
{children}
</InspectorProvider>
</ContentEditorProvider>
);
};
@ -141,11 +141,11 @@ export const InspectorKibanaProvider: FC<InspectorKibanaDependencies> = ({
* React hook for accessing pre-wired services.
*/
export function useServices() {
const context = useContext(InspectorContext);
const context = useContext(ContentEditorContext);
if (!context) {
throw new Error(
'InspectorContext is missing. Ensure your component or React root is wrapped with <InspectorProvider /> or <InspectorKibanaProvider />.'
'ContentEditorContext is missing. Ensure your component or React root is wrapped with <ContentEditorProvider /> or <ContentEditorKibanaProvider />.'
);
}

View file

@ -1,7 +0,0 @@
# @kbn/content-management-inspector
# Content inspector component
## API
TODO: https://github.com/elastic/kibana/issues/144402

View file

@ -49,7 +49,7 @@ NPM_MODULE_EXTRA_FILES = [
RUNTIME_DEPS = [
"//packages/kbn-i18n-react",
"//packages/kbn-i18n",
"//packages/content-management/inspector",
"//packages/content-management/content_editor",
"//packages/core/http/core-http-browser",
"//packages/core/theme/core-theme-browser",
"//packages/kbn-safer-lodash-set",
@ -76,7 +76,7 @@ RUNTIME_DEPS = [
TYPES_DEPS = [
"//packages/kbn-i18n:npm_module_types",
"//packages/kbn-i18n-react:npm_module_types",
"//packages/content-management/inspector:npm_module_types",
"//packages/content-management/content_editor:npm_module_types",
"//packages/core/http/core-http-browser:npm_module_types",
"//packages/core/theme/core-theme-browser:npm_module_types",
"//packages/core/mount-utils/core-mount-utils-browser:npm_module_types",

View file

@ -8,7 +8,7 @@
import React from 'react';
import type { ComponentType } from 'react';
import { from } from 'rxjs';
import { InspectorProvider } from '@kbn/content-management-inspector';
import { ContentEditorProvider } from '@kbn/content-management-content-editor';
import { TagList } from '../mocks';
import { TableListViewProvider, Services } from '../services';
@ -35,11 +35,11 @@ export function WithServices<P>(Comp: ComponentType<P>, overrides: Partial<Servi
return (props: P) => {
const services = getMockServices(overrides);
return (
<InspectorProvider openFlyout={jest.fn()} notifyError={() => undefined}>
<ContentEditorProvider openFlyout={jest.fn()} notifyError={() => undefined}>
<TableListViewProvider {...services}>
<Comp {...(props as any)} />
</TableListViewProvider>
</InspectorProvider>
</ContentEditorProvider>
);
};
}

View file

@ -12,7 +12,7 @@ import type { FormattedRelative } from '@kbn/i18n-react';
import type { MountPoint, OverlayRef } from '@kbn/core-mount-utils-browser';
import type { OverlayFlyoutOpenOptions } from '@kbn/core-overlays-browser';
import { RedirectAppLinksKibanaProvider } from '@kbn/shared-ux-link-redirect-app';
import { InspectorKibanaProvider } from '@kbn/content-management-inspector';
import { ContentEditorKibanaProvider } from '@kbn/content-management-content-editor';
import { TAG_MANAGEMENT_APP_URL } from './constants';
import type { Tag } from './types';
@ -218,7 +218,7 @@ export const TableListViewKibanaProvider: FC<TableListViewKibanaDependencies> =
return (
<RedirectAppLinksKibanaProvider coreStart={core}>
<InspectorKibanaProvider
<ContentEditorKibanaProvider
core={core}
toMountPoint={toMountPoint}
savedObjectsTagging={savedObjectsTagging}
@ -245,7 +245,7 @@ export const TableListViewKibanaProvider: FC<TableListViewKibanaDependencies> =
>
{children}
</TableListViewProvider>
</InspectorKibanaProvider>
</ContentEditorKibanaProvider>
</RedirectAppLinksKibanaProvider>
);
};

View file

@ -52,6 +52,7 @@ const requiredProps: TableListViewProps = {
};
// FLAKY: https://github.com/elastic/kibana/issues/145267
// Note: I will unskip as part of https://github.com/elastic/kibana/pull/145618
describe.skip('TableListView', () => {
beforeAll(() => {
jest.useFakeTimers({ legacyFakeTimers: true });
@ -538,7 +539,7 @@ describe.skip('TableListView', () => {
});
});
describe('inspector', () => {
describe('content editor', () => {
const setupInspector = registerTestBed<string, TableListViewProps>(
WithServices<TableListViewProps>(TableListView),
{
@ -570,13 +571,13 @@ describe.skip('TableListView', () => {
},
];
test('should have an "inpect" button if the inspector is enabled', async () => {
test('should have an "inpect" button if the content editor is enabled', async () => {
let testBed: TestBed;
await act(async () => {
testBed = await setupInspector({
findItems: jest.fn().mockResolvedValue({ total: hits.length, hits }),
inspector: { enabled: true },
contentEditor: { enabled: true },
});
});
@ -584,8 +585,8 @@ describe.skip('TableListView', () => {
component.update();
const { tableCellsValues } = table.getMetaData('itemsInMemTable');
expect(tableCellsValues[0][2]).toBe('Inspect Item 1');
expect(tableCellsValues[1][2]).toBe('Inspect Item 2');
expect(tableCellsValues[0][2]).toBe('View Item 1 details');
expect(tableCellsValues[1][2]).toBe('View Item 2 details');
});
});

View file

@ -26,8 +26,8 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import type { IHttpFetchError } from '@kbn/core-http-browser';
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
import { useOpenInspector } from '@kbn/content-management-inspector';
import type { OpenInspectorParams } from '@kbn/content-management-inspector';
import { useOpenContentEditor } from '@kbn/content-management-content-editor';
import type { OpenContentEditorParams } from '@kbn/content-management-content-editor';
import {
Table,
@ -43,8 +43,8 @@ import { getReducer } from './reducer';
import type { SortColumnField } from './components';
import { useTags } from './use_tags';
interface InspectorConfig
extends Pick<OpenInspectorParams, 'isReadonly' | 'onSave' | 'customValidators'> {
interface ContentEditorConfig
extends Pick<OpenContentEditorParams, 'isReadonly' | 'onSave' | 'customValidators'> {
enabled?: boolean;
}
@ -96,7 +96,7 @@ export interface Props<T extends UserContentCommonSchema = UserContentCommonSche
* @deprecated
*/
withoutPageTemplateWrapper?: boolean;
inspector?: InspectorConfig;
contentEditor?: ContentEditorConfig;
}
export interface State<T extends UserContentCommonSchema = UserContentCommonSchema> {
@ -151,7 +151,7 @@ function TableListViewComp<T extends UserContentCommonSchema>({
getDetailViewLink,
onClickTitle,
id = 'userContent',
inspector = { enabled: false },
contentEditor = { enabled: false },
children,
titleColumnName,
additionalRightSideActions = [],
@ -169,9 +169,9 @@ function TableListViewComp<T extends UserContentCommonSchema>({
);
}
if (inspector.isReadonly === false && inspector.onSave === undefined) {
if (contentEditor.isReadonly === false && contentEditor.onSave === undefined) {
throw new Error(
`[TableListView] A value for [inspector.onSave()] must be provided when [inspector.isReadonly] is false.`
`[TableListView] A value for [contentEditor.onSave()] must be provided when [contentEditor.isReadonly] is false.`
);
}
@ -275,7 +275,7 @@ function TableListViewComp<T extends UserContentCommonSchema>({
}
}, [searchQueryParser, findItems, searchQuery.text]);
const openInspector = useOpenInspector();
const openContentEditor = useOpenContentEditor();
const updateQuery = useCallback((query: Query) => {
dispatch({
@ -301,7 +301,7 @@ function TableListViewComp<T extends UserContentCommonSchema>({
return item.references.find(({ id: refId }) => refId === _id) as SavedObjectsReference;
});
const close = openInspector({
const close = openContentEditor({
item: {
id: item.id,
title: item.attributes.title,
@ -309,18 +309,18 @@ function TableListViewComp<T extends UserContentCommonSchema>({
tags,
},
entityName,
...inspector,
...contentEditor,
onSave:
inspector.onSave &&
contentEditor.onSave &&
(async (args) => {
await inspector.onSave!(args);
await contentEditor.onSave!(args);
await fetchItems();
close();
}),
});
},
[getTagIdsFromReferences, openInspector, entityName, inspector, fetchItems]
[getTagIdsFromReferences, openContentEditor, entityName, contentEditor, fetchItems]
);
const tableColumns = useMemo(() => {
@ -373,7 +373,7 @@ function TableListViewComp<T extends UserContentCommonSchema>({
}
// Add "Actions" column
if (editItem || inspector.enabled !== false) {
if (editItem || contentEditor.enabled !== false) {
const actions: EuiTableActionsColumnType<T>['actions'] = [];
if (editItem) {
@ -399,20 +399,23 @@ function TableListViewComp<T extends UserContentCommonSchema>({
});
}
if (inspector.enabled !== false) {
if (contentEditor.enabled !== false) {
actions.push({
name: (item) => {
return i18n.translate('contentManagement.tableList.listing.table.inspectActionName', {
defaultMessage: 'Inspect {itemDescription}',
values: {
itemDescription: get(item, 'attributes.title'),
},
});
return i18n.translate(
'contentManagement.tableList.listing.table.viewDetailsActionName',
{
defaultMessage: 'View {itemTitle} details',
values: {
itemTitle: get(item, 'attributes.title'),
},
}
);
},
description: i18n.translate(
'contentManagement.tableList.listing.table.inspectActionDescription',
'contentManagement.tableList.listing.table.viewDetailsActionDescription',
{
defaultMessage: 'Inspect',
defaultMessage: 'View details',
}
),
icon: 'inspect',
@ -443,7 +446,7 @@ function TableListViewComp<T extends UserContentCommonSchema>({
addOrRemoveIncludeTagFilter,
addOrRemoveExcludeTagFilter,
DateFormatterComp,
inspector,
contentEditor,
inspectItem,
]);

View file

@ -20,7 +20,7 @@ import { useLocation } from 'react-router-dom';
import type { SavedObjectsFindOptionsReference } from '@kbn/core/public';
import { useKibana, useExecutionContext } from '@kbn/kibana-react-plugin/public';
import { TableListView } from '@kbn/content-management-table-list';
import type { OpenInspectorParams } from '@kbn/content-management-inspector';
import type { OpenContentEditorParams } from '@kbn/content-management-content-editor';
import type { UserContentCommonSchema } from '@kbn/content-management-table-list';
import { findListItems } from '../../utils/saved_visualize_utils';
import { updateBasicSoAttributes } from '../../utils/saved_objects_utils/update_basic_attributes';
@ -188,7 +188,7 @@ export const VisualizeListing = () => {
[listingLimit, uiSettings, savedObjects.client]
);
const onInspectorSave = useCallback(
const onContentEditorSave = useCallback(
async (args: { id: string; title: string; description?: string; tags: string[] }) => {
const content = visualizedUserContent.current?.find(({ id }) => id === args.id);
@ -208,7 +208,7 @@ export const VisualizeListing = () => {
[overlays, savedObjects.client, savedObjectsTagging]
);
const inspectorValidators: OpenInspectorParams['customValidators'] = useMemo(
const contentEditorValidators: OpenContentEditorParams['customValidators'] = useMemo(
() => ({
title: [
{
@ -303,10 +303,10 @@ export const VisualizeListing = () => {
listingLimit={listingLimit}
initialPageSize={initialPageSize}
initialFilter={''}
inspector={{
contentEditor={{
isReadonly: !visualizeCapabilities.save,
onSave: onInspectorSave,
customValidators: inspectorValidators,
onSave: onContentEditorSave,
customValidators: contentEditorValidators,
}}
emptyPrompt={noItemsFragment}
entityName={i18n.translate('visualizations.listing.table.entityName', {

View file

@ -18,8 +18,8 @@
"@kbn/analytics-shippers-fullstory/*": ["packages/analytics/shippers/fullstory/*"],
"@kbn/analytics-shippers-gainsight": ["packages/analytics/shippers/gainsight"],
"@kbn/analytics-shippers-gainsight/*": ["packages/analytics/shippers/gainsight/*"],
"@kbn/content-management-inspector": ["packages/content-management/inspector"],
"@kbn/content-management-inspector/*": ["packages/content-management/inspector/*"],
"@kbn/content-management-content-editor": ["packages/content-management/content_editor"],
"@kbn/content-management-content-editor/*": ["packages/content-management/content_editor/*"],
"@kbn/content-management-table-list": ["packages/content-management/table_list"],
"@kbn/content-management-table-list/*": ["packages/content-management/table_list/*"],
"@kbn/core-analytics-browser": ["packages/core/analytics/core-analytics-browser"],

View file

@ -326,7 +326,6 @@
"console.welcomePage.supportedRequestFormatDescription": "Lors de la saisie d'une requête, la console fera des suggestions que vous pourrez accepter en appuyant sur Entrée/Tab. Ces suggestions sont faites en fonction de la structure de la requête, des index et des types.",
"console.welcomePage.supportedRequestFormatTitle": "La console prend en charge les requêtes dans un format compact, tel que le format cURL :",
"contentManagement.inspector.metadataForm.unableToSaveDangerMessage": "Impossible d'enregistrer {entityName}",
"contentManagement.inspector.saveButtonLabel": "Mettre à jour {entityName}",
"contentManagement.tableList.listing.createNewItemButtonLabel": "Créer {entityName}",
"contentManagement.tableList.listing.deleteButtonMessage": "Supprimer {itemCount} {entityName}",
"contentManagement.tableList.listing.deleteConfirmModalDescription": "Vous ne pourrez pas récupérer les {entityNamePlural} supprimés.",
@ -335,16 +334,9 @@
"contentManagement.tableList.listing.listingLimitExceededDescription": "Vous avez {totalItems} {entityNamePlural}, mais votre paramètre {listingLimitText} empêche le tableau ci-dessous d'en afficher plus de {listingLimitValue}.",
"contentManagement.tableList.listing.listingLimitExceededDescriptionPermissions": "Vous pouvez modifier ce paramètre sous {advancedSettingsLink}.",
"contentManagement.tableList.listing.table.editActionName": "Modifier {itemDescription}",
"contentManagement.tableList.listing.table.inspectActionName": "Inspecter {itemDescription}",
"contentManagement.tableList.listing.unableToDeleteDangerMessage": "Impossible de supprimer la/le/les {entityName}(s)",
"contentManagement.tableList.tagBadge.buttonLabel": "Bouton de balise {tagName}.",
"contentManagement.tableList.tagFilterPanel.modifierKeyHelpText": "{modifierKeyPrefix} + cliquer sur Exclure",
"contentManagement.inspector.cancelButtonLabel": "Annuler",
"contentManagement.inspector.flyoutTitle": "Inspecteur",
"contentManagement.inspector.metadataForm.descriptionInputLabel": "Description",
"contentManagement.inspector.metadataForm.nameInputLabel": "Nom",
"contentManagement.inspector.metadataForm.nameIsEmptyError": "Nom obligatoire.",
"contentManagement.inspector.metadataForm.tagsLabel": "Balises",
"contentManagement.tableList.lastUpdatedColumnTitle": "Dernière mise à jour",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "Annuler",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "Supprimer",
@ -355,7 +347,6 @@
"contentManagement.tableList.listing.listingLimitExceededTitle": "Limite de listing dépassée",
"contentManagement.tableList.listing.table.actionTitle": "Actions",
"contentManagement.tableList.listing.table.editActionDescription": "Modifier",
"contentManagement.tableList.listing.table.inspectActionDescription": "Inspecter",
"contentManagement.tableList.listing.tableSortSelect.headerLabel": "Trier par",
"contentManagement.tableList.listing.tableSortSelect.nameAscLabel": "Nom A-Z",
"contentManagement.tableList.listing.tableSortSelect.nameDescLabel": "Nom Z-A",

View file

@ -326,7 +326,6 @@
"console.welcomePage.supportedRequestFormatDescription": "リクエストの入力中、コンソールが候補を提案するので、Enter/Tabを押して確定できます。これらの候補はリクエストの構造、およびインデックス、タイプに基づくものです。",
"console.welcomePage.supportedRequestFormatTitle": "コンソールは cURL と同様に、コンパクトなフォーマットのリクエストを理解できます。",
"contentManagement.inspector.metadataForm.unableToSaveDangerMessage": "{entityName}を保存できません",
"contentManagement.inspector.saveButtonLabel": "{entityName}の作成",
"contentManagement.tableList.listing.createNewItemButtonLabel": "Create {entityName}",
"contentManagement.tableList.listing.deleteButtonMessage": "{itemCount} 件の {entityName} を削除",
"contentManagement.tableList.listing.deleteConfirmModalDescription": "削除された {entityNamePlural} は復元できません。",
@ -337,16 +336,9 @@
"contentManagement.tableList.listing.noAvailableItemsMessage": "利用可能な {entityNamePlural} がありません。",
"contentManagement.tableList.listing.noMatchedItemsMessage": "検索条件に一致する {entityNamePlural} がありません。",
"contentManagement.tableList.listing.table.editActionName": "{itemDescription}の編集",
"contentManagement.tableList.listing.table.inspectActionName": "{itemDescription}の検査",
"contentManagement.tableList.listing.unableToDeleteDangerMessage": "{entityName} を削除できません",
"contentManagement.tableList.tagBadge.buttonLabel": "{tagName}タグボタン。",
"contentManagement.tableList.tagFilterPanel.modifierKeyHelpText": "{modifierKeyPrefix} + 除外をクリック",
"contentManagement.inspector.cancelButtonLabel": "キャンセル",
"contentManagement.inspector.flyoutTitle": "インスペクター",
"contentManagement.inspector.metadataForm.descriptionInputLabel": "説明",
"contentManagement.inspector.metadataForm.nameInputLabel": "名前",
"contentManagement.inspector.metadataForm.nameIsEmptyError": "名前が必要です。",
"contentManagement.inspector.metadataForm.tagsLabel": "タグ",
"contentManagement.tableList.lastUpdatedColumnTitle": "最終更新",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "キャンセル",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "削除",
@ -357,7 +349,6 @@
"contentManagement.tableList.listing.listingLimitExceededTitle": "リスティング制限超過",
"contentManagement.tableList.listing.table.actionTitle": "アクション",
"contentManagement.tableList.listing.table.editActionDescription": "編集",
"contentManagement.tableList.listing.table.inspectActionDescription": "検査",
"contentManagement.tableList.listing.tableSortSelect.headerLabel": "並べ替え基準",
"contentManagement.tableList.listing.tableSortSelect.nameAscLabel": "名前A-Z",
"contentManagement.tableList.listing.tableSortSelect.nameDescLabel": "名前Z-A",

View file

@ -326,7 +326,6 @@
"console.welcomePage.supportedRequestFormatDescription": "键入请求时,控制台将提供建议,您可以通过按 Enter/Tab 键来接受建议。这些建议基于请求结构以及索引和类型进行提供。",
"console.welcomePage.supportedRequestFormatTitle": "Console 理解紧凑格式的请求,类似于 cURL",
"contentManagement.inspector.metadataForm.unableToSaveDangerMessage": "无法保存 {entityName}",
"contentManagement.inspector.saveButtonLabel": "更新 {entityName}",
"contentManagement.tableList.listing.createNewItemButtonLabel": "创建 {entityName}",
"contentManagement.tableList.listing.deleteButtonMessage": "删除 {itemCount} 个 {entityName}",
"contentManagement.tableList.listing.deleteConfirmModalDescription": "无法恢复删除的 {entityNamePlural}。",
@ -337,16 +336,9 @@
"contentManagement.tableList.listing.noAvailableItemsMessage": "没有可用的{entityNamePlural}。",
"contentManagement.tableList.listing.noMatchedItemsMessage": "没有任何{entityNamePlural}匹配您的搜索。",
"contentManagement.tableList.listing.table.editActionName": "编辑 {itemDescription}",
"contentManagement.tableList.listing.table.inspectActionName": "检查 {itemDescription}",
"contentManagement.tableList.listing.unableToDeleteDangerMessage": "无法删除{entityName}",
"contentManagement.tableList.tagBadge.buttonLabel": "{tagName} 标签按钮。",
"contentManagement.tableList.tagFilterPanel.modifierKeyHelpText": "{modifierKeyPrefix} + 单击排除",
"contentManagement.inspector.cancelButtonLabel": "取消",
"contentManagement.inspector.flyoutTitle": "检查器",
"contentManagement.inspector.metadataForm.descriptionInputLabel": "描述",
"contentManagement.inspector.metadataForm.nameInputLabel": "名称",
"contentManagement.inspector.metadataForm.nameIsEmptyError": "名称必填。",
"contentManagement.inspector.metadataForm.tagsLabel": "标签",
"contentManagement.tableList.lastUpdatedColumnTitle": "上次更新时间",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "取消",
"contentManagement.tableList.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "删除",
@ -357,7 +349,6 @@
"contentManagement.tableList.listing.listingLimitExceededTitle": "已超过列表限制",
"contentManagement.tableList.listing.table.actionTitle": "操作",
"contentManagement.tableList.listing.table.editActionDescription": "编辑",
"contentManagement.tableList.listing.table.inspectActionDescription": "检查",
"contentManagement.tableList.listing.tableSortSelect.headerLabel": "排序依据",
"contentManagement.tableList.listing.tableSortSelect.nameAscLabel": "名称 A-Z",
"contentManagement.tableList.listing.tableSortSelect.nameDescLabel": "名称 Z-A",

View file

@ -2817,7 +2817,7 @@
version "0.0.0"
uid ""
"@kbn/content-management-inspector@link:bazel-bin/packages/content-management/inspector":
"@kbn/content-management-content-editor@link:bazel-bin/packages/content-management/content_editor":
version "0.0.0"
uid ""