Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ModelCacheControl.tsx 2.14 KiB
import React, { useCallback, useState } from "react";
import { t } from "ttag";

import Button from "metabase/core/components/Button";
import LoadingSpinner from "metabase/components/LoadingSpinner";

import { delay } from "metabase/lib/promise";
import { CardApi } from "metabase/services";

import Databases from "metabase/entities/databases";

import Database from "metabase-lib/lib/metadata/Database";
import Question from "metabase-lib/lib/Question";

import { SpinnerContainer } from "./ModelCacheControl.styled";

interface ModelCacheControlProps {
  model: Question;
  size?: number;
  onChange?: (isPersisted: boolean) => void;
}

type DatabaseEntityLoaderProps = {
  database?: Database;
};

export const toggleModelPersistence = async (
  model: Question,
  onChange?: (isPersisted: boolean) => void,
) => {
  const id = model.id();
  const isPersisted = model.isPersisted();
  try {
    if (isPersisted) {
      await CardApi.unpersist({ id });
    } else {
      await CardApi.persist({ id });
    }
    onChange?.(!isPersisted);
  } catch (err) {
    console.warn("Failed to persist/unpersist model");
  } finally {
    await delay(200);
  }
};

function ModelCacheControl({
  model,
  size,
  onChange,
  ...props
}: ModelCacheControlProps) {
  const [isLoading, setLoading] = useState(false);
  const label = model.isPersisted() ? t`Unpersist model` : t`Persist model`;

  const handleClick = useCallback(async () => {
    setLoading(true);
    toggleModelPersistence(model, onChange);
    setLoading(false);
  }, [model, onChange]);

  return (
    <Databases.Loader id={model.databaseId()} loadingAndErrorWrapper={false}>
      {({ database }: DatabaseEntityLoaderProps) => {
        if (!database || !database["can-manage"]) {
          return null;
        }
        return isLoading ? (
          <SpinnerContainer>
            <LoadingSpinner size={size} />
          </SpinnerContainer>
        ) : (
          <Button
            {...props}
            icon="database"
            onClick={handleClick}
            iconSize={size}
          >
            {label}
          </Button>
        );
      }}
    </Databases.Loader>
  );
}

export default ModelCacheControl;