Skip to content

Commit

Permalink
Buggy version
Browse files Browse the repository at this point in the history
  • Loading branch information
Heenawter committed Feb 1, 2024
1 parent ec93377 commit 9d6790b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { isEqual, pick } from 'lodash';
import React, { createContext, useContext } from 'react';
import ReactDOM from 'react-dom';
import { Provider, TypedUseSelectorHook, useSelector } from 'react-redux';
import { BehaviorSubject, combineLatest, merge, Observable, Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, skip } from 'rxjs/operators';
import { BehaviorSubject, merge, Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, skip } from 'rxjs/operators';

import { OverlayRef } from '@kbn/core/public';
import { Container, EmbeddableFactory } from '@kbn/embeddable-plugin/public';
Expand All @@ -24,7 +24,7 @@ import {
persistableControlGroupInputKeys,
} from '../../../common';
import { pluginServices } from '../../services';
import { ControlEmbeddable, ControlInput, ControlOutput, isValidatableControl } from '../../types';
import { ControlEmbeddable, ControlInput, ControlOutput } from '../../types';
import { ControlGroup } from '../component/control_group_component';
import { openAddDataControlFlyout } from '../editor/open_add_data_control_flyout';
import { openEditControlGroupFlyout } from '../editor/open_edit_control_group_flyout';
Expand Down Expand Up @@ -91,6 +91,8 @@ export class ControlGroupContainer extends Container<
private recalculateFilters$: Subject<null>;
private relevantDataViewId?: string;
private lastUsedDataViewId?: string;
private invalidSelectionsState: { [childId: string]: boolean };

public diffingSubscription: Subscription = new Subscription();

// state management
Expand Down Expand Up @@ -153,6 +155,10 @@ export class ControlGroupContainer extends Container<

this.store = reduxEmbeddableTools.store;

this.invalidSelectionsState = this.getChildIds().reduce((prev, id) => {
return { ...prev, [id]: false };
}, {});

// when all children are ready setup subscriptions
this.untilAllChildrenReady().then(() => {
this.recalculateDataViews();
Expand All @@ -164,6 +170,16 @@ export class ControlGroupContainer extends Container<
this.fieldFilterPredicate = fieldFilterPredicate;
}

public reportInvalidSelections = ({
id,
hasInvalidSelections,
}: {
id: string;
hasInvalidSelections: boolean;
}) => {
this.invalidSelectionsState = { ...this.invalidSelectionsState, [id]: hasInvalidSelections };
};

private setupSubscriptions = () => {
/**
* refresh control order cache and make all panels refreshInputFromParent whenever panel orders change
Expand Down Expand Up @@ -197,24 +213,15 @@ export class ControlGroupContainer extends Container<
})
);

const hasInvalidSelections$: { [id: string]: BehaviorSubject<boolean> } =
this.getChildIds().reduce((previous, childId) => {
const child = this.getChild(childId);
if (isValidatableControl(child)) {
return { ...previous, [childId]: child.hasInvalidSelections$ };
}
return previous;
}, {});
this.subscriptions.add(
combineLatest(hasInvalidSelections$)
.pipe(
debounceTime(100),
map((hasInvalidSelections) => {
return Object.keys(hasInvalidSelections).filter((id) => hasInvalidSelections[id]);
}),
distinctUntilChanged((a, b) => isEqual(a, b))
)
.subscribe((childrenWithInvalidSelections) => {
this.getAnyChildOutputChange$()
.pipe(debounceTime(100))
.subscribe(() => {
const childrenWithInvalidSelections = cachedChildEmbeddableOrder(
this.getInput().panels
).idsInOrder.filter((childId) => {
return this.invalidSelectionsState[childId];
});
if (childrenWithInvalidSelections.length > 0) {
this.dispatch.setInvalidSelectionsControlId(childrenWithInvalidSelections[0]);
} else {
Expand All @@ -227,7 +234,9 @@ export class ControlGroupContainer extends Container<
* debounce output recalculation
*/
this.subscriptions.add(
this.recalculateFilters$.pipe(debounceTime(10)).subscribe(() => this.recalculateFilters())
this.recalculateFilters$.pipe(debounceTime(10)).subscribe(() => {
this.recalculateFilters();
})
);
};

Expand Down Expand Up @@ -317,6 +326,7 @@ export class ControlGroupContainer extends Container<
timeslice = childOutput.timeslice;
}
});

// if filters are different, publish them
if (
!compareFilters(this.output.filters ?? [], allFilters ?? [], COMPARE_ALL_OPTIONS) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,43 @@
* Side Public License, v 1.
*/

import ReactDOM from 'react-dom';
import { batch } from 'react-redux';
import deepEqual from 'fast-deep-equal';
import { isEmpty, isEqual } from 'lodash';
import { BehaviorSubject, merge, Subject, Subscription, switchMap, tap } from 'rxjs';
import React, { createContext, useContext } from 'react';
import { debounceTime, map, distinctUntilChanged, skip } from 'rxjs/operators';
import ReactDOM from 'react-dom';
import { batch } from 'react-redux';
import { merge, Subject, Subscription, switchMap, tap } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, skip } from 'rxjs/operators';

import { DataView, FieldSpec } from '@kbn/data-views-plugin/public';
import { Embeddable, IContainer } from '@kbn/embeddable-plugin/public';
import {
Filter,
compareFilters,
buildExistsFilter,
buildPhraseFilter,
buildPhrasesFilter,
compareFilters,
COMPARE_ALL_OPTIONS,
buildExistsFilter,
Filter,
} from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import { DataView, FieldSpec } from '@kbn/data-views-plugin/public';
import { Embeddable, IContainer } from '@kbn/embeddable-plugin/public';
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
import { ReduxEmbeddableTools, ReduxToolsPackage } from '@kbn/presentation-util-plugin/public';
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';

import {
ControlGroupContainer,
ControlInput,
ControlOutput,
OPTIONS_LIST_CONTROL,
OptionsListEmbeddableInput,
OPTIONS_LIST_CONTROL,
} from '../..';
import { pluginServices } from '../../services';
import { IValidatableControl, IClearableControl } from '../../types';
import { OptionsListControl } from '../components/options_list_control';
import { ControlsDataViewsService } from '../../services/data_views/types';
import { ControlsOptionsListService } from '../../services/options_list/types';
import { MIN_OPTIONS_LIST_REQUEST_SIZE, OptionsListReduxState } from '../types';
import { getDefaultComponentState, optionsListReducers } from '../options_list_reducers';
import { ControlsStorageService } from '../../services/storage/types';
import { IClearableControl } from '../../types';
import { OptionsListControl } from '../components/options_list_control';
import { getDefaultComponentState, optionsListReducers } from '../options_list_reducers';
import { MIN_OPTIONS_LIST_REQUEST_SIZE, OptionsListReduxState } from '../types';

const diffDataFetchProps = (
last?: OptionsListDataFetchProps,
Expand Down Expand Up @@ -80,10 +81,11 @@ type OptionsListReduxEmbeddableTools = ReduxEmbeddableTools<

export class OptionsListEmbeddable
extends Embeddable<OptionsListEmbeddableInput, ControlOutput>
implements IClearableControl, IValidatableControl
implements IClearableControl
{
public readonly type = OPTIONS_LIST_CONTROL;
public deferEmbeddableLoad = true;
public parent: ControlGroupContainer;

private subscriptions: Subscription = new Subscription();
private node?: HTMLElement;
Expand All @@ -106,7 +108,6 @@ export class OptionsListEmbeddable
public dispatch: OptionsListReduxEmbeddableTools['dispatch'];
public onStateChange: OptionsListReduxEmbeddableTools['onStateChange'];

public hasInvalidSelections$: BehaviorSubject<boolean>;
private cleanupStateTools: () => void;

constructor(
Expand All @@ -116,6 +117,7 @@ export class OptionsListEmbeddable
parent?: IContainer
) {
super(input, output, parent);
this.parent = parent as ControlGroupContainer;

// Destructure controls services
({
Expand All @@ -142,8 +144,6 @@ export class OptionsListEmbeddable
this.cleanupStateTools = reduxEmbeddableTools.cleanup;
this.onStateChange = reduxEmbeddableTools.onStateChange;

this.hasInvalidSelections$ = new BehaviorSubject<boolean>(false);

this.initialize();
}

Expand Down Expand Up @@ -355,15 +355,15 @@ export class OptionsListEmbeddable
validSelections: selectedOptions,
totalCardinality,
});
this.hasInvalidSelections$.next(false);
this.reportInvalidSelections(false);
} else {
const valid: string[] = [];
const invalid: string[] = [];
for (const selectedOption of selectedOptions ?? []) {
if (invalidSelections?.includes(String(selectedOption))) invalid.push(selectedOption);
else valid.push(selectedOption);
}
this.hasInvalidSelections$.next(true);
this.reportInvalidSelections(true);
this.dispatch.updateQueryResults({
availableOptions: suggestions,
invalidSelections: invalid,
Expand All @@ -387,6 +387,13 @@ export class OptionsListEmbeddable
}
};

private reportInvalidSelections = (hasInvalidSelections: boolean) => {
this.parent?.reportInvalidSelections({
id: this.id,
hasInvalidSelections,
});
};

private buildFilter = async () => {
const { existsSelected, selectedOptions } = this.getState().explicitInput ?? {};
const { exclude } = this.getInput();
Expand Down Expand Up @@ -424,6 +431,7 @@ export class OptionsListEmbeddable

public clearSelections() {
this.dispatch.clearSelections({});
this.reportInvalidSelections(false);
}

reload = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type RangeSliderReduxEmbeddableTools = ReduxEmbeddableTools<

export class RangeSliderEmbeddable
extends Embeddable<RangeSliderEmbeddableInput, ControlOutput>
implements IClearableControl, IValidatableControl
implements IClearableControl
{
public readonly type = RANGE_SLIDER_CONTROL;
public deferEmbeddableLoad = true;
Expand All @@ -101,7 +101,6 @@ export class RangeSliderEmbeddable
public dispatch: RangeSliderReduxEmbeddableTools['dispatch'];
public onStateChange: RangeSliderReduxEmbeddableTools['onStateChange'];

public hasInvalidSelections$: BehaviorSubject<boolean>;
private cleanupStateTools: () => void;

constructor(
Expand Down Expand Up @@ -133,8 +132,6 @@ export class RangeSliderEmbeddable
this.onStateChange = reduxEmbeddableTools.onStateChange;
this.cleanupStateTools = reduxEmbeddableTools.cleanup;

this.hasInvalidSelections$ = new BehaviorSubject<boolean>(false);

this.initialize();
}

Expand Down
10 changes: 0 additions & 10 deletions src/plugins/controls/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,6 @@ export const isClearableControl = (control: ControlEmbeddable): control is IClea
return Boolean((control as IClearableControl).clearSelections);
};

export interface IValidatableControl extends ControlEmbeddable {
hasInvalidSelections$: BehaviorSubject<boolean>;
}

export const isValidatableControl = (
control: ControlEmbeddable
): control is IValidatableControl => {
return Boolean((control as IValidatableControl).hasInvalidSelections$);
};

/**
* Control embeddable editor types
*/
Expand Down

0 comments on commit 9d6790b

Please sign in to comment.