update attachment & post
This commit is contained in:
@@ -19,7 +19,6 @@ import java.io.IOException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +124,6 @@ public class AttachmentApiController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping(value = "/api/v1/download/{uniqueId}")
|
@GetMapping(value = "/api/v1/download/{uniqueId}")
|
||||||
public ResponseEntity<?> downloadFile(@PathVariable String uniqueId) {
|
public ResponseEntity<?> downloadFile(@PathVariable String uniqueId) {
|
||||||
|
|
||||||
AttachmentDownloadResponseDto downloadFile = attachmentService.downloadFile(uniqueId);
|
AttachmentDownloadResponseDto downloadFile = attachmentService.downloadFile(uniqueId);
|
||||||
|
|
||||||
String mimeType = null;
|
String mimeType = null;
|
||||||
@@ -166,6 +164,44 @@ public class AttachmentApiController {
|
|||||||
return attachmentService.findByCode(attachmentCode);
|
return attachmentService.findByCode(attachmentCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 첨부파일 다운로드
|
||||||
|
*
|
||||||
|
* @param uniqueId
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/api/v1/attachments/download/{uniqueId}")
|
||||||
|
public ResponseEntity<?> downloadAttachment(@PathVariable String uniqueId) {
|
||||||
|
AttachmentDownloadResponseDto downloadFile = attachmentService.downloadAttachment(uniqueId);
|
||||||
|
|
||||||
|
String mimeType = null;
|
||||||
|
try {
|
||||||
|
// get mime type
|
||||||
|
URLConnection connection = new URL(downloadFile.getFile().getURL().toString()).openConnection();
|
||||||
|
mimeType = connection.getContentType();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("download fail", ex);
|
||||||
|
throw new BusinessMessageException("Sorry. download fail... \uD83D\uDE3F");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mimeType == null) {
|
||||||
|
mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentDisposition contentDisposition = ContentDisposition.builder("attachment")
|
||||||
|
.filename(downloadFile.getOriginalFileName(), StandardCharsets.UTF_8)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add(HttpHeaders.CONTENT_TYPE, mimeType);
|
||||||
|
headers.setContentDisposition(contentDisposition);
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.headers(headers)
|
||||||
|
.body(downloadFile.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 첨부파일 저장 - 물리적 파일은 .temp로 저장 된 후 호출되어야 함
|
* 첨부파일 저장 - 물리적 파일은 .temp로 저장 된 후 호출되어야 함
|
||||||
* 새롭게 attachment code를 생성해야 하는 경우
|
* 새롭게 attachment code를 생성해야 하는 경우
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.egovframe.cloud.portalservice.service.attachment;
|
package org.egovframe.cloud.portalservice.service.attachment;
|
||||||
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang.RandomStringUtils;
|
import org.apache.commons.lang.RandomStringUtils;
|
||||||
@@ -21,8 +20,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -170,7 +167,7 @@ public class AttachmentService extends AbstractService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 첨부파일 다운로드
|
* 첨부파일 다운로드 - 삭제 파일 불가
|
||||||
*
|
*
|
||||||
* @param uniqueId
|
* @param uniqueId
|
||||||
* @return
|
* @return
|
||||||
@@ -180,6 +177,10 @@ public class AttachmentService extends AbstractService {
|
|||||||
// 파일을 찾을 수 없습니다.
|
// 파일을 찾을 수 없습니다.
|
||||||
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.file.not_found") + " ID= " + uniqueId));
|
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.file.not_found") + " ID= " + uniqueId));
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(attachment.getIsDelete())) {
|
||||||
|
throw new BusinessMessageException(getMessage("err.entity.not.found"));
|
||||||
|
}
|
||||||
|
|
||||||
Resource resource = storageUtils.downloadFile(attachment.getPhysicalFileName());
|
Resource resource = storageUtils.downloadFile(attachment.getPhysicalFileName());
|
||||||
|
|
||||||
// 첨부파일 다운로드 할 때 마다 Download 횟수 + 1
|
// 첨부파일 다운로드 할 때 마다 Download 횟수 + 1
|
||||||
@@ -205,6 +206,28 @@ public class AttachmentService extends AbstractService {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 첨부파일 다운로드 - 삭제 파일 가능
|
||||||
|
*
|
||||||
|
* @param uniqueId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AttachmentDownloadResponseDto downloadAttachment(String uniqueId) {
|
||||||
|
Attachment attachment = attachmentRepository.findAllByUniqueId(uniqueId)
|
||||||
|
// 파일을 찾을 수 없습니다.
|
||||||
|
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.file.not_found") + " ID= " + uniqueId));
|
||||||
|
|
||||||
|
Resource resource = storageUtils.downloadFile(attachment.getPhysicalFileName());
|
||||||
|
|
||||||
|
// 첨부파일 다운로드 할 때 마다 Download 횟수 + 1
|
||||||
|
attachment.updateDownloadCnt();
|
||||||
|
|
||||||
|
return AttachmentDownloadResponseDto.builder()
|
||||||
|
.file(resource)
|
||||||
|
.originalFileName(attachment.getOriginalFileName())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 첨부파일 저장
|
* 첨부파일 저장
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -156,40 +156,5 @@ class AttachmentRepositoryTest {
|
|||||||
System.out.println(byId.get());
|
System.out.println(byId.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void 중복된유니크인덱스_오류() throws Exception {
|
|
||||||
//given
|
|
||||||
String code = UUID.randomUUID().toString();
|
|
||||||
String uniqueId = UUID.randomUUID().toString();
|
|
||||||
AttachmentId attachmentId1 = AttachmentId.builder()
|
|
||||||
.code(code)
|
|
||||||
.seq(1L).build();
|
|
||||||
Attachment attachment1 = Attachment.builder()
|
|
||||||
.attachmentId(attachmentId1)
|
|
||||||
.uniqueId(uniqueId)
|
|
||||||
.originalFileName("test1.png")
|
|
||||||
.physicalFileName(UUID.randomUUID().toString())
|
|
||||||
.size(1232L)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
AttachmentId attachmentId2 = AttachmentId.builder()
|
|
||||||
.code(code)
|
|
||||||
.seq(2L)
|
|
||||||
.build();
|
|
||||||
Attachment attachment2 = Attachment.builder()
|
|
||||||
.attachmentId(attachmentId2)
|
|
||||||
.uniqueId(uniqueId)
|
|
||||||
.originalFileName("test2.png")
|
|
||||||
.physicalFileName(UUID.randomUUID().toString())
|
|
||||||
.size(1232L)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
//when
|
|
||||||
attachmentRepository.save(attachment1);
|
|
||||||
attachmentRepository.save(attachment2);
|
|
||||||
|
|
||||||
//then
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -27,8 +27,7 @@ INSERT INTO `authorization` (authorization_name,url_pattern_value,http_method_co
|
|||||||
('사용자 정보 수정','/user-service/api/v1/users/info/?*','PUT',126,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
('사용자 정보 수정','/user-service/api/v1/users/info/?*','PUT',126,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
||||||
('사용자 회원탈퇴','/user-service/api/v1/users/leave','POST',127,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
('사용자 회원탈퇴','/user-service/api/v1/users/leave','POST',127,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
||||||
('사용자 삭제','/user-service/api/v1/users/delete/?*','DELETE',128,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
('사용자 삭제','/user-service/api/v1/users/delete/?*','DELETE',128,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now()),
|
||||||
('사용자 소셜 정보 조회,'/user-service/api/v1/users/social','POST',129,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now());
|
('사용자 소셜 정보 조회','/user-service/api/v1/users/social','POST',129,'65a00f65-8460-49af-98ec-042977e56f4b',now(),'65a00f65-8460-49af-98ec-042977e56f4b',now());
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `role` (role_id,role_name,role_content,sort_seq,created_date) VALUES
|
INSERT INTO `role` (role_id,role_name,role_content,sort_seq,created_date) VALUES
|
||||||
('ROLE_ADMIN','시스템 관리자','시스템 관리자 권한',101,'2021-10-20 13:39:15'),
|
('ROLE_ADMIN','시스템 관리자','시스템 관리자 권한',101,'2021-10-20 13:39:15'),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -35,10 +35,7 @@ const AttachList = (props: AttachListProps) => {
|
|||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const handleClick = (item: IAttachmentResponse) => () => {
|
const handleClick = (item: IAttachmentResponse) => () => {
|
||||||
let a = document.createElement('a')
|
fileService.download(item.id)
|
||||||
a.href = `${fileService.downloadUrl}/${item.id}`
|
|
||||||
a.download = item.originalFileName
|
|
||||||
a.click()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDelete = (item: IAttachmentResponse) => () => {
|
const handleDelete = (item: IAttachmentResponse) => () => {
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ const getColumns: ColumnType = (
|
|||||||
href={`${fileService.downloadUrl}/${params.row.id}`}
|
href={`${fileService.downloadUrl}/${params.row.id}`}
|
||||||
download={params.value}
|
download={params.value}
|
||||||
variant="body2"
|
variant="body2"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
attachmentService.download(params.row.id)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{params.value}
|
{params.value}
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -55,4 +55,22 @@ export const attachmentService = {
|
|||||||
errorCallback(error)
|
errorCallback(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
download: (id: string) => { // 첨부파일 다운로드 - 삭제 파일 가능
|
||||||
|
axios.get(`${ATTACHMENT_API}/download/${id}`, {
|
||||||
|
responseType: 'blob',
|
||||||
|
})
|
||||||
|
.then(response =>{
|
||||||
|
const downloadFileName = decodeURIComponent(response.headers['content-disposition'].replace('attachment; filename*=UTF-8\'\'', ''))
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(new Blob([response.data], { type: response.headers['content-type'] }))
|
||||||
|
let link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.setAttribute('download', downloadFileName)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
const element = { link }
|
||||||
|
delete element.link
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export type UploadPayload = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UPLOAD_API = '/portal-service/api/v1/attachments'
|
const UPLOAD_API = '/portal-service/api/v1/attachments'
|
||||||
const DOWNLOAD_API = `/server/portal-service/api/v1/download`
|
const DOWNLOAD_API = `/portal-service/api/v1/download`
|
||||||
|
|
||||||
let fileHeader = {
|
let fileHeader = {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
@@ -105,4 +105,22 @@ export const fileService = {
|
|||||||
},
|
},
|
||||||
deleteAll: (attachmentCode: string) =>
|
deleteAll: (attachmentCode: string) =>
|
||||||
axios.delete(`${UPLOAD_API}/${attachmentCode}/children`),
|
axios.delete(`${UPLOAD_API}/${attachmentCode}/children`),
|
||||||
|
download: (id: string) => { // 첨부파일 다운로드 - 삭제 파일 불가
|
||||||
|
axios.get(`${DOWNLOAD_API}/${id}`, {
|
||||||
|
responseType: 'blob',
|
||||||
|
})
|
||||||
|
.then(response =>{
|
||||||
|
const downloadFileName = decodeURIComponent(response.headers['content-disposition'].replace('attachment; filename*=UTF-8\'\'', ''))
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(new Blob([response.data], { type: response.headers['content-type'] }))
|
||||||
|
let link = document.createElement('a')
|
||||||
|
link.href = url
|
||||||
|
link.setAttribute('download', downloadFileName)
|
||||||
|
document.body.appendChild(link)
|
||||||
|
link.click()
|
||||||
|
|
||||||
|
const element = { link }
|
||||||
|
delete element.link
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import { EDITOR_MAX_LENGTH } from '@constants'
|
|||||||
import Divider from '@material-ui/core/Divider'
|
import Divider from '@material-ui/core/Divider'
|
||||||
import Hidden from '@material-ui/core/Hidden'
|
import Hidden from '@material-ui/core/Hidden'
|
||||||
import { BoardFormContext } from '@pages/board/[skin]/[board]/edit/[id]'
|
import { BoardFormContext } from '@pages/board/[skin]/[board]/edit/[id]'
|
||||||
import { IPostsForm, UploadInfoReqeust } from '@service'
|
import { IPostsForm } from '@service'
|
||||||
import { getTextLength } from '@utils'
|
import { getTextLength } from '@utils'
|
||||||
import produce from 'immer'
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import React, { useContext, useMemo, useRef } from 'react'
|
import React, { useContext, useEffect, useMemo, useRef } from 'react'
|
||||||
import { Controller, useForm } from 'react-hook-form'
|
import { Controller, useForm } from 'react-hook-form'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { EditFormProps } from '.'
|
import { EditFormProps } from '.'
|
||||||
@@ -24,7 +23,7 @@ const NormalEditForm = (props: NormalEditFormProps) => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const uploadRef = useRef<UploadType>()
|
const uploadRef = useRef<UploadType>()
|
||||||
const { post, board, attachList, setPostDataHandler, setAttachListHandler } =
|
const { post, board, attachList, setPostDataHandler, setAttachListHandler, setUploaderHandler } =
|
||||||
useContext(BoardFormContext)
|
useContext(BoardFormContext)
|
||||||
|
|
||||||
// form hook
|
// form hook
|
||||||
@@ -41,28 +40,11 @@ const NormalEditForm = (props: NormalEditFormProps) => {
|
|||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = methods
|
} = methods
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUploaderHandler(uploadRef)
|
||||||
|
}, [setUploaderHandler, uploadRef])
|
||||||
|
|
||||||
const handleFormSubmit = async (data: IPostsForm) => {
|
const handleFormSubmit = async (data: IPostsForm) => {
|
||||||
if (board.uploadUseAt) {
|
|
||||||
const isUpload = await uploadRef.current.isModified(attachList)
|
|
||||||
|
|
||||||
if (isUpload) {
|
|
||||||
const info: UploadInfoReqeust = {
|
|
||||||
entityName: 'posts',
|
|
||||||
entityId: board.boardNo?.toString(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 업로드 및 저장
|
|
||||||
const result = await uploadRef.current.upload(info, attachList)
|
|
||||||
if (result) {
|
|
||||||
if (result !== 'no attachments' && result !== 'no update list') {
|
|
||||||
data = produce(data, draft => {
|
|
||||||
draft.attachmentCode = result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setPostDataHandler(data)
|
setPostDataHandler(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,17 +53,20 @@ const NormalEditForm = (props: NormalEditFormProps) => {
|
|||||||
{
|
{
|
||||||
id: 'board-edit-save',
|
id: 'board-edit-save',
|
||||||
title: t('label.button.save'),
|
title: t('label.button.save'),
|
||||||
href: '',
|
href: '#',
|
||||||
className: 'blue',
|
className: 'blue',
|
||||||
handleClick: handleSubmit(handleFormSubmit),
|
handleClick: handleSubmit(handleFormSubmit),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'board-edit-list',
|
id: 'board-edit-list',
|
||||||
title: t('label.button.list'),
|
title: router.query.id === '-1' ? t('label.button.list') : t('label.button.cancel'),
|
||||||
href: `/board/${router.query.skin}/${router.query.board}`,
|
href: '#',
|
||||||
|
handleClick: () => {
|
||||||
|
router.back()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[router.query.board, router.query.skin],
|
[router],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const QnAEditForm = (props: QnAEditFormProps) => {
|
|||||||
ref={uploadRef}
|
ref={uploadRef}
|
||||||
multi
|
multi
|
||||||
uploadLimitCount={board.uploadLimitCount}
|
uploadLimitCount={board.uploadLimitCount}
|
||||||
uploadLimitSize={board.uploadLimitSize * 1024 * 1024}
|
uploadLimitSize={board.uploadLimitSize}
|
||||||
attachmentCode={post.attachmentCode}
|
attachmentCode={post.attachmentCode}
|
||||||
attachData={attachList}
|
attachData={attachList}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
IPostsForm,
|
IPostsForm,
|
||||||
PostsReqPayload,
|
PostsReqPayload,
|
||||||
SKINT_TYPE_CODE_NORMAL,
|
SKINT_TYPE_CODE_NORMAL,
|
||||||
SKINT_TYPE_CODE_QNA,
|
SKINT_TYPE_CODE_QNA, UploadInfoReqeust,
|
||||||
} from '@service'
|
} from '@service'
|
||||||
import { errorStateSelector } from '@stores'
|
import { errorStateSelector } from '@stores'
|
||||||
import { AxiosError } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
@@ -17,6 +17,13 @@ import { useRouter } from 'next/router'
|
|||||||
import React, { createContext, useCallback, useEffect, useState } from 'react'
|
import React, { createContext, useCallback, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useSetRecoilState } from 'recoil'
|
import { useSetRecoilState } from 'recoil'
|
||||||
|
import CustomAlert, { CustomAlertPrpps } from '@components/CustomAlert'
|
||||||
|
import { UploadType } from '@components/Upload'
|
||||||
|
import produce from 'immer'
|
||||||
|
|
||||||
|
interface AlertProps extends CustomAlertPrpps {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
interface BoardEditProps {
|
interface BoardEditProps {
|
||||||
post: IPosts
|
post: IPosts
|
||||||
@@ -29,12 +36,14 @@ export const BoardFormContext = createContext<{
|
|||||||
attachList: IAttachmentResponse[]
|
attachList: IAttachmentResponse[]
|
||||||
setPostDataHandler: (data: IPostsForm) => void
|
setPostDataHandler: (data: IPostsForm) => void
|
||||||
setAttachListHandler: (data: IAttachmentResponse[]) => void
|
setAttachListHandler: (data: IAttachmentResponse[]) => void
|
||||||
|
setUploaderHandler: (uploadType: React.MutableRefObject<UploadType>) => void
|
||||||
}>({
|
}>({
|
||||||
post: undefined,
|
post: undefined,
|
||||||
board: undefined,
|
board: undefined,
|
||||||
attachList: undefined,
|
attachList: undefined,
|
||||||
setPostDataHandler: () => {},
|
setPostDataHandler: () => {},
|
||||||
setAttachListHandler: () => {},
|
setAttachListHandler: () => {},
|
||||||
|
setUploaderHandler: () => {},
|
||||||
})
|
})
|
||||||
|
|
||||||
const BoardEdit = (props: BoardEditProps) => {
|
const BoardEdit = (props: BoardEditProps) => {
|
||||||
@@ -44,6 +53,12 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const setErrorState = useSetRecoilState(errorStateSelector)
|
const setErrorState = useSetRecoilState(errorStateSelector)
|
||||||
|
|
||||||
|
const [customAlert, setCustomAlert] = useState<AlertProps | undefined>({
|
||||||
|
open: false,
|
||||||
|
message: '',
|
||||||
|
handleAlert: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
const [postData, setPostData] = useState<IPostsForm>(undefined)
|
const [postData, setPostData] = useState<IPostsForm>(undefined)
|
||||||
const setPostDataHandler = (data: IPostsForm) => {
|
const setPostDataHandler = (data: IPostsForm) => {
|
||||||
setPostData(data)
|
setPostData(data)
|
||||||
@@ -52,6 +67,10 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
const setAttachListHandler = (data: IAttachmentResponse[]) => {
|
const setAttachListHandler = (data: IAttachmentResponse[]) => {
|
||||||
setAttachList(data)
|
setAttachList(data)
|
||||||
}
|
}
|
||||||
|
const [uploader, setUploader] = useState<React.MutableRefObject<UploadType>>(undefined)
|
||||||
|
const setUploaderHandler = (uploadType: React.MutableRefObject<UploadType>) => {
|
||||||
|
setUploader(uploadType)
|
||||||
|
}
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
const errorCallback = useCallback(
|
const errorCallback = useCallback(
|
||||||
@@ -66,13 +85,23 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
router.back()
|
router.back()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const save = useCallback(() => {
|
useEffect(() => {
|
||||||
const data: IPosts = {
|
if (typeof post.postsNo === 'undefined') {
|
||||||
boardNo: post.boardNo,
|
setCustomAlert({
|
||||||
postsNo: post.postsNo,
|
open: true,
|
||||||
...postData,
|
message: t('err.entity.not.found'),
|
||||||
|
handleAlert: () => {
|
||||||
|
setCustomAlert({
|
||||||
|
...customAlert,
|
||||||
|
open: false,
|
||||||
|
})
|
||||||
|
router.back()
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}, [post])
|
||||||
|
|
||||||
|
const save = useCallback((data: IPosts) => {
|
||||||
if (post.postsNo === -1) {
|
if (post.postsNo === -1) {
|
||||||
boardService.savePost({
|
boardService.savePost({
|
||||||
boardNo: post.boardNo,
|
boardNo: post.boardNo,
|
||||||
@@ -90,11 +119,41 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// boardService.
|
// boardService.
|
||||||
}, [postData, post, successCallback, errorCallback])
|
}, [post, successCallback, errorCallback])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (postData) {
|
if (postData) {
|
||||||
save()
|
let data: IPosts = {
|
||||||
|
boardNo: post.boardNo,
|
||||||
|
postsNo: post.postsNo,
|
||||||
|
...postData,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (board.uploadUseAt) {
|
||||||
|
uploader.current.isModified(attachList)
|
||||||
|
.then(isUpload => {
|
||||||
|
if (isUpload === true) {
|
||||||
|
const info: UploadInfoReqeust = {
|
||||||
|
entityName: 'posts',
|
||||||
|
entityId: board.boardNo?.toString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 업로드 및 저장
|
||||||
|
uploader.current.upload(info, attachList)
|
||||||
|
.then(result => {
|
||||||
|
if (result) {
|
||||||
|
if (result !== 'no attachments' && result !== 'no update list') {
|
||||||
|
data = produce(data, draft => {
|
||||||
|
draft.attachmentCode = result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
save(data)
|
||||||
}
|
}
|
||||||
}, [postData, attachList])
|
}, [postData, attachList])
|
||||||
|
|
||||||
@@ -130,6 +189,7 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
attachList,
|
attachList,
|
||||||
setPostDataHandler,
|
setPostDataHandler,
|
||||||
setAttachListHandler,
|
setAttachListHandler,
|
||||||
|
setUploaderHandler,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{board.skinTypeCode === SKINT_TYPE_CODE_NORMAL && (
|
{board.skinTypeCode === SKINT_TYPE_CODE_NORMAL && (
|
||||||
@@ -141,6 +201,11 @@ const BoardEdit = (props: BoardEditProps) => {
|
|||||||
{/* <QnAEditForm /> */}
|
{/* <QnAEditForm /> */}
|
||||||
</BoardFormContext.Provider>
|
</BoardFormContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
|
<CustomAlert
|
||||||
|
contentText={customAlert.message}
|
||||||
|
open={customAlert.open}
|
||||||
|
handleAlert={customAlert.handleAlert}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
|
import CustomAlert, { CustomAlertPrpps } from '@components/CustomAlert'
|
||||||
|
|
||||||
|
interface AlertProps extends CustomAlertPrpps {
|
||||||
|
message: string
|
||||||
|
}
|
||||||
|
|
||||||
interface BaordViewProps {
|
interface BaordViewProps {
|
||||||
post: IPosts
|
post: IPosts
|
||||||
@@ -48,6 +53,12 @@ const BoardView = (props: BaordViewProps) => {
|
|||||||
|
|
||||||
const setErrorState = useSetRecoilState(errorStateSelector)
|
const setErrorState = useSetRecoilState(errorStateSelector)
|
||||||
|
|
||||||
|
const [customAlert, setCustomAlert] = useState<AlertProps | undefined>({
|
||||||
|
open: false,
|
||||||
|
message: '',
|
||||||
|
handleAlert: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
// 첨부파일
|
// 첨부파일
|
||||||
const [attachList, setAttachList] = useState<IAttachmentResponse[]>(undefined)
|
const [attachList, setAttachList] = useState<IAttachmentResponse[]>(undefined)
|
||||||
|
|
||||||
@@ -126,7 +137,20 @@ const BoardView = (props: BaordViewProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (post) {
|
if (typeof post.postsNo === 'undefined') {
|
||||||
|
setCustomAlert({
|
||||||
|
open: true,
|
||||||
|
message: t('err.entity.not.found'),
|
||||||
|
handleAlert: () => {
|
||||||
|
setCustomAlert({
|
||||||
|
...customAlert,
|
||||||
|
open: false,
|
||||||
|
})
|
||||||
|
router.back()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (post.postsNo) {
|
||||||
getComments({
|
getComments({
|
||||||
boardNo: post.boardNo,
|
boardNo: post.boardNo,
|
||||||
postsNo: post.postsNo,
|
postsNo: post.postsNo,
|
||||||
@@ -241,7 +265,7 @@ const BoardView = (props: BaordViewProps) => {
|
|||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{t('common.written_date')}</dt>
|
<dt>{t('common.written_date')}</dt>
|
||||||
<dd>{dateFormat(new Date(post.createdDate), 'yyyy-MM-dd')}</dd>
|
<dd>{post.createdDate && dateFormat(new Date(post.createdDate), 'yyyy-MM-dd')}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>{t('common.read_count')}</dt>
|
<dt>{t('common.read_count')}</dt>
|
||||||
@@ -361,6 +385,11 @@ const BoardView = (props: BaordViewProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<BottomButtons handleButtons={bottomButtons} />
|
<BottomButtons handleButtons={bottomButtons} />
|
||||||
|
<CustomAlert
|
||||||
|
contentText={customAlert.message}
|
||||||
|
open={customAlert.open}
|
||||||
|
handleAlert={customAlert.handleAlert}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user