mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-21 07:49:34 +01:00
feat(web2): edit account dialog
This commit is contained in:
parent
dadf0a99dc
commit
c70e6dd64f
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
|
93
web2/src/components/UserDialog.vue
Normal file
93
web2/src/components/UserDialog.vue
Normal 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>
|
@ -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>
|
@ -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,
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user