feature: acct list can hover pencil btn
This commit is contained in:
3
src/assets/icon-detail-on.svg
Normal file
3
src/assets/icon-detail-on.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M18.75 10.5C18.75 10.6989 18.671 10.8897 18.5303 11.0303C18.3897 11.171 18.1989 11.25 18 11.25H14.25C14.0511 11.25 13.8603 11.171 13.7197 11.0303C13.579 10.8897 13.5 10.6989 13.5 10.5C13.5 10.3011 13.579 10.1103 13.7197 9.96967C13.8603 9.82902 14.0511 9.75 14.25 9.75H18C18.1989 9.75 18.3897 9.82902 18.5303 9.96967C18.671 10.1103 18.75 10.3011 18.75 10.5ZM18 12.75H14.25C14.0511 12.75 13.8603 12.829 13.7197 12.9697C13.579 13.1103 13.5 13.3011 13.5 13.5C13.5 13.6989 13.579 13.8897 13.7197 14.0303C13.8603 14.171 14.0511 14.25 14.25 14.25H18C18.1989 14.25 18.3897 14.171 18.5303 14.0303C18.671 13.8897 18.75 13.6989 18.75 13.5C18.75 13.3011 18.671 13.1103 18.5303 12.9697C18.3897 12.829 18.1989 12.75 18 12.75ZM12.2625 15.5625C12.2878 15.6573 12.2941 15.7562 12.2809 15.8535C12.2677 15.9507 12.2353 16.0444 12.1855 16.129C12.1358 16.2136 12.0698 16.2875 11.9912 16.3463C11.9127 16.4052 11.8233 16.4479 11.7281 16.4719C11.6327 16.4973 11.5332 16.5037 11.4353 16.4906C11.3374 16.4775 11.2431 16.4452 11.1578 16.3955C11.0724 16.3459 10.9977 16.2799 10.9379 16.2013C10.8781 16.1227 10.8344 16.033 10.8094 15.9375C10.6823 15.4576 10.4 15.0333 10.0067 14.7305C9.61326 14.4278 9.13079 14.2636 8.63437 14.2636C8.13796 14.2636 7.65549 14.4278 7.26209 14.7305C6.8687 15.0333 6.58648 15.4576 6.45938 15.9375C6.41615 16.0985 6.32112 16.2409 6.18896 16.3425C6.0568 16.4442 5.89486 16.4995 5.72812 16.5L5.54062 16.4719C5.44547 16.4479 5.35603 16.4052 5.2775 16.3463C5.19898 16.2875 5.13294 16.2136 5.08322 16.129C5.0335 16.0444 5.00109 15.9507 4.98788 15.8535C4.97466 15.7562 4.98091 15.6573 5.00625 15.5625C5.23456 14.676 5.77774 13.9028 6.53437 13.3875C6.10882 12.9704 5.81713 12.436 5.69649 11.8524C5.57586 11.2688 5.63175 10.6626 5.85703 10.1109C6.08232 9.55922 6.46679 9.08714 6.96143 8.75484C7.45608 8.42254 8.03848 8.24507 8.63437 8.24507C9.23027 8.24507 9.81267 8.42254 10.3073 8.75484C10.802 9.08714 11.1864 9.55922 11.4117 10.1109C11.637 10.6626 11.6929 11.2688 11.5723 11.8524C11.4516 12.436 11.1599 12.9704 10.7344 13.3875C11.491 13.9028 12.0342 14.676 12.2625 15.5625ZM8.63437 12.75C8.93105 12.75 9.22106 12.662 9.46773 12.4972C9.7144 12.3324 9.90666 12.0981 10.0202 11.824C10.1337 11.5499 10.1634 11.2483 10.1056 10.9574C10.0477 10.6664 9.90481 10.3991 9.69504 10.1893C9.48526 9.97956 9.21798 9.8367 8.92701 9.77882C8.63604 9.72094 8.33444 9.75065 8.06035 9.86418C7.78626 9.97771 7.55199 10.17 7.38717 10.4166C7.22235 10.6633 7.13438 10.9533 7.13437 11.25C7.13437 11.6478 7.29241 12.0294 7.57372 12.3107C7.85502 12.592 8.23655 12.75 8.63437 12.75ZM21.75 5.25V18.75C21.75 19.1478 21.592 19.5294 21.3107 19.8107C21.0294 20.092 20.6478 20.25 20.25 20.25H3.75C3.35218 20.25 2.97064 20.092 2.68934 19.8107C2.40804 19.5294 2.25 19.1478 2.25 18.75V5.25C2.25 4.85218 2.40804 4.47064 2.68934 4.18934C2.97064 3.90804 3.35218 3.75 3.75 3.75H20.25C20.6478 3.75 21.0294 3.90804 21.3107 4.18934C21.592 4.47064 21.75 4.85218 21.75 5.25ZM20.25 18.75V5.25H3.75V18.75H20.25Z" fill="#0099FF"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
3
src/assets/icon-edit-off.svg
Normal file
3
src/assets/icon-edit-off.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 19H6.4L15.025 10.375L13.625 8.975L5 17.6V19ZM19.3 8.925L15.05 4.725L16.45 3.325C16.8333 2.94167 17.3043 2.75 17.863 2.75C18.421 2.75 18.8917 2.94167 19.275 3.325L20.675 4.725C21.0583 5.10833 21.2583 5.571 21.275 6.113C21.2917 6.65433 21.1083 7.11667 20.725 7.5L19.3 8.925ZM4 21C3.71667 21 3.47933 20.904 3.288 20.712C3.096 20.5207 3 20.2833 3 20V17.175C3 17.0417 3.025 16.9127 3.075 16.788C3.125 16.6627 3.2 16.55 3.3 16.45L13.6 6.15L17.85 10.4L7.55 20.7C7.45 20.8 7.33767 20.875 7.213 20.925C7.08767 20.975 6.95833 21 6.825 21H4ZM14.325 9.675L13.625 8.975L15.025 10.375L14.325 9.675Z" fill="#64748B"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 718 B |
3
src/assets/icon-edit-on.svg
Normal file
3
src/assets/icon-edit-on.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M5 19H6.4L15.025 10.375L13.625 8.975L5 17.6V19ZM19.3 8.925L15.05 4.725L16.45 3.325C16.8333 2.94167 17.3043 2.75 17.863 2.75C18.421 2.75 18.8917 2.94167 19.275 3.325L20.675 4.725C21.0583 5.10833 21.2583 5.571 21.275 6.113C21.2917 6.65433 21.1083 7.11667 20.725 7.5L19.3 8.925ZM4 21C3.71667 21 3.47933 20.904 3.288 20.712C3.096 20.5207 3 20.2833 3 20V17.175C3 17.0417 3.025 16.9127 3.075 16.788C3.125 16.6627 3.2 16.55 3.3 16.45L13.6 6.15L17.85 10.4L7.55 20.7C7.45 20.8 7.33767 20.875 7.213 20.925C7.08767 20.975 6.95833 21 6.825 21H4ZM14.325 9.675L13.625 8.975L15.025 10.375L14.325 9.675Z" fill="#0099FF"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 718 B |
@@ -1,3 +0,0 @@
|
|||||||
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M2 17H3.4L12.025 8.375L10.625 6.975L2 15.6V17ZM16.3 6.925L12.05 2.725L13.45 1.325C13.8333 0.941667 14.3043 0.75 14.863 0.75C15.421 0.75 15.8917 0.941667 16.275 1.325L17.675 2.725C18.0583 3.10833 18.2583 3.571 18.275 4.113C18.2917 4.65433 18.1083 5.11667 17.725 5.5L16.3 6.925ZM1 19C0.716667 19 0.479333 18.904 0.288 18.712C0.0960001 18.5207 0 18.2833 0 18V15.175C0 15.0417 0.025 14.9127 0.075 14.788C0.125 14.6627 0.2 14.55 0.3 14.45L10.6 4.15L14.85 8.4L4.55 18.7C4.45 18.8 4.33767 18.875 4.213 18.925C4.08767 18.975 3.95833 19 3.825 19H1ZM11.325 7.675L10.625 6.975L12.025 8.375L11.325 7.675Z" fill="#64748B"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 723 B |
@@ -20,6 +20,7 @@
|
|||||||
"AccountActivation": "Account Activation",
|
"AccountActivation": "Account Activation",
|
||||||
"Detail": "Detail",
|
"Detail": "Detail",
|
||||||
"Edit": "Edit",
|
"Edit": "Edit",
|
||||||
|
"Delete": "Delete",
|
||||||
"AccountEdit": "Account Edit",
|
"AccountEdit": "Account Edit",
|
||||||
"AccountInformation": "Account Information",
|
"AccountInformation": "Account Information",
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const response = await this.$axios.get(apiGetUserList);
|
const response = await this.$axios.get(apiGetUserList);
|
||||||
const customizedResponseData = await this.customizeAllUserList(response.data);
|
const customizedResponseData = await this.customizeAllUserList(response.data);
|
||||||
this.allUserAccoutList = customizedResponseData;
|
this.allUserAccoutList = customizedResponseData;
|
||||||
|
console.log('getAllUserAccounts success');
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to get all users.');
|
apiError(error, 'Failed to get all users.');
|
||||||
}
|
}
|
||||||
@@ -54,7 +55,8 @@ export default defineStore('acctMgmtStore', {
|
|||||||
return rawResponseData.map(user => ({
|
return rawResponseData.map(user => ({
|
||||||
...user, // 保留後端傳來的欄位
|
...user, // 保留後端傳來的欄位
|
||||||
isDeleteHovered: false, // 針對前端顯示而額外增加的欄位
|
isDeleteHovered: false, // 針對前端顯示而額外增加的欄位
|
||||||
isRowHovered: true,
|
isRowHovered: false,
|
||||||
|
isEditHovered: false,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -79,5 +81,16 @@ export default defineStore('acctMgmtStore', {
|
|||||||
userToChange.isRowHovered = isRowHovered;
|
userToChange.isRowHovered = isRowHovered;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* According to mouseover or mouseleave status, change the bool value.
|
||||||
|
* @param {string} username
|
||||||
|
* @param {boolean} isEditHovered
|
||||||
|
*/
|
||||||
|
changeIsEditHoveredByUser(username, isEditHovered) {
|
||||||
|
const userToChange = this.allUserAccoutList.find(user => user.username === username);
|
||||||
|
if (userToChange) {
|
||||||
|
userToChange.isEditHovered = isEditHovered;
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -6,65 +6,84 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="acct_mgmt_data_grid" class="flex w-full overflow-y-auto h-[570px]" @scroll="handleScroll">
|
<div id="acct_mgmt_data_grid" class="flex w-full overflow-y-auto h-[570px]" @scroll="handleScroll">
|
||||||
<DataTable :value="internalInfiniteAcctData" dataKey="username" tableClass="w-full mt-4 text-sm relative table-fixed"
|
<DataTable :value="internalInfiniteAcctData" dataKey="username" tableClass="w-full mt-4 text-sm relative table-fixed"
|
||||||
|
:rowClass="getRowClass"
|
||||||
>
|
>
|
||||||
<template #body="slotProps">
|
|
||||||
<div class="flex w-full h-full whole-row"
|
|
||||||
:class="{
|
|
||||||
'hover:bg-[#CBD5E1]': slotProps.data.isRowHovered,
|
|
||||||
}"
|
|
||||||
@mouseover="handleRowMouseOver(slotProps.data.username)"
|
|
||||||
@mouseout="handleRowMouseOut(slotProps.data.username)"
|
|
||||||
> <!--處理一整列的互動監聽-->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<Column field="username" :header="i18next.t('AcctMgmt.Account')" bodyClass="font-medium" sortable>
|
<Column field="username" :header="i18next.t('AcctMgmt.Account')" bodyClass="font-medium" sortable>
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
|
<div class="row-container flex-w-full-hoverable w-full" @mouseenter="handleRowMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleRowMouseOut(slotProps.data.username)">
|
||||||
<div @dblclick="onAcctDoubleClick()" class="cursor-pointer">
|
<div @dblclick="onAcctDoubleClick()" class="cursor-pointer">
|
||||||
{{ slotProps.data.username }}
|
{{ slotProps.data.username }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="name" :header="i18next.t('AcctMgmt.FullName')" bodyClass="text-neutral-500" sortable>
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="row-container flex-w-full-hoverable w-full" @mouseenter="handleRowMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleRowMouseOut(slotProps.data.username)">
|
||||||
|
<div class="">
|
||||||
|
{{ slotProps.data.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column field="name" :header="i18next.t('AcctMgmt.FullName')" bodyClass="text-neutral-500" sortable></Column>
|
|
||||||
<Column field="is_admin" :header="i18next.t('AcctMgmt.AdminRights')" bodyClass="text-neutral-500 flex justify-center"
|
<Column field="is_admin" :header="i18next.t('AcctMgmt.AdminRights')" bodyClass="text-neutral-500 flex justify-center"
|
||||||
headerClass="header-center">
|
headerClass="header-center">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
<img v-if="slotProps.data.is_admin" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"
|
<div class="row-container flex-w-full-hoverable flex w-full justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleRowMouseOut(slotProps.data.username)">
|
||||||
|
<img v-if="slotProps.data.is_admin" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex justify-center"
|
||||||
@click="onAdminRightsBtnClick(true)"
|
@click="onAdminRightsBtnClick(true)"
|
||||||
/>
|
/>
|
||||||
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex"
|
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex justify-center"
|
||||||
@click="onAdminRightsBtnClick(false)"
|
@click="onAdminRightsBtnClick(false)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column field="is_active" :header="i18next.t('AcctMgmt.AccountActivation')" bodyClass="text-neutral-500"
|
<Column field="is_active" :header="i18next.t('AcctMgmt.AccountActivation')" bodyClass="text-neutral-500"
|
||||||
headerClass="header-center">
|
headerClass="header-center">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
|
<div class="row-container flex-w-full-hoverable w-full" @mouseenter="handleRowMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleRowMouseOut(slotProps.data.username)">
|
||||||
<div class="w-full flex justify-center">
|
<div class="w-full flex justify-center">
|
||||||
<img v-if="slotProps.data.is_active" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"/>
|
<img v-if="slotProps.data.is_active" src="@/assets/radioOn.svg" alt="Radio On" class="cursor-pointer flex"/>
|
||||||
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex"/>
|
<img v-else src="@/assets/radioOff.svg" alt="Radio Off" class="cursor-pointer flex"/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column :header="i18next.t('AcctMgmt.Detail')" bodyClass="text-neutral-500">
|
<Column :header="i18next.t('AcctMgmt.Detail')" bodyClass="text-neutral-500" headerClass="header-center">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
|
<div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleRowMouseOut(slotProps.data.username)">
|
||||||
<img src="@/assets/icon-detail-card.svg" alt="Detail" class="cursor-pointer" @click="onDetailBtnClick(slotProps.data.username)"/>
|
<img src="@/assets/icon-detail-card.svg" alt="Detail" class="cursor-pointer" @click="onDetailBtnClick(slotProps.data.username)"/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column :header="i18next.t('AcctMgmt.Edit')" bodyClass="text-neutral-500">
|
<Column :header="i18next.t('AcctMgmt.Edit')" bodyClass="text-neutral-500" headerClass="header-center">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
<img src="@/assets/icon-edit.svg" alt="Edit" class="cursor-pointer" @click="onEditBtnClick(slotProps.data.username)"/>
|
<div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)">
|
||||||
|
<img :src="slotProps.data.isEditHovered ? iconEditOn : iconEditOff" alt="Edit" class="cursor-pointer"
|
||||||
|
@click="onEditBtnClick(slotProps.data.username)"
|
||||||
|
@mouseover="handleEditMouseOver(slotProps.data.username)"
|
||||||
|
@mouseout="handleEditMouseOut(slotProps.data.username)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
<Column :header="i18next.t('AcctMgmt.Delete')" bodyClass="text-neutral-500">
|
<Column :header="i18next.t('AcctMgmt.Delete')" bodyClass="text-neutral-500 flex justify-center" headerClass="header-center">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
|
<div class="row-container flex-w-full-hoverable w-full flex justify-center" @mouseenter="handleRowMouseOver(slotProps.data.username)">
|
||||||
<img :src="slotProps.data.isDeleteHovered ? iconDeleteRed : iconDeleteGray"
|
<img :src="slotProps.data.isDeleteHovered ? iconDeleteRed : iconDeleteGray"
|
||||||
:alt="slotProps.data.isDeleteHovered ? 'hovered' : 'not-hovered'"
|
:alt="slotProps.data.isDeleteHovered ? 'hovered' : 'not-hovered'"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer flex"
|
||||||
@mouseover="handleDeleteMouseOver(slotProps.data.username)"
|
@mouseover="handleDeleteMouseOver(slotProps.data.username)"
|
||||||
@mouseout="handleDeleteMouseOut(slotProps.data.username)"
|
@mouseout="handleDeleteMouseOut(slotProps.data.username)"
|
||||||
@click="onDeleteBtnClick(slotProps.data.username)"
|
@click="onDeleteBtnClick(slotProps.data.username)"
|
||||||
>
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
@@ -90,6 +109,8 @@ import {
|
|||||||
} from "@/constants/constants.js";
|
} from "@/constants/constants.js";
|
||||||
import iconDeleteGray from '@/assets/icon-delete-gray.svg';
|
import iconDeleteGray from '@/assets/icon-delete-gray.svg';
|
||||||
import iconDeleteRed from '@/assets/icon-delete-red.svg';
|
import iconDeleteRed from '@/assets/icon-delete-red.svg';
|
||||||
|
import iconEditOff from '@/assets/icon-edit-off.svg';
|
||||||
|
import iconEditOn from '@/assets/icon-edit-on.svg';
|
||||||
|
|
||||||
const ONCE_RENDER_NUM_OF_DATA = 9;
|
const ONCE_RENDER_NUM_OF_DATA = 9;
|
||||||
|
|
||||||
@@ -163,10 +184,22 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleEditMouseOver = (username) => {
|
||||||
|
acctMgmtStore.changeIsEditHoveredByUser(username, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditMouseOut = (username) => {
|
||||||
|
acctMgmtStore.changeIsEditHoveredByUser(username, false);
|
||||||
|
};
|
||||||
|
|
||||||
const onDeleteBtnClick = (usernameToDelete) => {
|
const onDeleteBtnClick = (usernameToDelete) => {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getRowClass = (curData) => {
|
||||||
|
return curData.isRowHovered ? 'bg-[#F1F5F9]' : '';
|
||||||
|
};
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
await fetchLoginUserData();
|
await fetchLoginUserData();
|
||||||
await getFirstPageUserData();
|
await getFirstPageUserData();
|
||||||
@@ -178,13 +211,18 @@ export default {
|
|||||||
modalStore,
|
modalStore,
|
||||||
loginUserData,
|
loginUserData,
|
||||||
internalInfiniteAcctData,
|
internalInfiniteAcctData,
|
||||||
|
getRowClass,
|
||||||
onDeleteBtnClick,
|
onDeleteBtnClick,
|
||||||
handleDeleteMouseOver,
|
handleDeleteMouseOver,
|
||||||
handleDeleteMouseOut,
|
handleDeleteMouseOut,
|
||||||
handleRowMouseOver,
|
handleRowMouseOver,
|
||||||
handleRowMouseOut,
|
handleRowMouseOut,
|
||||||
|
handleEditMouseOver,
|
||||||
|
handleEditMouseOut,
|
||||||
iconDeleteGray,
|
iconDeleteGray,
|
||||||
iconDeleteRed,
|
iconDeleteRed,
|
||||||
|
iconEditOff,
|
||||||
|
iconEditOn,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|||||||
Reference in New Issue
Block a user