Skip to content

Commit

Permalink
Merge branch 'main' into ml-aiops-brush-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
walterra committed Aug 4, 2022
2 parents 7ed53db + 70efbf0 commit 68c5466
Show file tree
Hide file tree
Showing 181 changed files with 1,003 additions and 406 deletions.
2 changes: 1 addition & 1 deletion examples/response_stream/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The request's headers get passed on to automatically identify if compression is
On the client, the custom hook is used like this:

```ts
const { error, start, cancel, data, isRunning } = useFetchStream<
const { errors, start, cancel, data, isRunning } = useFetchStream<
ApiSimpleStringStream, typeof basePath
>(`${basePath}/internal/response_stream/simple_string_stream`);
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const PageReducerStream: FC = () => {

const [simulateErrors, setSimulateErrors] = useState(false);

const { dispatch, start, cancel, data, error, isCancelled, isRunning } = useFetchStream<
const { dispatch, start, cancel, data, errors, isCancelled, isRunning } = useFetchStream<
ApiReducerStream,
typeof basePath
>(
Expand All @@ -65,13 +65,15 @@ export const PageReducerStream: FC = () => {
}
};

// TODO This approach needs to be adapted as it might miss when error messages arrive bulk.
// This is for low level errors on the stream/HTTP level.
useEffect(() => {
if (error) {
notifications.toasts.addDanger(error);
if (errors.length > 0) {
notifications.toasts.addDanger(errors[errors.length - 1]);
}
}, [error, notifications.toasts]);
}, [errors, notifications.toasts]);

// TODO This approach needs to be adapted as it might miss when error messages arrive bulk.
// This is for errors on the application level
useEffect(() => {
if (data.errors.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const PageSimpleStringStream: FC = () => {
const { core } = useDeps();
const basePath = core.http?.basePath.get() ?? '';

const { dispatch, error, start, cancel, data, isRunning } = useFetchStream<
const { dispatch, errors, start, cancel, data, isRunning } = useFetchStream<
ApiSimpleStringStream,
typeof basePath
>(`${basePath}/internal/response_stream/simple_string_stream`, { timeout: 500 });
Expand Down Expand Up @@ -61,9 +61,17 @@ export const PageSimpleStringStream: FC = () => {
<EuiText>
<p>{data}</p>
</EuiText>
{error && (
{errors.length > 0 && (
<EuiCallOut title="Sorry, there was an error" color="danger" iconType="alert">
<p>{error}</p>
{errors.length === 1 ? (
<p>{errors[0]}</p>
) : (
<ul>
{errors.map((e, i) => (
<li key={i}>{e}</li>
))}
</ul>
)}{' '}
</EuiCallOut>
)}
</Page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,24 @@ storiesOf('SearchBar', module)
showSubmitButton: false,
} as SearchBarProps)
)
.add('show only datepicker without submit', () =>
wrapSearchBarInContext({
showDatePicker: true,
showFilterBar: false,
showAutoRefreshOnly: false,
showQueryInput: false,
showSubmitButton: false,
} as SearchBarProps)
)
.add('show only query bar and timepicker without submit', () =>
wrapSearchBarInContext({
showDatePicker: true,
showFilterBar: false,
showAutoRefreshOnly: false,
showQueryInput: true,
showSubmitButton: false,
} as SearchBarProps)
)
.add('with filter bar on but pinning option is hidden from menus', () =>
wrapSearchBarInContext({
showDatePicker: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function wrapQueryBarTopRowInContext(testProps: any) {
describe('QueryBarTopRowTopRow', () => {
const QUERY_INPUT_SELECTOR = 'QueryStringInputUI';
const TIMEPICKER_SELECTOR = 'Memo(EuiSuperDatePicker)';
const REFRESH_BUTTON_SELECTOR = 'EuiSuperUpdateButton';
const TIMEPICKER_DURATION = '[data-shared-timefilter-duration]';

beforeEach(() => {
Expand Down Expand Up @@ -195,6 +196,23 @@ describe('QueryBarTopRowTopRow', () => {
expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1);
});

it('Should render timepicker without the submit button if showSubmitButton is false', () => {
const component = mount(
wrapQueryBarTopRowInContext({
isDirty: false,
screenTitle: 'Another Screen',
showDatePicker: true,
showSubmitButton: false,
dateRangeFrom: 'now-7d',
dateRangeTo: 'now',
timeHistory: mockTimeHistory,
})
);

expect(component.find(REFRESH_BUTTON_SELECTOR).length).toBe(0);
expect(component.find(TIMEPICKER_SELECTOR).length).toBe(1);
});

it('Should render the timefilter duration container for sharing', () => {
const component = mount(
wrapQueryBarTopRowInContext({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,9 @@ export const QueryBarTopRow = React.memo(
}

function renderUpdateButton() {
if (!shouldRenderUpdatebutton()) {
if (!shouldRenderUpdatebutton() && !shouldRenderDatePicker()) {
return null;
}

const buttonLabelUpdate = i18n.translate('unifiedSearch.queryBarTopRow.submitButton.update', {
defaultMessage: 'Needs updating',
});
Expand Down Expand Up @@ -421,16 +420,17 @@ export const QueryBarTopRow = React.memo(
</EuiFlexItem>
);

if (!shouldRenderDatePicker()) {
// allows to render the button without the datepicker
if (!shouldRenderDatePicker() && shouldRenderUpdatebutton()) {
return button;
}

return (
<EuiFlexItem grow={false}>
<NoDataPopover storage={storage} showNoDataPopover={props.indicateNoData}>
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
{renderDatePicker()}
{button}
{shouldRenderDatePicker() ? renderDatePicker() : null}
{shouldRenderUpdatebutton() ? button : null}
</EuiFlexGroup>
</NoDataPopover>
</EuiFlexItem>
Expand Down
29 changes: 18 additions & 11 deletions x-pack/packages/ml/aiops_utils/src/fetch_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,24 @@ export async function* fetchStream<I extends UseFetchStreamParamsDefault, BasePa
): AsyncGenerator<
[GeneratorError, ReducerAction<I['reducer']> | Array<ReducerAction<I['reducer']>> | undefined]
> {
const stream = await fetch(endpoint, {
signal: abortCtrl.current.signal,
method: 'POST',
headers: {
// This refers to the format of the request body,
// not the response, which will be a uint8array Buffer.
'Content-Type': 'application/json',
'kbn-xsrf': 'stream',
},
...(Object.keys(body).length > 0 ? { body: JSON.stringify(body) } : {}),
});
let stream: Response;

try {
stream = await fetch(endpoint, {
signal: abortCtrl.current.signal,
method: 'POST',
headers: {
// This refers to the format of the request body,
// not the response, which will be a uint8array Buffer.
'Content-Type': 'application/json',
'kbn-xsrf': 'stream',
},
...(Object.keys(body).length > 0 ? { body: JSON.stringify(body) } : {}),
});
} catch (error) {
yield [error.toString(), undefined];
return;
}

if (!stream.ok) {
yield [`Error ${stream.status}: ${stream.statusText}`, undefined];
Expand Down
16 changes: 10 additions & 6 deletions x-pack/packages/ml/aiops_utils/src/use_fetch_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface UseFetchStreamReturnType<Data, Action> {
cancel: () => void;
data: Data;
dispatch: Dispatch<Action>;
error: string | undefined;
errors: string[];
isCancelled: boolean;
isRunning: boolean;
start: () => Promise<void>;
Expand Down Expand Up @@ -76,7 +76,7 @@ export function useFetchStream<I extends UseFetchStreamParamsDefault, BasePath e
body: I['body'],
options?: { reducer: I['reducer']; initialState: ReducerState<I['reducer']> }
): UseFetchStreamReturnType<ReducerState<I['reducer']>, ReducerAction<I['reducer']>> {
const [error, setError] = useState<string | undefined>();
const [errors, setErrors] = useState<string[]>([]);
const [isCancelled, setIsCancelled] = useState(false);
const [isRunning, setIsRunning] = useState(false);

Expand All @@ -87,13 +87,17 @@ export function useFetchStream<I extends UseFetchStreamParamsDefault, BasePath e

const abortCtrl = useRef(new AbortController());

const addError = (error: string) => {
setErrors((prevErrors) => [...prevErrors, error]);
};

const start = async () => {
if (isRunning) {
setError('Restart not supported yet.');
addError('Restart not supported yet.');
return;
}

setError(undefined);
setErrors([]);
setIsRunning(true);
setIsCancelled(false);

Expand All @@ -104,7 +108,7 @@ export function useFetchStream<I extends UseFetchStreamParamsDefault, BasePath e
BasePath
>(endpoint, abortCtrl, body, options !== undefined)) {
if (fetchStreamError !== null) {
setError(fetchStreamError);
addError(fetchStreamError);
} else if (actions.length > 0) {
dispatch(actions as ReducerAction<I['reducer']>);
}
Expand All @@ -128,7 +132,7 @@ export function useFetchStream<I extends UseFetchStreamParamsDefault, BasePath e
cancel,
data,
dispatch,
error,
errors,
isCancelled,
isRunning,
start,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { ChangePoint, ChangePointHistogram } from '@kbn/ml-agg-utils';
export const API_ACTION_NAME = {
ADD_CHANGE_POINTS: 'add_change_points',
ADD_CHANGE_POINTS_HISTOGRAM: 'add_change_points_histogram',
ERROR: 'error',
ADD_ERROR: 'add_error',
RESET: 'reset',
UPDATE_LOADING_STATE: 'update_loading_state',
} as const;
Expand Down Expand Up @@ -44,14 +44,14 @@ export function addChangePointsHistogramAction(
};
}

interface ApiActionError {
type: typeof API_ACTION_NAME.ERROR;
interface ApiActionAddError {
type: typeof API_ACTION_NAME.ADD_ERROR;
payload: string;
}

export function errorAction(payload: ApiActionError['payload']): ApiActionError {
export function addErrorAction(payload: ApiActionAddError['payload']): ApiActionAddError {
return {
type: API_ACTION_NAME.ERROR,
type: API_ACTION_NAME.ADD_ERROR,
payload,
};
}
Expand Down Expand Up @@ -85,6 +85,6 @@ export function updateLoadingStateAction(
export type AiopsExplainLogRateSpikesApiAction =
| ApiActionAddChangePoints
| ApiActionAddChangePointsHistogram
| ApiActionError
| ApiActionAddError
| ApiActionReset
| ApiActionUpdateLoadingState;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
export {
addChangePointsAction,
addChangePointsHistogramAction,
errorAction,
addErrorAction,
resetAction,
updateLoadingStateAction,
API_ACTION_NAME,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/aiops/common/api/stream_reducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('streamReducer', () => {
loaded: 50,
loadingState: 'Loaded 50%',
changePoints: [],
errors: [],
});
});

Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/aiops/common/api/stream_reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import { API_ACTION_NAME, AiopsExplainLogRateSpikesApiAction } from './explain_l
interface StreamState {
ccsWarning: boolean;
changePoints: ChangePoint[];
errors: string[];
loaded: number;
loadingState: string;
}

export const initialState: StreamState = {
ccsWarning: false,
changePoints: [],
errors: [],
loaded: 0,
loadingState: '',
};
Expand All @@ -45,6 +47,8 @@ export function streamReducer(
return cp;
});
return { ...state, changePoints };
case API_ACTION_NAME.ADD_ERROR:
return { ...state, errors: [...state.errors, action.payload] };
case API_ACTION_NAME.RESET:
return initialState;
case API_ACTION_NAME.UPDATE_LOADING_STATE:
Expand Down
Loading

0 comments on commit 68c5466

Please sign in to comment.