return async function(dispatch, getState) { const dashboardType = getDashboardType(dashId); if (dashboardType === "public") { result = await PublicApi.dashboard({ uuid: dashId }); result = { ...result, id: dashId, ordered_cards: result.ordered_cards.map(dc => ({ ...dc, dashboard_id: dashId, })), }; } else if (dashboardType === "embed") { result = await EmbedApi.dashboard({ token: dashId }); result = { ...result, id: dashId, ordered_cards: result.ordered_cards.map(dc => ({ ...dc, dashboard_id: dashId, })), }; } else if (dashboardType === "transient") { const subPath = dashId .split("/") .slice(3) .join("/"); result = await AutoApi.dashboard({ subPath }); result = { ...result, id: dashId, ordered_cards: result.ordered_cards.map(dc => ({ ...dc, dashboard_id: dashId, })), }; } else { result = await DashboardApi.get({ dashId: dashId }); } const parameterValues = {}; if (result.parameters) { for (const parameter of result.parameters) { if (queryParams && queryParams[parameter.slug] != null) { parameterValues[parameter.id] = queryParams[parameter.slug]; } else if (enableDefaultParameters && parameter.default != null) { parameterValues[parameter.id] = parameter.default; } } } if (dashboardType === "normal" || dashboardType === "transient") { // fetch database metadata for every card _.chain(result.ordered_cards) .map(dc => [dc.card].concat(dc.series)) .flatten() .filter( card => card && card.dataset_query && card.dataset_query.database, ) .map(card => card.dataset_query.database) .uniq() .each(dbId => dispatch(fetchDatabaseMetadata(dbId))); } // copy over any virtual cards from the dashcard to the underlying card/question result.ordered_cards.forEach(card => { if (card.visualization_settings.virtual_card) { card.card = Object.assign( card.card || {}, card.visualization_settings.virtual_card, ); } }); if (result.param_values) { dispatch(addParamValues(result.param_values)); } if (result.param_fields) { dispatch(addFields(result.param_fields)); } return { ...normalize(result, dashboard), // includes `result` and `entities` dashboardId: dashId, parameterValues: parameterValues, }; };
return async function(dispatch, getState) { // If the dataset_query was filtered then we don't have permisison to view this card, so // shortcircuit and return a fake 403 if (!card.dataset_query) { return { dashcard_id: dashcard.id, card_id: card.id, result: { error: { status: 403 } }, }; } const dashboardType = getDashboardType(dashcard.dashboard_id); const { dashboardId, dashboards, parameterValues, dashcardData, } = getState().dashboard; const dashboard = dashboards[dashboardId]; // if we have a parameter, apply it to the card query before we execute const datasetQuery = applyParameters( card, dashboard.parameters, parameterValues, dashcard && dashcard.parameter_mappings, ); if (!reload) { // if reload not set, check to see if the last result has the same query dict and return that const lastResult = getIn(dashcardData, [dashcard.id, card.id]); // "constraints" is added by the backend, remove it when comparing if ( lastResult && Utils.equals(_.omit(lastResult.json_query, "constraints"), datasetQuery) ) { return { dashcard_id: dashcard.id, card_id: card.id, result: lastResult, }; } } if (clear) { // clears the card data to indicate the card is reloading dispatch(clearCardData(card.id, dashcard.id)); } let result = null; // start a timer that will show the expected card duration if the query takes too long let slowCardTimer = setTimeout(() => { if (result === null) { dispatch(markCardAsSlow(card, datasetQuery)); } }, DATASET_SLOW_TIMEOUT); // make the actual request if (dashboardType === "public") { result = await fetchDataOrError( PublicApi.dashboardCardQuery({ uuid: dashcard.dashboard_id, cardId: card.id, parameters: datasetQuery.parameters ? JSON.stringify(datasetQuery.parameters) : undefined, }), ); } else if (dashboardType === "embed") { result = await fetchDataOrError( EmbedApi.dashboardCardQuery({ token: dashcard.dashboard_id, dashcardId: dashcard.id, cardId: card.id, ...getParametersBySlug(dashboard.parameters, parameterValues), }), ); } else if (dashboardType === "transient") { result = await fetchDataOrError(MetabaseApi.dataset(datasetQuery)); } else { result = await fetchDataOrError( CardApi.query({ cardId: card.id, parameters: datasetQuery.parameters }), ); } clearTimeout(slowCardTimer); return { dashcard_id: dashcard.id, card_id: card.id, result: result, }; };