diff --git a/src/client/components/filter-menu/number-filter-menu/number-filter-menu.mocha.tsx b/src/client/components/filter-menu/number-filter-menu/number-filter-menu.mocha.tsx
deleted file mode 100644
index 28499ac38..000000000
--- a/src/client/components/filter-menu/number-filter-menu/number-filter-menu.mocha.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015-2016 Imply Data, Inc.
- * Copyright 2017-2019 Allegro.pl
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { expect } from "chai";
-import React from "react";
-import * as TestUtils from "react-dom/test-utils";
-import { DimensionFixtures } from "../../../../common/models/dimension/dimension.fixtures";
-import { EssenceFixtures } from "../../../../common/models/essence/essence.fixtures";
-import { StageFixtures } from "../../../../common/models/stage/stage.fixtures";
-import { TimekeeperFixtures } from "../../../../common/models/timekeeper/timekeeper.fixtures";
-import { findDOMNode, renderIntoDocument } from "../../../utils/test-utils";
-import { NumberFilterMenu } from "./number-filter-menu";
-
-describe("NumberFilterMenu", () => {
- const div = document.createElement("div");
- div.setAttribute("id", "Div1");
-
- it("adds the correct class", () => {
- const renderedComponent = renderIntoDocument(
-
- );
-
- expect(TestUtils.isCompositeComponent(renderedComponent), "should be composite").to.equal(true);
- expect(findDOMNode(renderedComponent).className, "should contain class").to.contain("number-filter-menu");
- });
-
-});
diff --git a/src/client/components/number-range-picker/number-range-picker.mocha.tsx b/src/client/components/number-range-picker/number-range-picker.mocha.tsx
deleted file mode 100644
index cd5498a24..000000000
--- a/src/client/components/number-range-picker/number-range-picker.mocha.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2015-2016 Imply Data, Inc.
- * Copyright 2017-2019 Allegro.pl
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { expect } from "chai";
-import React from "react";
-import * as TestUtils from "react-dom/test-utils";
-import { DimensionFixtures } from "../../../common/models/dimension/dimension.fixtures";
-import { EssenceFixtures } from "../../../common/models/essence/essence.fixtures";
-import { TimekeeperFixtures } from "../../../common/models/timekeeper/timekeeper.fixtures";
-import { findDOMNode, renderIntoDocument } from "../../utils/test-utils";
-import { NumberRangePicker } from "./number-range-picker";
-
-describe("NumberRangePicker", () => {
- it("adds the correct class", () => {
- const renderedComponent = renderIntoDocument(
-
- );
-
- expect(TestUtils.isCompositeComponent(renderedComponent), "should be composite").to.equal(true);
- expect(findDOMNode(renderedComponent).className, "should contain class").to.contain("number-range-picker");
- });
-
-});
diff --git a/src/client/components/number-range-picker/number-range-picker.tsx b/src/client/components/number-range-picker/number-range-picker.tsx
index 0e2898807..d864eab41 100644
--- a/src/client/components/number-range-picker/number-range-picker.tsx
+++ b/src/client/components/number-range-picker/number-range-picker.tsx
@@ -15,13 +15,14 @@
* limitations under the License.
*/
-import { $, Dataset, ply } from "plywood";
+import { Dataset } from "plywood";
import React from "react";
import { Dimension } from "../../../common/models/dimension/dimension";
import { Essence } from "../../../common/models/essence/essence";
import { Timekeeper } from "../../../common/models/timekeeper/timekeeper";
import { getNumberOfWholeDigits, isTruthy, toSignificantDigits } from "../../../common/utils/general/general";
import { clamp, classNames, getXFromEvent } from "../../utils/dom/dom";
+import { ApiContext, ApiContextValue } from "../../views/cube-view/api-context";
import { Loader } from "../loader/loader";
import { QueryError } from "../query-error/query-error";
import { RangeHandle } from "../range-handle/range-handle";
@@ -72,6 +73,9 @@ export interface NumberRangePickerState {
}
export class NumberRangePicker extends React.Component {
+ static contextType = ApiContext;
+
+ context: ApiContextValue;
public mounted: boolean;
private picker = React.createRef();
@@ -87,19 +91,12 @@ export class NumberRangePicker extends React.Component {
if (!this.mounted) return;
diff --git a/src/client/views/cube-view/api-context.tsx b/src/client/views/cube-view/api-context.tsx
index 39eec84dd..e4a2b36ee 100644
--- a/src/client/views/cube-view/api-context.tsx
+++ b/src/client/views/cube-view/api-context.tsx
@@ -32,14 +32,21 @@ export type RawDataQuery = Unary>;
export type BooleanFilterQuery = Binary>;
export type StringFilterQuery = Binary>;
+
+export type NumberFilterQuery = Binary>;
+
export interface ApiContextValue {
visualizationQuery: VisualizationQuery;
booleanFilterQuery: BooleanFilterQuery;
rawDataQuery: RawDataQuery;
stringFilterQuery: StringFilterQuery;
+ numberFilterQuery: NumberFilterQuery;
}
export const ApiContext = React.createContext({
+ get numberFilterQuery(): NumberFilterQuery {
+ throw new Error("Attempted to consume ApiContext when there was no Provider");
+ },
get booleanFilterQuery(): BooleanFilterQuery {
throw new Error("Attempted to consume ApiContext when there was no Provider");
},
@@ -62,7 +69,7 @@ interface QueryResponse {
result: DatasetJS;
}
-type QueryEndpoints = "visualization" | "boolean-filter" | "string-filter" | "number-filter" | "raw-data";
+type QueryEndpoints = "visualization" | "pinboard" | "boolean-filter" | "string-filter" | "number-filter" | "raw-data";
type ExtraParams = Record;
@@ -97,6 +104,10 @@ function createVizQueryApi(settings: ClientAppSettings): VisualizationQuery {
return createApiCall(settings, "visualization", emptyParams);
}
+function createNumberFilterQuery(settings: ClientAppSettings): NumberFilterQuery {
+ return createApiCall(settings, "number-filter", (dimension: Dimension) => ({ dimension: dimension.name }));
+}
+
function createBooleanFilterQuery(settings: ClientAppSettings): BooleanFilterQuery {
return createApiCall(settings, "boolean-filter", (dimension: Dimension) => ({ dimension: dimension.name }));
}
@@ -114,6 +125,7 @@ function createRawDataQueryApi(settings: ClientAppSettings): RawDataQuery {
function createApi(settings: ClientAppSettings): ApiContextValue {
return {
+ numberFilterQuery: createNumberFilterQuery(settings),
booleanFilterQuery: createBooleanFilterQuery(settings),
visualizationQuery: createVizQueryApi(settings),
rawDataQuery: createRawDataQueryApi(settings),
diff --git a/src/common/utils/functional/functional.ts b/src/common/utils/functional/functional.ts
index c44d9922f..ff730673a 100644
--- a/src/common/utils/functional/functional.ts
+++ b/src/common/utils/functional/functional.ts
@@ -119,10 +119,10 @@ export function range(from: number, to: number): number[] {
}
// TODO: fix to use infer on arguments tuple https://stackoverflow.com/a/50014868/1089761
-export function debounceWithPromise any>(fn: T, ms: number): ((...args: any[]) => Promise) & { cancel: Fn } {
+export function debounceWithPromise Promise>(fn: T, ms: number): ((...args: Parameters) => Promise) & { cancel: Fn } {
let timeoutId: any;
- const debouncedFn = (...args: any[]) => {
+ const debouncedFn = (...args: Parameters) => {
let resolve: Function;
const promise = new Promise(pResolve => {
resolve = pResolve;
diff --git a/src/server/routes/query/query.ts b/src/server/routes/query/query.ts
index 3ac460456..8cf3a96d7 100644
--- a/src/server/routes/query/query.ts
+++ b/src/server/routes/query/query.ts
@@ -154,7 +154,36 @@ export function queryRouter(settings: Pick {
+
+ function getQuery(essence: Essence, dimension: Dimension, timekeeper: Timekeeper): Expression {
+ const { dataCube } = essence;
+ const filterExpression = essence
+ .getEffectiveFilter(timekeeper, { unfilterDimension: dimension })
+ .toExpression(dataCube);
+ const $main = $("main");
+ return ply()
+ .apply("main", $main.filter(filterExpression))
+ .apply("Min", $main.min($(dimension.name)))
+ .apply("Max", $main.max($(dimension.name)));
+ }
+
+ try {
+ const dataCube = await parseDataCube(req, settings);
+ const viewDefinition = parseViewDefinition(req);
+ const dimension = parseDimension(req, dataCube);
+ const essence = createEssence(viewDefinition, converter, dataCube, settings.appSettings);
+
+ const query = getQuery(essence, dimension, settings.getTimekeeper());
+ const queryDecorator = getQueryDecorator(req, dataCube, settings);
+ const result = await executeQuery(dataCube, query, essence.timezone, queryDecorator);
+ res.json({ result });
} catch (error) {
handleRequestErrors(error, res, settings.logger);
}