Commit 7536742d authored by Jakub Beránek's avatar Jakub Beránek
Browse files

ENH: load datasets selectively

parent 62335cc7
......@@ -8,7 +8,7 @@ import {Project} from '../../../../lib/project/project';
import {RangeFilter} from '../../../../lib/view/range-filter';
import {View} from '../../../../lib/view/view';
import {AppState} from '../../../../state/app/reducers';
import {SelectChartViewParams} from '../../../../state/session/pages/chart-page/actions';
import {SelectChartViewParams, setAllViewsActiveAction} from '../../../../state/session/pages/chart-page/actions';
import {getSelectedProject} from '../../../../state/session/project/reducers';
import {getViews} from '../../../../state/session/view/reducers';
import {formatKey} from '../../../../util/measurement';
......@@ -35,8 +35,12 @@ interface StateProps
project: Project;
views: View[];
}
interface DispatchProps
{
setAllViewsActive(): void;
}
type Props = OwnProps & StateProps & RouteComponentProps<void>;
type Props = OwnProps & StateProps & DispatchProps & RouteComponentProps<void>;
const initialState = {
viewFilter: {
......@@ -81,6 +85,11 @@ class GridChartPageComponent extends PureComponent<Props, State>
showAverageTrend: false
};
componentDidMount()
{
this.props.setAllViewsActive();
}
render()
{
return (
......@@ -124,8 +133,6 @@ class GridChartPageComponent extends PureComponent<Props, State>
renderView = (view: View): JSX.Element =>
{
const measurements = view.measurements;
if (measurements.length === 0) return null;
const datasets = view.yAxes.map(yAxis => ({
name: `${view.name} (${formatKey(yAxis)})`,
yAxis,
......@@ -163,7 +170,9 @@ class GridChartPageComponent extends PureComponent<Props, State>
}
}
export const GridChartPage = withRouter(connect<StateProps, {}, OwnProps>((state: AppState) => ({
export const GridChartPage = withRouter(connect<StateProps, DispatchProps, OwnProps>((state: AppState) => ({
project: getSelectedProject(state),
views: getViews(state)
}))(GridChartPageComponent));
}), {
setAllViewsActive: setAllViewsActiveAction
})(GridChartPageComponent));
......@@ -48,7 +48,6 @@ export class EditableText extends Component<Props>
if (this.props.validate(value))
{
console.log('validate');
this.props.onChange(value);
}
else this.text.current.textContent = this.props.value;
......
......@@ -13,6 +13,7 @@ import {initProjectSession, initUserSession} from './actions';
import {loadGlobalMeasurements} from './pages/actions';
import {reloadViewMeasurementsAction} from './pages/chart-page/actions';
import {chartEpics} from './pages/chart-page/epics';
import {getChartState} from './pages/chart-page/reducer';
import {pageEpics} from './pages/epics';
import {measurementsEpics} from './pages/measurements-page/epics';
import {getRangeFilter} from './pages/reducers';
......@@ -75,7 +76,10 @@ const initProjectSessionEpic: AppEpic = (action$, store, deps) =>
params: range,
result: globalMeasurements
}),
reloadViewMeasurementsAction.started(getRangeFilter(store.value)),
reloadViewMeasurementsAction.started({
rangeFilter: getRangeFilter(store.value),
views: getChartState(store.value).selectedViews
}),
initProjectSession.done({
params: {},
result: {}
......
......@@ -9,7 +9,16 @@ const actionCreator = actionCreatorFactory('chart-state');
export const updateChartXAxisSettingsAction = actionCreator<XAxisSettings>('set-x-axis-settings');
export const updateSelectedViewsAction = actionCreator<string[]>('update-selected-views');
export const reloadViewMeasurementsAction = actionCreator.async<RangeFilter, View[]>('reload-datasets');
export interface ReloadViewMeasurementsParams
{
rangeFilter: RangeFilter;
views: string[]; // views that should be loaded
}
export const reloadViewMeasurementsAction = actionCreator.async<
ReloadViewMeasurementsParams, View[]>('reload-datasets');
// sets all views as active, downloads datasets for them
export const setAllViewsActiveAction = actionCreator('set-all-views-active');
export interface SelectChartViewParams
{
......
......@@ -11,6 +11,19 @@ interface CacheRecord
}
const items: Map<string, CacheRecord> = new Map();
const activeViews: Set<string> = new Set();
export function addToActiveViews(views: string[])
{
for (const view of views)
{
activeViews.add(view);
}
}
export function getActiveViews(): string[]
{
return Array.from(activeViews);
}
export function insertMeasurementsRecord(view: View, rangeFilter: RangeFilter, measurements: Measurement[])
{
......
import {combineEpics} from 'redux-observable';
import {EMPTY, from, of} from 'rxjs';
import {map, switchMap, tap} from 'rxjs/operators';
import {Action, Success} from 'typescript-fsa';
import {BatchedMeasurements} from '../../../../lib/api/snail-client';
import {Measurement} from '../../../../lib/measurement/measurement';
import {RangeFilter} from '../../../../lib/view/range-filter';
......@@ -9,6 +10,7 @@ import {ofAction, ofActions} from '../../../../util/redux-observable';
import {createRequestEpic} from '../../../../util/request';
import {isBlank} from '../../../../util/string';
import {AppEpic} from '../../../app/app-epic';
import {AppState} from '../../../app/reducers';
import {getSelectedProject} from '../../project/reducers';
import {getToken} from '../../user/reducers';
import {ViewActions} from '../../view/actions';
......@@ -19,16 +21,36 @@ import {getRangeFilter} from '../reducers';
import {
reloadViewMeasurementsAction,
selectChartViewAction,
selectViewAction,
selectViewAction, setAllViewsActiveAction,
updateChartXAxisSettingsAction,
updateSelectedViewsAction
} from './actions';
import {clearCache, getMeasurementsRecord, insertMeasurementsRecord} from './dataset-cache';
import {
addToActiveViews,
clearCache,
getActiveViews,
getMeasurementsRecord,
insertMeasurementsRecord
} from './dataset-cache';
import {getChartState} from './reducer';
function getDirtyViews(views: View[], rangeFilter: RangeFilter): View[]
function getDirtyViews(state: AppState, rangeFilter: RangeFilter, newViews: string[]): View[]
{
return views.filter(v => getMeasurementsRecord(v, rangeFilter) === null);
addToActiveViews(newViews);
const views = getViews(state);
const viewMap = new Map();
for (const view of views)
{
viewMap.set(view.id, view);
}
const selected = getActiveViews()
.map(id => viewMap.get(id))
.filter(v => v !== undefined);
return selected.filter(v => getMeasurementsRecord(v, rangeFilter) === null);
}
function getMeasurements(batch: BatchedMeasurements, view: View): Measurement[]
{
......@@ -38,12 +60,11 @@ function getMeasurements(batch: BatchedMeasurements, view: View): Measurement[]
}
const reloadViews = createRequestEpic(reloadViewMeasurementsAction, (action, store, deps) => {
const rangeFilter = action.payload;
const rangeFilter = action.payload.rangeFilter;
const state = store.value;
const views = getViews(state);
const dirtyViews = getDirtyViews(views, rangeFilter);
const dirtyViews = getDirtyViews(state, rangeFilter, action.payload.views);
if (dirtyViews.length === 0) return of(views);
if (dirtyViews.length === 0) return of(getViews(state));
const dirtyViewSet = new Set(dirtyViews.map(v => v.id));
const token = getToken(state);
......@@ -75,6 +96,15 @@ const reloadViews = createRequestEpic(reloadViewMeasurementsAction, (action, sto
}
}, true);
const setAllViewsActive: AppEpic = (action$, store) =>
action$.pipe(
ofAction(setAllViewsActiveAction),
map(() => reloadViewMeasurementsAction.started({
rangeFilter: getRangeFilter(store.value),
views: getViews(store.value).map(v => v.id)
}))
);
const handleViewGridChartSelect: AppEpic = (action$, store) =>
action$.pipe(
ofAction(selectChartViewAction),
......@@ -111,16 +141,30 @@ const handleViewSelect: AppEpic = (action$, store) =>
const reloadDatasetsAfterViewChange: AppEpic = (action$, store) =>
action$.pipe(
ofActions([ViewActions.create.done, ViewActions.update.done]),
map(() => reloadViewMeasurementsAction.started(getRangeFilter(store.value)))
map((action: Action<Success<View, View>>) => reloadViewMeasurementsAction.started({
rangeFilter: getRangeFilter(store.value),
views: [action.payload.result.id]
}))
);
const reloadDatasetsAfterSelectedViewsChange: AppEpic = (action$, store) =>
action$.pipe(
ofAction(updateSelectedViewsAction),
map(() => reloadViewMeasurementsAction.started({
rangeFilter: getRangeFilter(store.value),
views: getChartState(store.value).selectedViews
}))
);
const reloadDatasetsAfterRangeFilterChange: AppEpic = action$ =>
action$.pipe(
ofAction(changeRangeFilterAction),
map(action => reloadViewMeasurementsAction.started(action.payload))
map(action => reloadViewMeasurementsAction.started({
rangeFilter: action.payload,
views: []
}))
);
const clearCacheAfterMeasurementDelete: AppEpic = action$ =>
action$.pipe(
ofActions([deleteMeasurementAction.done, deleteAllMeasurementsAction.done]),
......@@ -135,6 +179,8 @@ export const chartEpics = combineEpics(
handleViewSelect,
handleViewGridChartSelect,
reloadViews,
reloadDatasetsAfterViewChange,
reloadDatasetsAfterSelectedViewsChange,
reloadDatasetsAfterRangeFilterChange,
reloadDatasetsAfterViewChange
setAllViewsActive
);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment