diff --git a/frontend/src/metabase/dashboard/actions.js b/frontend/src/metabase/dashboard/actions.js index 82a9e2522e75d2a3f7e8e06257dcfd02531531b1..000424de89fbefdd6a31f331432cd3c1c558db8d 100644 --- a/frontend/src/metabase/dashboard/actions.js +++ b/frontend/src/metabase/dashboard/actions.js @@ -212,6 +212,12 @@ function isNewDashcard(dashcard) { return dashcard.id < 1 && dashcard.id >= 0; } +function isNewAdditionalSeriesCard(card, dashcard) { + return ( + card.id !== dashcard.card_id && !dashcard.series.some(s => s.id === card.id) + ); +} + export const addCardToDashboard = ({ dashId, cardId }) => async ( dispatch, getState, @@ -603,10 +609,11 @@ export const fetchCardData = createThunkAction(FETCH_CARD_DATA, function( ), ); } else { - // new cards aren't yet saved to the dashboard, so they need to be run using the card query endpoint - const endpoint = isNewDashcard(dashcard) - ? CardApi.query - : DashboardApi.cardQuery; + // new dashcards and new additional series cards aren't yet saved to the dashboard, so they need to be run using the card query endpoint + const endpoint = + isNewDashcard(dashcard) || isNewAdditionalSeriesCard(card, dashcard) + ? CardApi.query + : DashboardApi.cardQuery; result = await fetchDataOrError( maybeUsePivotEndpoint(endpoint, card)( diff --git a/frontend/src/metabase/dashboard/components/DashCard.jsx b/frontend/src/metabase/dashboard/components/DashCard.jsx index 0b0ae728546bdc0a66a8bb78a07000ddcd6f5e52..c772171fc49f6597376223aaab21bcb5bf977829 100644 --- a/frontend/src/metabase/dashboard/components/DashCard.jsx +++ b/frontend/src/metabase/dashboard/components/DashCard.jsx @@ -411,6 +411,7 @@ const RemoveButton = ({ onRemove }) => ( const AddSeriesButton = ({ series, onAddSeries }) => ( <a + data-testid="add-series-button" data-metabase-event={"Dashboard;Edit Series Modal;open"} className="text-dark-hover cursor-pointer h3 flex-no-shrink relative mr1 drag-disabled" onClick={onAddSeries} diff --git a/frontend/test/metabase/scenarios/dashboard/reproductions/20637-add-series-to-dashcard.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/reproductions/20637-add-series-to-dashcard.cy.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..7eae4982058bf30b37686b360ffb4a8b75ab720b --- /dev/null +++ b/frontend/test/metabase/scenarios/dashboard/reproductions/20637-add-series-to-dashcard.cy.spec.js @@ -0,0 +1,104 @@ +import { restore } from "__support__/e2e/cypress"; + +import { SAMPLE_DATABASE } from "__support__/e2e/cypress_sample_database"; + +const { PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE; + +describe("adding an additional series to a dashcard (metabase#20637)", () => { + beforeEach(() => { + restore(); + cy.signInAsAdmin(); + }); + + it("should use the correct query endpoints (metabase#20637)", () => { + createQuestionsAndDashboard(); + cy.wait("@dashcardQuery"); + + // edit the dashboard and open the add series modal + cy.icon("pencil").click(); + // the button is made clickable by css using :hover so we need to force it + cy.findByTestId("add-series-button").click({ force: true }); + + cy.findByText("20637 Question 2").click(); + // make sure the card query endpoint was used + cy.wait("@additionalSeriesCardQuery"); + + cy.get(".AddSeriesModal").within(() => { + cy.findByText("Done").click(); + }); + saveDashboard(); + + // refresh the page and make sure the dashcard query endpoint was used + cy.reload(); + cy.wait(["@dashcardQuery", "@additionalSeriesDashcardQuery"]); + }); +}); + +function saveDashboard() { + cy.intercept("PUT", "/api/dashboard/*").as("updateDashboard"); + cy.intercept("PUT", "/api/dashboard/*/cards").as("updateDashCards"); + cy.intercept("GET", "/api/dashboard/*").as("loadDashboard"); + + cy.findByText("Save").click(); + + cy.wait(["@updateDashboard", "@updateDashCards", "@loadDashboard"]); +} + +function createQuestionsAndDashboard() { + const dashcardQuestion = { + name: "20637 Question 1", + query: { + "source-table": PRODUCTS_ID, + aggregation: [["count"]], + breakout: [["field", PRODUCTS.CATEGORY, null]], + }, + display: "line", + }; + + const additionalSeriesQuestion = { + name: "20637 Question 2", + query: { + "source-table": PRODUCTS_ID, + aggregation: [["count"]], + breakout: [["field", PRODUCTS.CATEGORY, null]], + }, + display: "bar", + }; + + cy.createQuestion(additionalSeriesQuestion).then( + ({ body: { id: additionalSeriesId } }) => { + cy.intercept("POST", `/api/card/${additionalSeriesId}/query`).as( + "additionalSeriesCardQuery", + ); + + cy.createQuestionAndDashboard({ questionDetails: dashcardQuestion }).then( + ({ body: { id, card_id, dashboard_id } }) => { + cy.request("PUT", `/api/dashboard/${dashboard_id}/cards`, { + cards: [ + { + id, + card_id, + row: 0, + col: 0, + sizeX: 12, + sizeY: 10, + }, + ], + }); + + cy.visit(`/dashboard/${dashboard_id}`); + + cy.intercept( + "POST", + `/api/dashboard/${dashboard_id}/dashcard/*/card/${card_id}/query`, + ).as("dashcardQuery"); + + cy.intercept( + "POST", + `/api/dashboard/${dashboard_id}/dashcard/*/card/${additionalSeriesId}/query`, + ).as("additionalSeriesDashcardQuery"); + }, + ); + }, + ); +}