PageBulkExportSettings.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { type JSX, useCallback, useEffect, useState } from 'react';
  2. import { LoadingSpinner } from '@growi/ui/dist/components';
  3. import { useTranslation } from 'next-i18next';
  4. import { apiv3Put } from '~/client/util/apiv3-client';
  5. import { toastError, toastSuccess } from '~/client/util/toastr';
  6. import { useSWRxAppSettings } from '~/stores/admin/app-settings';
  7. import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
  8. const PageBulkExportSettings = (): JSX.Element => {
  9. const { t } = useTranslation(['admin', 'commons']);
  10. const { data, error, mutate } = useSWRxAppSettings();
  11. const [isBulkExportPagesEnabled, setIsBulkExportPagesEnabled] = useState(
  12. data?.isBulkExportPagesEnabled,
  13. );
  14. const [
  15. bulkExportDownloadExpirationSeconds,
  16. setBulkExportDownloadExpirationSeconds,
  17. ] = useState(data?.bulkExportDownloadExpirationSeconds);
  18. const changeBulkExportDownloadExpirationSeconds = (
  19. bulkExportDownloadExpirationDays: number,
  20. ) => {
  21. const bulkExportDownloadExpirationSeconds =
  22. bulkExportDownloadExpirationDays * 24 * 60 * 60;
  23. setBulkExportDownloadExpirationSeconds(bulkExportDownloadExpirationSeconds);
  24. };
  25. const onSubmitHandler = useCallback(async () => {
  26. try {
  27. await apiv3Put('/app-settings/page-bulk-export-settings', {
  28. isBulkExportPagesEnabled,
  29. bulkExportDownloadExpirationSeconds,
  30. });
  31. toastSuccess(
  32. t('commons:toaster.update_successed', {
  33. target: t('app_setting.page_bulk_export_settings'),
  34. }),
  35. );
  36. } catch (err) {
  37. toastError(err);
  38. }
  39. mutate();
  40. }, [
  41. isBulkExportPagesEnabled,
  42. bulkExportDownloadExpirationSeconds,
  43. mutate,
  44. t,
  45. ]);
  46. useEffect(() => {
  47. if (data?.useOnlyEnvVarForFileUploadType) {
  48. setIsBulkExportPagesEnabled(data?.envIsBulkExportPagesEnabled);
  49. } else {
  50. setIsBulkExportPagesEnabled(data?.isBulkExportPagesEnabled);
  51. }
  52. setBulkExportDownloadExpirationSeconds(
  53. data?.bulkExportDownloadExpirationSeconds,
  54. );
  55. }, [data]);
  56. const isLoading = data === undefined && error === undefined;
  57. return (
  58. <>
  59. {isLoading && (
  60. <div className="text-muted text-center mb-5">
  61. <LoadingSpinner className="me-1 fs-3" />
  62. </div>
  63. )}
  64. {!isLoading && (
  65. <>
  66. <p className="card custom-card bg-warning-subtle my-3">
  67. {t('admin:app_setting.page_bulk_export_explanation')} <br />
  68. <span className="text-danger mt-1">
  69. {t('admin:app_setting.page_bulk_export_warning')}
  70. </span>
  71. </p>
  72. <div className="my-4 row">
  73. <div className="text-start text-md-end col-md-3 col-form-label"></div>
  74. <div className="col-md-6">
  75. <div className="form-check form-switch form-check-info">
  76. <input
  77. type="checkbox"
  78. className="form-check-input"
  79. id="cbIsPageBulkExportEnabled"
  80. checked={isBulkExportPagesEnabled}
  81. disabled={data?.useOnlyEnvVarsForIsBulkExportPagesEnabled}
  82. onChange={(e) =>
  83. setIsBulkExportPagesEnabled(e.target.checked)
  84. }
  85. />
  86. <label
  87. className="form-label form-check-label"
  88. htmlFor="cbIsPageBulkExportEnabled"
  89. >
  90. {t('app_setting.enable_page_bulk_export')}
  91. </label>
  92. </div>
  93. {data?.useOnlyEnvVarsForIsBulkExportPagesEnabled && (
  94. <p className="form-text text-muted">
  95. {/* eslint-disable-next-line react/no-danger */}
  96. <b
  97. // eslint-disable-next-line react/no-danger
  98. // biome-ignore lint/security/noDangerouslySetInnerHtml: includes markup from i18n strings
  99. dangerouslySetInnerHTML={{
  100. __html: t('admin:app_setting.fixed_by_env_var', {
  101. envKey: 'BULK_EXPORT_PAGES_ENABLED',
  102. envVar: isBulkExportPagesEnabled,
  103. }),
  104. }}
  105. />
  106. </p>
  107. )}
  108. </div>
  109. </div>
  110. <div className="mb-4">
  111. <div className="row">
  112. <label
  113. className="text-start text-md-end col-md-3 col-form-label"
  114. htmlFor="admin-page-bulk-export-expiration"
  115. >
  116. {t('app_setting.page_bulk_export_storage_period')}
  117. </label>
  118. <div className="col-md-2">
  119. <select
  120. className="form-select"
  121. id="admin-page-bulk-export-expiration"
  122. value={
  123. (bulkExportDownloadExpirationSeconds ?? 0) / (24 * 60 * 60)
  124. }
  125. onChange={(e) => {
  126. changeBulkExportDownloadExpirationSeconds(
  127. Number(e.target.value),
  128. );
  129. }}
  130. >
  131. {Array.from({ length: 7 }, (_, i) => i + 1).map((number) => (
  132. <option
  133. key={`be-download-expiration-option-${number}`}
  134. value={number}
  135. >
  136. {number} {t('admin:days')}
  137. </option>
  138. ))}
  139. </select>
  140. </div>
  141. </div>
  142. </div>
  143. <AdminUpdateButtonRow onClick={onSubmitHandler} />
  144. </>
  145. )}
  146. </>
  147. );
  148. };
  149. export default PageBulkExportSettings;