Skip to content

Commit

Permalink
Feat: add enable and list filters for Scheds
Browse files Browse the repository at this point in the history
  • Loading branch information
alexVasylenko committed Jan 4, 2023
1 parent 0cbbb42 commit 908e21f
Show file tree
Hide file tree
Showing 12 changed files with 220 additions and 35 deletions.
9 changes: 9 additions & 0 deletions querybook/server/logic/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
TaskRunRecord,
)
from models.datadoc import DataDoc
from models.board import BoardItem

DATADOC_SCHEDULE_PREFIX = "run_data_doc_"

Expand Down Expand Up @@ -194,6 +195,14 @@ def get_scheduled_data_docs_by_user(
if "name" in filters:
query = query.filter(DataDoc.title.contains(filters.get("name")))

if "status" in filters:
query = query.filter(TaskSchedule.enabled == filters.get("status"))

if filters.get("board_ids"):
query = query.join(BoardItem, BoardItem.data_doc_id == DataDoc.id).filter(
BoardItem.parent_board_id.in_(filters.get("board_ids"))
)

count = query.count()
docs_with_schedules = query.offset(offset).limit(limit).all()
docs_with_schedules_and_records = get_task_run_record_run_with_schedule(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ import { useField, useFormikContext } from 'formik';
import React, { useMemo } from 'react';

import { SimpleField } from 'ui/FormikField/SimpleField';

interface OptionsType {
value: string;
key: string;
hidden?: boolean;
}
import { OptionsType } from 'const/options';

export const EnvironmentSelection = ({
options = [],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useMemo } from 'react';
import { IStoreState } from 'redux/store/types';
import { useSelector } from 'react-redux';
import { SimpleField } from 'ui/FormikField/SimpleField';

export const DataDocBoardsSelect = ({ onChange, value }) => {
const activeBoardId = useSelector(
(state: IStoreState) => state.board.boardById
);

const boards = useMemo(() => {
return Object.values(activeBoardId).map((board) => ({
value: board.id,
label: board.name,
}));
}, [activeBoardId]);

return (
<SimpleField
label="Lists"
name="board_ids"
value={value}
defaultValue={boards.filter((board) =>
value.includes(board.value)
)}
options={boards}
onChange={onChange}
optionSelector={(v) => v}
closeMenuOnSelect={false}
hideSelectedOptions={false}
isMulti
type="react-select"
/>
);
};
150 changes: 139 additions & 11 deletions querybook/webapp/components/DataDocScheduleList/DataDocScheduleList.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import React, {
useEffect,
useMemo,
useState,
useRef,
useCallback,
} from 'react';
import { debounce } from 'lodash';
import { useSelector, useDispatch } from 'react-redux';
import { Dispatch, IStoreState } from 'redux/store/types';
import { getScheduledDocs } from 'redux/scheduledDataDoc/action';

import { IScheduledDocFilters } from 'redux/scheduledDataDoc/types';
import { Dispatch, IStoreState } from 'redux/store/types';
import { Checkbox } from 'ui/Checkbox/Checkbox';
import { Container } from 'ui/Container/Container';
import { DebouncedInput } from 'ui/DebouncedInput/DebouncedInput';
import { Pagination } from 'ui/Pagination/Pagination';
import { PrettyNumber } from 'ui/PrettyNumber/PrettyNumber';
import { AccentText, EmptyText } from 'ui/StyledText/StyledText';
import { IconButton } from 'ui/Button/IconButton';
import { Popover } from 'ui/Popover/Popover';
import { fetchBoards } from 'redux/board/action';

import { DataDocScheduleItem } from './DataDocScheduleItem';
import { OptionTypeBase } from 'react-select';
import { SimpleField } from 'ui/FormikField/SimpleField';
import { Form, Formik } from 'formik';
import { DataDocBoardsSelect } from './DataDocBoardsSelect';

import './DataDocScheduleList.scss';

const enabledOptions = [
{ key: '', value: 'All' },
{ key: true, value: 'Enabled' },
{ key: false, value: 'Disabled' },
];

function useDataDocScheduleFiltersAndPagination() {
const {
page: initPage,
Expand All @@ -24,34 +44,62 @@ function useDataDocScheduleFiltersAndPagination() {
} = useSelector((state: IStoreState) => state.scheduledDocs);

const [docName, setDocName] = useState(initFilters.name ?? '');
const [scheduledOnly, setScheduledOnly] = useState(
initFilters.scheduled_only ?? false

const [extraFilters, setExtraFilters] = useState<IScheduledDocFilters>({
status: initFilters.status ?? null,
board_ids: initFilters.board_ids ?? [],
scheduled_only: initFilters.scheduled_only ?? false,
});

const updateFilters = useCallback(
(
params:
| OptionTypeBase[]
| { scheduled_only: boolean }
| { status: boolean }
) => {
setExtraFilters((state) => ({
...state,
...params,
}));
},
[]
);

const filters: IScheduledDocFilters = useMemo(() => {
const _filters: IScheduledDocFilters = {};
if (docName) {
_filters.name = docName;
}
if (scheduledOnly) {

if (extraFilters.scheduled_only) {
_filters.scheduled_only = true;
}

if (extraFilters.status !== null) {
_filters.status = extraFilters.status;
}

if (extraFilters.board_ids) {
_filters.board_ids = extraFilters.board_ids?.map((l) => l.value);
}

return _filters;
}, [docName, scheduledOnly]);
}, [docName, extraFilters]);

const [page, setPage] = useState(initPage);
const [pageSize, setPageSize] = useState(initPageSize);

return {
filters,
setDocName,
setScheduledOnly,

numberOfResults,
page,
setPage,
pageSize,
setPageSize,
updateFilters,
};
}

Expand Down Expand Up @@ -92,7 +140,7 @@ const DataDocScheduleList: React.FC = () => {

filters,
setDocName,
setScheduledOnly,
updateFilters,
} = useDataDocScheduleFiltersAndPagination();

const dataDocsWithSchedule = useDataDocWithSchedules(
Expand All @@ -102,6 +150,74 @@ const DataDocScheduleList: React.FC = () => {
);

const totalPages = Math.ceil(numberOfResults / pageSize);
const [showSearchFilter, setShowSearchFilter] = useState(false);
const filterButtonRef = useRef();
const dispatch = useDispatch();

useEffect(() => {
dispatch(fetchBoards());
}, []);

const handleUpdateList = React.useCallback(
debounce((params: OptionTypeBase[]) => {
updateFilters({
board_ids: params,
});
}, 500),
[]
);

const handleUpdateStatus = React.useCallback((value) => {
updateFilters({
status: value === '' ? null : value === 'true',
});
}, []);

const handleUpdateScheduledOnly = React.useCallback((value: boolean) => {
updateFilters({
scheduled_only: value,
});
}, []);

const searchFiltersPickerDOM = showSearchFilter && (
<Popover
layout={['bottom', 'right']}
onHide={() => {
setShowSearchFilter(false);
}}
anchor={filterButtonRef.current}
>
<div className="DataTableNavigatorSearchFilter">
<div className="DataDocScheduleList_select-wrapper">
<Formik
initialValues={{
status: '',
board_ids: [],
}}
>
{({}) => {
return (
<>
<SimpleField
label="Status"
type="select"
name="status"
options={enabledOptions}
onChange={handleUpdateStatus}
value={filters.status}
/>
<DataDocBoardsSelect
value={filters.board_ids}
onChange={handleUpdateList}
/>
</>
);
}}
</Formik>
</div>
</div>
</Popover>
);

return (
<Container>
Expand All @@ -116,11 +232,23 @@ const DataDocScheduleList: React.FC = () => {
}}
/>
</div>

<IconButton
ref={filterButtonRef}
className="mr8"
size={'18px'}
noPadding
onClick={() => {
setShowSearchFilter(true);
}}
icon="Sliders"
/>
{searchFiltersPickerDOM}
<div>
<Checkbox
title="Scheduled DataDocs Only"
value={filters.scheduled_only}
onChange={setScheduledOnly}
onChange={handleUpdateScheduledOnly}
/>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions querybook/webapp/const/options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface OptionsType {
value: string;
key: string;
hidden?: boolean;
}
1 change: 1 addition & 0 deletions querybook/webapp/redux/dataDoc/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,4 @@ export const queryCellSelector = createSelector(dataDocCellsSelector, (cells) =>
};
})
);

8 changes: 6 additions & 2 deletions querybook/webapp/redux/scheduledDataDoc/action.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { DataDocScheduleResource } from 'resource/dataDoc';

import { IScheduledDoc, IScheduledDocFilters, ThunkResult } from './types';
import {
IScheduledDoc,
ITransformedScheduledDocFilters,
ThunkResult,
} from './types';

export function getScheduledDocs({
paginationPage,
Expand All @@ -9,7 +13,7 @@ export function getScheduledDocs({
}: {
paginationPage?: number;
paginationPageSize?: number;
paginationFilter?: IScheduledDocFilters;
paginationFilter?: ITransformedScheduledDocFilters;
}): ThunkResult<Promise<IScheduledDoc[]>> {
return async (dispatch, getState) => {
const envId = getState().environment.currentEnvironmentId;
Expand Down
18 changes: 15 additions & 3 deletions querybook/webapp/redux/scheduledDataDoc/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,23 @@ import { IDataDoc } from 'const/datadoc';
import { ITaskSchedule, ITaskStatusRecord } from 'const/schedule';

import { IStoreState } from '../store/types';
import { OptionsType } from 'const/options';

export interface IScheduledDocFilters {
interface IBasicScheduledDocFilters {
name?: string;
scheduled_only?: boolean;
status?: boolean;
}

export interface IScheduledDocFilters extends IBasicScheduledDocFilters {
board_ids?: OptionsType[];
}

export interface ITransformedScheduledDocFilters
extends IBasicScheduledDocFilters {
board_ids?: number[];
}

export interface IScheduledDoc {
doc: IDataDoc;
last_record?: ITaskStatusRecord;
Expand All @@ -26,7 +38,7 @@ export interface IReceiveDocWithScheduleAction extends Action {
total: number;
page: number;
pageSize: number;
filters: IScheduledDocFilters;
filters: ITransformedScheduledDocFilters;
};
}

Expand All @@ -50,5 +62,5 @@ export interface IScheduledDataDocState {
numberOfResults: number;
page: number;
pageSize: number;
filters: IScheduledDocFilters;
filters: ITransformedScheduledDocFilters;
}
4 changes: 2 additions & 2 deletions querybook/webapp/resource/dataDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import dataDocSocket from 'lib/data-doc/datadoc-socketio';
import ds from 'lib/datasource';
import {
IScheduledDoc,
IScheduledDocFilters,
ITransformedScheduledDocFilters,
} from 'redux/scheduledDataDoc/types';

export const DataDocResource = {
Expand Down Expand Up @@ -188,7 +188,7 @@ export const DataDocScheduleResource = {
envId: number;
limit: number;
offset: number;
filters: IScheduledDocFilters;
filters: ITransformedScheduledDocFilters;
}) =>
ds.fetch<{ docs: IScheduledDoc[]; count: number }>(
'/datadoc/scheduled/',
Expand Down
2 changes: 1 addition & 1 deletion querybook/webapp/ui/Form/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const FormField: React.FunctionComponent<IFormFieldProps> = ({
);
};

const FormFieldLabelSection: React.FunctionComponent<
export const FormFieldLabelSection: React.FunctionComponent<
IFormFieldSectionProps
> = ({ children, className = '' }) => (
<AccentText
Expand Down
Loading

0 comments on commit 908e21f

Please sign in to comment.