Add dashboard user MCU menu

This commit is contained in:
sas.fajri
2026-05-07 16:20:02 +07:00
parent 33e111b7b5
commit 5207eec99a
6 changed files with 562 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
<template>
<v-layout class="mb-2" column>
<v-dialog v-model="dialogsuccess" persistent max-width="320">
<v-card>
<v-card-title class="headline success white--text">Berhasil</v-card-title>
<v-card-text>{{ msgsuccess }}</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="closeDialogSuccess">OK</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-card>
<v-subheader red--text text--lighten-1>
DASHBOARD USER MCU
<v-spacer></v-spacer>
<v-btn small color="warning" @click="newForm">Baru</v-btn>
<v-btn small color="primary" @click="saveUser">Simpan</v-btn>
<v-btn small color="info" @click="resetPassword">Reset Password</v-btn>
</v-subheader>
<v-divider></v-divider>
<v-layout row wrap class="pa-2">
<v-flex xs12 pa-1>
<v-text-field label="Username*" v-model="username"></v-text-field>
</v-flex>
<v-flex xs12 pa-1>
<v-text-field label="Display Name" v-model="displayName"></v-text-field>
</v-flex>
<v-flex xs12 pa-1>
<v-text-field label="Password*" type="password" v-model="password"></v-text-field>
</v-flex>
<v-flex xs12 pa-1>
<v-autocomplete
v-model="selectedProject"
:items="projectItems"
:search-input.sync="projectKeyword"
item-text="label"
return-object
label="Cari Project (Nomor / Nama)"
no-filter
></v-autocomplete>
</v-flex>
<v-flex xs12 pa-1>
<v-btn small color="primary" @click="assignProject">Assign Project</v-btn>
</v-flex>
<v-flex xs12 pa-1>
<div class="caption mb-1">Project Assigned</div>
<v-chip
v-for="(p, idx) in assignedProjects"
:key="idx"
class="mr-1 mb-1"
close
@input="removeProject(p)"
>
{{ p.project_number }} - {{ p.project_name }}
</v-chip>
<div v-if="assignedProjects.length == 0" class="grey--text caption">Belum ada project</div>
</v-flex>
</v-layout>
</v-card>
</v-layout>
</template>
<script>
module.exports = {
data() {
return {
username: '',
displayName: '',
password: '',
selectedProject: null,
projectKeyword: ''
}
},
computed: {
selectedUser() { return this.$store.state.dashboard_user.selected_user || {} },
assignedProjects() { return this.selectedUser.projects || [] },
dialogsuccess() { return this.$store.state.dashboard_user.dialog_success },
msgsuccess() { return this.$store.state.dashboard_user.msg_success },
projectItems() {
return (this.$store.state.dashboard_user.project_options || []).map(p => {
return Object.assign({}, p, { label: p.project_number + ' - ' + p.project_name })
})
}
},
watch: {
selectedUser: {
deep: true,
immediate: true,
handler(val) {
this.username = val.User_Username || ''
this.displayName = val.User_DisplayName || ''
this.password = ''
}
},
projectKeyword(val) {
this.$store.dispatch('dashboard_user/search_project', { search: val || '' })
}
},
methods: {
closeDialogSuccess() {
this.$store.commit('dashboard_user/update_dialog_success', false)
this.refreshList()
},
refreshList() {
this.$store.dispatch('dashboard_user/search', {
username: this.$store.state.dashboard_user.search_username || '',
project: this.$store.state.dashboard_user.search_project && this.$store.state.dashboard_user.search_project.mcu_id ? this.$store.state.dashboard_user.search_project.mcu_id : 'all',
page: this.$store.state.dashboard_user.page || 1,
limit: this.$store.state.dashboard_user.limit || 20
})
},
validateBasic() {
if (!this.username) {
alert('Username wajib diisi')
return false
}
if (!this.password) {
alert('Password wajib diisi')
return false
}
return true
},
async saveUser() {
if (!this.validateBasic()) return
let resp = await this.$store.dispatch('dashboard_user/save', {
username: this.username,
password: this.password,
display_name: this.displayName
})
if (resp.status == 'OK') {
this.$store.commit('dashboard_user/update_selected_user', {})
} else {
alert(resp.message || 'Gagal simpan user')
}
},
async resetPassword() {
if (!this.validateBasic()) return
let resp = await this.$store.dispatch('dashboard_user/reset_password', {
username: this.username,
password: this.password
})
if (resp.status != 'OK') {
alert(resp.message || 'Gagal reset password')
}
},
async assignProject() {
if (!this.username) {
alert('Pilih atau isi username dulu')
return
}
if (!this.selectedProject || !this.selectedProject.mcu_id) {
alert('Pilih project dulu')
return
}
let resp = await this.$store.dispatch('dashboard_user/assign_project', {
username: this.username,
mcu_id: this.selectedProject.mcu_id
})
if (resp.status == 'OK') {
this.selectedProject = null
this.projectKeyword = ''
this.refreshList()
} else {
alert(resp.message || 'Gagal assign project')
}
},
async removeProject(project) {
if (!this.username || !project || !project.mcu_id) return
let resp = await this.$store.dispatch('dashboard_user/remove_project', {
username: this.username,
mcu_id: project.mcu_id
})
if (resp.status == 'OK') {
this.refreshList()
} else {
alert(resp.message || 'Gagal remove project')
}
},
newForm() {
this.$store.commit('dashboard_user/update_selected_user', {})
this.username = ''
this.displayName = ''
this.password = ''
this.selectedProject = null
this.projectKeyword = ''
}
}
}
</script>

View File

@@ -0,0 +1,115 @@
<template>
<v-layout class="fill-height" column>
<v-card class="mb-2 pa-2 searchbox">
<v-layout row wrap>
<v-flex xs5 pa-1>
<v-text-field label="Username" outline hide-details @keyup.enter="doSearch(1)" v-model="username"></v-text-field>
</v-flex>
<v-flex xs5 pa-1>
<v-autocomplete
label="Project"
outline
hide-details
return-object
item-text="label"
:items="projectItems"
:search-input.sync="projectSearch"
v-model="project"
></v-autocomplete>
</v-flex>
<v-flex xs2 pa-1>
<v-btn color="primary" block @click="doSearch(1)">Cari</v-btn>
</v-flex>
</v-layout>
</v-card>
<v-card>
<v-layout row>
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table :headers="headers" :items="users" :loading="isLoading" hide-actions class="elevation-1">
<template slot="items" slot-scope="props">
<td class="text-xs-left pa-2" @click="selectMe(props.item)" :class="{ 'amber lighten-4': isSelected(props.item) }">{{ props.item.User_Username }}</td>
<td class="text-xs-left pa-2" @click="selectMe(props.item)" :class="{ 'amber lighten-4': isSelected(props.item) }">{{ props.item.User_DisplayName || '-' }}</td>
<td class="text-xs-left pa-2" @click="selectMe(props.item)" :class="{ 'amber lighten-4': isSelected(props.item) }">
<div v-if="props.item.projects && props.item.projects.length > 0">
<div v-for="(p, idx) in props.item.projects" :key="idx">{{ p.project_number }} - {{ p.project_name }}</div>
</div>
<div v-else>-</div>
</td>
</template>
</v-data-table>
<div class="text-xs-center mt-2">
<v-pagination v-model="pageSync" :length="totalPages"></v-pagination>
</div>
</v-flex>
</v-layout>
</v-card>
</v-layout>
</template>
<script>
module.exports = {
data() {
return {
headers: [
{ text: 'USERNAME', align: 'Center', sortable: false, value: 'username', class: 'blue lighten-4' },
{ text: 'NAMA', align: 'Center', sortable: false, value: 'display_name', class: 'blue lighten-4' },
{ text: 'PROJECT', align: 'Center', sortable: false, value: 'project', class: 'blue lighten-4' }
]
}
},
mounted() {
this.doSearch(1)
},
computed: {
users() { return this.$store.state.dashboard_user.users },
isLoading() { return this.$store.state.dashboard_user.search_status == 1 },
totalPages() {
let p = this.$store.state.dashboard_user.total_pages
return p > 0 ? p : 1
},
username: {
get() { return this.$store.state.dashboard_user.search_username },
set(val) { this.$store.commit('dashboard_user/update_search_username', val) }
},
project: {
get() { return this.$store.state.dashboard_user.search_project },
set(val) { this.$store.commit('dashboard_user/update_search_project', val || { mcu_id: 'all', project_number: 'All', project_name: 'Semua Project' }) }
},
projectSearch: {
get() { return this.$store.state.dashboard_user.project_keyword },
set(val) {
this.$store.commit('dashboard_user/update_project_keyword', val)
this.$store.dispatch('dashboard_user/search_project', { search: val || '' })
}
},
projectItems() {
let base = [{ mcu_id: 'all', project_number: 'All', project_name: 'Semua Project', label: 'All - Semua Project' }]
let records = (this.$store.state.dashboard_user.project_options || []).map(p => {
return Object.assign({}, p, { label: p.project_number + ' - ' + p.project_name })
})
return base.concat(records)
},
pageSync: {
get() { return this.$store.state.dashboard_user.page },
set(val) { this.doSearch(val) }
}
},
methods: {
doSearch(page) {
this.$store.dispatch('dashboard_user/search', {
username: this.username || '',
project: this.project && this.project.mcu_id ? this.project.mcu_id : 'all',
page: page || 1,
limit: this.$store.state.dashboard_user.limit
})
},
selectMe(item) {
this.$store.commit('dashboard_user/update_selected_user', item)
},
isSelected(item) {
return this.$store.state.dashboard_user.selected_user.User_ID == item.User_ID
}
}
}
</script>