diff --git a/apps/api/src/domains/feedback/dtos/requests/export-feedbacks-request.dto.ts b/apps/api/src/domains/feedback/dtos/requests/export-feedbacks-request.dto.ts index 0a29bd6b6..76cebfb6b 100644 --- a/apps/api/src/domains/feedback/dtos/requests/export-feedbacks-request.dto.ts +++ b/apps/api/src/domains/feedback/dtos/requests/export-feedbacks-request.dto.ts @@ -23,7 +23,7 @@ export class ExportFeedbacksRequestDto extends FindFeedbacksByChannelIdRequestDt @IsString() type: 'xlsx' | 'csv'; - @ApiProperty({ required: false }) + @ApiProperty({ required: false, type: [Number] }) @IsOptional() @IsArray() fieldIds?: number[]; diff --git a/apps/api/src/domains/feedback/feedback.service.ts b/apps/api/src/domains/feedback/feedback.service.ts index 00e44640d..321bedf1c 100644 --- a/apps/api/src/domains/feedback/feedback.service.ts +++ b/apps/api/src/domains/feedback/feedback.service.ts @@ -156,9 +156,9 @@ export class FeedbackService { } return Object.keys(convertedFeedback) - .filter((key) => fieldsToExport.find((field) => field.key === key)) + .filter((key) => fieldsToExport.find((field) => field.name === key)) .reduce((obj, key) => { - obj[key] = feedback[key]; + obj[key] = convertedFeedback[key]; return obj; }, {}); } @@ -228,6 +228,7 @@ export class FeedbackService { fieldsByKey, fieldsToExport, ); + worksheet.addRow(convertedFeedback).commit(); feedbackIds.push(feedback.id); } diff --git a/apps/web/.prettierignore b/apps/web/.prettierignore new file mode 100644 index 000000000..963bf1ba5 --- /dev/null +++ b/apps/web/.prettierignore @@ -0,0 +1 @@ +src/types/api.type.ts \ No newline at end of file diff --git a/apps/web/public/locales/en/common.json b/apps/web/public/locales/en/common.json index 09b452264..d7a899da9 100644 --- a/apps/web/public/locales/en/common.json +++ b/apps/web/public/locales/en/common.json @@ -220,6 +220,7 @@ "apiKeys": "Manage API Key information in the feedback collection API. If you collect feedback using API, please generate Key information.", "issueTracker": "UserFeedback feedback and Issue Tracking System can be linked and managed. Please enter your Issue Tracking System information." }, + "error-member": "User information that does not currently exist.", "continue-channel-creation": "UserFeedback must be created up to the Channel before UserFeedback is available.\nWould you like to continue creating a channel?", "guide": { "invalid-member": "Invalid Member List exists.", @@ -311,7 +312,8 @@ "no-channel": "There is no registered channel.", "guide": "Guide", "more": "more", - "shrink": "shrink" + "shrink": "shrink", + "feedback-detail": "Feedback Detail" }, "toast": { "sign-in": "Login Successful", diff --git a/apps/web/public/locales/ja/common.json b/apps/web/public/locales/ja/common.json index c80828f8d..74d5f6aae 100644 --- a/apps/web/public/locales/ja/common.json +++ b/apps/web/public/locales/ja/common.json @@ -220,6 +220,7 @@ "apiKeys": "フィードバック収集APIのAPI Key情報を管理します。 APIを活用してフィードバックを収集するなら、Key情報を生成してください。", "issueTracker": "UserFeedbackフィードバックとIssue Tracking Systemを接続して管理することができます。 使用中のIssue Tracking System情報を入力してください。" }, + "error-member": "現在存在しないユーザ情報です。", "continue-channel-creation": "Channelまで生成しないとUser Feedbackを使用できません。\nChannel生成を続けますか?", "guide": { "invalid-member": "無効なMemberリストが存在します。", @@ -311,7 +312,8 @@ "no-channel": "登録されたチャンネルがありません。", "guide": "案内", "more": "もっと", - "shrink": "縮む" + "shrink": "縮む", + "feedback-detail": "フィードバック詳細です" }, "toast": { "sign-in": "ログイン成功", diff --git a/apps/web/public/locales/ko/common.json b/apps/web/public/locales/ko/common.json index 31d8c1a3f..c4c8bf789 100644 --- a/apps/web/public/locales/ko/common.json +++ b/apps/web/public/locales/ko/common.json @@ -221,6 +221,7 @@ "apiKeys": "피드백 수집 API의 API Key 정보를 관리합니다. API를 활용해 피드백을 수집한다면 Key 정보를 생성해 주세요.", "issueTracker": "UserFeedback 피드백과 Issue Tracking System을 연결해서 관리할 수 있습니다. 사용 중인 Issue Tracking System 정보를 입력해 주세요." }, + "error-member": "현재 존재하지 않는 User 정보 입니다.", "continue-channel-creation": "Channel까지 생성해야 UserFeedback을 사용할 수 있습니다.\nChannel 생성을 이어서 하시겠어요?", "guide": { "invalid-member": "유효하지 않은 Member 목록이 존재합니다.", @@ -312,7 +313,8 @@ "no-channel": "등록된 Channel이 없습니다.", "guide": "안내", "more": "더보기", - "shrink": "줄이기" + "shrink": "줄이기", + "feedback-detail": "피드백 상세" }, "toast": { "sign-in": "로그인 성공", diff --git a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx index 99c860220..2108f830b 100644 --- a/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx +++ b/apps/web/src/components/etc/CheckedTableHead/CheckedTableHead.tsx @@ -29,6 +29,7 @@ interface IProps { projectId: number; channelId: number; ids: number[]; + fieldIds: number[]; }; disabled?: boolean; } @@ -73,6 +74,7 @@ const CheckedTableHead: React.FC = (props) => {
diff --git a/apps/web/src/components/etc/DescriptionTooltip/DescriptionTooltip.tsx b/apps/web/src/components/etc/DescriptionTooltip/DescriptionTooltip.tsx index 59b9b8492..e6d4a9159 100644 --- a/apps/web/src/components/etc/DescriptionTooltip/DescriptionTooltip.tsx +++ b/apps/web/src/components/etc/DescriptionTooltip/DescriptionTooltip.tsx @@ -19,18 +19,26 @@ import type { Placement } from '@floating-ui/react'; import { Icon, Tooltip, TooltipContent, TooltipTrigger } from '@ufb/ui'; export interface ITooltipProps { - description?: string; + description: string; placement?: Placement; + color?: 'red'; } const DescriptionTooltip: React.FC = ({ description, placement, + color, }) => { return ( - + {description} diff --git a/apps/web/src/containers/create-project/InputIssueTracker.tsx b/apps/web/src/containers/create-project/InputIssueTracker.tsx index 533db8580..5c4b9e901 100644 --- a/apps/web/src/containers/create-project/InputIssueTracker.tsx +++ b/apps/web/src/containers/create-project/InputIssueTracker.tsx @@ -107,6 +107,7 @@ const InputIssueTracker: React.FC = () => { userId: member.user.id, })), roles: input.roles, + timezoneOffset: '+90:00', }); }; diff --git a/apps/web/src/containers/create-project/InputMember.tsx b/apps/web/src/containers/create-project/InputMember.tsx index 6ea0e4edb..d25380d52 100644 --- a/apps/web/src/containers/create-project/InputMember.tsx +++ b/apps/web/src/containers/create-project/InputMember.tsx @@ -30,7 +30,7 @@ import { PopoverTrigger, } from '@ufb/ui'; -import { SelectBox, TableSortIcon } from '@/components'; +import { DescriptionTooltip, SelectBox, TableSortIcon } from '@/components'; import { useCreateProject } from '@/contexts/create-project.context'; import { useUserSearch } from '@/hooks'; import type { InputMemberType } from '@/types/member.type'; @@ -45,6 +45,8 @@ const columns = (deleteMember: (index: number) => void, users: UserType[]) => [ header: 'Email', enableSorting: false, cell: ({ getValue }) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const { t } = useTranslation(); return ( <> {users.some((v) => v.email === getValue()) ? ( @@ -52,10 +54,9 @@ const columns = (deleteMember: (index: number) => void, users: UserType[]) => [ ) : (
{getValue()} -
)} diff --git a/apps/web/src/containers/tables/FeedbackTable/DownloadButton/DownloadButton.tsx b/apps/web/src/containers/tables/FeedbackTable/DownloadButton/DownloadButton.tsx index a2edc3fcb..2f371d9f8 100644 --- a/apps/web/src/containers/tables/FeedbackTable/DownloadButton/DownloadButton.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/DownloadButton/DownloadButton.tsx @@ -27,13 +27,15 @@ import useFeedbackTable from '../feedback-table.context'; export interface IDownloadButtonProps { query: any; + fieldIds: number[]; count?: number; isHead?: boolean; } const DownloadButton: React.FC = ({ - count, query, + fieldIds, + count, isHead = false, }) => { const { channelId, projectId, createdAtRange } = useFeedbackTable(); @@ -49,10 +51,7 @@ const DownloadButton: React.FC = ({ }, [query]); const { mutateAsync } = useDownload({ - params: { - channelId, - projectId, - }, + params: { channelId, projectId }, options: { onSuccess: async () => { setIsClicked(false); @@ -71,8 +70,7 @@ const DownloadButton: React.FC = ({ toast.promise( mutateAsync({ type, - limit: count, - page: 1, + fieldIds, query: { ...query, createdAt: { diff --git a/apps/web/src/containers/tables/FeedbackTable/FeedbackDetail/FeedbackDetail.tsx b/apps/web/src/containers/tables/FeedbackTable/FeedbackDetail/FeedbackDetail.tsx index ac31cfb03..c1083c7ec 100644 --- a/apps/web/src/containers/tables/FeedbackTable/FeedbackDetail/FeedbackDetail.tsx +++ b/apps/web/src/containers/tables/FeedbackTable/FeedbackDetail/FeedbackDetail.tsx @@ -25,6 +25,7 @@ import { useRole, } from '@floating-ui/react'; import dayjs from 'dayjs'; +import { useTranslation } from 'react-i18next'; import { Badge, Icon } from '@ufb/ui'; @@ -44,6 +45,7 @@ interface IProps { } const FeedbackDetail: React.FC = (props) => { + const { t } = useTranslation(); const { channelId, id, projectId, onOpenChange, open } = props; const { data } = useFeedbackSearch(projectId, channelId, { query: { ids: [id] }, @@ -83,7 +85,9 @@ const FeedbackDetail: React.FC = (props) => { >
-

피드백 상세

+

+ {t('text.feedback-detail')} +