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

[SR] Add tooltips for disabled fields on managed SLM repository and policy #196565

Merged
merged 7 commits into from
Oct 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { Fragment, useState } from 'react';
import React, { Fragment, useState, ReactElement } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import {
EuiDescribedFormGroup,
Expand All @@ -22,6 +22,7 @@ import {
EuiText,
EuiCallOut,
EuiCode,
EuiToolTip,
} from '@elastic/eui';

import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public';
Expand Down Expand Up @@ -54,6 +55,21 @@ export const PolicyStepLogistics: React.FunctionComponent<StepProps> = ({
const { i18n, history } = useServices();
const { docLinks } = useCore();

const disableToolTip = (component: ReactElement): ReactElement => {
return policy?.isManagedPolicy ? (
<EuiToolTip
content={i18n.translate('xpack.snapshotRestore.policyForm.disableToolTipContent', {
defaultMessage: 'This field is disabled because you are editing a managed policy.',
})}
display="block"
>
{component}
</EuiToolTip>
) : (
component
);
};

const [showRepositoryNotFoundWarning, setShowRepositoryNotFoundWarning] =
useState<boolean>(false);

Expand Down Expand Up @@ -257,7 +273,7 @@ export const PolicyStepLogistics: React.FunctionComponent<StepProps> = ({
setShowRepositoryNotFoundWarning(!doesRepositoryExist);
}

return (
return disableToolTip(
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't we reuse the new DisableToolTip component here instead of this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's because the tooltip message is different for the managed repository and the managed policy. But if we want to handle both cases (managed repository and managed policy) within the same component, I guess we can refactor the DisableTooltip component to something like:

x-pack/plugins/snapshot_restore/public/application/components/disable_tooltip.tsx

export const DisableToolTip: React.FunctionComponent<Props> = ({
  isManagedRepository,
  isManagedPolicy,
  component,
}) => {
  let tooltipContent = '';

  if (isManagedRepository) {
    tooltipContent = i18n.translate('xpack.snapshotRestore.repositoryForm.disableToolTipContent', {
      defaultMessage: 'This field is disabled because you are editing a managed repository.',
    });
  } else if (isManagedPolicy) {
    tooltipContent = i18n.translate('xpack.snapshotRestore.policyForm.disableToolTipContent', {
      defaultMessage: 'This field is disabled because you are editing a managed policy.',
    });
  }

  return isManagedRepository || isManagedPolicy ? (
    <EuiToolTip content={tooltipContent} display="block">
      {component}
    </EuiToolTip>
  ) : (
    component
  );
};

Let me know what you think 😃

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah I see... I would suggest that you pass the message as a prop to the component and rename the isManagedRepository prop to just isManaged. Something like this:

export const DisableToolTip: React.FunctionComponent<Props> = ({
  isManaged,
  tooltipMessage,
  component,
}) => {
  return isManaged ? (
    <EuiToolTip
      content={tooltipMessage}
      display="block"
    >
      {component}
    </EuiToolTip>
  ) : (
    component
  );
};

Also, could you please add documentation above this component to explain what we use it for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

and add a const tooltipMessage to define the tooltip message for each of the files, correct? (i.e. azure_settings.tsx, gcs_settings.tsx, s3_settings.tsx and step_logistics.tsx)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For example:

const tooltipMessage = i18n.translate('xpack.snapshotRestore.repositoryForm.disableToolTip', {
    defaultMessage: 'This field is disabled because you are editing a managed repository.',
  });

Copy link
Contributor

@ElenaStoeva ElenaStoeva Oct 24, 2024

Choose a reason for hiding this comment

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

Yeah, I think it would be nice to add two constants (one for the repo message and one for the policy message) in x-pack/plugins/snapshot_restore/public/application/constants/index.ts. You could name them something more descriptive like managed<Policy/Repository>FieldTooltipMessage for example.

Copy link
Contributor Author

@renshuki renshuki Oct 24, 2024

Choose a reason for hiding this comment

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

@ElenaStoeva I pushed the latest changes (component refactor + constants definition) to the branch with the documentation for the component.

<EuiSelect
options={repositories.map(({ name }: Repository) => ({
value: name,
Expand Down Expand Up @@ -325,26 +341,28 @@ export const PolicyStepLogistics: React.FunctionComponent<StepProps> = ({
}
fullWidth
>
<EuiFieldText
defaultValue={policy.snapshotName}
fullWidth
onChange={(e) => {
updatePolicy({
snapshotName: e.target.value,
});
}}
onBlur={() => setTouched({ ...touched, snapshotName: true })}
placeholder={i18n.translate(
'xpack.snapshotRestore.policyForm.stepLogistics.policySnapshotNamePlaceholder',
{
defaultMessage: `'<daily-snap-{now/d}>'`,
description:
'Example date math snapshot name. Keeping the same syntax is important: <SOME-TRANSLATION-{now/d}>',
}
)}
data-test-subj="snapshotNameInput"
disabled={policy?.isManagedPolicy && isEditing}
/>
{disableToolTip(
<EuiFieldText
defaultValue={policy.snapshotName}
fullWidth
onChange={(e) => {
updatePolicy({
snapshotName: e.target.value,
});
}}
onBlur={() => setTouched({ ...touched, snapshotName: true })}
placeholder={i18n.translate(
'xpack.snapshotRestore.policyForm.stepLogistics.policySnapshotNamePlaceholder',
{
defaultMessage: `'<daily-snap-{now/d}>'`,
description:
'Example date math snapshot name. Keeping the same syntax is important: <SOME-TRANSLATION-{now/d}>',
}
)}
data-test-subj="snapshotNameInput"
disabled={policy?.isManagedPolicy && isEditing}
/>
)}
</EuiFormRow>
</EuiDescribedFormGroup>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { ReactElement } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiToolTip } from '@elastic/eui';

interface Props {
isManagedRepository?: boolean;
component: ReactElement;
}

export const DisableToolTip: React.FunctionComponent<Props> = ({
isManagedRepository,
component,
}) => {
return isManagedRepository ? (
<EuiToolTip
content={i18n.translate('xpack.snapshotRestore.repositoryForm.disableToolTipContent', {
defaultMessage: 'This field is disabled because you are editing a managed repository.',
})}
display="block"
>
{component}
</EuiToolTip>
) : (
component
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import { AzureRepository, Repository } from '../../../../../common/types';
import { RepositorySettingsValidation } from '../../../services/validation';
import { ChunkSizeField, MaxSnapshotsField, MaxRestoreField } from './common';
import { DisableToolTip } from '../../repository_disable_tooltip';

interface Props {
repository: AzureRepository;
Expand Down Expand Up @@ -94,16 +95,21 @@ export const AzureSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.client)}
error={settingErrors.client}
>
<EuiFieldText
defaultValue={client || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
client: e.target.value,
});
}}
data-test-subj="clientInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={client || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
client: e.target.value,
});
}}
data-test-subj="clientInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down Expand Up @@ -139,16 +145,21 @@ export const AzureSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.container)}
error={settingErrors.container}
>
<EuiFieldText
defaultValue={container || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
container: e.target.value,
});
}}
data-test-subj="containerInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={container || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
container: e.target.value,
});
}}
data-test-subj="containerInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down Expand Up @@ -184,16 +195,21 @@ export const AzureSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.basePath)}
error={settingErrors.basePath}
>
<EuiFieldText
defaultValue={basePath || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
basePath: e.target.value,
});
}}
data-test-subj="basePathInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={basePath || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
basePath: e.target.value,
});
}}
data-test-subj="basePathInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { EuiDescribedFormGroup, EuiFieldText, EuiFormRow, EuiSwitch, EuiTitle }
import { GCSRepository, Repository } from '../../../../../common/types';
import { RepositorySettingsValidation } from '../../../services/validation';
import { ChunkSizeField, MaxSnapshotsField, MaxRestoreField } from './common';
import { DisableToolTip } from '../../repository_disable_tooltip';

interface Props {
repository: GCSRepository;
Expand Down Expand Up @@ -82,16 +83,21 @@ export const GCSSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.client)}
error={settingErrors.client}
>
<EuiFieldText
defaultValue={client || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
client: e.target.value,
});
}}
data-test-subj="clientInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={client || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
client: e.target.value,
});
}}
data-test-subj="clientInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down Expand Up @@ -127,16 +133,21 @@ export const GCSSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.bucket)}
error={settingErrors.bucket}
>
<EuiFieldText
defaultValue={bucket || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
bucket: e.target.value,
});
}}
data-test-subj="bucketInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={bucket || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
bucket: e.target.value,
});
}}
data-test-subj="bucketInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down Expand Up @@ -172,16 +183,21 @@ export const GCSSettings: React.FunctionComponent<Props> = ({
isInvalid={Boolean(hasErrors && settingErrors.basePath)}
error={settingErrors.basePath}
>
<EuiFieldText
defaultValue={basePath || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
basePath: e.target.value,
});
}}
data-test-subj="basePathInput"
disabled={isManagedRepository}
<DisableToolTip
isManagedRepository={isManagedRepository}
component={
<EuiFieldText
defaultValue={basePath || ''}
fullWidth
onChange={(e) => {
updateRepositorySettings({
basePath: e.target.value,
});
}}
data-test-subj="basePathInput"
disabled={isManagedRepository}
/>
}
/>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down
Loading