CustomizeLogoSetting.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import React, { FC, useState } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import AdminCustomizeContainer from '~/client/services/AdminCustomizeContainer';
  4. import AppContainer from '~/client/services/AppContainer';
  5. import {
  6. toastError, toastSuccess,
  7. } from '~/client/util/apiNotification';
  8. import ImageCropModal from '~/components/Common/ImageCropModal';
  9. import { withUnstatedContainers } from '../../UnstatedUtils';
  10. import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
  11. type Props = {
  12. adminCustomizeContainer : AdminCustomizeContainer
  13. }
  14. const CustomizeLogoSetting: FC<Props> = (props: Props) => {
  15. const { t } = useTranslation();
  16. const { adminCustomizeContainer } = props;
  17. const [isShow, setIsShow] = useState<boolean>(false);
  18. const [src, setSrc] = useState<ArrayBuffer | string | null>(null);
  19. const {
  20. uploadedLogoSrc, isDefaultLogo, defaultLogoSrc,
  21. } = adminCustomizeContainer.state;
  22. const hideModal = () => {
  23. setIsShow(false);
  24. };
  25. const cancelModal = () => {
  26. hideModal();
  27. };
  28. const showModal = () => {
  29. setIsShow(true);
  30. };
  31. const onSelectFile = (e) => {
  32. if (e.target.files != null && e.target.files.length > 0) {
  33. const reader = new FileReader();
  34. reader.addEventListener('load', () => setSrc(reader.result));
  35. reader.readAsDataURL(e.target.files[0]);
  36. showModal();
  37. }
  38. };
  39. const onClickSubmit = async() => {
  40. try {
  41. await adminCustomizeContainer.updateCustomizeLogo();
  42. toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.custom_logo') }));
  43. }
  44. catch (err) {
  45. toastError(err);
  46. }
  47. };
  48. const onClickDeleteBtn = async() => {
  49. try {
  50. await adminCustomizeContainer.deleteLogo();
  51. toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.current_logo') }));
  52. }
  53. catch (err) {
  54. toastError(err);
  55. }
  56. };
  57. const onCropCompleted = async(croppedImage) => {
  58. try {
  59. await adminCustomizeContainer.uploadBrandLogo(croppedImage);
  60. toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.current_logo') }));
  61. }
  62. catch (err) {
  63. toastError(err);
  64. }
  65. hideModal();
  66. };
  67. return (
  68. <React.Fragment>
  69. <div className="row">
  70. <div className="col-12">
  71. <div className="mb-5">
  72. <h2 className="border-bottom my-4 admin-setting-header">{t('admin:customize_setting.custom_logo')}</h2>
  73. <div className="row">
  74. <div className="col-md-6 col-12 mb-3 mb-md-0">
  75. <h4>
  76. <div className="custom-control custom-radio radio-primary">
  77. <input
  78. type="radio"
  79. id="radioDefaultLogo"
  80. className="custom-control-input"
  81. form="formImageType"
  82. name="imagetypeForm[isDefaultLogo]"
  83. checked={isDefaultLogo}
  84. onChange={() => { adminCustomizeContainer.switchDefaultLogo() }}
  85. />
  86. <label className="custom-control-label" htmlFor="radioDefaultLogo">
  87. {t('admin:customize_setting.default_logo')}
  88. </label>
  89. </div>
  90. </h4>
  91. <img src={defaultLogoSrc} width="64" />
  92. </div>
  93. <div className="col-md-6 col-12">
  94. <h4>
  95. <div className="custom-control custom-radio radio-primary">
  96. <input
  97. type="radio"
  98. id="radioUploadLogo"
  99. className="custom-control-input"
  100. form="formImageType"
  101. name="imagetypeForm[isDefaultLogo]"
  102. checked={!isDefaultLogo}
  103. onChange={() => { adminCustomizeContainer.switchDefaultLogo() }}
  104. />
  105. <label className="custom-control-label" htmlFor="radioUploadLogo">
  106. { t('admin:customize_setting.upload_logo') }
  107. </label>
  108. </div>
  109. </h4>
  110. <div className="row mb-3">
  111. <label className="col-sm-4 col-12 col-form-label text-left">
  112. { t('admin:customize_setting.current_logo') }
  113. </label>
  114. <div className="col-sm-8 col-12">
  115. <p><img src={uploadedLogoSrc || defaultLogoSrc} className="picture picture-lg " id="settingBrandLogo" width="64" /></p>
  116. {(uploadedLogoSrc != null) && (
  117. <button type="button" className="btn btn-danger" onClick={onClickDeleteBtn}>
  118. { t('admin:customize_setting.delete_logo') }
  119. </button>
  120. )}
  121. </div>
  122. </div>
  123. <div className="row">
  124. <label className="col-sm-4 col-12 col-form-label text-left">
  125. { t('admin:customize_setting.upload_new_logo') }
  126. </label>
  127. <div className="col-sm-8 col-12">
  128. <input type="file" onChange={onSelectFile} name="brandLogo" accept="image/*" />
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. <AdminUpdateButtonRow onClick={onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
  134. </div>
  135. </div>
  136. </div>
  137. <ImageCropModal
  138. isShow={isShow}
  139. src={src}
  140. onModalClose={cancelModal}
  141. onCropCompleted={onCropCompleted}
  142. isCircular={false}
  143. />
  144. </React.Fragment>
  145. );
  146. };
  147. const CustomizeLogoSettingWrapper = withUnstatedContainers(CustomizeLogoSetting, [AppContainer, AdminCustomizeContainer]);
  148. export default CustomizeLogoSettingWrapper;