fix: acct_mgmt_button
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mx-auto px-4 h-14">
|
<div class="mx-auto px-4 h-14 z-50">
|
||||||
<div class="flex justify-between items-center h-full">
|
<div class="flex justify-between items-center h-full">
|
||||||
<figure>
|
<figure>
|
||||||
<DspLogo />
|
<DspLogo />
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
Logout
|
Logout
|
||||||
</button> -->
|
</button> -->
|
||||||
<img v-show="true" id="acct_mgmt_button" src="@/assets/icon-head-black.svg" width="32" height="32"
|
<img v-show="true" id="acct_mgmt_button" src="@/assets/icon-head-black.svg" width="32" height="32"
|
||||||
class="cursor-pointer" @click="onAcctHeadClick"
|
class="cursor-pointer z-50" @click="toggleIsAcctMenuOpen"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { storeToRefs, mapActions, } from 'pinia';
|
import { storeToRefs, } from 'pinia';
|
||||||
import i18next from '@/i18n/i18n';
|
import i18next from '@/i18n/i18n';
|
||||||
import loginStore from '@/stores/login.ts';
|
import loginStore from '@/stores/login.ts';
|
||||||
import acctMenuStore from "@/stores/acctMgmt.ts";
|
import useAcctMgmtStore from '@/stores/acctMgmt.ts';
|
||||||
import DspLogo from '@/components/icons/DspLogo.vue';
|
import DspLogo from '@/components/icons/DspLogo.vue';
|
||||||
import AllMapDataStore from '@/stores/allMapData.js';
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
import ConformanceStore from '@/stores/conformance.js';
|
import ConformanceStore from '@/stores/conformance.js';
|
||||||
@@ -39,10 +39,23 @@ export default {
|
|||||||
const { logOut } = store;
|
const { logOut } = store;
|
||||||
const allMapDataStore = AllMapDataStore();
|
const allMapDataStore = AllMapDataStore();
|
||||||
const conformanceStore = ConformanceStore();
|
const conformanceStore = ConformanceStore();
|
||||||
|
const acctMgmtStore = useAcctMgmtStore();
|
||||||
const { tempFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore);
|
const { tempFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore);
|
||||||
const { conformanceLogTempCheckId, conformanceFilterTempCheckId, conformanceFileName } = storeToRefs(conformanceStore);
|
const { conformanceLogTempCheckId, conformanceFilterTempCheckId, conformanceFileName } = storeToRefs(conformanceStore);
|
||||||
|
|
||||||
return { logOut, temporaryData, tempFilterId, postRuleData, ruleData, conformanceLogTempCheckId, conformanceFilterTempCheckId, allMapDataStore, conformanceStore, conformanceFileName }
|
const toggleIsAcctMenuOpen = () => {
|
||||||
|
console.log('head clicked', );
|
||||||
|
acctMgmtStore.toggleIsAcctMenuOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { logOut, temporaryData, tempFilterId,
|
||||||
|
postRuleData, ruleData,
|
||||||
|
conformanceLogTempCheckId,
|
||||||
|
conformanceFilterTempCheckId,
|
||||||
|
allMapDataStore, conformanceStore,
|
||||||
|
conformanceFileName,
|
||||||
|
toggleIsAcctMenuOpen,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
DspLogo,
|
DspLogo,
|
||||||
@@ -63,10 +76,6 @@ export default {
|
|||||||
this.logOut();
|
this.logOut();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAcctHeadClick(){
|
|
||||||
this.toggleIsAcctMenuOpen();
|
|
||||||
},
|
|
||||||
...mapActions(acctMenuStore, ['toggleIsAcctMenuOpen']),
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$route.name === 'Login' || this.$route.name === 'NotFound404' ? this.showMember = false : this.showMember = true;
|
this.$route.name === 'Login' || this.$route.name === 'NotFound404' ? this.showMember = false : this.showMember = true;
|
||||||
|
|||||||
@@ -1,276 +0,0 @@
|
|||||||
import { defineStore } from "pinia";
|
|
||||||
import apiError from '@/module/apiError.js';
|
|
||||||
import { JUST_CREATE_ACCOUNT_HOT_DURATION_MINS } from '@/constants/constants.js';
|
|
||||||
|
|
||||||
export default defineStore('acctMgmtStore', {
|
|
||||||
state: () => ({
|
|
||||||
allUserAccoutList: [],
|
|
||||||
isAcctMenuOpen: false,
|
|
||||||
currentViewingUser: {
|
|
||||||
username: "",
|
|
||||||
detail: {},
|
|
||||||
},
|
|
||||||
response: {
|
|
||||||
deleteAccount: null,
|
|
||||||
},
|
|
||||||
isOneAccountJustCreate: false, //如果有一個帳號剛剛建立,則會在列表上的第一列顯示這個帳號,並且右置一個徽章
|
|
||||||
justCreateUsername: "", // unique username
|
|
||||||
shouldUpdateList: false, // 控制是否該刷新列表
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
/**
|
|
||||||
* Set related boolean to true
|
|
||||||
*/
|
|
||||||
openAcctMenu(){
|
|
||||||
this.isAcctMenuOpen = true;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Set related boolean to false
|
|
||||||
*/
|
|
||||||
closeAcctMenu(){
|
|
||||||
this.isAcctMenuOpen = false;
|
|
||||||
},
|
|
||||||
toggleIsAcctMenuOpen() {
|
|
||||||
this.isAcctMenuOpen = !this.isAcctMenuOpen;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* For convenience, set current viewing data according to unique user ID.
|
|
||||||
* @param {string} username
|
|
||||||
*/
|
|
||||||
setCurrentViewingUser(username) {
|
|
||||||
const userFind = this.allUserAccoutList.find(user => user.username === username);
|
|
||||||
this.currentViewingUser = userFind ? userFind : {};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* We have this method because we want to handle create new modal case.
|
|
||||||
*/
|
|
||||||
clearCurrentViewingUser() {
|
|
||||||
this.currentViewingUser = {
|
|
||||||
username: '',
|
|
||||||
name: '',
|
|
||||||
is_admin: false,
|
|
||||||
is_sso: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Get all user accounts
|
|
||||||
*/
|
|
||||||
async getAllUserAccounts() {
|
|
||||||
const apiGetUserList = `/api/users`;
|
|
||||||
try {
|
|
||||||
const response = await this.$axios.get(apiGetUserList);
|
|
||||||
const customizedResponseData = await this.customizeAllUserList(response.data);
|
|
||||||
this.allUserAccoutList = customizedResponseData;
|
|
||||||
} catch(error) {
|
|
||||||
apiError(error, 'Failed to get all users.');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* For example, add isHovered field
|
|
||||||
*/
|
|
||||||
async customizeAllUserList(rawResponseData){
|
|
||||||
return rawResponseData.map(user => ({
|
|
||||||
...user, // 保留後端傳來的欄位
|
|
||||||
isDeleteHovered: false, // 針對前端顯示而額外增加的欄位
|
|
||||||
isRowHovered: false,
|
|
||||||
isEditHovered: false,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Create new user in database.
|
|
||||||
* @param {object} userToCreate
|
|
||||||
* userToCreate {
|
|
||||||
* "username": "string",
|
|
||||||
* "password": "string",
|
|
||||||
* "name": "string",
|
|
||||||
* "is_admin": boolean,
|
|
||||||
* "is_active": boolean,
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
async createNewAccount(userToCreate) {
|
|
||||||
const apiCreateAccount = `/api/users`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.post(apiCreateAccount, userToCreate);
|
|
||||||
if(response.status === 200) {
|
|
||||||
this.isOneAccountJustCreate = true;
|
|
||||||
this.justCreateUsername = userToCreate.username;
|
|
||||||
setTimeout(this.resetJustCreateFlag, JUST_CREATE_ACCOUNT_HOT_DURATION_MINS * 1000 * 60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
apiError(error, 'Failed to add a new account.');
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Delete an account from database.
|
|
||||||
* @param {string} userToDelete this value is unique in database.
|
|
||||||
* @returns the result of whether the deletion is success or not.
|
|
||||||
*/
|
|
||||||
async deleteAccount(userToDelete) {
|
|
||||||
const apiDelete = `/api/users/${userToDelete}`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.delete(apiDelete);
|
|
||||||
if(response.status === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
apiError(error, 'Failed to delete the account.');
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Edit an account.
|
|
||||||
* @param {string} userToEdit this value is unique in database.
|
|
||||||
* @param {object} editDetail
|
|
||||||
*/
|
|
||||||
async editAccount(userToEdit, editDetail) {
|
|
||||||
const apiEdit = `/api/users/${userToEdit}`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.put(apiEdit, {
|
|
||||||
username: editDetail.newUsername ? editDetail.newUsername : editDetail.username,
|
|
||||||
password: editDetail.password,
|
|
||||||
name: editDetail.name,
|
|
||||||
is_active: editDetail.is_active,
|
|
||||||
});
|
|
||||||
if(response.status === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
apiError(error, 'Failed to edit the account.');
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/** Add a role to the user in database.
|
|
||||||
* @param {string} usernameToEdit
|
|
||||||
* @param {string} roleCode
|
|
||||||
*/
|
|
||||||
async addRoleToUser(usernameToEdit, roleCode) {
|
|
||||||
const apiAddRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.put(apiAddRole);
|
|
||||||
if(response.status === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
apiError(error, 'Failed to add role to the account.');
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/** Delete a role from the user in database.
|
|
||||||
* @param {string} usernameToEdit
|
|
||||||
* @param {string} roleCode
|
|
||||||
*/
|
|
||||||
async deleteRoleToUser(usernameToEdit, roleCode) {
|
|
||||||
const apiDeleteRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.delete(apiDeleteRole);
|
|
||||||
if(response.status === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
apiError(error, 'Failed to delete a role frome the account.');
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Get user detail by unique username.
|
|
||||||
* @param {string} uniqueUsername
|
|
||||||
*/
|
|
||||||
async getUserDetail(uniqueUsername) {
|
|
||||||
const apiUserDetail = `/api/users/${uniqueUsername}`;
|
|
||||||
|
|
||||||
try{
|
|
||||||
const response = await this.$axios.get(apiUserDetail);
|
|
||||||
this.currentViewingUser = {
|
|
||||||
...this.currentViewingUser,
|
|
||||||
detail: response.data,
|
|
||||||
}
|
|
||||||
if(response.status === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
//不需要跳出錯誤,因為如果是錯誤反而是好事,表示帳號是獨一的
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* According to mouseover or mouseleave status, change the bool value.
|
|
||||||
* @param {string} username
|
|
||||||
* @param {boolean} isDeleteHovered
|
|
||||||
*/
|
|
||||||
changeIsDeleteHoveredByUser(username, isDeleteHovered) {
|
|
||||||
const userToChange = this.allUserAccoutList.find(user => user.username === username);
|
|
||||||
if (userToChange) {
|
|
||||||
userToChange.isDeleteHovered = isDeleteHovered;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* According to mouseover or mouseleave status, change the bool value.
|
|
||||||
* @param {string} username
|
|
||||||
* @param {boolean} isRowHovered
|
|
||||||
*/
|
|
||||||
changeIsRowHoveredByUser(username, isRowHovered){
|
|
||||||
const userToChange = this.allUserAccoutList.find(user => user.username === username);
|
|
||||||
if (userToChange) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* According to mouseover or mouseleave status, change the bool value.
|
|
||||||
* @param {string} username
|
|
||||||
* @param {boolean} isEditHovered
|
|
||||||
*/
|
|
||||||
changeIsDetailHoveredByUser(username, isDetailHovered) {
|
|
||||||
const userToChange = this.allUserAccoutList.find(user => user.username === username);
|
|
||||||
if (userToChange) {
|
|
||||||
userToChange.isDetailHovered = isDetailHovered;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Reset isOneAccountJustCreate to false, causing the badge to disappear.
|
|
||||||
*/
|
|
||||||
resetJustCreateFlag(){
|
|
||||||
this.isOneAccountJustCreate = false;
|
|
||||||
},
|
|
||||||
/** Set the value of shouldUpdateList variable.
|
|
||||||
* @param {boolean} shouldUpdateBoolean
|
|
||||||
*/
|
|
||||||
setShouldUpdateList(shouldUpdateBoolean) {
|
|
||||||
this.shouldUpdateList = shouldUpdateBoolean;
|
|
||||||
},
|
|
||||||
/** Only update one single account in the pinia state.
|
|
||||||
* @param {object} userDataToReplace
|
|
||||||
*/
|
|
||||||
updateSingleAccountPiniaState(userDataToReplace){
|
|
||||||
const userIndex = this.allUserAccoutList.findIndex(user => user.username === userDataToReplace.username);
|
|
||||||
if (userIndex !== -1) {
|
|
||||||
this.allUserAccoutList[userIndex] = { ...this.allUserAccoutList[userIndex], ...userDataToReplace };
|
|
||||||
} else {
|
|
||||||
// Error handling here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -334,6 +334,10 @@ export default defineComponent({
|
|||||||
[inputPwd, inputConfirmPwd],
|
[inputPwd, inputConfirmPwd],
|
||||||
([newPwd, newConfirmPwd]) => {
|
([newPwd, newConfirmPwd]) => {
|
||||||
isPwdMatched.value = newPwd === newConfirmPwd && newPwd.length;
|
isPwdMatched.value = newPwd === newConfirmPwd && newPwd.length;
|
||||||
|
// 只要[確認密碼]或[密碼]有更動,confirm 按鈕就可點選
|
||||||
|
if (newPwd || newConfirmPwd) {
|
||||||
|
// isConfirmDisabled.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, ref, computed, onBeforeMount, watch, } from 'vue';
|
import { defineComponent, } from 'vue';
|
||||||
import { useModalStore } from '@/stores/modal.js';
|
import { useModalStore } from '@/stores/modal.js';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import useAcctMgmtStore from '@/stores/acctMgmt.js';
|
import useAcctMgmtStore from '@/stores/acctMgmt';
|
||||||
import i18next from '@/i18n/i18n.js';
|
import i18next from '@/i18n/i18n.js';
|
||||||
import { useToast } from 'vue-toast-notification';
|
import { useToast } from 'vue-toast-notification';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user