kibana/examples/controls_example/public/edit_example.tsx
Hannah Mudge 91635994fd
[Tech Debt] Remove deprecated EuiLoadingContent (#156316)
## Summary

This PR removes the deprecated `EuiLoadingContent` in favour of the new
`EuiSkeletonText` + `EuiSkeletonRectangle` components in all
Presentation-owned files.

cc @elastic/eui-team 


### Checklist

- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)



### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
2023-05-03 08:01:37 -06:00

202 lines
5.9 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { pickBy } from 'lodash';
import React, { useState } from 'react';
import {
EuiButton,
EuiButtonEmpty,
EuiButtonGroup,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
EuiSkeletonRectangle,
} from '@elastic/eui';
import { ViewMode } from '@kbn/embeddable-plugin/public';
import { OPTIONS_LIST_CONTROL, RANGE_SLIDER_CONTROL } from '@kbn/controls-plugin/common';
import {
type ControlGroupInput,
ControlGroupRenderer,
AwaitingControlGroupAPI,
ACTION_EDIT_CONTROL,
ACTION_DELETE_CONTROL,
} from '@kbn/controls-plugin/public';
import { ControlInputTransform } from '@kbn/controls-plugin/common/types';
const INPUT_KEY = 'kbnControls:saveExample:input';
const WITH_CUSTOM_PLACEHOLDER = 'Custom Placeholder';
export const EditExample = () => {
const [isSaving, setIsSaving] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [controlGroupAPI, setControlGroupAPI] = useState<AwaitingControlGroupAPI>(null);
const [toggleIconIdToSelectedMapIcon, setToggleIconIdToSelectedMapIcon] = useState<{
[id: string]: boolean;
}>({});
function onChangeIconsMultiIcons(optionId: string) {
const newToggleIconIdToSelectedMapIcon = {
...toggleIconIdToSelectedMapIcon,
...{
[optionId]: !toggleIconIdToSelectedMapIcon[optionId],
},
};
if (controlGroupAPI) {
const disabledActions: string[] = Object.keys(
pickBy(newToggleIconIdToSelectedMapIcon, (value) => value)
);
controlGroupAPI.updateInput({ disabledActions });
}
setToggleIconIdToSelectedMapIcon(newToggleIconIdToSelectedMapIcon);
}
async function onSave() {
if (!controlGroupAPI) return;
setIsSaving(true);
localStorage.setItem(INPUT_KEY, JSON.stringify(controlGroupAPI.getInput()));
// simulated async save await
await new Promise((resolve) => setTimeout(resolve, 1000));
setIsSaving(false);
}
async function onLoad() {
setIsLoading(true);
// simulated async load await
await new Promise((resolve) => setTimeout(resolve, 6000));
let input: Partial<ControlGroupInput> = {};
const inputAsString = localStorage.getItem(INPUT_KEY);
if (inputAsString) {
try {
input = JSON.parse(inputAsString);
const disabledActions = input.disabledActions ?? [];
setToggleIconIdToSelectedMapIcon({
[ACTION_EDIT_CONTROL]: disabledActions.includes(ACTION_EDIT_CONTROL),
[ACTION_DELETE_CONTROL]: disabledActions.includes(ACTION_DELETE_CONTROL),
[WITH_CUSTOM_PLACEHOLDER]: false,
});
} catch (e) {
// ignore parse errors
}
}
setIsLoading(false);
return input;
}
const controlInputTransform: ControlInputTransform = (newState, type) => {
if (type === OPTIONS_LIST_CONTROL && toggleIconIdToSelectedMapIcon[WITH_CUSTOM_PLACEHOLDER]) {
return {
...newState,
placeholder: 'Custom Placeholder',
};
}
if (type === RANGE_SLIDER_CONTROL) {
return {
...newState,
value: ['0', '4'],
};
}
return newState;
};
return (
<>
<EuiTitle>
<h2>Edit and save example</h2>
</EuiTitle>
<EuiText>
<p>Customize controls and persist state to local storage.</p>
</EuiText>
<EuiSpacer size="m" />
<EuiPanel hasBorder={true}>
<EuiFlexGroup gutterSize="m" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="primary"
iconType="plusInCircle"
isDisabled={controlGroupAPI === undefined}
onClick={() => {
controlGroupAPI!.openAddDataControlFlyout({ controlInputTransform });
}}
>
Add control
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={true}>
<EuiButtonGroup
legend="Text style"
buttonSize="m"
options={[
{
id: ACTION_EDIT_CONTROL,
label: 'Disable edit action',
value: ACTION_EDIT_CONTROL,
},
{
id: ACTION_DELETE_CONTROL,
label: 'Disable delete action',
value: ACTION_DELETE_CONTROL,
},
{
id: WITH_CUSTOM_PLACEHOLDER,
label: WITH_CUSTOM_PLACEHOLDER,
value: WITH_CUSTOM_PLACEHOLDER,
},
]}
idToSelectedMap={toggleIconIdToSelectedMapIcon}
type="multi"
onChange={(id: string) => onChangeIconsMultiIcons(id)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
color="primary"
isDisabled={controlGroupAPI === undefined || isSaving}
onClick={onSave}
isLoading={isSaving}
>
Save
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
{isLoading ? (
<>
<EuiSpacer />
<EuiSkeletonRectangle width="100%" height="2em" />
</>
) : null}
<ControlGroupRenderer
ref={setControlGroupAPI}
getCreationOptions={async (initialInput, builder) => {
const persistedInput = await onLoad();
return {
initialInput: {
...initialInput,
...persistedInput,
viewMode: ViewMode.EDIT,
},
};
}}
/>
</EuiPanel>
</>
);
};