diff --git a/cypress/integration/boolean-filter-menu.spec.ts b/cypress/integration/boolean-filter-menu.spec.ts
index 52aa47398..a9b801260 100644
--- a/cypress/integration/boolean-filter-menu.spec.ts
+++ b/cypress/integration/boolean-filter-menu.spec.ts
@@ -17,7 +17,8 @@
context("Boolean Filter Menu", () => {
// TODO: FIX references
- const booleanTile = () => cy.get(".filter-tile .items .filter:nth-child(2)");
+ const filterTiles = () => cy.get(".center-top-bar:not(.fallback) .filter-tile-row");
+ const booleanTile = () => filterTiles().find(".items .tile:nth-child(2)");
const booleanMenu = () => cy.get(".boolean-filter-menu");
const booleanMenuTable = () => booleanMenu().find(".menu-table");
const falseOption = () => booleanMenuTable().find(".row:contains('false')");
diff --git a/cypress/integration/fixed-time-filter-menu.spec.ts b/cypress/integration/fixed-time-filter-menu.spec.ts
index 122ed9d73..232ddc9b9 100644
--- a/cypress/integration/fixed-time-filter-menu.spec.ts
+++ b/cypress/integration/fixed-time-filter-menu.spec.ts
@@ -16,7 +16,8 @@
context("Fixed Time Filter Menu", () => {
// TODO: FIX references
- const filterTile = () => cy.get(".filter-tile .items .filter:first");
+ const filterTiles = () => cy.get(".center-top-bar:not(.fallback) .filter-tile-row");
+ const filterTile = () => filterTiles().get(".items .tile:first");
const timeFilter = () => cy.get(".time-filter-menu");
const tabSelector = () => timeFilter().find(".group-container");
const datePicker = () => timeFilter().find(".date-range-picker");
diff --git a/cypress/integration/line-chart.spec.ts b/cypress/integration/line-chart.spec.ts
index 92d516ed1..e6028b226 100644
--- a/cypress/integration/line-chart.spec.ts
+++ b/cypress/integration/line-chart.spec.ts
@@ -16,7 +16,9 @@
context("Line Chart", () => {
const header = () => cy.get(".cube-header-bar");
- const timeFilter = () => cy.get(".filter-tile .filter:first");
+ const topBar = () => cy.get(".center-top-bar:not(.fallback)");
+ const filterTiles = () => topBar().find(".filter-tile-row");
+ const timeFilter = () => filterTiles().get(".tile:first");
const lineChart = () => cy.get(".line-base-chart");
const chartLine = () => lineChart().find(".chart-line");
const highlighter = () => lineChart().find(".highlighter");
@@ -24,7 +26,7 @@ context("Line Chart", () => {
const highlightModal = () => cy.get(".highlight-modal");
const acceptHighlight = () => highlightModal().find(".accept");
const dropHighlight = () => highlightModal().find(".drop");
- const visSelector = () => cy.get(".vis-item");
+ const visSelector = () => topBar().find(".vis-item");
const visSelectorMenu = () => cy.get(".vis-selector-menu");
const visSelectorOk = () => visSelectorMenu().find(".button.primary");
const visSettings = () => cy.get(".vis-settings");
diff --git a/cypress/integration/pinboard.spec.ts b/cypress/integration/pinboard.spec.ts
index f5f5dc988..2b3742177 100644
--- a/cypress/integration/pinboard.spec.ts
+++ b/cypress/integration/pinboard.spec.ts
@@ -21,7 +21,8 @@ context("Pinboard", () => {
const pinboardSortError = () => pinboardMeasureTile().find(".pinboard-sort-error");
const pinboardSortSelected = () => pinboardSort().find(".selected-item");
const pinboardTiles = () => pinboardPanel().find(".pinboard-tile");
- const measureTile = (title: string) => cy.get(`.series.measure:contains(${title})`);
+ const seriesTiles = () => cy.get(".center-top-bar:not(.fallback) .series-tile-row");
+ const measureTile = (title: string) => seriesTiles().find(`.tile.measure:contains(${title})`);
describe("Pinboard", () => {
const urls = {
diff --git a/cypress/integration/relative-time-filter-menu.spec.ts b/cypress/integration/relative-time-filter-menu.spec.ts
index 7c4da9e0f..0900adb11 100644
--- a/cypress/integration/relative-time-filter-menu.spec.ts
+++ b/cypress/integration/relative-time-filter-menu.spec.ts
@@ -16,7 +16,8 @@
context("Relative Time Filter Menu", () => {
// TODO: FIX references
- const filterTile = () => cy.get(".filter-tile .items .filter:first");
+ const filterTiles = () => cy.get(".center-top-bar:not(.fallback) .filter-tile-row");
+ const filterTile = () => filterTiles().get(".items .tile:first");
const timeFilter = () => cy.get(".time-filter-menu");
const tabSelector = () => timeFilter().find(".group-container");
const filterMenuOkButton = () => timeFilter().find(".button.primary");
diff --git a/cypress/integration/split-tile.spec.ts b/cypress/integration/split-tile.spec.ts
index 6d78fcae9..8ebfe6428 100644
--- a/cypress/integration/split-tile.spec.ts
+++ b/cypress/integration/split-tile.spec.ts
@@ -15,13 +15,13 @@
*/
context("Split Tile", () => {
- const splitsContainer = () => cy.get(".split-tile");
+ const splitsContainer = () => cy.get(".center-top-bar:not(.fallback) .split-tile-row");
const dragMask = () => cy.get(".drag-mask");
- const splitTile = (dimension: string) => cy.get(`.split-tile .split.dimension:contains(${dimension})`);
- const addSplitButton = () => cy.get(".split-tile .add-tile");
- const splitItemsRow = () => cy.get(".split-tile .items");
- const splitItems = () => cy.get(".split-tile .items .split.dimension");
- const splitOverflow = () => cy.get(".split-tile .items .overflow.dimension");
+ const splitTile = (dimension: string) => splitsContainer().find(`.tile.dimension:contains(${dimension})`);
+ const addSplitButton = () => splitsContainer().find(".add-tile");
+ const splitItemsRow = () => splitsContainer().find(".items");
+ const splitItems = () => splitsContainer().find(".items .tile.dimension");
+ const splitOverflow = () => splitsContainer().find(".items .overflow.dimension");
const splitOverflowMenu = () => cy.get(".overflow-menu");
const addSplitMenu = () => cy.get(".add-tile-menu");
const splitMenu = () => cy.get(".split-menu");
@@ -43,7 +43,7 @@ context("Split Tile", () => {
splitItems().should("have.length", splits.length);
splitItemsRow().within(() => {
splits.forEach((split, idx) => {
- cy.get(`.split.dimension:nth-child(${idx + 1})`)
+ cy.get(`.tile.dimension:nth-child(${idx + 1})`)
.should("contain", split);
});
});
@@ -174,14 +174,14 @@ context("Split Tile", () => {
it("should show overflowed split after clicking tile", () => {
splitOverflow().click();
- splitOverflowMenu().find(".split.dimension")
+ splitOverflowMenu().find(".tile.dimension")
.should("contain", "City Name");
});
it("should open split menu inside overflow tile", () => {
splitOverflow().click();
- splitOverflowMenu().find(".split.dimension")
+ splitOverflowMenu().find(".tile.dimension")
.click();
splitMenu().should("exist");
diff --git a/cypress/integration/string-split-menu.spec.ts b/cypress/integration/string-split-menu.spec.ts
index 8cf718518..327749f55 100644
--- a/cypress/integration/string-split-menu.spec.ts
+++ b/cypress/integration/string-split-menu.spec.ts
@@ -14,7 +14,8 @@
* limitations under the License.
*/
context("String Split Menu", () => {
- const channelTile = () => cy.get(".split-tile .split.dimension:contains(Channel)");
+ const splitTiles = () => cy.get(".center-top-bar:not(.fallback) .split-tile-row");
+ const channelTile = () => splitTiles().find(".tile.dimension:contains(Channel)");
const openChannelMenu = () => channelTile().click();
const splitMenu = () => cy.get(".split-menu");
const limitDropdown = () => splitMenu().find(".dropdown.down:nth-child(2)");
diff --git a/cypress/integration/table.spec.ts b/cypress/integration/table.spec.ts
index 2868a450f..c70dbbd2a 100644
--- a/cypress/integration/table.spec.ts
+++ b/cypress/integration/table.spec.ts
@@ -16,8 +16,8 @@
context("Table", () => {
const header = () => cy.get(".cube-header-bar");
- const filterTileRow = () => cy.get(".filter-tile");
- const filterTile = (i: number) => filterTileRow().find(`.filter:nth-child(${i})`);
+ const filterTiles = () => cy.get(".center-top-bar:not(.fallback) .filter-tile-row");
+ const filterTile = (i: number) => filterTiles().find(`.tile:nth-child(${i})`);
const table = () => cy.get(".table");
const clickTarget = () => table().find(".event-target");
const highlightModal = () => cy.get(".highlight-modal");
diff --git a/cypress/integration/totals.spec.ts b/cypress/integration/totals.spec.ts
index 175c43b2c..35c250e03 100644
--- a/cypress/integration/totals.spec.ts
+++ b/cypress/integration/totals.spec.ts
@@ -14,33 +14,39 @@
* limitations under the License.
*/
context("Totals", () => {
+
+ const topBar = () => cy.get(".center-top-bar:not(.fallback)");
+ const filters = () => topBar().find(".filter-tile-row .tile");
+ const series = () => topBar().find(".series-tile-row .tile");
+ const visualization = () => cy.get(".visualization-root");
+
beforeEach(() => {
cy.visit("http://localhost:9090/#wiki");
});
it("should load Totals visualisation", () => {
- cy.get(".visualization-root")
+ visualization()
.should("have.class", "totals");
});
it("should set Latest day time filter", () => {
- cy.get(".filter-tile .filter")
+ filters()
.should("have.length", 1)
.should("contain", "Latest day");
});
it('should set default series "Added"', () => {
- cy.get(".series-tile .series")
+ series()
.should("have.length", 1)
.should("contain", "Added");
});
it("should load data for defined filters and measures", () => {
- cy.get(".visualization .total .measure-name")
+ visualization().find(".measure-name")
.should("have.length", 1)
.should("contain", "Added");
- cy.get(".visualization .total .measure-value")
+ visualization().find(".measure-value")
.should("have.length", 1)
.should("contain", "9.4 m");
});
diff --git a/src/client/components/filter-tile/filter-clause-label.scss b/src/client/components/filter-tile/filter-clause-label.scss
new file mode 100644
index 000000000..d3e9bfe1b
--- /dev/null
+++ b/src/client/components/filter-tile/filter-clause-label.scss
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017-2022 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.
+ */
+
+.reading {
+ .filter-clause-title {
+ margin-right: 5px;
+ }
+}
diff --git a/src/client/components/filter-tile/filter-clause-label.tsx b/src/client/components/filter-tile/filter-clause-label.tsx
new file mode 100644
index 000000000..277e2edfb
--- /dev/null
+++ b/src/client/components/filter-tile/filter-clause-label.tsx
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-2022 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 React from "react";
+import { Dimension } from "../../../common/models/dimension/dimension";
+import { Essence } from "../../../common/models/essence/essence";
+import { FilterClause } from "../../../common/models/filter-clause/filter-clause";
+import { getFormattedClause } from "../../../common/utils/formatter/formatter";
+import "./filter-clause-label.scss";
+import timeShiftLabel from "./time-shift-label";
+
+interface LabelProps {
+ dimension: Dimension;
+ clause: FilterClause;
+ essence: Essence;
+}
+
+export function FilterClauseLabel(props: LabelProps) {
+ const { dimension, clause, essence } = props;
+ const { title, values } = getFormattedClause(dimension, clause, essence.timezone);
+ const timeShift = timeShiftLabel(dimension, essence);
+
+ return
+ {title ? {title} : null}
+ {values} {timeShift}
+
;
+}
diff --git a/src/client/components/filter-tile/filter-tile.scss b/src/client/components/filter-tile/filter-tile.scss
deleted file mode 100644
index 14e2627af..000000000
--- a/src/client/components/filter-tile/filter-tile.scss
+++ /dev/null
@@ -1,69 +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 '../../imports';
-
-$overflow-width: 40px;
-
-.filter-tile {
- @extend %module;
- @extend %module-h-title;
-
- .drag-mask {
- @include pin-full;
- }
-
- .items {
- @include unpin-left($bar-title-width);
- transition: height 0.1s ease-in-out;
- overflow: hidden;
-
- .filter {
- @extend %tiles-item;
- @extend %tiles-item-h;
- position: absolute;
- left: 0; // It gets horizontal position from the JS
-
- .dimension-title {
- margin-right: 5px;
- }
-
- &.excluded {
- .values {
- text-decoration: line-through;
- }
- }
- }
- }
-
- .overflow {
- @extend %overflow;
- }
-
- .fancy-drag-indicator {
- @include unpin-left($bar-title-width);
- }
-
- .add-tile {
- @include pin-right(25px);
- padding-right: 5px;
- }
-}
-
-.overflow-menu {
- @extend %overflow-menu
-}
diff --git a/src/client/components/filter-tile/filter-tile.tsx b/src/client/components/filter-tile/filter-tile.tsx
index c123c7dc6..5cf9efb10 100644
--- a/src/client/components/filter-tile/filter-tile.tsx
+++ b/src/client/components/filter-tile/filter-tile.tsx
@@ -16,7 +16,6 @@
import React from "react";
import { Clicker } from "../../../common/models/clicker/clicker";
-import { isTimeAttribute } from "../../../common/models/data-cube/data-cube";
import { Dimension } from "../../../common/models/dimension/dimension";
import { Essence } from "../../../common/models/essence/essence";
import { FilterClause, isTimeFilter } from "../../../common/models/filter-clause/filter-clause";
@@ -30,29 +29,8 @@ import { classNames } from "../../utils/dom/dom";
import { FilterMenu } from "../filter-menu/filter-menu";
import { SvgIcon } from "../svg-icon/svg-icon";
import { WithRef } from "../with-ref/with-ref";
-
-function timeShiftLabel(dimension: Dimension, essence: Essence) {
- if (!isTimeAttribute(essence.dataCube, dimension.expression)) return null;
- if (!essence.hasComparison()) return null;
- return `(Shift: ${essence.timeShift.getDescription(true)})`;
-}
-
-interface LabelProps {
- dimension: Dimension;
- clause: FilterClause;
- essence: Essence;
-}
-
-function Label(props: LabelProps) {
- const { dimension, clause, essence } = props;
- const { title, values } = getFormattedClause(dimension, clause, essence.timezone);
- const timeShift = timeShiftLabel(dimension, essence);
-
- return
- {title ? {title} : null}
- {values} {timeShift}
-
;
-}
+import { FilterClauseLabel } from "./filter-clause-label";
+import timeShiftLabel from "./time-shift-label";
function tileTitle(dimension: Dimension, clause: FilterClause, essence: Essence): string {
const { title, values } = getFormattedClause(dimension, clause, essence.timezone);
@@ -102,7 +80,7 @@ export const FilterTile: React.FunctionComponent = props => {
return
{({ ref: openOn, setRef }) =>
= props => {
style={style}
title={tileTitle(dimension, clause, essence)}
>
-
+
{removeClause &&
removeClause(clause)}>
}
diff --git a/src/client/components/filter-tile/filter-tiles-row.tsx b/src/client/components/filter-tile/filter-tiles-row.tsx
index 9deeadccf..1a9f6445f 100644
--- a/src/client/components/filter-tile/filter-tiles-row.tsx
+++ b/src/client/components/filter-tile/filter-tiles-row.tsx
@@ -34,7 +34,6 @@ import { CubeContext, CubeContextValue } from "../../views/cube-view/cube-contex
import { PartialFilter } from "../../views/cube-view/partial-tiles-provider";
import { DragIndicator } from "../drag-indicator/drag-indicator";
import { AddFilter } from "./add-filter";
-import "./filter-tile.scss";
import { FilterTiles } from "./filter-tiles";
interface FilterTilesRowProps {
@@ -199,7 +198,7 @@ export class FilterTilesRow extends React.Component
+ return
{STRINGS.filter}
const { closeItem, saveClause, essence, timekeeper, locale, clicker, stage, dimension, style } = props;
return
{({ ref: openOn, setRef }) =>
{dimension.title}
diff --git a/src/client/components/filter-tile/time-shift-label.ts b/src/client/components/filter-tile/time-shift-label.ts
new file mode 100644
index 000000000..5274ae4ac
--- /dev/null
+++ b/src/client/components/filter-tile/time-shift-label.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-2022 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 { isTimeAttribute } from "../../../common/models/data-cube/data-cube";
+import { Dimension } from "../../../common/models/dimension/dimension";
+import { Essence } from "../../../common/models/essence/essence";
+
+export default function timeShiftLabel(dimension: Dimension, essence: Essence) {
+ if (!isTimeAttribute(essence.dataCube, dimension.expression)) return null;
+ if (!essence.hasComparison()) return null;
+ return `(Shift: ${essence.timeShift.getDescription(true)})`;
+}
diff --git a/src/client/components/series-tile/placeholder-series.tsx b/src/client/components/series-tile/placeholder-series.tsx
index b32ae16b2..c31c6707a 100644
--- a/src/client/components/series-tile/placeholder-series.tsx
+++ b/src/client/components/series-tile/placeholder-series.tsx
@@ -42,7 +42,7 @@ export const PlaceholderSeriesTile: React.FunctionComponent
{({ ref: openOn, setRef }) =>
{measure.title}
diff --git a/src/client/components/series-tile/series-tile.tsx b/src/client/components/series-tile/series-tile.tsx
index e87fe2323..4f997721b 100644
--- a/src/client/components/series-tile/series-tile.tsx
+++ b/src/client/components/series-tile/series-tile.tsx
@@ -56,7 +56,7 @@ export const SeriesTile: React.FunctionComponent
= props => {
return
{({ ref: openOn, setRef }) =>
openSeriesMenu(definition)}
diff --git a/src/client/components/series-tile/series-tiles-row.tsx b/src/client/components/series-tile/series-tiles-row.tsx
index 794f13c34..ab3b9d330 100644
--- a/src/client/components/series-tile/series-tiles-row.tsx
+++ b/src/client/components/series-tile/series-tiles-row.tsx
@@ -32,7 +32,6 @@ import { PartialSeries } from "../../views/cube-view/partial-tiles-provider";
import { DragIndicator } from "../drag-indicator/drag-indicator";
import { AddSeries } from "./add-series";
import { SeriesTiles } from "./series-tiles";
-import "./series-tiles-row.scss";
interface SeriesTilesRowProps {
menuStage: Stage;
@@ -195,7 +194,7 @@ export class SeriesTilesRow extends React.Component
+ return
{STRINGS.series}
= props => {
return
{({ ref: openOn, setRef }) =>
+ return
{STRINGS.split}
;
+}
+
+interface MoreTilesProps {
+ className: string;
+ max: number;
+ count: number;
+}
+
+function MoreTiles({ className, max, count }: MoreTilesProps) {
+ if (max >= count) return null;
+ const x = max * SECTION_WIDTH;
+ const left = count - max;
+ return
;
+}
+
+interface TilesProps {
+ essence: Essence;
+ stage?: Stage;
+}
+
+function FilterTiles({ essence, stage }: TilesProps) {
+ if (!stage) return null;
+ const { filter, dataCube } = essence;
+ const count = filter.length();
+ const maxItems = getMaxItems(stage.width, count);
+ return <>
+ {filter.clauses.take(maxItems).map((clause, idx) => {
+ const dimension = findDimensionByName(dataCube.dimensions, clause.reference);
+ const excluded = clause && !isTimeFilter(clause) && clause.not;
+ return
+
+
;
+ })}
+
+ >;
+}
+
+function SplitTiles({ stage, essence }: TilesProps) {
+ if (!stage) return null;
+ const { splits, dataCube } = essence;
+ const maxItems = getMaxItems(stage.width, splits.length());
+ return <>
+ {splits.splits.take(maxItems).map((split, idx) => {
+ const dimension = findDimensionByName(dataCube.dimensions, split.reference);
+ return
+
{split.getTitle(dimension)}
+
;
+ })
+ }
+
+ >;
+}
+
+function SeriesTiles({ stage, essence }: TilesProps) {
+ if (!stage) return null;
+ const seriesList = essence.getConcreteSeries();
+ const maxItems = getMaxItems(stage.width, seriesList.count());
+ return <>
+ {seriesList.take(maxItems).map((series, idx) => {
+ return ;
+ })
+ }
+
+ >;
+}
+
+interface VisSkeletonProps {
+ essence: Essence;
+ stage?: Stage;
+ timekeeper: Timekeeper;
+ customization: ClientCustomization;
+}
+
+function VisualizationControlsSkeleton({ essence, stage }: VisSkeletonProps) {
+ return
+
+
{STRINGS.filter}
+
+
+
+
+
+
{STRINGS.split}
+
+
+
+
+
+
{STRINGS.series}
+
+
+
+
+ >
+ }
+ selector={
+
+
+
+ }/>;
+}
+
+export const VisSkeleton: React.FunctionComponent = props => {
+ return <>
+
+
+ >;
+};
diff --git a/src/client/components/series-tile/series-tiles-row.scss b/src/client/components/visualization-controls-layout/visualization-controls-layout.scss
similarity index 86%
rename from src/client/components/series-tile/series-tiles-row.scss
rename to src/client/components/visualization-controls-layout/visualization-controls-layout.scss
index 4ae4295c7..21afb3a3e 100644
--- a/src/client/components/series-tile/series-tiles-row.scss
+++ b/src/client/components/visualization-controls-layout/visualization-controls-layout.scss
@@ -1,6 +1,5 @@
/*
- * Copyright 2015-2016 Imply Data, Inc.
- * Copyright 2017-2019 Allegro.pl
+ * Copyright 2017-2022 Allegro.pl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +16,7 @@
@import '../../imports';
-.series-tile {
+.tile-row {
@extend %module;
@extend %module-h-title;
@@ -30,12 +29,18 @@
transition: height 0.1s ease-in-out;
overflow: hidden;
- .series {
+ .tile {
@extend %tiles-item;
@extend %tiles-item-h;
position: absolute;
left: 0; // It gets horizontal position from the JS
}
+
+ &.excluded {
+ .values {
+ text-decoration: line-through;
+ }
+ }
}
.overflow {
@@ -55,3 +60,8 @@
.overflow-menu {
@extend %overflow-menu
}
+
+.vis-selector {
+ @extend %module;
+}
+
diff --git a/src/client/components/visualization-controls-layout/visualization-controls-layout.tsx b/src/client/components/visualization-controls-layout/visualization-controls-layout.tsx
new file mode 100644
index 000000000..159cc6173
--- /dev/null
+++ b/src/client/components/visualization-controls-layout/visualization-controls-layout.tsx
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-2022 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 React from "react";
+import { classNames } from "../../utils/dom/dom";
+import "./visualization-controls-layout.scss";
+
+interface VisualizationControlsLayoutProps {
+ tiles: React.ReactNode;
+ selector: React.ReactNode;
+ className?: string;
+}
+
+export default function VisualizationControlsLayout({
+ className,
+ selector,
+ tiles
+ }: VisualizationControlsLayoutProps) {
+
+ return
+
+ {tiles}
+
+ {selector}
+
;
+}
diff --git a/src/client/utils/styles/_overflow.scss b/src/client/utils/styles/_overflow.scss
index b0b1e3438..a8a98f997 100644
--- a/src/client/utils/styles/_overflow.scss
+++ b/src/client/utils/styles/_overflow.scss
@@ -32,9 +32,7 @@
}
%overflow-menu {
- .split,
- .series,
- .filter {
+ .tile {
@extend %tiles-item;
position: absolute;
left: 8px;
diff --git a/src/client/utils/styles/_tiles-item.scss b/src/client/utils/styles/_tiles-item.scss
index a7878636f..e3c21bb28 100644
--- a/src/client/utils/styles/_tiles-item.scss
+++ b/src/client/utils/styles/_tiles-item.scss
@@ -26,6 +26,10 @@
transition: transform 0.1s ease-in-out;
width: $item-width;
+ &.disabled {
+ cursor: wait;
+ }
+
&.dimension {
@include css-variable(background-color, item-dimension);
@include css-variable(color, item-dimension-text);
diff --git a/src/client/views/cube-view/center-panel/center-panel.tsx b/src/client/views/cube-view/center-panel/center-panel.tsx
index 580726e8a..0386829d1 100644
--- a/src/client/views/cube-view/center-panel/center-panel.tsx
+++ b/src/client/views/cube-view/center-panel/center-panel.tsx
@@ -36,6 +36,7 @@ import {
SplitTilesRowBaseProps
} from "../../../components/split-tile/split-tiles-row";
import { VisSelector } from "../../../components/vis-selector/vis-selector";
+import VisualizationControlsLayout from "../../../components/visualization-controls-layout/visualization-controls-layout";
import { classNames } from "../../../utils/dom/dom";
import { DataProvider, QueryFactory } from "../../../visualizations/data-provider/data-provider";
import { HighlightController } from "../../../visualizations/highlight-controller/highlight-controller";
@@ -59,7 +60,7 @@ interface VisualizationControlsProps extends VisualizationControlsBaseProps {
}
export const DefaultVisualizationControls: React.FunctionComponent = props => {
- return ;
+ return ;
};
export const VisualizationControls: React.FunctionComponent = props => {
@@ -76,29 +77,31 @@ export const VisualizationControls: React.FunctionComponent
-
-
-
-
-
-
- ;
+ return
+
+
+
+ >
+ }
+ selector={
+ }/>;
};
interface ChartPanelProps {
@@ -169,7 +172,15 @@ type ChartWrapperProps = Pick;
function ChartWrapper(props: ChartWrapperProps) {
- const { chartComponent: ChartComponent, queryFactory, essence, clicker, timekeeper, stage, lastRefreshRequestTimestamp } = props;
+ const {
+ chartComponent: ChartComponent,
+ queryFactory,
+ essence,
+ clicker,
+ timekeeper,
+ stage,
+ lastRefreshRequestTimestamp
+ } = props;
if (essence.visResolve.isManual()) {
return ;
}
diff --git a/src/client/views/cube-view/cube-view.scss b/src/client/views/cube-view/cube-view.scss
index d4749b290..9a3a9966d 100644
--- a/src/client/views/cube-view/cube-view.scss
+++ b/src/client/views/cube-view/cube-view.scss
@@ -85,22 +85,22 @@ $control-panel-height: 3 * $control-tile-height + 2px;
.filter-split-section {
@include unpin-full(0, $vis-selector-width + 1px, 0, 0);
- .filter-tile,
- .series-tile,
- .split-tile {
+ .filter-tile-row,
+ .series-tile-row,
+ .split-tile-row {
height: $control-tile-height;
}
- .filter-tile,
- .split-tile {
+ .filter-tile-row,
+ .split-tile-row {
margin-bottom: 1px;
}
- .series-tile {
+ .series-tile-row {
border-radius: $corner 0 0 0;
}
- .filter-tile {
+ .filter-tile-row {
border-radius: 0 0 0 $corner;
}
}
diff --git a/src/client/views/cube-view/cube-view.tsx b/src/client/views/cube-view/cube-view.tsx
index ae9f5fd2a..3cc8d34f3 100644
--- a/src/client/views/cube-view/cube-view.tsx
+++ b/src/client/views/cube-view/cube-view.tsx
@@ -47,11 +47,11 @@ import { maxTimeQuery } from "../../../common/utils/query/max-time-query";
import { datesEqual } from "../../../common/utils/time/time";
import { DimensionMeasurePanel } from "../../components/dimension-measure-panel/dimension-measure-panel";
import { GlobalEventListener } from "../../components/global-event-listener/global-event-listener";
-import { Loader } from "../../components/loader/loader";
import { PinboardPanel } from "../../components/pinboard-panel/pinboard-panel";
import { Direction, DragHandle, ResizeHandle } from "../../components/resize-handle/resize-handle";
import { SideDrawer } from "../../components/side-drawer/side-drawer";
import { SvgIcon } from "../../components/svg-icon/svg-icon";
+import { VisSkeleton } from "../../components/vis-skeleton/vis-skeleton";
import { DruidQueryModal } from "../../modals/druid-query-modal/druid-query-modal";
import { RawDataModal } from "../../modals/raw-data-modal/raw-data-modal";
import { UrlShortenerModal } from "../../modals/url-shortener-modal/url-shortener-modal";
@@ -570,6 +570,7 @@ export class CubeView extends React.Component {
/>;
const Visualization = this.getVisualization(essence.visualization.name);
+ const chartStage = this.chartStage();
return
@@ -604,12 +605,16 @@ export class CubeView extends React.Component {
onClick={this.toggleFactPanel}>
-
+ }>
= props
return
{({ ref: openOn, setRef }) =>