mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Drilldowns] misc improvements & fixes (#75276)
Added support for isCompatible. It is checked during execution. Pass actionFactory context into createConfig, IsConfigValid Fix bug that selectedTriggers wasn't reset when switching action factories Check if license is active in action factories
This commit is contained in:
parent
e30220f04c
commit
50f9a97a41
9 changed files with 83 additions and 17 deletions
|
@ -26,12 +26,12 @@ export interface Configurable<Config extends object = object, Context = object>
|
|||
/**
|
||||
* Create default config for this item, used when item is created for the first time.
|
||||
*/
|
||||
readonly createConfig: () => Config;
|
||||
readonly createConfig: (context: Context) => Config;
|
||||
|
||||
/**
|
||||
* Is this config valid. Used to validate user's input before saving.
|
||||
*/
|
||||
readonly isConfigValid: (config: Config) => boolean;
|
||||
readonly isConfigValid: (config: Config, context: Context) => boolean;
|
||||
|
||||
/**
|
||||
* `UiComponent` to be rendered when collecting configuration for this item.
|
||||
|
|
|
@ -11,6 +11,7 @@ import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../p
|
|||
import { RangeSelectContext } from '../../../../../src/plugins/embeddable/public';
|
||||
import { CollectConfigProps } from '../../../../../src/plugins/kibana_utils/public';
|
||||
import { SELECT_RANGE_TRIGGER } from '../../../../../src/plugins/ui_actions/public';
|
||||
import { BaseActionFactoryContext } from '../../../../plugins/ui_actions_enhanced/public/dynamic_actions';
|
||||
|
||||
export interface Config {
|
||||
name: string;
|
||||
|
@ -52,10 +53,24 @@ export class DashboardHelloWorldOnlyRangeSelectDrilldown
|
|||
name: '',
|
||||
});
|
||||
|
||||
public readonly isConfigValid = (config: Config): config is Config => {
|
||||
public readonly isConfigValid = (
|
||||
config: Config,
|
||||
context: BaseActionFactoryContext<typeof SELECT_RANGE_TRIGGER>
|
||||
): config is Config => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Showcasing, that can access action factory context:', context);
|
||||
|
||||
return !!config.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Showcase isCompatible. Disabled drilldown action in case if range.length === 0
|
||||
*/
|
||||
isCompatible(config: Config, context: RangeSelectContext): Promise<boolean> {
|
||||
if (context.data.range.length === 0) return Promise.resolve(false);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
public readonly execute = async (config: Config, context: RangeSelectContext) => {
|
||||
alert(`Hello, ${config.name}, your selected range: ${JSON.stringify(context.data.range)}`);
|
||||
};
|
||||
|
|
|
@ -220,7 +220,9 @@ export function Demo({ actionFactories }: { actionFactories: Array<ActionFactory
|
|||
|
||||
setState({
|
||||
currentActionFactory: newActionFactory,
|
||||
config: newActionFactory.createConfig(),
|
||||
config: newActionFactory.createConfig({
|
||||
triggers: state.selectedTriggers ?? [],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -255,7 +257,11 @@ export function Demo({ actionFactories }: { actionFactories: Array<ActionFactory
|
|||
<div>Action Factory Config: {JSON.stringify(state.config)}</div>
|
||||
<div>
|
||||
Is config valid:{' '}
|
||||
{JSON.stringify(state.currentActionFactory?.isConfigValid(state.config!) ?? false)}
|
||||
{JSON.stringify(
|
||||
state.currentActionFactory?.isConfigValid(state.config!, {
|
||||
triggers: state.selectedTriggers ?? [],
|
||||
}) ?? false
|
||||
)}
|
||||
</div>
|
||||
<div>Picked trigger: {state.selectedTriggers?.[0]}</div>
|
||||
</>
|
||||
|
|
|
@ -57,6 +57,7 @@ export interface FlyoutDrilldownWizardProps<
|
|||
}
|
||||
|
||||
function useWizardConfigState(
|
||||
actionFactoryContext: BaseActionFactoryContext,
|
||||
initialDrilldownWizardConfig?: DrilldownWizardConfig
|
||||
): [
|
||||
DrilldownWizardConfig,
|
||||
|
@ -102,7 +103,10 @@ function useWizardConfigState(
|
|||
setWizardConfig({
|
||||
...wizardConfig,
|
||||
actionFactory,
|
||||
actionConfig: actionConfigCache[actionFactory.id] ?? actionFactory.createConfig(),
|
||||
actionConfig:
|
||||
actionConfigCache[actionFactory.id] ??
|
||||
actionFactory.createConfig(actionFactoryContext),
|
||||
selectedTriggers: [],
|
||||
});
|
||||
} else {
|
||||
if (wizardConfig.actionFactory?.id) {
|
||||
|
@ -147,7 +151,18 @@ export function FlyoutDrilldownWizard<CurrentActionConfig extends object = objec
|
|||
const [
|
||||
wizardConfig,
|
||||
{ setActionFactory, setActionConfig, setName, setSelectedTriggers },
|
||||
] = useWizardConfigState(initialDrilldownWizardConfig);
|
||||
] = useWizardConfigState(
|
||||
{ ...extraActionFactoryContext, triggers: supportedTriggers },
|
||||
initialDrilldownWizardConfig
|
||||
);
|
||||
|
||||
const actionFactoryContext: BaseActionFactoryContext = useMemo(
|
||||
() => ({
|
||||
...extraActionFactoryContext,
|
||||
triggers: wizardConfig.selectedTriggers ?? [],
|
||||
}),
|
||||
[extraActionFactoryContext, wizardConfig.selectedTriggers]
|
||||
);
|
||||
|
||||
const isActionValid = (
|
||||
config: DrilldownWizardConfig
|
||||
|
@ -157,17 +172,12 @@ export function FlyoutDrilldownWizard<CurrentActionConfig extends object = objec
|
|||
if (!wizardConfig.actionConfig) return false;
|
||||
if (!wizardConfig.selectedTriggers || wizardConfig.selectedTriggers.length === 0) return false;
|
||||
|
||||
return wizardConfig.actionFactory.isConfigValid(wizardConfig.actionConfig);
|
||||
return wizardConfig.actionFactory.isConfigValid(
|
||||
wizardConfig.actionConfig,
|
||||
actionFactoryContext
|
||||
);
|
||||
};
|
||||
|
||||
const actionFactoryContext: BaseActionFactoryContext = useMemo(
|
||||
() => ({
|
||||
...extraActionFactoryContext,
|
||||
triggers: wizardConfig.selectedTriggers ?? [],
|
||||
}),
|
||||
[extraActionFactoryContext, wizardConfig.selectedTriggers]
|
||||
);
|
||||
|
||||
const footer = (
|
||||
<EuiButton
|
||||
onClick={() => {
|
||||
|
|
|
@ -106,6 +106,15 @@ export interface DrilldownDefinition<
|
|||
*/
|
||||
getDisplayName: () => string;
|
||||
|
||||
/**
|
||||
* isCompatible during execution
|
||||
* Could be used to prevent drilldown from execution
|
||||
*/
|
||||
isCompatible?(
|
||||
config: Config,
|
||||
context: ExecutionContext | ActionExecutionContext<ExecutionContext>
|
||||
): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Implements the "navigation" action of the drilldown. This happens when
|
||||
* user clicks something in the UI that executes a trigger to which this
|
||||
|
|
|
@ -37,6 +37,14 @@ describe('License & ActionFactory', () => {
|
|||
expect(factory.isCompatibleLicence()).toBe(false);
|
||||
});
|
||||
|
||||
test('licence has expired', async () => {
|
||||
const factory = new ActionFactory({ ...def, minimalLicense: 'gold' }, () =>
|
||||
licensingMock.createLicense({ license: { type: 'gold', status: 'expired' } })
|
||||
);
|
||||
expect(await factory.isCompatible({ triggers: [] })).toBe(true);
|
||||
expect(factory.isCompatibleLicence()).toBe(false);
|
||||
});
|
||||
|
||||
test('enough license level', async () => {
|
||||
const factory = new ActionFactory({ ...def, minimalLicense: 'gold' }, () =>
|
||||
licensingMock.createLicense({ license: { type: 'gold' } })
|
||||
|
|
|
@ -70,7 +70,8 @@ export class ActionFactory<
|
|||
*/
|
||||
public isCompatibleLicence() {
|
||||
if (!this.minimalLicense) return true;
|
||||
return this.getLicence().hasAtLeast(this.minimalLicense);
|
||||
const licence = this.getLicence();
|
||||
return licence.isAvailable && licence.isActive && licence.hasAtLeast(this.minimalLicense);
|
||||
}
|
||||
|
||||
public create(
|
||||
|
|
|
@ -75,5 +75,18 @@ describe('UiActionsService', () => {
|
|||
'Action factory [actionFactoryId = UNKNOWN_ID] does not exist.'
|
||||
);
|
||||
});
|
||||
|
||||
test('isCompatible from definition is used on registered factory', async () => {
|
||||
const service = new UiActionsServiceEnhancements({ getLicenseInfo });
|
||||
|
||||
service.registerActionFactory({
|
||||
...factoryDefinition1,
|
||||
isCompatible: () => Promise.resolve(false),
|
||||
});
|
||||
|
||||
await expect(
|
||||
service.getActionFactory(factoryDefinition1.id).isCompatible({ triggers: [] })
|
||||
).resolves.toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -95,6 +95,7 @@ export class UiActionsServiceEnhancements {
|
|||
getHref,
|
||||
minimalLicense,
|
||||
supportedTriggers,
|
||||
isCompatible,
|
||||
}: DrilldownDefinition<Config, SupportedTriggers, FactoryContext, ExecutionContext>): void => {
|
||||
const actionFactory: ActionFactoryDefinition<
|
||||
Config,
|
||||
|
@ -119,6 +120,9 @@ export class UiActionsServiceEnhancements {
|
|||
getDisplayName: () => serializedAction.name,
|
||||
execute: async (context) => await execute(serializedAction.config, context),
|
||||
getHref: getHref ? async (context) => getHref(serializedAction.config, context) : undefined,
|
||||
isCompatible: isCompatible
|
||||
? async (context) => isCompatible(serializedAction.config, context)
|
||||
: undefined,
|
||||
}),
|
||||
} as ActionFactoryDefinition<Config, SupportedTriggers, FactoryContext, ExecutionContext>;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue