|
@@ -1,45 +1,34 @@
|
|
|
-import React, { useCallback, useEffect, useState } from 'react';
|
|
|
|
|
|
|
+import React, { useCallback, useMemo, useState } from 'react';
|
|
|
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
|
|
|
import { toastError, toastSuccess } from '~/client/util/apiNotification';
|
|
import { toastError, toastSuccess } from '~/client/util/apiNotification';
|
|
|
import {
|
|
import {
|
|
|
- apiv3Delete, apiv3Get, apiv3PostForm, apiv3Put,
|
|
|
|
|
|
|
+ apiv3Delete, apiv3PostForm, apiv3Put,
|
|
|
} from '~/client/util/apiv3-client';
|
|
} from '~/client/util/apiv3-client';
|
|
|
import ImageCropModal from '~/components/Common/ImageCropModal';
|
|
import ImageCropModal from '~/components/Common/ImageCropModal';
|
|
|
|
|
+import { useIsDefaultLogo, useIsCustomizedLogoUploaded } from '~/stores/context';
|
|
|
|
|
|
|
|
import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
|
|
import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
|
|
|
|
|
|
|
|
|
|
+
|
|
|
const DEFAULT_LOGO = '/images/logo.svg';
|
|
const DEFAULT_LOGO = '/images/logo.svg';
|
|
|
|
|
+const CUSTOMIZED_LOGO = '/attachment/brand-logo';
|
|
|
|
|
|
|
|
const CustomizeLogoSetting = (): JSX.Element => {
|
|
const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
|
|
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
|
|
+ const { data: isDefaultLogo } = useIsDefaultLogo();
|
|
|
|
|
+ const { data: isCustomizedLogoUploaded, mutate: mutateIsCustomizedLogoUploaded } = useIsCustomizedLogoUploaded();
|
|
|
|
|
|
|
|
const [uploadLogoSrc, setUploadLogoSrc] = useState<ArrayBuffer | string | null>(null);
|
|
const [uploadLogoSrc, setUploadLogoSrc] = useState<ArrayBuffer | string | null>(null);
|
|
|
const [isImageCropModalShow, setIsImageCropModalShow] = useState<boolean>(false);
|
|
const [isImageCropModalShow, setIsImageCropModalShow] = useState<boolean>(false);
|
|
|
- const [isDefaultLogo, setIsDefaultLogo] = useState<boolean>(true);
|
|
|
|
|
|
|
+ const [isDefaultLogoSelected, setIsDefaultLogoSelected] = useState<boolean>(isDefaultLogo ?? true);
|
|
|
const [retrieveError, setRetrieveError] = useState<any>();
|
|
const [retrieveError, setRetrieveError] = useState<any>();
|
|
|
- const [customizedLogoSrc, setCustomizedLogoSrc] = useState< string | null >(null);
|
|
|
|
|
-
|
|
|
|
|
- const retrieveData = useCallback(async() => {
|
|
|
|
|
- try {
|
|
|
|
|
- const response = await apiv3Get('/customize-setting/customize-logo');
|
|
|
|
|
- const { isDefaultLogo: _isDefaultLogo, customizedLogoSrc } = response.data;
|
|
|
|
|
- const isDefaultLogo = _isDefaultLogo ?? true;
|
|
|
|
|
-
|
|
|
|
|
- setIsDefaultLogo(isDefaultLogo);
|
|
|
|
|
- setCustomizedLogoSrc(customizedLogoSrc);
|
|
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
- setRetrieveError(err);
|
|
|
|
|
- throw new Error('Failed to fetch data');
|
|
|
|
|
- }
|
|
|
|
|
- }, []);
|
|
|
|
|
|
|
|
|
|
- useEffect(() => {
|
|
|
|
|
- retrieveData();
|
|
|
|
|
- }, [retrieveData]);
|
|
|
|
|
|
|
+ const currentLogo = useMemo(() => {
|
|
|
|
|
+ return isDefaultLogo ? DEFAULT_LOGO : CUSTOMIZED_LOGO;
|
|
|
|
|
+ }, [isDefaultLogo]);
|
|
|
|
|
|
|
|
const onSelectFile = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const onSelectFile = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
if (e.target.files != null && e.target.files.length > 0) {
|
|
if (e.target.files != null && e.target.files.length > 0) {
|
|
@@ -52,22 +41,18 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
|
|
|
|
|
const onClickSubmit = useCallback(async() => {
|
|
const onClickSubmit = useCallback(async() => {
|
|
|
try {
|
|
try {
|
|
|
- const response = await apiv3Put('/customize-setting/customize-logo', {
|
|
|
|
|
- isDefaultLogo,
|
|
|
|
|
- });
|
|
|
|
|
- const { customizedParams } = response.data;
|
|
|
|
|
- setIsDefaultLogo(customizedParams.isDefaultLogo);
|
|
|
|
|
|
|
+ await apiv3Put('/customize-setting/customize-logo', { isDefaultLogo: isDefaultLogoSelected });
|
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.custom_logo'), ns: 'commons' }));
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.custom_logo'), ns: 'commons' }));
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
|
toastError(err);
|
|
toastError(err);
|
|
|
}
|
|
}
|
|
|
- }, [t, isDefaultLogo]);
|
|
|
|
|
|
|
+ }, [t, isDefaultLogoSelected]);
|
|
|
|
|
|
|
|
const onClickDeleteBtn = useCallback(async() => {
|
|
const onClickDeleteBtn = useCallback(async() => {
|
|
|
try {
|
|
try {
|
|
|
await apiv3Delete('/customize-setting/delete-brand-logo');
|
|
await apiv3Delete('/customize-setting/delete-brand-logo');
|
|
|
- setCustomizedLogoSrc(null);
|
|
|
|
|
|
|
+ mutateIsCustomizedLogoUploaded(false);
|
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' }));
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' }));
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
@@ -75,15 +60,15 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
setRetrieveError(err);
|
|
setRetrieveError(err);
|
|
|
throw new Error('Failed to delete logo');
|
|
throw new Error('Failed to delete logo');
|
|
|
}
|
|
}
|
|
|
- }, [t]);
|
|
|
|
|
|
|
+ }, [mutateIsCustomizedLogoUploaded, t]);
|
|
|
|
|
|
|
|
|
|
|
|
|
const processImageCompletedHandler = useCallback(async(croppedImage) => {
|
|
const processImageCompletedHandler = useCallback(async(croppedImage) => {
|
|
|
try {
|
|
try {
|
|
|
const formData = new FormData();
|
|
const formData = new FormData();
|
|
|
formData.append('file', croppedImage);
|
|
formData.append('file', croppedImage);
|
|
|
- const { data } = await apiv3PostForm('/customize-setting/upload-brand-logo', formData);
|
|
|
|
|
- setCustomizedLogoSrc(data.attachment.filePathProxied);
|
|
|
|
|
|
|
+ await apiv3PostForm('/customize-setting/upload-brand-logo', formData);
|
|
|
|
|
+ mutateIsCustomizedLogoUploaded(true);
|
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' }));
|
|
toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' }));
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
@@ -91,7 +76,7 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
setRetrieveError(err);
|
|
setRetrieveError(err);
|
|
|
throw new Error('Failed to upload brand logo');
|
|
throw new Error('Failed to upload brand logo');
|
|
|
}
|
|
}
|
|
|
- }, [t]);
|
|
|
|
|
|
|
+ }, [mutateIsCustomizedLogoUploaded, t]);
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<React.Fragment>
|
|
<React.Fragment>
|
|
@@ -109,8 +94,8 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
className="custom-control-input"
|
|
className="custom-control-input"
|
|
|
form="formImageType"
|
|
form="formImageType"
|
|
|
name="imagetypeForm[isDefaultLogo]"
|
|
name="imagetypeForm[isDefaultLogo]"
|
|
|
- checked={isDefaultLogo}
|
|
|
|
|
- onChange={() => { setIsDefaultLogo(true) }}
|
|
|
|
|
|
|
+ checked={isDefaultLogoSelected}
|
|
|
|
|
+ onChange={() => { setIsDefaultLogoSelected(true) }}
|
|
|
/>
|
|
/>
|
|
|
<label className="custom-control-label" htmlFor="radioDefaultLogo">
|
|
<label className="custom-control-label" htmlFor="radioDefaultLogo">
|
|
|
{t('admin:customize_settings.default_logo')}
|
|
{t('admin:customize_settings.default_logo')}
|
|
@@ -128,8 +113,8 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
className="custom-control-input"
|
|
className="custom-control-input"
|
|
|
form="formImageType"
|
|
form="formImageType"
|
|
|
name="imagetypeForm[isDefaultLogo]"
|
|
name="imagetypeForm[isDefaultLogo]"
|
|
|
- checked={!isDefaultLogo}
|
|
|
|
|
- onChange={() => { setIsDefaultLogo(false) }}
|
|
|
|
|
|
|
+ checked={!isDefaultLogoSelected}
|
|
|
|
|
+ onChange={() => { setIsDefaultLogoSelected(false) }}
|
|
|
/>
|
|
/>
|
|
|
<label className="custom-control-label" htmlFor="radioUploadLogo">
|
|
<label className="custom-control-label" htmlFor="radioUploadLogo">
|
|
|
{ t('admin:customize_settings.upload_logo') }
|
|
{ t('admin:customize_settings.upload_logo') }
|
|
@@ -141,11 +126,15 @@ const CustomizeLogoSetting = (): JSX.Element => {
|
|
|
{ t('admin:customize_settings.current_logo') }
|
|
{ t('admin:customize_settings.current_logo') }
|
|
|
</label>
|
|
</label>
|
|
|
<div className="col-sm-8 col-12">
|
|
<div className="col-sm-8 col-12">
|
|
|
- <p><img src={customizedLogoSrc || DEFAULT_LOGO} className="picture picture-lg " id="settingBrandLogo" width="64" /></p>
|
|
|
|
|
- {(customizedLogoSrc != null) && (
|
|
|
|
|
- <button type="button" className="btn btn-danger" onClick={onClickDeleteBtn}>
|
|
|
|
|
- { t('admin:customize_settings.delete_logo') }
|
|
|
|
|
- </button>
|
|
|
|
|
|
|
+ {isCustomizedLogoUploaded && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <img src='/attachment/brand-logo' className="picture picture-lg " id="settingBrandLogo" width="64" />
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <button type="button" className="btn btn-danger" onClick={onClickDeleteBtn}>
|
|
|
|
|
+ { t('admin:customize_settings.delete_logo') }
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </>
|
|
|
)}
|
|
)}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|