chore: show toast message when update test run/case (#25)
This commit is contained in:
@@ -189,6 +189,7 @@
|
|||||||
"back_to_cases": "Back to test cases",
|
"back_to_cases": "Back to test cases",
|
||||||
"updating": "Updating...",
|
"updating": "Updating...",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
|
"updated_test_case": "Updated test case",
|
||||||
"basic": "Basic",
|
"basic": "Basic",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"please_enter_title": "Please enter title",
|
"please_enter_title": "Please enter title",
|
||||||
@@ -241,6 +242,7 @@
|
|||||||
"back_to_runs": "Back to test runs",
|
"back_to_runs": "Back to test runs",
|
||||||
"updating": "Updating...",
|
"updating": "Updating...",
|
||||||
"update": "Update",
|
"update": "Update",
|
||||||
|
"updated_test_run": "Updated test run",
|
||||||
"progress": "Progress",
|
"progress": "Progress",
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
|||||||
@@ -190,6 +190,7 @@
|
|||||||
"back_to_cases": "テストケース一覧に戻る",
|
"back_to_cases": "テストケース一覧に戻る",
|
||||||
"updating": "更新中...",
|
"updating": "更新中...",
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
|
"updated_test_case": "テストケースを更新しました",
|
||||||
"basic": "基本データ",
|
"basic": "基本データ",
|
||||||
"title": "タイトル",
|
"title": "タイトル",
|
||||||
"please_enter_title": "タイトルを入力してください",
|
"please_enter_title": "タイトルを入力してください",
|
||||||
@@ -242,6 +243,7 @@
|
|||||||
"back_to_runs": "テストラン一覧に戻る",
|
"back_to_runs": "テストラン一覧に戻る",
|
||||||
"updating": "更新中...",
|
"updating": "更新中...",
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
|
"updated_test_run": "テストランを更新しました",
|
||||||
"progress": "進捗",
|
"progress": "進捗",
|
||||||
"refresh": "再読み込み",
|
"refresh": "再読み込み",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { fetchCase, updateCase } from '@/utils/caseControl';
|
|||||||
import { updateSteps } from './stepControl';
|
import { updateSteps } from './stepControl';
|
||||||
import { fetchCreateAttachments, fetchDownloadAttachment, fetchDeleteAttachment } from './attachmentControl';
|
import { fetchCreateAttachments, fetchDownloadAttachment, fetchDeleteAttachment } from './attachmentControl';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
|
import { ToastContext } from '@/utils/ToastProvider';
|
||||||
import { useFormGuard } from '@/utils/formGuard';
|
import { useFormGuard } from '@/utils/formGuard';
|
||||||
import { CaseType, AttachmentType, CaseMessages, StepType } from '@/types/case';
|
import { CaseType, AttachmentType, CaseMessages, StepType } from '@/types/case';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
@@ -52,7 +53,8 @@ export default function CaseEditor({
|
|||||||
priorityMessages,
|
priorityMessages,
|
||||||
locale,
|
locale,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const context = useContext(TokenContext);
|
const toakenContext = useContext(TokenContext);
|
||||||
|
const toastContext = useContext(ToastContext);
|
||||||
const [testCase, setTestCase] = useState<CaseType>(defaultTestCase);
|
const [testCase, setTestCase] = useState<CaseType>(defaultTestCase);
|
||||||
const [isTitleInvalid, setIsTitleInvalid] = useState<boolean>(false);
|
const [isTitleInvalid, setIsTitleInvalid] = useState<boolean>(false);
|
||||||
const [isUpdating, setIsUpdating] = useState<boolean>(false);
|
const [isUpdating, setIsUpdating] = useState<boolean>(false);
|
||||||
@@ -192,11 +194,11 @@ export default function CaseEditor({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchDataEffect() {
|
async function fetchDataEffect() {
|
||||||
if (!context.isSignedIn()) {
|
if (!toakenContext.isSignedIn()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const data = await fetchCase(context.token.access_token, Number(caseId));
|
const data = await fetchCase(toakenContext.token.access_token, Number(caseId));
|
||||||
data.Steps.forEach((step: StepType) => {
|
data.Steps.forEach((step: StepType) => {
|
||||||
step.editState = 'notChanged';
|
step.editState = 'notChanged';
|
||||||
});
|
});
|
||||||
@@ -207,7 +209,7 @@ export default function CaseEditor({
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context]);
|
}, [toakenContext]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -230,15 +232,17 @@ export default function CaseEditor({
|
|||||||
<Button
|
<Button
|
||||||
startContent={<Save size={16} />}
|
startContent={<Save size={16} />}
|
||||||
size="sm"
|
size="sm"
|
||||||
isDisabled={!context.isProjectDeveloper(Number(projectId))}
|
isDisabled={!toakenContext.isProjectDeveloper(Number(projectId))}
|
||||||
color="primary"
|
color="primary"
|
||||||
isLoading={isUpdating}
|
isLoading={isUpdating}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
await updateCase(context.token.access_token, testCase);
|
await updateCase(toakenContext.token.access_token, testCase);
|
||||||
if (testCase.Steps) {
|
if (testCase.Steps) {
|
||||||
await updateSteps(context.token.access_token, Number(caseId), testCase.Steps);
|
await updateSteps(toakenContext.token.access_token, Number(caseId), testCase.Steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toastContext.showToast(messages.updatedTestCase, 'dark');
|
||||||
setIsUpdating(false);
|
setIsUpdating(false);
|
||||||
setIsDirty(false);
|
setIsDirty(false);
|
||||||
}}
|
}}
|
||||||
@@ -383,7 +387,7 @@ export default function CaseEditor({
|
|||||||
<Button
|
<Button
|
||||||
startContent={<Plus size={16} />}
|
startContent={<Plus size={16} />}
|
||||||
size="sm"
|
size="sm"
|
||||||
isDisabled={!context.isProjectDeveloper(Number(projectId))}
|
isDisabled={!toakenContext.isProjectDeveloper(Number(projectId))}
|
||||||
color="primary"
|
color="primary"
|
||||||
className="ms-3"
|
className="ms-3"
|
||||||
onPress={() => onPlusClick(1)}
|
onPress={() => onPlusClick(1)}
|
||||||
@@ -393,7 +397,7 @@ export default function CaseEditor({
|
|||||||
</div>
|
</div>
|
||||||
{testCase.Steps && (
|
{testCase.Steps && (
|
||||||
<CaseStepsEditor
|
<CaseStepsEditor
|
||||||
isDisabled={!context.isProjectDeveloper(Number(projectId))}
|
isDisabled={!toakenContext.isProjectDeveloper(Number(projectId))}
|
||||||
steps={testCase.Steps}
|
steps={testCase.Steps}
|
||||||
onStepUpdate={(stepId, changeStep) => {
|
onStepUpdate={(stepId, changeStep) => {
|
||||||
if (testCase.Steps) {
|
if (testCase.Steps) {
|
||||||
@@ -421,7 +425,7 @@ export default function CaseEditor({
|
|||||||
<h6 className="font-bold">{messages.attachments}</h6>
|
<h6 className="font-bold">{messages.attachments}</h6>
|
||||||
{testCase.Attachments && (
|
{testCase.Attachments && (
|
||||||
<CaseAttachmentsEditor
|
<CaseAttachmentsEditor
|
||||||
isDisabled={!context.isProjectDeveloper(Number(projectId))}
|
isDisabled={!toakenContext.isProjectDeveloper(Number(projectId))}
|
||||||
attachments={testCase.Attachments}
|
attachments={testCase.Attachments}
|
||||||
onAttachmentDownload={(attachmentId: number, downloadFileName: string) =>
|
onAttachmentDownload={(attachmentId: number, downloadFileName: string) =>
|
||||||
fetchDownloadAttachment(attachmentId, downloadFileName)
|
fetchDownloadAttachment(attachmentId, downloadFileName)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export default function Page({
|
|||||||
backToCases: t('back_to_cases'),
|
backToCases: t('back_to_cases'),
|
||||||
updating: t('updating'),
|
updating: t('updating'),
|
||||||
update: t('update'),
|
update: t('update'),
|
||||||
|
updatedTestCase: t('updated_test_case'),
|
||||||
basic: t('basic'),
|
basic: t('basic'),
|
||||||
title: t('title'),
|
title: t('title'),
|
||||||
pleaseEnterTitle: t('please_enter_title'),
|
pleaseEnterTitle: t('please_enter_title'),
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import {
|
|||||||
} from '../runsControl';
|
} from '../runsControl';
|
||||||
import { fetchFolders } from '../../folders/foldersControl';
|
import { fetchFolders } from '../../folders/foldersControl';
|
||||||
import { TokenContext } from '@/utils/TokenProvider';
|
import { TokenContext } from '@/utils/TokenProvider';
|
||||||
|
import { ToastContext } from '@/utils/ToastProvider';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { useFormGuard } from '@/utils/formGuard';
|
import { useFormGuard } from '@/utils/formGuard';
|
||||||
import { PriorityMessages } from '@/types/priority';
|
import { PriorityMessages } from '@/types/priority';
|
||||||
@@ -73,7 +74,8 @@ export default function RunEditor({
|
|||||||
testTypeMessages,
|
testTypeMessages,
|
||||||
locale,
|
locale,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const context = useContext(TokenContext);
|
const tokenContext = useContext(TokenContext);
|
||||||
|
const toastContext = useContext(ToastContext);
|
||||||
const { theme, setTheme } = useTheme();
|
const { theme, setTheme } = useTheme();
|
||||||
const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
|
const [testRun, setTestRun] = useState<RunType>(defaultTestRun);
|
||||||
const [folders, setFolders] = useState<FolderType[]>([]);
|
const [folders, setFolders] = useState<FolderType[]>([]);
|
||||||
@@ -89,13 +91,13 @@ export default function RunEditor({
|
|||||||
useFormGuard(isDirty, messages.areYouSureLeave);
|
useFormGuard(isDirty, messages.areYouSureLeave);
|
||||||
|
|
||||||
const fetchRunAndStatusCount = async () => {
|
const fetchRunAndStatusCount = async () => {
|
||||||
const { run, statusCounts } = await fetchRun(context.token.access_token, Number(runId));
|
const { run, statusCounts } = await fetchRun(tokenContext.token.access_token, Number(runId));
|
||||||
setTestRun(run);
|
setTestRun(run);
|
||||||
setRunStatusCounts(statusCounts);
|
setRunStatusCounts(statusCounts);
|
||||||
};
|
};
|
||||||
|
|
||||||
const initTestCases = async () => {
|
const initTestCases = async () => {
|
||||||
const casesData = await fetchProjectCases(context.token.access_token, Number(projectId));
|
const casesData = await fetchProjectCases(tokenContext.token.access_token, Number(projectId));
|
||||||
casesData.forEach((testCase: CaseType) => {
|
casesData.forEach((testCase: CaseType) => {
|
||||||
if (testCase.RunCases && testCase.RunCases.length > 0) {
|
if (testCase.RunCases && testCase.RunCases.length > 0) {
|
||||||
testCase.RunCases[0].editState = 'notChanged';
|
testCase.RunCases[0].editState = 'notChanged';
|
||||||
@@ -106,13 +108,13 @@ export default function RunEditor({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchDataEffect() {
|
async function fetchDataEffect() {
|
||||||
if (!context.isSignedIn()) {
|
if (!tokenContext.isSignedIn()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fetchRunAndStatusCount();
|
await fetchRunAndStatusCount();
|
||||||
const foldersData = await fetchFolders(context.token.access_token, Number(projectId));
|
const foldersData = await fetchFolders(tokenContext.token.access_token, Number(projectId));
|
||||||
setFolders(foldersData);
|
setFolders(foldersData);
|
||||||
setSelectedFolder(foldersData[0]);
|
setSelectedFolder(foldersData[0]);
|
||||||
initTestCases();
|
initTestCases();
|
||||||
@@ -122,7 +124,7 @@ export default function RunEditor({
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchDataEffect();
|
fetchDataEffect();
|
||||||
}, [context]);
|
}, [tokenContext]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function onFilter() {
|
function onFilter() {
|
||||||
@@ -168,9 +170,11 @@ export default function RunEditor({
|
|||||||
|
|
||||||
const onSave = async () => {
|
const onSave = async () => {
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
await updateRun(context.token.access_token, testRun);
|
await updateRun(tokenContext.token.access_token, testRun);
|
||||||
await updateRunCases(context.token.access_token, Number(runId), testCases);
|
await updateRunCases(tokenContext.token.access_token, Number(runId), testCases);
|
||||||
await initTestCases();
|
await initTestCases();
|
||||||
|
|
||||||
|
toastContext.showToast(messages.updatedTestRun, 'dark');
|
||||||
setIsUpdating(false);
|
setIsUpdating(false);
|
||||||
setIsDirty(false);
|
setIsDirty(false);
|
||||||
};
|
};
|
||||||
@@ -199,7 +203,7 @@ export default function RunEditor({
|
|||||||
<Button
|
<Button
|
||||||
startContent={<Save size={16} />}
|
startContent={<Save size={16} />}
|
||||||
size="sm"
|
size="sm"
|
||||||
isDisabled={!context.isProjectReporter(Number(projectId))}
|
isDisabled={!tokenContext.isProjectReporter(Number(projectId))}
|
||||||
color="primary"
|
color="primary"
|
||||||
isLoading={isUpdating}
|
isLoading={isUpdating}
|
||||||
onPress={onSave}
|
onPress={onSave}
|
||||||
@@ -294,7 +298,7 @@ export default function RunEditor({
|
|||||||
<DropdownTrigger>
|
<DropdownTrigger>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
isDisabled={!context.isProjectReporter(Number(projectId))}
|
isDisabled={!tokenContext.isProjectReporter(Number(projectId))}
|
||||||
color="primary"
|
color="primary"
|
||||||
endContent={<ChevronDown size={16} />}
|
endContent={<ChevronDown size={16} />}
|
||||||
>
|
>
|
||||||
@@ -341,7 +345,7 @@ export default function RunEditor({
|
|||||||
<div className="w-9/12">
|
<div className="w-9/12">
|
||||||
<TestCaseSelector
|
<TestCaseSelector
|
||||||
cases={filteredTestCases}
|
cases={filteredTestCases}
|
||||||
isDisabled={!context.isProjectReporter(Number(projectId))}
|
isDisabled={!tokenContext.isProjectReporter(Number(projectId))}
|
||||||
selectedKeys={selectedKeys}
|
selectedKeys={selectedKeys}
|
||||||
onSelectionChange={setSelectedKeys}
|
onSelectionChange={setSelectedKeys}
|
||||||
onChangeStatus={handleChangeStatus}
|
onChangeStatus={handleChangeStatus}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export default function Page({ params }: { params: { projectId: string; runId: s
|
|||||||
backToRuns: t('back_to_runs'),
|
backToRuns: t('back_to_runs'),
|
||||||
updating: t('updating'),
|
updating: t('updating'),
|
||||||
update: t('update'),
|
update: t('update'),
|
||||||
|
updatedTestRun: t('updated_test_run'),
|
||||||
progress: t('progress'),
|
progress: t('progress'),
|
||||||
refresh: t('refresh'),
|
refresh: t('refresh'),
|
||||||
id: t('id'),
|
id: t('id'),
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ type CaseMessages = {
|
|||||||
backToCases: string;
|
backToCases: string;
|
||||||
updating: string;
|
updating: string;
|
||||||
update: string;
|
update: string;
|
||||||
|
updatedTestCase: string;
|
||||||
basic: string;
|
basic: string;
|
||||||
title: string;
|
title: string;
|
||||||
pleaseEnterTitle: string;
|
pleaseEnterTitle: string;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type RunMessages = {
|
|||||||
backToRuns: string;
|
backToRuns: string;
|
||||||
updating: string;
|
updating: string;
|
||||||
update: string;
|
update: string;
|
||||||
|
updatedTestRun: string;
|
||||||
progress: string;
|
progress: string;
|
||||||
refresh: string;
|
refresh: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ export type ToastMessages = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ToastContextType = {
|
export type ToastContextType = {
|
||||||
showToast: (text: string, mode: string) => void;
|
showToast: (text: string, mode: 'error' | 'dark') => void;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { ToastContainer, toast } from 'react-toastify';
|
|||||||
import 'react-toastify/dist/ReactToastify.css';
|
import 'react-toastify/dist/ReactToastify.css';
|
||||||
|
|
||||||
const defaultContext = {
|
const defaultContext = {
|
||||||
showToast: (text: string, mode: string) => {},
|
showToast: (text: string, mode: 'error' | 'dark') => {},
|
||||||
};
|
};
|
||||||
const ToastContext = createContext<ToastContextType>(defaultContext);
|
const ToastContext = createContext<ToastContextType>(defaultContext);
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ const ToastProvider = ({ children }: ToastProps) => {
|
|||||||
if (mode === 'error') {
|
if (mode === 'error') {
|
||||||
toast.error(text);
|
toast.error(text);
|
||||||
} else {
|
} else {
|
||||||
toast(text, { theme: 'light' });
|
toast(text, { theme: 'dark' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ const ToastProvider = ({ children }: ToastProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ToastContext.Provider value={toastContext}>
|
<ToastContext.Provider value={toastContext}>
|
||||||
<ToastContainer position="bottom-right" hideProgressBar={true} theme="colored" />
|
<ToastContainer position="bottom-right" hideProgressBar={true} />
|
||||||
{children}
|
{children}
|
||||||
</ToastContext.Provider>
|
</ToastContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user