mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 13:07:08 +00:00
Add component for editing users
This commit is contained in:
256
lib/www/client/source/src/components/user-settings.vue
Normal file
256
lib/www/client/source/src/components/user-settings.vue
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title>
|
||||||
|
User {{ name }} <v-chip class="mx-3" small>{{id}}</v-chip>
|
||||||
|
<v-chip v-if="self.id == value.id"
|
||||||
|
small
|
||||||
|
color="primary"
|
||||||
|
>It's me!</v-chip>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-subtitle>User settings</v-card-subtitle>
|
||||||
|
<v-card-text>
|
||||||
|
<v-form>
|
||||||
|
<!--
|
||||||
|
<v-text-field
|
||||||
|
label="User ID"
|
||||||
|
hint="Unique user ID (read-only)"
|
||||||
|
persistent-hint
|
||||||
|
readonly
|
||||||
|
disabled
|
||||||
|
v-model="id"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<v-switch
|
||||||
|
dense
|
||||||
|
label="Active"
|
||||||
|
:title="(self.id == value.id) ? 'You cannot make yourself inactive' : active ? 'Make this user inactive' : 'Make this user active'"
|
||||||
|
:disabled="self.id == value.id"
|
||||||
|
v-model="active"
|
||||||
|
></v-switch>
|
||||||
|
|
||||||
|
<label class="mr-3 pt-5">Colour
|
||||||
|
<v-menu v-model="colourMenu"
|
||||||
|
:close-on-content-click="false"
|
||||||
|
offset-y
|
||||||
|
>
|
||||||
|
<template v-slot:activator="{ on, attrs }">
|
||||||
|
<v-btn
|
||||||
|
:title="colour"
|
||||||
|
dense
|
||||||
|
small
|
||||||
|
icon
|
||||||
|
v-on="on"
|
||||||
|
><v-icon :color="colour">mdi-palette</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-color-picker
|
||||||
|
dot-size="25"
|
||||||
|
mode="hexa"
|
||||||
|
swatches-max-height="200"
|
||||||
|
v-model="colour"
|
||||||
|
></v-color-picker>
|
||||||
|
</v-menu>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-if="showIp || ip"
|
||||||
|
label="IP address"
|
||||||
|
hint="IP address or subnet specification for auto-login"
|
||||||
|
v-model="ip"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-if="showHost || host"
|
||||||
|
label="Host name"
|
||||||
|
hint="Hostname (for auto-login)"
|
||||||
|
v-model="host"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
label="Name"
|
||||||
|
hint="User name"
|
||||||
|
v-model="name"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
v-if="showPasswordField"
|
||||||
|
:type="visiblePassword ? 'text' : 'password'"
|
||||||
|
:append-icon="visiblePassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||||
|
@click:append="visiblePassword = !visiblePassword"
|
||||||
|
label="Password"
|
||||||
|
hint="User password"
|
||||||
|
v-model="password"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
|
||||||
|
<v-text-field
|
||||||
|
label="Email"
|
||||||
|
hint="Email address"
|
||||||
|
v-model="email"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
|
||||||
|
<v-textarea
|
||||||
|
class="mb-5"
|
||||||
|
label="Remarks"
|
||||||
|
hint="User description (visible to the user)"
|
||||||
|
auto-grow
|
||||||
|
v-model="description"
|
||||||
|
></v-textarea>
|
||||||
|
|
||||||
|
<dougal-organisations
|
||||||
|
:self="self"
|
||||||
|
:organisations.sync="organisations"
|
||||||
|
></dougal-organisations>
|
||||||
|
|
||||||
|
</v-form>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<slot name="actions" v-bind="{ isValid, hasErrors, errors, dirty }"></slot>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapGetters } from 'vuex';
|
||||||
|
import { User } from '@/lib/user';
|
||||||
|
|
||||||
|
import DougalOrganisations from './organisations'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DougalUserSettings",
|
||||||
|
|
||||||
|
components: {
|
||||||
|
DougalOrganisations
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: Object,
|
||||||
|
self: Object, // User calling the dialogue
|
||||||
|
|
||||||
|
// The next three props determine whether the
|
||||||
|
// ip, host, and password fields are shown even
|
||||||
|
// when null / empty. If non-null, those fields
|
||||||
|
// are always shown
|
||||||
|
showIp: { type: Boolean, default: false },
|
||||||
|
showHost: { type: Boolean, default: false },
|
||||||
|
showPassword: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
colourMenu: null,
|
||||||
|
visiblePassword: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
id () { return this.value.id },
|
||||||
|
|
||||||
|
ip: {
|
||||||
|
get () { return this.value.ip },
|
||||||
|
set (v) { this.input("ip", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
host: {
|
||||||
|
get () { return this.value.host },
|
||||||
|
set (v) { this.input("host", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
name: {
|
||||||
|
get () { return this.value.name },
|
||||||
|
set (v) { this.input("name", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
password: {
|
||||||
|
get () { return this.value.password },
|
||||||
|
set (v) { this.input("password", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
active: {
|
||||||
|
get () { return this.value.active },
|
||||||
|
set (v) { this.input("active", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
email: {
|
||||||
|
get () { return this.value.email },
|
||||||
|
set (v) { this.input("email", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
colour: {
|
||||||
|
get () { return this.value.colour },
|
||||||
|
set (v) { this.input("colour", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
description: {
|
||||||
|
get () { return this.value.description },
|
||||||
|
set (v) { this.input("description", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
organisations: {
|
||||||
|
get () { return this.value.organisations },
|
||||||
|
set (v) { this.input("organisations", v) }
|
||||||
|
},
|
||||||
|
|
||||||
|
errors () {
|
||||||
|
return this.value.errors;
|
||||||
|
},
|
||||||
|
|
||||||
|
hasErrors () {
|
||||||
|
return !this.isValid;
|
||||||
|
},
|
||||||
|
|
||||||
|
isValid () {
|
||||||
|
return this.value.isValid;
|
||||||
|
},
|
||||||
|
|
||||||
|
dirty () {
|
||||||
|
return this.value?.dirty ?? false;
|
||||||
|
},
|
||||||
|
|
||||||
|
showPasswordField () {
|
||||||
|
return this.password || (this.showPassword &&
|
||||||
|
!(this.showIp || this.ip || this.showHost || this.host));
|
||||||
|
},
|
||||||
|
|
||||||
|
...mapGetters(['user', 'loading', 'serverEvent'])
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
validationErrors () {
|
||||||
|
this.$emit("update:errors", this.validationErrors);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
input (k, v) {
|
||||||
|
const user = new User(this.value);
|
||||||
|
user[k] = v;
|
||||||
|
this.$emit("input", user);
|
||||||
|
},
|
||||||
|
|
||||||
|
reset () {
|
||||||
|
},
|
||||||
|
|
||||||
|
save () {
|
||||||
|
},
|
||||||
|
|
||||||
|
back () {
|
||||||
|
this.$emit('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user