JSONExportDialog.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import React, { useState } from "react";
  2. import { ActionsManagerInterface } from "../actions/types";
  3. import { NonDeletedExcalidrawElement } from "../element/types";
  4. import { t } from "../i18n";
  5. import { useIsMobile } from "./App";
  6. import { AppState } from "../types";
  7. import { Dialog } from "./Dialog";
  8. import { exportFile, exportToFileIcon, link } from "./icons";
  9. import { ToolButton } from "./ToolButton";
  10. import { actionSaveAsScene } from "../actions/actionExport";
  11. import { Card } from "./Card";
  12. import "./ExportDialog.scss";
  13. import { supported as fsSupported } from "browser-fs-access";
  14. export type ExportCB = (
  15. elements: readonly NonDeletedExcalidrawElement[],
  16. scale?: number,
  17. ) => void;
  18. const JSONExportModal = ({
  19. elements,
  20. appState,
  21. actionManager,
  22. onExportToBackend,
  23. }: {
  24. appState: AppState;
  25. elements: readonly NonDeletedExcalidrawElement[];
  26. actionManager: ActionsManagerInterface;
  27. onExportToBackend?: ExportCB;
  28. onCloseRequest: () => void;
  29. }) => {
  30. return (
  31. <div className="ExportDialog ExportDialog--json">
  32. <div className="ExportDialog-cards">
  33. <Card color="lime">
  34. <div className="Card-icon">{exportToFileIcon}</div>
  35. <h2>{t("exportDialog.disk_title")}</h2>
  36. <div className="Card-details">
  37. {t("exportDialog.disk_details")}
  38. {!fsSupported && actionManager.renderAction("changeProjectName")}
  39. </div>
  40. <ToolButton
  41. className="Card-button"
  42. type="button"
  43. title={t("exportDialog.disk_button")}
  44. aria-label={t("exportDialog.disk_button")}
  45. showAriaLabel={true}
  46. onClick={() => {
  47. actionManager.executeAction(actionSaveAsScene);
  48. }}
  49. />
  50. </Card>
  51. {onExportToBackend && (
  52. <Card color="pink">
  53. <div className="Card-icon">{link}</div>
  54. <h2>{t("exportDialog.link_title")}</h2>
  55. <div className="Card-details">{t("exportDialog.link_details")}</div>
  56. <ToolButton
  57. className="Card-button"
  58. type="button"
  59. title={t("exportDialog.link_button")}
  60. aria-label={t("exportDialog.link_button")}
  61. showAriaLabel={true}
  62. onClick={() => onExportToBackend(elements)}
  63. />
  64. </Card>
  65. )}
  66. </div>
  67. </div>
  68. );
  69. };
  70. export const JSONExportDialog = ({
  71. elements,
  72. appState,
  73. actionManager,
  74. onExportToBackend,
  75. }: {
  76. appState: AppState;
  77. elements: readonly NonDeletedExcalidrawElement[];
  78. actionManager: ActionsManagerInterface;
  79. onExportToBackend?: ExportCB;
  80. }) => {
  81. const [modalIsShown, setModalIsShown] = useState(false);
  82. const handleClose = React.useCallback(() => {
  83. setModalIsShown(false);
  84. }, []);
  85. return (
  86. <>
  87. <ToolButton
  88. onClick={() => {
  89. setModalIsShown(true);
  90. }}
  91. data-testid="json-export-button"
  92. icon={exportFile}
  93. type="button"
  94. aria-label={t("buttons.export")}
  95. showAriaLabel={useIsMobile()}
  96. title={t("buttons.export")}
  97. />
  98. {modalIsShown && (
  99. <Dialog onCloseRequest={handleClose} title={t("buttons.export")}>
  100. <JSONExportModal
  101. elements={elements}
  102. appState={appState}
  103. actionManager={actionManager}
  104. onExportToBackend={onExportToBackend}
  105. onCloseRequest={handleClose}
  106. />
  107. </Dialog>
  108. )}
  109. </>
  110. );
  111. };