Пример #1
0
  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,
    };
  };
Пример #2
0
  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,
    };
  };