Ctrl K
ComunidadGuías…

dashboard/src/components/ActionIcons.tsx

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import React, { useState, useEffect } from 'react';
import axiosInstance from '@/config/axios';
import { copyToClipboard } from '@/utils/clipboard';

// The icons sit on the purple->orange field, where a red glyph drops to 1.09:1
// against the orange end — invisible. Grouping them on a dark scrim lifts red-300
// to 4.80:1, so delete can finally read as destructive instead of white.
const ACTION_GROUP =
  'inline-flex items-center gap-px flex-shrink-0 relative rounded-lg p-0.5 bg-violet-950/50 border border-white/20';
const ACTION_BUTTON = 'px-2 py-1.5 rounded-md transition-colors duration-200 flex-shrink-0';

interface ActionIconsProps {
  onDownload: () => void;
  onEdit: () => void;
  onDelete: () => void;
  showDownload?: boolean;
  artifactLink?: string;
}

export const ActionIcons: React.FC<ActionIconsProps> = ({
  onDownload,
  onEdit,
  onDelete,
  showDownload = true,
  artifactLink,
}) => {
  const [copied, setCopied] = useState(false);
  const [copyError, setCopyError] = useState<string | null>(null);

  // Cleanup function to remove any temporary elements
  useEffect(() => {
    return () => {
      const tempElements = document.querySelectorAll('.temp-clipboard-element');
      tempElements.forEach(el => el.remove());
    };
  }, []);

  const handleCopyLink = async (e: React.MouseEvent) => {
    e.stopPropagation();
    setCopyError(null);
    if (artifactLink) {
      try {
        // First try to fetch the signed URL
        const response = await axiosInstance.get(artifactLink);
        
        // Check if the response is JSON with a download_url
        const urlToCopy = response.data && typeof response.data === 'object' && 'download_url' in response.data
          ? response.data.download_url
          : artifactLink;
        
        const success = await copyToClipboard(urlToCopy);
        
        if (success) {
          setCopied(true);
          setTimeout(() => setCopied(false), 2000);
        } else {
          setCopyError('Failed to copy link. Please try selecting and copying manually.');
          setTimeout(() => setCopyError(null), 3000);
        }
      } catch (err) {
        // If there's an error, try to copy the original link
        try {
          const success = await copyToClipboard(artifactLink);
          if (success) {
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
          } else {
            setCopyError('Failed to copy link. Please try selecting and copying manually.');
            setTimeout(() => setCopyError(null), 3000);
          }
        } catch (clipboardErr) {
          console.error('Failed to copy link:', clipboardErr);
          setCopyError('Failed to copy link. Please try selecting and copying manually.');
          setTimeout(() => setCopyError(null), 3000);
        }
      }
    }
  };

  return (
    <div className={ACTION_GROUP}>
      {copyError && (
        <div className="absolute bottom-full mb-2 p-2 bg-red-500 bg-opacity-20 border border-red-500 rounded text-red-500 text-sm whitespace-nowrap">
          {copyError}
        </div>
      )}
      {showDownload && (
        <>
          <button
            onClick={(e) => {
              e.stopPropagation();
              onDownload();
            }}
            className={`${ACTION_BUTTON} text-green-400 hover:bg-green-500/20`}
            title="Download"
            aria-label="Download"
          >
            <i className="fas fa-download"></i>
          </button>
          {artifactLink && (
            <button
              onClick={handleCopyLink}
              className={`${ACTION_BUTTON} text-purple-300 hover:bg-purple-400/20`}
              title={copied ? "Copied!" : "Copy link"}
              aria-label={copied ? "Copied" : "Copy link"}
            >
              <i className={`fas ${copied ? 'fa-check' : 'fa-copy'}`}></i>
            </button>
          )}
        </>
      )}
      <button
        onClick={(e) => {
          e.stopPropagation();
          onEdit();
        }}
        className={`${ACTION_BUTTON} text-gray-200 hover:bg-white/15`}
        title="Edit"
        aria-label="Edit"
      >
        <i className="fas fa-edit"></i>
      </button>
      <button
        onClick={(e) => {
          e.stopPropagation();
          onDelete();
        }}
        className={`${ACTION_BUTTON} text-red-300 hover:bg-red-500/25`}
        title="Delete"
        aria-label="Delete"
      >
        <i className="fas fa-trash"></i>
      </button>
    </div>
  );
};