Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Infrastructure UI] Adopt new saved views API #155827

Merged
merged 42 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7b488c3
feat(infra): wip useInventoryViews
Apr 19, 2023
7228a31
feat(infra): extract react query config
Apr 20, 2023
34e8571
feat(infra): wip useInventoryViews mutations
Apr 20, 2023
54a5172
refactor(infra): remove currentView placeholder
Apr 20, 2023
a6b3809
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani Apr 26, 2023
a76f79a
refactor(infra): update types
Apr 26, 2023
4fd307b
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani Apr 26, 2023
5f65776
refactor(infra): finalize types
Apr 26, 2023
f3f18a9
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani Apr 26, 2023
d23b773
feat(infra): use new useInventoryView hook
Apr 26, 2023
c95eed3
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Apr 26, 2023
f1ff109
fix(infra): update insertion logic for view
Apr 26, 2023
8d150fa
fix(infra): wait to update source
Apr 26, 2023
8f86912
Merge branch '154725-create-saved-views-hooks' of github.com:tonyghia…
Apr 26, 2023
b3265ca
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Apr 26, 2023
d597acf
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Apr 26, 2023
5de74e8
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Apr 26, 2023
08d7b49
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani Apr 27, 2023
ac20959
feat(infra): update typing Inventory Views
Apr 27, 2023
9cc2345
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Apr 27, 2023
a164def
feat(infra): add useMetricsExplorerViews hook
Apr 27, 2023
38edf9b
feat(infra): refine types for metrics views
Apr 27, 2023
cd974bd
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani Apr 27, 2023
b0b9f03
fix(infra): types
Apr 27, 2023
4092e28
tests(infra): remove legacy tests
Apr 27, 2023
4cfe534
tests(infra): remove exclusive tests
Apr 27, 2023
5a88bef
refactor(translation): remove unused translations
Apr 27, 2023
78df44d
refactor(translation): update toolbar types
Apr 27, 2023
d55002f
refactor(infra): switch to icon button for better alignment
Apr 27, 2023
ee872cd
refactor(infra): update test
Apr 27, 2023
7c8dae6
refactor(infra): update types
Apr 27, 2023
b526b14
refactor(infra): minor components changes
Apr 28, 2023
1ffd3e4
tests(infra): update views tets
Apr 28, 2023
cca3426
fix(infra): handle not found view with fallback to default
Apr 28, 2023
183b88c
fix(infra): remove memo
Apr 28, 2023
04ac8c7
fix(infra): fix flaky test
Apr 28, 2023
fa009c9
Update x-pack/plugins/infra/public/components/saved_views/manage_view…
tonyghiani May 2, 2023
3e3cc33
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani May 2, 2023
6915fb5
Update x-pack/plugins/infra/public/hooks/use_inventory_views.ts
tonyghiani May 2, 2023
bcd0eb3
Update x-pack/plugins/infra/public/services/inventory_views/types.ts
tonyghiani May 2, 2023
bf3718c
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani May 2, 2023
d881c37
Merge branch 'main' into 154725-create-saved-views-hooks
tonyghiani May 2, 2023
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 @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useState } from 'react';
import React, { useMemo } from 'react';
import useToggle from 'react-use/lib/useToggle';

import {
Expand All @@ -22,107 +22,85 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { SavedView } from '../../containers/saved_view/saved_view';
import { EuiBasicTableColumn } from '@elastic/eui';
import { EuiButtonIcon } from '@elastic/eui';
import { MetricsExplorerView } from '../../../common/metrics_explorer_views';
import type { InventoryView } from '../../../common/inventory_views';
import { UseInventoryViewsResult } from '../../hooks/use_inventory_views';
import { UseMetricsExplorerViewsResult } from '../../hooks/use_metrics_explorer_views';

interface Props<ViewState> {
views: Array<SavedView<ViewState>>;
type View = InventoryView | MetricsExplorerView;
type UseViewResult = UseInventoryViewsResult | UseMetricsExplorerViewsResult;

export interface ManageViewsFlyoutProps {
views: UseViewResult['views'];
loading: boolean;
sourceIsLoading: boolean;
onClose(): void;
onMakeDefaultView(id: string): void;
setView(viewState: ViewState): void;
onDeleteView(id: string): void;
onMakeDefaultView: UseViewResult['setDefaultViewById'];
onSwitchView: UseViewResult['switchViewById'];
onDeleteView: UseViewResult['deleteViewById'];
}

interface DeleteConfimationProps {
isDisabled?: boolean;
onConfirm(): void;
}

const DeleteConfimation = ({ isDisabled, onConfirm }: DeleteConfimationProps) => {
const [isConfirmVisible, toggleVisibility] = useToggle(false);

return isConfirmVisible ? (
<EuiFlexGroup>
<EuiButtonEmpty onClick={toggleVisibility} data-test-subj="hideConfirm">
<FormattedMessage defaultMessage="cancel" id="xpack.infra.waffle.savedViews.cancel" />
</EuiButtonEmpty>
<EuiButton
disabled={isDisabled}
fill={true}
iconType="trash"
color="danger"
onClick={onConfirm}
data-test-subj="showConfirm"
>
<FormattedMessage
defaultMessage="Delete view?"
id="xpack.infra.openView.actionNames.deleteConfirmation"
/>
</EuiButton>
</EuiFlexGroup>
) : (
<EuiButtonEmpty
data-test-subj="infraDeleteConfimationButton"
iconType="trash"
color="danger"
onClick={toggleVisibility}
/>
);
const searchConfig = {
box: { incremental: true },
};

export function SavedViewManageViewsFlyout<ViewState>({
export function ManageViewsFlyout({
onClose,
views,
setView,
views = [],
onSwitchView,
onMakeDefaultView,
onDeleteView,
loading,
sourceIsLoading,
}: Props<ViewState>) {
const [inProgressView, setInProgressView] = useState<string | null>(null);
}: ManageViewsFlyoutProps) {
// Add name as top level property to allow in memory search
const namedViews = useMemo(() => views.map(addOwnName), [views]);

const renderName = (name: string, item: SavedView<ViewState>) => (
const renderName = (name: string, item: View) => (
<EuiButtonEmpty
key={item.id}
data-test-subj="infraRenderNameButton"
onClick={() => {
setView(item);
onSwitchView(item.id);
onClose();
}}
>
{name}
</EuiButtonEmpty>
);

const renderDeleteAction = (item: SavedView<ViewState>) => {
const renderDeleteAction = (item: View) => {
return (
<DeleteConfimation
key={item.id}
isDisabled={item.isDefault}
isDisabled={item.attributes.isDefault}
Copy link
Member

Choose a reason for hiding this comment

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

Q: Should we do this check earlier and disable the delete icon button? Maybe showing a tooltip that the default view can't be deleted if it's not clear there πŸ€” When I tested I saw that I can still click it the delete icon and after that I see a disabled button:

Screen.Recording.2023-04-28.at.16.13.49.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I spoke with @kkurstak in advance about this and I agree we could make a lot of improvements on the UX for saved views!
This work is however intended to only migrate the implementation for the saved views feature, we'll have the chance to further improve its usage when this work is finalized.

onConfirm={() => {
onDeleteView(item.id);
}}
/>
);
};

const renderMakeDefaultAction = (item: SavedView<ViewState>) => {
const renderMakeDefaultAction = (item: View) => {
return (
<EuiButtonEmpty
<EuiButtonIcon
key={item.id}
data-test-subj="infraRenderMakeDefaultActionButton"
isLoading={inProgressView === item.id && sourceIsLoading}
iconType={item.isDefault ? 'starFilled' : 'starEmpty'}
iconType={item.attributes.isDefault ? 'starFilled' : 'starEmpty'}
size="s"
onClick={() => {
setInProgressView(item.id);
onMakeDefaultView(item.id);
}}
/>
);
};

const columns = [
const columns: Array<EuiBasicTableColumn<View>> = [
{
field: 'name',
name: i18n.translate('xpack.infra.openView.columnNames.name', { defaultMessage: 'Name' }),
Expand All @@ -139,7 +117,7 @@ export function SavedViewManageViewsFlyout<ViewState>({
render: renderMakeDefaultAction,
},
{
available: (item: SavedView<ViewState>) => item.id !== '0',
available: (item) => !item.attributes.isStatic,
render: renderDeleteAction,
},
],
Expand All @@ -161,10 +139,10 @@ export function SavedViewManageViewsFlyout<ViewState>({
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiInMemoryTable
items={views}
items={namedViews}
columns={columns}
loading={loading}
search={true}
search={searchConfig}
pagination={true}
sorting={true}
/>
Expand All @@ -178,3 +156,41 @@ export function SavedViewManageViewsFlyout<ViewState>({
</EuiPortal>
);
}

const DeleteConfimation = ({ isDisabled, onConfirm }: DeleteConfimationProps) => {
const [isConfirmVisible, toggleVisibility] = useToggle(false);

return isConfirmVisible ? (
<EuiFlexGroup>
<EuiButtonEmpty onClick={toggleVisibility} data-test-subj="hideConfirm">
<FormattedMessage defaultMessage="cancel" id="xpack.infra.waffle.savedViews.cancel" />
</EuiButtonEmpty>
<EuiButton
disabled={isDisabled}
fill={true}
iconType="trash"
color="danger"
onClick={onConfirm}
data-test-subj="showConfirm"
>
<FormattedMessage
defaultMessage="Delete view?"
id="xpack.infra.openView.actionNames.deleteConfirmation"
/>
</EuiButton>
</EuiFlexGroup>
) : (
<EuiButtonIcon
data-test-subj="infraDeleteConfimationButton"
iconType="trash"
color="danger"
size="s"
onClick={toggleVisibility}
/>
);
};

/**
* Helpers
*/
const addOwnName = (view: View) => ({ ...view, name: view.attributes.name });
Loading