Skip to content

Commit

Permalink
[Lens] introduce unified user messages system (#147818)
Browse files Browse the repository at this point in the history
  • Loading branch information
drewdaemon authored Jan 23, 2023
1 parent 2a18937 commit 2ed0123
Show file tree
Hide file tree
Showing 65 changed files with 3,338 additions and 2,552 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,4 @@ export const getRotatingNumberVisualization = ({
domElement
);
},

getErrorMessages(state) {
// Is it possible to break it?
return undefined;
},
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions x-pack/plugins/lens/public/app_plugin/app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import moment from 'moment';

import { setState, LensAppState } from '../state_management';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../editor_frame_service/editor_frame/expression_helpers');
jest.mock('@kbn/core/public');
jest.mock('../persistence/saved_objects_utils/check_for_duplicate_title', () => ({
Expand Down Expand Up @@ -85,6 +86,7 @@ describe('Lens App', () => {
visualizationMap,
topNavMenuEntryGenerators: [],
theme$: new Observable(),
coreStart: coreMock.createStart(),
};
}

Expand Down Expand Up @@ -144,6 +146,8 @@ describe('Lens App', () => {
expect(frame.EditorFrameContainer).toHaveBeenLastCalledWith(
{
indexPatternService: expect.any(Object),
getUserMessages: expect.any(Function),
addUserMessages: expect.any(Function),
lensInspector: {
adapters: {
expression: expect.any(Object),
Expand Down
110 changes: 109 additions & 1 deletion x-pack/plugins/lens/public/app_plugin/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { LensAppLocatorParams } from '../../common/locator/locator';
import { LensAppProps, LensAppServices } from './types';
import { LensTopNavMenu } from './lens_top_nav';
import { LensByReferenceInput } from '../embeddable';
import { EditorFrameInstance } from '../types';
import { AddUserMessages, EditorFrameInstance, UserMessage, UserMessagesGetter } from '../types';
import { Document } from '../persistence/saved_object_store';

import {
Expand All @@ -28,6 +28,9 @@ import {
DispatchSetState,
selectSavedObjectFormat,
updateIndexPatterns,
updateDatasourceState,
selectActiveDatasourceId,
selectFrameDatasourceAPI,
} from '../state_management';
import { SaveModalContainer, runSaveLensVisualization } from './save_modal_container';
import { LensInspector } from '../lens_inspector_service';
Expand All @@ -38,6 +41,7 @@ import {
createIndexPatternService,
} from '../data_views_service/service';
import { replaceIndexpattern } from '../state_management/lens_slice';
import { filterUserMessages, getApplicationUserMessages } from './get_application_user_messages';

export type SaveProps = Omit<OnSaveProps, 'onTitleDuplicate' | 'newDescription'> & {
returnToOrigin: boolean;
Expand All @@ -62,6 +66,7 @@ export function App({
topNavMenuEntryGenerators,
initialContext,
theme$,
coreStart,
}: LensAppProps) {
const lensAppServices = useKibana<LensAppServices>().services;

Expand Down Expand Up @@ -98,8 +103,10 @@ export function App({
sharingSavedObjectProps,
isLinkedToOriginatingApp,
searchSessionId,
datasourceStates,
isLoading,
isSaveable,
visualization,
} = useLensSelector((state) => state.lens);

const selectorDependencies = useMemo(
Expand Down Expand Up @@ -473,6 +480,98 @@ export function App({
})
: undefined;

const activeDatasourceId = useLensSelector(selectActiveDatasourceId);

const frameDatasourceAPI = useLensSelector((state) =>
selectFrameDatasourceAPI(state, datasourceMap)
);

const [userMessages, setUserMessages] = useState<UserMessage[]>([]);

useEffect(() => {
setUserMessages([
...(activeDatasourceId
? datasourceMap[activeDatasourceId].getUserMessages(
datasourceStates[activeDatasourceId].state,
{
frame: frameDatasourceAPI,
setState: (newStateOrUpdater) =>
dispatch(
updateDatasourceState({
updater: newStateOrUpdater,
datasourceId: activeDatasourceId,
})
),
}
)
: []),
...(visualization.activeId && visualization.state
? visualizationMap[visualization.activeId]?.getUserMessages?.(visualization.state, {
frame: frameDatasourceAPI,
}) ?? []
: []),
...getApplicationUserMessages({
visualizationType: persistedDoc?.visualizationType,
visualizationMap,
visualization,
activeDatasource: activeDatasourceId ? datasourceMap[activeDatasourceId] : null,
activeDatasourceState: activeDatasourceId ? datasourceStates[activeDatasourceId] : null,
core: coreStart,
dataViews: frameDatasourceAPI.dataViews,
}),
]);
}, [
activeDatasourceId,
coreStart,
datasourceMap,
datasourceStates,
dispatch,
frameDatasourceAPI,
persistedDoc?.visualizationType,
visualization,
visualizationMap,
]);

// these are messages managed from other parts of Lens
const [additionalUserMessages, setAdditionalUserMessages] = useState<Record<string, UserMessage>>(
{}
);

const getUserMessages: UserMessagesGetter = (locationId, filterArgs) =>
filterUserMessages(
[...userMessages, ...Object.values(additionalUserMessages)],
locationId,
filterArgs
);

const addUserMessages: AddUserMessages = (messages) => {
const newMessageMap = {
...additionalUserMessages,
};

const addedMessageIds: string[] = [];
messages.forEach((message) => {
if (!newMessageMap[message.uniqueId]) {
addedMessageIds.push(message.uniqueId);
newMessageMap[message.uniqueId] = message;
}
});

if (addedMessageIds.length) {
setAdditionalUserMessages(newMessageMap);
}

return () => {
const withMessagesRemoved = {
...additionalUserMessages,
};

addedMessageIds.forEach((id) => delete withMessagesRemoved[id]);

setAdditionalUserMessages(withMessagesRemoved);
};
};

return (
<>
<div className="lnsApp" data-test-subj="lnsApp" role="main">
Expand Down Expand Up @@ -506,6 +605,7 @@ export function App({
theme$={theme$}
indexPatternService={indexPatternService}
onTextBasedSavedAndExit={onTextBasedSavedAndExit}
getUserMessages={getUserMessages}
shortUrlService={shortUrlService}
/>
{getLegacyUrlConflictCallout()}
Expand All @@ -515,6 +615,8 @@ export function App({
showNoDataPopover={showNoDataPopover}
lensInspector={lensInspector}
indexPatternService={indexPatternService}
getUserMessages={getUserMessages}
addUserMessages={addUserMessages}
/>
)}
</div>
Expand Down Expand Up @@ -582,18 +684,24 @@ export function App({
const MemoizedEditorFrameWrapper = React.memo(function EditorFrameWrapper({
editorFrame,
showNoDataPopover,
getUserMessages,
addUserMessages,
lensInspector,
indexPatternService,
}: {
editorFrame: EditorFrameInstance;
lensInspector: LensInspector;
showNoDataPopover: () => void;
getUserMessages: UserMessagesGetter;
addUserMessages: AddUserMessages;
indexPatternService: IndexPatternServiceAPI;
}) {
const { EditorFrameContainer } = editorFrame;
return (
<EditorFrameContainer
showNoDataPopover={showNoDataPopover}
getUserMessages={getUserMessages}
addUserMessages={addUserMessages}
lensInspector={lensInspector}
indexPatternService={indexPatternService}
/>
Expand Down
Loading

0 comments on commit 2ed0123

Please sign in to comment.