DomainsFormatter.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import cn from "classnames";
  2. import type { ReactNode } from "react";
  3. import { formatDateTime, T } from "src/locale";
  4. interface Props {
  5. domains: string[];
  6. createdOn?: string;
  7. niceName?: string;
  8. provider?: string;
  9. color?: string;
  10. }
  11. const DomainLink = ({ domain, color }: { domain?: string; color?: string }) => {
  12. // when domain contains a wildcard, make the link go nowhere.
  13. // Apparently the domain can be null or undefined sometimes.
  14. // This try is just a safeguard to prevent the whole formatter from breaking.
  15. if (!domain) return null;
  16. try {
  17. let onClick: ((e: React.MouseEvent) => void) | undefined;
  18. if (domain.includes("*")) {
  19. onClick = (e: React.MouseEvent) => e.preventDefault();
  20. }
  21. return (
  22. <a
  23. key={domain}
  24. href={`http://${domain}`}
  25. target="_blank"
  26. onClick={onClick}
  27. className={cn("badge", color ? `bg-${color}-lt` : null, "domain-name", "me-2")}
  28. >
  29. {domain}
  30. </a>
  31. );
  32. } catch {
  33. return null;
  34. }
  35. };
  36. export function DomainsFormatter({ domains, createdOn, niceName, provider, color }: Props) {
  37. const elms: ReactNode[] = [];
  38. if ((!domains || domains.length === 0) && !niceName) {
  39. elms.push(
  40. <span key="nice-name" className="badge bg-danger-lt me-2">
  41. Unknown
  42. </span>,
  43. );
  44. }
  45. if (!domains || (niceName && provider !== "letsencrypt")) {
  46. elms.push(
  47. <span key="nice-name" className="badge bg-info-lt me-2">
  48. {niceName}
  49. </span>,
  50. );
  51. }
  52. if (domains) {
  53. domains.map((domain: string) => elms.push(<DomainLink key={domain} domain={domain} color={color} />));
  54. }
  55. return (
  56. <div className="flex-fill">
  57. <div className="font-weight-medium">{...elms}</div>
  58. {createdOn ? (
  59. <div className="text-secondary mt-1">
  60. <T id="created-on" data={{ date: formatDateTime(createdOn) }} />
  61. </div>
  62. ) : null}
  63. </div>
  64. );
  65. }