feat(用例管理): 用例详情新增测试计划tab页
This commit is contained in:
parent
4f97fd5428
commit
7478a1dff0
|
@ -8,9 +8,12 @@ import lombok.Data;
|
||||||
public class FunctionalCaseTestPlanDTO extends TestPlanFunctionalCase {
|
public class FunctionalCaseTestPlanDTO extends TestPlanFunctionalCase {
|
||||||
|
|
||||||
@Schema(description = "测试计划ID")
|
@Schema(description = "测试计划ID")
|
||||||
private String testPlanNum;
|
private Long testPlanNum;
|
||||||
|
|
||||||
@Schema(description = "所属项目")
|
@Schema(description = "测试计划名称")
|
||||||
|
private String testPlanName;
|
||||||
|
|
||||||
|
@Schema(description = "所属项目名称")
|
||||||
private String projectName;
|
private String projectName;
|
||||||
|
|
||||||
@Schema(description = "计划状态")
|
@Schema(description = "计划状态")
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
<select id="getPlanList" parameterType="io.metersphere.functional.request.AssociatePlanPageRequest" resultType="io.metersphere.functional.dto.FunctionalCaseTestPlanDTO">
|
<select id="getPlanList" parameterType="io.metersphere.functional.request.AssociatePlanPageRequest" resultType="io.metersphere.functional.dto.FunctionalCaseTestPlanDTO">
|
||||||
SELECT
|
SELECT
|
||||||
tpfc.*, tp.num as testPlanNum, tp.status as planStatus, p.name as projectName
|
tpfc.*, tp.name as testPlanName, tp.num as testPlanNum, tp.status as planStatus, p.name as projectName
|
||||||
FROM
|
FROM
|
||||||
test_plan_functional_case tpfc
|
test_plan_functional_case tpfc
|
||||||
LEFT JOIN test_plan tp ON tpfc.test_plan_id = tp.id
|
LEFT JOIN test_plan tp ON tpfc.test_plan_id = tp.id
|
||||||
|
@ -71,6 +71,9 @@
|
||||||
OR tp.num LIKE concat('%', #{request.keyword},'%')
|
OR tp.num LIKE concat('%', #{request.keyword},'%')
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
|
<include refid="planFilters">
|
||||||
|
<property name="filter" value="request.filter"/>
|
||||||
|
</include>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<sql id="queryWhereConditionByBaseQueryRequest">
|
<sql id="queryWhereConditionByBaseQueryRequest">
|
||||||
|
@ -133,5 +136,22 @@
|
||||||
</if>
|
</if>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
<sql id="planFilters">
|
||||||
|
<if test="${filter} != null and ${filter}.size() > 0">
|
||||||
|
<foreach collection="${filter}.entrySet()" index="key" item="values">
|
||||||
|
<if test="values != null and values.size() > 0">
|
||||||
|
<choose>
|
||||||
|
<when test="key=='planStatus'">
|
||||||
|
AND tp.status in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
</when>
|
||||||
|
<when test="key=='lastExecResult'">
|
||||||
|
AND tpfc.last_exec_result in
|
||||||
|
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
</if>
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
</sql>
|
||||||
</mapper>
|
</mapper>
|
|
@ -36,6 +36,7 @@ import {
|
||||||
GetAssociatedDebuggerUrl,
|
GetAssociatedDebuggerUrl,
|
||||||
GetAssociatedDrawerCaseUrl,
|
GetAssociatedDrawerCaseUrl,
|
||||||
GetAssociatedFilePageUrl,
|
GetAssociatedFilePageUrl,
|
||||||
|
GetAssociatedTestPlanUrl,
|
||||||
GetAssociationPublicCaseModuleCountUrl,
|
GetAssociationPublicCaseModuleCountUrl,
|
||||||
GetAssociationPublicCasePageUrl,
|
GetAssociationPublicCasePageUrl,
|
||||||
GetAssociationPublicModuleTreeUrl,
|
GetAssociationPublicModuleTreeUrl,
|
||||||
|
@ -96,6 +97,7 @@ import type {
|
||||||
} from '@/models/caseManagement/featureCase';
|
} from '@/models/caseManagement/featureCase';
|
||||||
import type { CommonList, ModuleTreeNode, MoveModules, TableQueryParams } from '@/models/common';
|
import type { CommonList, ModuleTreeNode, MoveModules, TableQueryParams } from '@/models/common';
|
||||||
import { ProjectListItem } from '@/models/setting/project';
|
import { ProjectListItem } from '@/models/setting/project';
|
||||||
|
import { AssociateFunctionalCaseItem, TestPlanItem } from '@/models/testPlan/testPlan';
|
||||||
|
|
||||||
// 获取模块树
|
// 获取模块树
|
||||||
export function getCaseModuleTree(params: TableQueryParams) {
|
export function getCaseModuleTree(params: TableQueryParams) {
|
||||||
|
@ -428,4 +430,9 @@ export function getAssociatedProjectOptions(orgId: string, module: string) {
|
||||||
return MSR.get<ProjectListItem[]>({ url: `${associatedProjectOptionsUrl}/${orgId}/${module}` });
|
return MSR.get<ProjectListItem[]>({ url: `${associatedProjectOptionsUrl}/${orgId}/${module}` });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取已关联测试计划列表
|
||||||
|
export function getLinkedCaseTestPlanList(data: TableQueryParams) {
|
||||||
|
return MSR.post<CommonList<AssociateFunctionalCaseItem>>({ url: GetAssociatedTestPlanUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
export default {};
|
export default {};
|
||||||
|
|
|
@ -151,3 +151,6 @@ export const getChangeHistoryListUrl = '/functional/case/operation-history';
|
||||||
export const cancelDisassociate = '/functional/case/test/disassociate/case';
|
export const cancelDisassociate = '/functional/case/test/disassociate/case';
|
||||||
// 关联用例关联功能用例项目下拉
|
// 关联用例关联功能用例项目下拉
|
||||||
export const associatedProjectOptionsUrl = '/project/list/options';
|
export const associatedProjectOptionsUrl = '/project/list/options';
|
||||||
|
|
||||||
|
// 获取详情已关联测试计划列表
|
||||||
|
export const GetAssociatedTestPlanUrl = '/functional/case/test/has/associate/plan/page';
|
||||||
|
|
|
@ -21,6 +21,14 @@ export interface TestPlanItem {
|
||||||
groupId: string;
|
groupId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AssociateFunctionalCaseItem {
|
||||||
|
testPlanId: string;
|
||||||
|
testPlanNum: number;
|
||||||
|
testPlanName: string;
|
||||||
|
projectName: string;
|
||||||
|
planStatus: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ResourcesItem {
|
export interface ResourcesItem {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
@ -141,7 +141,7 @@
|
||||||
<TabCaseReview :case-id="props.detailId" />
|
<TabCaseReview :case-id="props.detailId" />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="activeTab === 'testPlan'">
|
<template v-if="activeTab === 'testPlan'">
|
||||||
<TabTestPlan />
|
<TabTestPlan :case-id="props.detailId" />
|
||||||
</template>
|
</template>
|
||||||
<template v-if="activeTab === 'comments'">
|
<template v-if="activeTab === 'comments'">
|
||||||
<TabComment ref="commentRef" :case-id="props.detailId" />
|
<TabComment ref="commentRef" :case-id="props.detailId" />
|
||||||
|
@ -666,6 +666,12 @@
|
||||||
canHide: true,
|
canHide: true,
|
||||||
isShow: true,
|
isShow: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
value: 'testPlan',
|
||||||
|
label: t('caseManagement.featureCase.testPlan'),
|
||||||
|
canHide: true,
|
||||||
|
isShow: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
value: 'comments',
|
value: 'comments',
|
||||||
label: t('caseManagement.featureCase.comments'),
|
label: t('caseManagement.featureCase.comments'),
|
||||||
|
|
|
@ -7,14 +7,101 @@
|
||||||
:placeholder="t('caseManagement.featureCase.searchByNameAndId')"
|
:placeholder="t('caseManagement.featureCase.searchByNameAndId')"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="mx-[8px] w-[240px]"
|
class="mx-[8px] w-[240px]"
|
||||||
|
@search="searchList"
|
||||||
|
@press-enter="searchList"
|
||||||
|
@clear="searchList"
|
||||||
></a-input-search>
|
></a-input-search>
|
||||||
</div>
|
</div>
|
||||||
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
<ms-base-table v-bind="propsRes" v-on="propsEvent">
|
||||||
<template #name="{ record }">
|
<template #testPlanNum="{ record }">
|
||||||
<a-button type="text" class="px-0">{{ record.name }}</a-button>
|
<a-button type="text" class="px-0" @click="goToPlan(record)">{{ record.testPlanNum }}</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #status="{ record }">
|
<template #planStatus="{ record }">
|
||||||
<statusTag :status="record.status" />
|
<statusTag :status="record.planStatus" />
|
||||||
|
</template>
|
||||||
|
<template #statusFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="statusFilterVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
class="arco-btn-text--secondary p-[8px_4px] text-[14px]"
|
||||||
|
@click="statusFilterVisible = true"
|
||||||
|
>
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
<icon-down :class="statusFilterVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</a-button>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group v-model:model-value="statusFilters" direction="vertical" size="small">
|
||||||
|
<a-checkbox v-for="key of Object.keys(planStatusMap)" :key="key" :value="key">
|
||||||
|
<a-tag
|
||||||
|
:color="planStatusMap[key as planStatusType].color"
|
||||||
|
:class="[planStatusMap[key as planStatusType].class, 'px-[4px]']"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ t(planStatusMap[key as planStatusType].label) }}
|
||||||
|
</a-tag>
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="filter-button">
|
||||||
|
<a-button size="mini" class="mr-[8px]" @click="resetStatusFilter">
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||||
|
{{ t('system.orgTemplate.confirm') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
|
</template>
|
||||||
|
<template #lastExecResult="{ record }">
|
||||||
|
<execute-result :execute-result="record.lastExecResult" />
|
||||||
|
</template>
|
||||||
|
<template #lastExecResultFilter="{ columnConfig }">
|
||||||
|
<a-trigger
|
||||||
|
v-model:popup-visible="lastExecResultVisible"
|
||||||
|
trigger="click"
|
||||||
|
@popup-visible-change="handleFilterHidden"
|
||||||
|
>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
class="arco-btn-text--secondary p-[8px_4px] text-[14px]"
|
||||||
|
@click="lastExecResultVisible = true"
|
||||||
|
>
|
||||||
|
{{ t(columnConfig.title as string) }}
|
||||||
|
<icon-down :class="lastExecResultVisible ? 'text-[rgb(var(--primary-5))]' : ''" />
|
||||||
|
</a-button>
|
||||||
|
<template #content>
|
||||||
|
<div class="arco-table-filters-content">
|
||||||
|
<div class="flex items-center justify-center px-[6px] py-[2px]">
|
||||||
|
<a-checkbox-group v-model:model-value="lastExecResultFilters" direction="vertical" size="small">
|
||||||
|
<a-checkbox v-for="key of Object.keys(executionResultMap)" :key="key" :value="key">
|
||||||
|
<MsIcon
|
||||||
|
:type="executionResultMap[key]?.icon || ''"
|
||||||
|
class="mr-1"
|
||||||
|
:class="[executionResultMap[key].color]"
|
||||||
|
></MsIcon>
|
||||||
|
<span>{{ executionResultMap[key]?.statusText || '' }} </span>
|
||||||
|
</a-checkbox>
|
||||||
|
</a-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div class="filter-button">
|
||||||
|
<a-button size="mini" class="mr-[8px]" @click="resetLastExecuteResultFilter">
|
||||||
|
{{ t('common.reset') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" size="mini" @click="handleFilterHidden(false)">
|
||||||
|
{{ t('system.orgTemplate.confirm') }}
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-trigger>
|
||||||
</template>
|
</template>
|
||||||
</ms-base-table>
|
</ms-base-table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,34 +109,48 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { debounce } from 'lodash-es';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
import type { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
import useTable from '@/components/pure/ms-table/useTable';
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import ExecuteResult from '@/components/business/ms-case-associate/executeResult.vue';
|
||||||
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
import statusTag from '@/views/case-management/caseReview/components/statusTag.vue';
|
||||||
|
|
||||||
import { getRecycleListRequest } from '@/api/modules/case-management/featureCase';
|
import { getLinkedCaseTestPlanList } from '@/api/modules/case-management/featureCase';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useFeatureCaseStore from '@/store/modules/case/featureCase';
|
|
||||||
|
|
||||||
|
import { AssociateFunctionalCaseItem, planStatusType } from '@/models/testPlan/testPlan';
|
||||||
|
import { TestPlanRouteEnum } from '@/enums/routeEnum';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
const featureCaseStore = useFeatureCaseStore();
|
import { executionResultMap } from '@/views/case-management/caseManagementFeature/components/utils';
|
||||||
const activeTab = computed(() => featureCaseStore.activeTab);
|
import { planStatusMap } from '@/views/test-plan/testPlan/config';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
const keyword = ref<string>('');
|
const keyword = ref<string>('');
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
caseId: string; // 用例id
|
||||||
|
}>();
|
||||||
|
|
||||||
const columns: MsTableColumn = [
|
const columns: MsTableColumn = [
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.defectID',
|
title: 'ID',
|
||||||
dataIndex: 'id',
|
dataIndex: 'testPlanNum',
|
||||||
|
slotName: 'testPlanNum',
|
||||||
showTooltip: true,
|
showTooltip: true,
|
||||||
width: 90,
|
width: 90,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.testPlanName',
|
title: 'caseManagement.featureCase.testPlanName',
|
||||||
slotName: 'name',
|
slotName: 'testPlanName',
|
||||||
dataIndex: 'name',
|
dataIndex: 'testPlanName',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -62,28 +163,114 @@
|
||||||
title: 'caseManagement.featureCase.planStatus',
|
title: 'caseManagement.featureCase.planStatus',
|
||||||
slotName: 'planStatus',
|
slotName: 'planStatus',
|
||||||
dataIndex: 'planStatus',
|
dataIndex: 'planStatus',
|
||||||
|
titleSlotName: 'statusFilter',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.tableColumnExecutionResult',
|
title: 'caseManagement.featureCase.tableColumnExecutionResult',
|
||||||
slotName: 'executionResult',
|
slotName: 'lastExecResult',
|
||||||
dataIndex: 'executionResult',
|
dataIndex: 'lastExecResult',
|
||||||
|
titleSlotName: 'lastExecResultFilter',
|
||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'caseManagement.featureCase.executionTime',
|
title: 'caseManagement.featureCase.executionTime',
|
||||||
slotName: 'executionTime',
|
slotName: 'lastExecTime',
|
||||||
dataIndex: 'executionTime',
|
dataIndex: 'lastExecTime',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
showInTable: false,
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
|
showDrag: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getRecycleListRequest, {
|
const statusFilterVisible = ref(false);
|
||||||
columns,
|
const statusFilters = ref<string[]>([]);
|
||||||
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_TEST_PLAN,
|
|
||||||
scroll: { x: '100%' },
|
const lastExecResultVisible = ref(false);
|
||||||
heightUsed: 340,
|
const lastExecResultFilters = ref<string[]>([]);
|
||||||
enableDrag: true,
|
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
|
||||||
|
getLinkedCaseTestPlanList,
|
||||||
|
{
|
||||||
|
columns,
|
||||||
|
tableKey: TableKeyEnum.CASE_MANAGEMENT_TAB_TEST_PLAN,
|
||||||
|
scroll: { x: '100%' },
|
||||||
|
heightUsed: 340,
|
||||||
|
enableDrag: false,
|
||||||
|
},
|
||||||
|
(item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
lastExecTime: item.lastExecTime ? `${dayjs(item.lastExecTime).format('YYYY-MM-DD HH:mm:ss')}` : '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
async function initData() {
|
||||||
|
setLoadListParams({
|
||||||
|
keyword: keyword.value,
|
||||||
|
caseId: props.caseId,
|
||||||
|
filter: {
|
||||||
|
planStatus: statusFilters.value,
|
||||||
|
lastExecResult: lastExecResultFilters.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchList = debounce(() => {
|
||||||
|
initData();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
function handleFilterHidden(val: boolean) {
|
||||||
|
if (!val) {
|
||||||
|
statusFilterVisible.value = false;
|
||||||
|
lastExecResultVisible.value = false;
|
||||||
|
searchList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetStatusFilter() {
|
||||||
|
statusFilterVisible.value = false;
|
||||||
|
statusFilters.value = [];
|
||||||
|
searchList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetLastExecuteResultFilter() {
|
||||||
|
lastExecResultVisible.value = false;
|
||||||
|
lastExecResultFilters.value = [];
|
||||||
|
searchList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去测试计划页面
|
||||||
|
function goToPlan(record: AssociateFunctionalCaseItem) {
|
||||||
|
router.push({
|
||||||
|
name: TestPlanRouteEnum.TEST_PLAN_INDEX,
|
||||||
|
query: {
|
||||||
|
...route.query,
|
||||||
|
id: record.testPlanId,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
params: JSON.stringify(setLoadListParams()),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.caseId,
|
||||||
|
(val) => {
|
||||||
|
if (val) {
|
||||||
|
initData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initData();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -65,12 +65,12 @@ export const executionResultMap: Record<string, any> = {
|
||||||
statusText: t('caseManagement.featureCase.passed'),
|
statusText: t('caseManagement.featureCase.passed'),
|
||||||
color: '',
|
color: '',
|
||||||
},
|
},
|
||||||
SKIPPED: {
|
/* SKIPPED: {
|
||||||
key: 'SKIPPED',
|
key: 'SKIPPED',
|
||||||
icon: StatusType.SKIPPED,
|
icon: StatusType.SKIPPED,
|
||||||
statusText: t('caseManagement.featureCase.skip'),
|
statusText: t('caseManagement.featureCase.skip'),
|
||||||
color: 'text-[rgb(var(--link-6))]',
|
color: 'text-[rgb(var(--link-6))]',
|
||||||
},
|
}, */
|
||||||
BLOCKED: {
|
BLOCKED: {
|
||||||
key: 'BLOCKED',
|
key: 'BLOCKED',
|
||||||
icon: StatusType.BLOCKED,
|
icon: StatusType.BLOCKED,
|
||||||
|
|
Loading…
Reference in New Issue