Skip to content

Commit

Permalink
feat: 🎸 autorun enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejrybaniec committed Oct 30, 2020
1 parent 0cb1f6d commit 079921c
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 19 deletions.
4 changes: 3 additions & 1 deletion lib/js/app/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
getViewMode,
setViewMode,
getVisualization,
getQueryAutorun,
switchToQueriesList,
createNewQuery,
explorerMounted,
Expand Down Expand Up @@ -47,6 +48,7 @@ import {
const mapStateToProps = (state: AppState) => ({
savedQuery: getSavedQuery(state),
visualization: getVisualization(state),
autorunQuery: getQueryAutorun(state),
view: getViewMode(state),
query: getQuerySettings(state),
});
Expand Down Expand Up @@ -134,7 +136,7 @@ class App extends Component {
onRunQuery={() => this.props.runQuery(this.props.query)}
onSelectQuery={(queryName) => {
this.props.resetQueryResults();
this.props.selectSavedQuery(queryName);
this.props.selectSavedQuery(queryName, this.props.autorunQuery);
}}
onEditQuery={(queryName) => {
this.props.editQuery(queryName);
Expand Down
22 changes: 22 additions & 0 deletions lib/js/app/components/AutorunQuery/AutorunQuery.styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import styled from 'styled-components';
import { motion } from 'framer-motion';
import { colors } from '@keen.io/colors';
import { UI_LAYERS } from '@keen.io/ui-core';

export const Container = styled.div`
display: flex;
Expand All @@ -13,3 +15,23 @@ export const Label = styled.div`
color: ${colors.black[100]};
margin-right: 10px;
`;

export const HintContainer = styled.div`
display: flex;
align-items: center;
margin-right: 5px;
position: relative;
`;

export const TooltipMotion = styled(motion.div)`
position: absolute;
top: 100%;
z-index: ${UI_LAYERS.tooltip};
`;

export const TooltipContent = styled.div`
width: 120px;
color: ${colors.black[100]};
font-size: 14px;
font-family: Lato Regular, sans-serif;
`;
25 changes: 24 additions & 1 deletion lib/js/app/components/AutorunQuery/AutorunQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,34 @@ import AutorunQuery from './AutorunQuery';
test('calls on "onToggle" event handler', () => {
const mockFn = jest.fn();
const { getByTestId } = render(
<AutorunQuery autorun={false} onToggle={mockFn} label="label" />
<AutorunQuery
autorun={false}
onToggle={mockFn}
tooltipMessage="tooltipMessage"
label="label"
/>
);

const element = getByTestId('toggle');
fireEvent.click(element);

expect(mockFn).toHaveBeenCalledWith(true);
});

test('shows tooltip with hint message', () => {
const mockFn = jest.fn();
const tooltipMessage = 'tooltipMessage';
const { getByTestId, getByText } = render(
<AutorunQuery
autorun={false}
onToggle={mockFn}
tooltipMessage={tooltipMessage}
label="label"
/>
);

const element = getByTestId('hint-container');
fireEvent.mouseEnter(element);

expect(getByText(tooltipMessage)).toBeInTheDocument();
});
56 changes: 47 additions & 9 deletions lib/js/app/components/AutorunQuery/AutorunQuery.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import React, { FC } from 'react';
import { Toggle } from '@keen.io/ui-core';
import React, { FC, useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import { Toggle, Tooltip } from '@keen.io/ui-core';
import { Icon } from '@keen.io/icons';
import { colors } from '@keen.io/colors';

import { Container, Label } from './AutorunQuery.styles';
import {
Container,
HintContainer,
Label,
TooltipContent,
TooltipMotion,
} from './AutorunQuery.styles';

import { TOOLTIP_MOTION } from '../../constants';

type Props = {
/** Toggle autorun event handler */
Expand All @@ -10,13 +21,40 @@ type Props = {
autorun: boolean;
/** Settings label */
label: string;
/** Autorun tooltip hint message */
tooltipMessage: string;
};

const AutorunQuery: FC<Props> = ({ autorun, label, onToggle }) => (
<Container>
<Label>{label}</Label>
<Toggle isOn={autorun} onChange={onToggle} />
</Container>
);
const AutorunQuery: FC<Props> = ({
autorun,
label,
tooltipMessage,
onToggle,
}) => {
const [showTooltip, setTooltipVisibility] = useState(false);

return (
<Container>
<HintContainer
data-testid="hint-container"
onMouseEnter={() => setTooltipVisibility(true)}
onMouseLeave={() => setTooltipVisibility(false)}
>
<Icon type="info" fill={colors.blue[500]} height={16} width={16} />
<AnimatePresence>
{showTooltip && (
<TooltipMotion {...TOOLTIP_MOTION}>
<Tooltip hasArrow={false}>
<TooltipContent>{tooltipMessage}</TooltipContent>
</Tooltip>
</TooltipMotion>
)}
</AnimatePresence>
</HintContainer>
<Label>{label}</Label>
<Toggle isOn={autorun} onChange={onToggle} />
</Container>
);
};

export default AutorunQuery;
1 change: 1 addition & 0 deletions lib/js/app/components/BrowserPreview/BrowserPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const BrowserPreview: FC<Props> = ({
<AutorunQuery
autorun={autorunQuery}
label={t('browser_preview.autorun_query_label')}
tooltipMessage={t('browser_preview.autorun_query_tooltip')}
onToggle={(autorun) => dispatch(setQueryAutorun(autorun))}
/>
</HeaderContainer>
Expand Down
4 changes: 2 additions & 2 deletions lib/js/app/modules/app/reducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import {
} from './actions';

test('set query autorun settings', () => {
const action = setQueryAutorun(true);
const action = setQueryAutorun(false);
const { autorunQuery } = appReducer(initialState, action);

expect(autorunQuery).toBeTruthy();
expect(autorunQuery).toBeFalsy();
});

test('shows extraction settings modal', () => {
Expand Down
2 changes: 1 addition & 1 deletion lib/js/app/modules/app/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from './constants';

export const initialState: ReducerState = {
autorunQuery: false,
autorunQuery: true,
confirmModal: {
visible: false,
action: null,
Expand Down
6 changes: 5 additions & 1 deletion lib/js/app/modules/savedQuery/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ export const updateSaveQuery = (
payload: properties,
});

export const selectSavedQuery = (name: string): SavedQueryActions => ({
export const selectSavedQuery = (
name: string,
autorunQuery?: boolean
): SavedQueryActions => ({
type: SELECT_SAVED_QUERY,
payload: {
name,
autorunQuery,
},
});

Expand Down
21 changes: 21 additions & 0 deletions lib/js/app/modules/savedQuery/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/camelcase */

export const savedQueries = [
{
refreshRate: 0,
cached: false,
displayName: 'purchases',
name: 'purchases',
tags: [],
visualization: {
type: 'bar',
chartSettings: {
layout: 'vertical',
},
widgetSettings: {},
},
query: {
analysis_type: 'count',
},
},
];
62 changes: 62 additions & 0 deletions lib/js/app/modules/savedQuery/saga.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* eslint-disable @typescript-eslint/camelcase */
import sagaHelper from 'redux-saga-testing';
import { select, put } from 'redux-saga/effects';
import { Layout } from '@keen.io/ui-core';

import { selectSavedQuery, updateSaveQuery } from './actions';
import { selectSavedQuery as selectSavedQueryFlow } from './saga';

import { runQuery, getSavedQueries, setQuerySettings } from '../queries';
import { setVisualization } from '../app';

import { savedQueries } from './fixtures';

import { SelectSavedQueryAction } from './types';

describe('selectSavedQuery()', () => {
describe('Scenario 1: User selects query with enabled autorun', () => {
const action = selectSavedQuery('purchases', true);
const it = sagaHelper(
selectSavedQueryFlow(action as SelectSavedQueryAction)
);

it('get list of saved queries from state', (result) => {
expect(result).toEqual(select(getSavedQueries));
return savedQueries;
});

it('setup visualization type', (result) => {
const chartSettings = {
layout: 'vertical' as Layout,
};

expect(result).toEqual(put(setVisualization('bar', chartSettings, {})));
});

it('setup query settings', (result) => {
const query = {
analysis_type: 'count',
};

expect(result).toEqual(put(setQuerySettings(query)));
});

it('updates save query settings', (result) => {
const savedQuery = {
cached: false,
displayName: 'purchases',
name: 'purchases',
tags: [],
};
expect(result).toMatchObject(put(updateSaveQuery(savedQuery)));
});

it('runs selected query', (result) => {
const query = {
analysis_type: 'count',
};

expect(result).toEqual(put(runQuery(query)));
});
});
});
6 changes: 3 additions & 3 deletions lib/js/app/modules/savedQuery/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { takeLatest, select, put } from 'redux-saga/effects';

import { updateSaveQuery } from './actions';

import { setVisualization, getQueryAutorun } from '../app';
import { setVisualization } from '../app';
import { SavedQueryListItem } from '../queries';
import {
setQuerySettings,
Expand All @@ -21,7 +21,7 @@ import { SavedQueryAPIResponse } from '../../types';

import { serializeSavedQuery, convertMilisecondsToMinutes } from './utils';

function* selectSavedQuery({ payload }: SelectSavedQueryAction) {
export function* selectSavedQuery({ payload }: SelectSavedQueryAction) {
const savedQueries: SavedQueryListItem[] = yield select(getSavedQueries);

try {
Expand Down Expand Up @@ -50,7 +50,7 @@ function* selectSavedQuery({ payload }: SelectSavedQueryAction) {
yield put(setQuerySettings(query));
yield put(updateSaveQuery(savedQuery));

const autorunQuery = yield select(getQueryAutorun);
const { autorunQuery } = payload;
if (autorunQuery) {
yield put(runQuery(query));
}
Expand Down
1 change: 1 addition & 0 deletions lib/js/app/modules/savedQuery/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface SelectSavedQueryAction {
type: typeof SELECT_SAVED_QUERY;
payload: {
name: string;
autorunQuery?: boolean;
};
}

Expand Down
3 changes: 2 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
},
"browser_preview": {
"title": "Preview",
"autorun_query_label": "Auto-run selected query"
"autorun_query_label": "Auto-run selected query",
"autorun_query_tooltip": "Every run query count as one query for your usage"
},
"query_summary": {
"analysis": "Analysis:",
Expand Down

0 comments on commit 079921c

Please sign in to comment.