feat(web2): edit account dialog

This commit is contained in:
Denis Gukov 2020-11-03 14:44:12 +05:00
parent dadf0a99dc
commit c70e6dd64f
6 changed files with 284 additions and 17 deletions

View File

@ -4,6 +4,11 @@
v-model="newProjectDialog"
/>
<UserDialog
v-model="userDialog"
:user-id="user.id"
/>
<v-snackbar
v-model="snackbar"
:color="snackbarColor"
@ -198,7 +203,7 @@
</v-list-item-content>
</v-list-item>
<v-list-item key="edit" to="/user">
<v-list-item key="edit" @click="userDialog = true">
<v-list-item-icon>
<v-icon>mdi-pencil</v-icon>
</v-list-item-icon>
@ -320,6 +325,7 @@
import axios from 'axios';
import NewProjectDialog from '@/components/NewProjectDialog.vue';
import { getErrorMessage } from '@/lib/error';
import UserDialog from '@/components/UserDialog.vue';
import EventBus from './event-bus';
const PROJECT_COLORS = [
@ -333,6 +339,7 @@ export default {
name: 'App',
components: {
NewProjectDialog,
UserDialog,
},
data() {
return {
@ -344,6 +351,7 @@ export default {
snackbarColor: '',
projects: null,
newProjectDialog: null,
userDialog: null,
};
},
@ -420,6 +428,33 @@ export default {
await this.tryToSwitchToLastProject();
});
EventBus.$on('i-user', async (e) => {
let text;
switch (e.action) {
case 'new':
text = `User ${e.item.name} created`;
break;
case 'edit':
text = `User ${e.item.name} saved`;
break;
case 'delete':
text = `User #${e.item.id} deleted`;
break;
default:
throw new Error('Unknown project action');
}
EventBus.$emit('i-snackbar', {
color: 'success',
text,
});
if (e.item.id === this.user.id) {
await this.loadUserInfo();
}
});
EventBus.$on('i-project', async (e) => {
let text;

View File

@ -73,13 +73,14 @@ export default {
async save() {
const item = await this.$refs.form.save();
if (!item) {
return;
return null;
}
EventBus.$emit('i-project', {
action: 'new',
item,
});
this.dialog = false;
return item;
},
},
};

View File

@ -85,8 +85,7 @@ export default {
/**
* Saves or creates project via API.
* Method must be wrapped to try-catch block because it can throws exception.
* @returns {Promise<null>} null if validation not passed or project data if project saved.
* @returns {Promise<null>} null if validation didn't pass or project data if project saved.
*/
async save() {
this.formError = null;

View File

@ -0,0 +1,93 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<v-dialog
v-model="dialog"
max-width="400"
persistent
:transition="false"
>
<v-card>
<v-card-title class="headline">{{ isNew ? 'New' : 'Edit' }} User</v-card-title>
<v-card-text>
<UserForm :user-id="userId" ref="form" />
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="dialog = false"
>
Cancel
</v-btn>
<v-btn
color="blue darken-1"
text
@click="save()"
>
{{ isNew ? 'Create' : 'Save' }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import UserForm from '@/components/UserForm.vue';
import EventBus from '@/event-bus';
export default {
components: { UserForm },
props: {
userId: [Number, String],
value: Boolean,
},
data() {
return {
dialog: false,
};
},
computed: {
isNew() {
return this.userId === 'new';
},
},
watch: {
async dialog(val) {
this.$emit('input', val);
if (await this.$refs.form) {
await this.$refs.form.reset();
}
},
async value(val) {
if (!val) {
this.dialog = val;
return;
}
this.dialog = val;
},
},
methods: {
async save() {
const item = await this.$refs.form.save();
if (!item) {
return null;
}
EventBus.$emit('i-user', {
action: this.isNew ? 'new' : 'edit',
item,
});
this.dialog = false;
return item;
},
},
};
</script>

View File

@ -0,0 +1,134 @@
<template>
<v-form
ref="form"
lazy-validation
v-model="formValid"
v-if="isNew || isLoaded"
>
<v-alert
:value="formError"
color="error"
class="pb-2"
>{{ formError }}</v-alert>
<v-text-field
v-model="item.name"
label="Name"
:rules="[v => !!v || 'Name is required']"
required
:disabled="formSaving"
></v-text-field>
<v-text-field
v-model="item.username"
label="Username"
:rules="[v => !!v || 'Username is required']"
required
:disabled="formSaving"
></v-text-field>
<v-text-field
v-model="item.email"
label="Email"
:rules="[v => !!v || 'Email is required']"
required
:disabled="formSaving"
></v-text-field>
<v-checkbox
v-model="item.admin"
label="Admin user"
></v-checkbox>
<v-checkbox
v-model="item.alert"
label="Send alerts"
></v-checkbox>
</v-form>
</template>
<script>
import axios from 'axios';
import { getErrorMessage } from '@/lib/error';
export default {
props: {
userId: [Number, String],
},
data() {
return {
item: null,
formValid: false,
formError: null,
formSaving: false,
};
},
async created() {
await this.loadData();
},
computed: {
isLoaded() {
return this.item != null;
},
isNew() {
return this.userId === 'new';
},
itemId() {
return this.userId;
},
},
methods: {
async reset() {
this.$refs.form.resetValidation();
await this.loadData();
},
async loadData() {
if (this.isNew) {
this.item = {};
} else {
this.item = (await axios({
method: 'get',
url: `/api/users/${this.userId}`,
responseType: 'json',
})).data;
}
},
/**
* Saves or creates user via API.
* @returns {Promise<null>} null if validation didn't pass or user data if user saved.
*/
async save() {
this.formError = null;
if (!this.$refs.form.validate()) {
return null;
}
this.formSaving = true;
let item;
try {
item = (await axios({
method: this.isNew ? 'post' : 'put',
url: this.isNew
? '/api/users'
: `/api/users/${this.userId}`,
responseType: 'json',
data: this.item,
})).data;
} catch (err) {
this.formError = getErrorMessage(err);
} finally {
this.formSaving = false;
}
return item || this.item;
},
},
};
</script>

View File

@ -1,5 +1,7 @@
<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<div v-if="items != null">
<UserDialog :user-id="itemId" v-model="editDialog" />
<v-toolbar flat color="white">
<v-btn
icon
@ -32,40 +34,43 @@
<script>
import axios from 'axios';
import EventBus from '@/event-bus';
import UserDialog from '@/components/UserDialog.vue';
export default {
components: {
UserDialog,
},
data() {
return {
headers: [
{
text: 'Alias',
value: 'alias',
},
{
text: 'Playbook',
value: 'playbook',
text: 'Name',
value: 'name',
sortable: false,
},
{
text: 'SSH key',
text: 'Username',
value: 'username',
sortable: false,
},
{
text: 'Email',
value: 'email',
sortable: false,
},
{
text: 'Inventory',
value: 'inventory',
text: 'Alert',
value: 'alert',
sortable: false,
},
{
text: 'Environment',
value: 'environment',
text: 'Admin',
value: 'admin',
sortable: false,
},
{
text: 'Repository',
value: 'repository',
text: 'External',
value: 'external',
sortable: false,
},
{