Skip to content
Snippets Groups Projects
Commit 016c6a9d authored by Tom Robinson's avatar Tom Robinson
Browse files

Add 'hide_parameters' hash option for dashboards and embedded dashboards/questions

parent b9a1994c
No related branches found
No related tags found
No related merge requests found
...@@ -98,6 +98,7 @@ type Props = { ...@@ -98,6 +98,7 @@ type Props = {
refreshElapsed: number, refreshElapsed: number,
isFullscreen: boolean, isFullscreen: boolean,
isNightMode: boolean, isNightMode: boolean,
hideParameters: ?string,
onRefreshPeriodChange: (?number) => void, onRefreshPeriodChange: (?number) => void,
onNightModeChange: boolean => void, onNightModeChange: boolean => void,
...@@ -226,6 +227,7 @@ export default class Dashboard extends Component { ...@@ -226,6 +227,7 @@ export default class Dashboard extends Component {
location, location,
isFullscreen, isFullscreen,
isNightMode, isNightMode,
hideParameters,
} = this.props; } = this.props;
let { error } = this.state; let { error } = this.state;
isNightMode = isNightMode && isFullscreen; isNightMode = isNightMode && isFullscreen;
...@@ -238,6 +240,7 @@ export default class Dashboard extends Component { ...@@ -238,6 +240,7 @@ export default class Dashboard extends Component {
isEditing={isEditing} isEditing={isEditing}
isFullscreen={isFullscreen} isFullscreen={isFullscreen}
isNightMode={isNightMode} isNightMode={isNightMode}
hideParameters={hideParameters}
parameters={parameters.map(p => ({ parameters={parameters.map(p => ({
...p, ...p,
value: parameterValues[p.id], value: parameterValues[p.id],
......
...@@ -26,6 +26,7 @@ type State = { ...@@ -26,6 +26,7 @@ type State = {
isNightMode: boolean, isNightMode: boolean,
refreshPeriod: ?number, refreshPeriod: ?number,
refreshElapsed: ?number, refreshElapsed: ?number,
hideParameters: ?string,
}; };
const TICK_PERIOD = 0.25; // seconds const TICK_PERIOD = 0.25; // seconds
...@@ -47,6 +48,8 @@ export default (ComposedComponent: ReactClass<any>) => ...@@ -47,6 +48,8 @@ export default (ComposedComponent: ReactClass<any>) =>
refreshPeriod: null, refreshPeriod: null,
refreshElapsed: null, refreshElapsed: null,
hideParameters: null,
}; };
_interval: ?number; _interval: ?number;
...@@ -88,6 +91,7 @@ export default (ComposedComponent: ReactClass<any>) => ...@@ -88,6 +91,7 @@ export default (ComposedComponent: ReactClass<any>) =>
); );
this.setNightMode(options.theme === "night" || options.night); // DEPRECATED: options.night this.setNightMode(options.theme === "night" || options.night); // DEPRECATED: options.night
this.setFullscreen(options.fullscreen); this.setFullscreen(options.fullscreen);
this.setHideParameters(options.hide_parameters);
}; };
updateDashboardParams = () => { updateDashboardParams = () => {
...@@ -164,6 +168,10 @@ export default (ComposedComponent: ReactClass<any>) => ...@@ -164,6 +168,10 @@ export default (ComposedComponent: ReactClass<any>) =>
} }
}; };
setHideParameters = parameters => {
this.setState({ hideParameters: parameters });
};
_tickRefreshClock = async () => { _tickRefreshClock = async () => {
let refreshElapsed = (this.state.refreshElapsed || 0) + TICK_PERIOD; let refreshElapsed = (this.state.refreshElapsed || 0) + TICK_PERIOD;
if ( if (
......
...@@ -25,6 +25,7 @@ type Props = { ...@@ -25,6 +25,7 @@ type Props = {
isFullscreen?: boolean, isFullscreen?: boolean,
isNightMode?: boolean, isNightMode?: boolean,
hideParameters?: ?string, // comma separated list of slugs
isEditing?: boolean, isEditing?: boolean,
isQB?: boolean, isQB?: boolean,
vertical?: boolean, vertical?: boolean,
...@@ -122,6 +123,7 @@ export default class Parameters extends Component { ...@@ -122,6 +123,7 @@ export default class Parameters extends Component {
isEditing, isEditing,
isFullscreen, isFullscreen,
isNightMode, isNightMode,
hideParameters,
isQB, isQB,
setParameterName, setParameterName,
setParameterValue, setParameterValue,
...@@ -132,6 +134,8 @@ export default class Parameters extends Component { ...@@ -132,6 +134,8 @@ export default class Parameters extends Component {
commitImmediately, commitImmediately,
} = this.props; } = this.props;
const hiddenParameters = new Set((hideParameters || "").split(","));
const parameters = this._parametersWithValues(); const parameters = this._parametersWithValues();
let ParameterWidget; let ParameterWidget;
...@@ -156,40 +160,42 @@ export default class Parameters extends Component { ...@@ -156,40 +160,42 @@ export default class Parameters extends Component {
distance={9} distance={9}
onSortEnd={this.handleSortEnd} onSortEnd={this.handleSortEnd}
> >
{parameters.map((parameter, index) => ( {parameters
<ParameterWidget .filter(p => !hiddenParameters.has(p.slug))
key={parameter.id} .map((parameter, index) => (
index={index} <ParameterWidget
className={cx("relative hover-parent hover--visibility", { key={parameter.id}
mb2: vertical, className={cx("relative hover-parent hover--visibility", {
})} mb2: vertical,
isEditing={isEditing} })}
isFullscreen={isFullscreen} isEditing={isEditing}
isNightMode={isNightMode} isFullscreen={isFullscreen}
parameter={parameter} isNightMode={isNightMode}
parameters={parameters} parameter={parameter}
editingParameter={editingParameter} parameters={parameters}
setEditingParameter={setEditingParameter} editingParameter={editingParameter}
setName={ setEditingParameter={setEditingParameter}
setParameterName && (name => setParameterName(parameter.id, name)) setName={
} setParameterName &&
setValue={ (name => setParameterName(parameter.id, name))
setParameterValue && }
(value => setParameterValue(parameter.id, value)) setValue={
} setParameterValue &&
setDefaultValue={ (value => setParameterValue(parameter.id, value))
setParameterDefaultValue && }
(value => setParameterDefaultValue(parameter.id, value)) setDefaultValue={
} setParameterDefaultValue &&
remove={removeParameter && (() => removeParameter(parameter.id))} (value => setParameterDefaultValue(parameter.id, value))
commitImmediately={commitImmediately} }
> remove={removeParameter && (() => removeParameter(parameter.id))}
{/* show drag handle if editing and setParameterIndex provided */} commitImmediately={commitImmediately}
{isEditing && setParameterIndex ? ( >
<SortableParameterHandle /> {/* show drag handle if editing and setParameterIndex provided */}
) : null} {isEditing && setParameterIndex ? (
</ParameterWidget> <SortableParameterHandle />
))} ) : null}
</ParameterWidget>
))}
</ParameterWidgetList> </ParameterWidgetList>
); );
} }
......
...@@ -94,7 +94,7 @@ export default class EmbedFrame extends Component { ...@@ -94,7 +94,7 @@ export default class EmbedFrame extends Component {
const footer = true; const footer = true;
const { bordered, titled, theme } = { const { bordered, titled, theme, hide_parameters } = {
...DEFAULT_OPTIONS, ...DEFAULT_OPTIONS,
...parseHashOptions(location.hash), ...parseHashOptions(location.hash),
}; };
...@@ -127,6 +127,7 @@ export default class EmbedFrame extends Component { ...@@ -127,6 +127,7 @@ export default class EmbedFrame extends Component {
query={location.query} query={location.query}
setParameterValue={setParameterValue} setParameterValue={setParameterValue}
syncQueryString syncQueryString
hideParameters={hide_parameters}
isQB isQB
/> />
</div> </div>
......
...@@ -28,6 +28,7 @@ import { ...@@ -28,6 +28,7 @@ import {
ParameterOptionItem, ParameterOptionItem,
ParameterOptionsSection, ParameterOptionsSection,
} from "metabase/dashboard/components/ParametersPopover"; } from "metabase/dashboard/components/ParametersPopover";
import ParameterWidget from "metabase/parameters/components/ParameterWidget";
import ParameterValueWidget from "metabase/parameters/components/ParameterValueWidget"; import ParameterValueWidget from "metabase/parameters/components/ParameterValueWidget";
import { PredefinedRelativeDatePicker } from "metabase/parameters/components/widgets/DateRelativeWidget"; import { PredefinedRelativeDatePicker } from "metabase/parameters/components/widgets/DateRelativeWidget";
import HeaderModal from "metabase/components/HeaderModal"; import HeaderModal from "metabase/components/HeaderModal";
...@@ -118,6 +119,14 @@ describe("Dashboard", () => { ...@@ -118,6 +119,14 @@ describe("Dashboard", () => {
describe("dashboard page", () => { describe("dashboard page", () => {
let dashboardId = null; let dashboardId = null;
const checkDashboardWasCreated = () => {
if (!dashboardId) {
throw new Error(
"Test fails because previous tests failed to create a dashboard",
);
}
};
it("lets you change title and description", async () => { it("lets you change title and description", async () => {
const name = "Customer Feedback Analysis"; const name = "Customer Feedback Analysis";
const description = const description =
...@@ -152,11 +161,7 @@ describe("Dashboard", () => { ...@@ -152,11 +161,7 @@ describe("Dashboard", () => {
}); });
it("lets you add a filter", async () => { it("lets you add a filter", async () => {
if (!dashboardId) { checkDashboardWasCreated();
throw new Error(
"Test fails because previous tests failed to create a dashboard",
);
}
const store = await createTestStore(); const store = await createTestStore();
store.pushPath(Urls.dashboard(dashboardId)); store.pushPath(Urls.dashboard(dashboardId));
...@@ -195,14 +200,36 @@ describe("Dashboard", () => { ...@@ -195,14 +200,36 @@ describe("Dashboard", () => {
// Wait until the header modal exit animation is finished // Wait until the header modal exit animation is finished
await store.waitForActions([SET_EDITING_PARAMETER_ID]); await store.waitForActions([SET_EDITING_PARAMETER_ID]);
// save
clickButton(app.find(".Button.Button--small.Button--primary"));
await store.waitForActions([FETCH_DASHBOARD]);
});
it("shows previously added parameter", async () => {
checkDashboardWasCreated();
const store = await createTestStore();
const dashboardUrl = Urls.dashboard(dashboardId);
store.pushPath(dashboardUrl);
const app = mount(store.getAppContainer());
await store.waitForActions([FETCH_DASHBOARD]);
expect(app.find(ParameterWidget)).toHaveLength(1);
});
it("hides parameters named in 'hide_parameters' option", async () => {
checkDashboardWasCreated();
const store = await createTestStore();
const dashboardUrl = Urls.dashboard(dashboardId);
store.pushPath(dashboardUrl + "#hide_parameters=relative_date");
const app = mount(store.getAppContainer());
await store.waitForActions([FETCH_DASHBOARD]);
expect(app.find(ParameterWidget)).toHaveLength(0);
}); });
it("lets you open and close the revisions screen", async () => { it("lets you open and close the revisions screen", async () => {
if (!dashboardId) { checkDashboardWasCreated();
throw new Error(
"Test fails because previous tests failed to create a dashboard",
);
}
const store = await createTestStore(); const store = await createTestStore();
const dashboardUrl = Urls.dashboard(dashboardId); const dashboardUrl = Urls.dashboard(dashboardId);
...@@ -226,6 +253,8 @@ describe("Dashboard", () => { ...@@ -226,6 +253,8 @@ describe("Dashboard", () => {
}); });
it("lets you go directly to the revisions screen via url", async () => { it("lets you go directly to the revisions screen via url", async () => {
checkDashboardWasCreated();
const store = await createTestStore(); const store = await createTestStore();
const dashboardUrl = Urls.dashboard(dashboardId); const dashboardUrl = Urls.dashboard(dashboardId);
store.pushPath(dashboardUrl + `/history`); store.pushPath(dashboardUrl + `/history`);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment