Skip to content

Commit a576e2c

Browse files
committed
wip
1 parent 55910ac commit a576e2c

2 files changed

Lines changed: 38 additions & 25 deletions

File tree

src/layout/EditableTitle.vue

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,82 @@ import ValidationError from '@/components/ValidationError.vue'
44
import { required } from '@vuelidate/validators'
55
import useVuelidate from '@vuelidate/core'
66
import { CheckIcon, PencilIcon, XIcon } from '@heroicons/vue/outline'
7-
import { computed, defineEmits, defineProps, reactive, ref } from 'vue'
7+
import { computed, defineEmits, defineProps, effect, ref, watchEffect } from 'vue'
88
99
const emit = defineEmits(['change'])
1010
1111
const props = defineProps({
1212
busy: Boolean,
1313
disabled: Boolean,
1414
placeholder: String,
15+
validate: [Function, Object],
1516
value: String
1617
})
1718
18-
const formState = reactive({
19-
newValue: props.value || ''
20-
})
19+
const newValue = ref('')
2120
22-
const v$ = useVuelidate({ newValue: [required] }, formState)
21+
const v$ = useVuelidate({ newValue: props.validate || { required } }, { newValue })
2322
24-
const canSave = computed(() => !v$.value.$invalid)
23+
const canSave = computed(() => !props.disabled && !v$.value.$invalid)
2524
const editing = ref(false)
26-
const inputRef = ref()
25+
const inputRef = ref(null)
26+
27+
function reset() {
28+
editing.value = false
29+
v$.value.newValue.$model = props.value || ''
30+
v$.value.$reset()
31+
}
2732
2833
function startEdit() {
2934
editing.value = true
30-
inputRef.value.focus()
3135
}
3236
33-
function stopEdit(change = true) {
37+
async function stopEdit() {
38+
if (!await v$.value.$validate()) return
39+
40+
emit('change', newValue.value)
41+
3442
editing.value = false
35-
if (change) {
36-
emit('change', formState.newValue)
37-
}
3843
}
44+
45+
effect(() => {
46+
reset()
47+
})
48+
49+
watchEffect(() => {
50+
if (inputRef.value) inputRef.value.focus()
51+
})
3952
</script>
4053

4154
<template>
4255
<div class="editable-title__container flex">
4356
<div v-if="editing">
4457
<input
4558
v-model="v$.newValue.$model"
46-
@keypress.enter="stopEdit"
59+
@keypress.enter.prevent="stopEdit"
4760
class="editable-title__value"
48-
:placeholder="value || placeholder"
49-
:ref="inputRef"
61+
:placeholder="placeholder"
62+
ref="inputRef"
5063
type="text"
5164
/>
5265
<ValidationError :errors="v$.newValue.$errors" />
5366
</div>
5467
<h1 v-else class="w-max mb-0">{{ value }}</h1>
5568

56-
<div v-if=editing class="mt-3">
69+
<div class="mt-3">
5770
<button v-if="busy" class="ml-2" disabled>
5871
<LoadingSpinner v-if="busy" />
5972
</button>
60-
<button v-else class="ml-2" @click="stopEdit" :disabled="!canSave">
73+
<button v-else-if="editing" class="ml-2" @click="stopEdit" :disabled="!canSave">
6174
<CheckIcon class="button__icon text-green hover:text-green-600" />
6275
</button>
63-
<button v-if="!busy" @click="stopEdit(false)" class="ml-2">
64-
<XIcon class="button__icon text-red hover:text-red-600" />
65-
</button>
66-
</div>
67-
<div v-else-if="!disabled" class="mt-3">
68-
<button class="ml-2" @click="startEdit">
76+
<button v-else class="ml-2" @click="startEdit" :disabled="disabled">
6977
<PencilIcon class="button__icon text-gray-400 hover:text-green" />
7078
</button>
79+
80+
<button v-if="!busy && editing" @click="reset" class="ml-2">
81+
<XIcon class="button__icon text-red hover:text-red-600" />
82+
</button>
7183
</div>
7284
</div>
7385
</template>

src/modules/vpns/views/VPN.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ import { ArrowLeftIcon } from '@heroicons/vue/outline'
66
import EditableTitle from '../../../layout/EditableTitle.vue'
77
import { useStore } from 'vuex'
88
import { RouterLink, useRoute } from 'vue-router'
9+
import { and, minLength, required } from '@vuelidate/validators'
910
import { computed, effect, ref } from 'vue'
1011
1112
const route = useRoute()
1213
const store = useStore()
1314
1415
const data = ref()
1516
const error = ref()
16-
const busy = ref(false)
1717
const loading = ref(false)
1818
19-
const server = computed(() => data.value && data.value.server)
2019
const vpn = computed(() => data.value && data.value.vpn)
2120
2221
async function reload() {
@@ -52,6 +51,8 @@ effect(() => {
5251
</div>
5352

5453
<EditableTitle
54+
placeholder="VPN name"
55+
:validate="and(required, minLength(3))"
5556
:value="vpn.name"
5657
@change="updateName"
5758
/>

0 commit comments

Comments
 (0)