mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 03:57:03 -04:00
132 lines
4.3 KiB
Vue
132 lines
4.3 KiB
Vue
<template>
|
|
<ListInput v-model="v" :prototype="prototype()" :group="group" :readonly="readonly" :maxitems="maxitems">
|
|
<template #default="s">
|
|
<input
|
|
v-model="s.val.username"
|
|
type="text"
|
|
class="form-control"
|
|
:placeholder="`@${$t('user.account.changeUsername.header').toLowerCase()}`"
|
|
required
|
|
@input="validateUser(s.val.username)"
|
|
@keyup="validateUser(s.val.username)"
|
|
>
|
|
<button v-if="s.val.username" :key="updateKey" type="button" :class="['btn', accountStatus(s.val.username).btn]" @click.prevent>
|
|
<Tooltip v-if="accountStatus(s.val.username).text" :text="$t(accountStatus(s.val.username).text)">
|
|
<Icon :v="accountStatus(s.val.username).icon" />
|
|
</Tooltip>
|
|
<Icon v-else :v="accountStatus(s.val.username).icon" />
|
|
</button>
|
|
<input
|
|
v-model="s.val.relationship"
|
|
type="text"
|
|
class="form-control"
|
|
:placeholder="$t('profile.circles.relationship')"
|
|
required
|
|
maxlength="64"
|
|
>
|
|
</template>
|
|
<template #validation="s">
|
|
<p v-if="validation(s.val)" class="small text-danger">
|
|
<Icon v="exclamation-triangle" />
|
|
<span class="ml-1">{{ $t(validation(s.val)) }}</span>
|
|
</p>
|
|
</template>
|
|
</ListInput>
|
|
</template>
|
|
|
|
<script>
|
|
// TODO remove duplication
|
|
const normalise = (s) => decodeURIComponent(s.trim().toLowerCase());
|
|
const normaliseWithLink = (s) => normalise(s.replace(/^@/, '').replace(new RegExp('^https://.*?/@'), ''));
|
|
|
|
export default {
|
|
props: {
|
|
modelValue: {},
|
|
group: {},
|
|
readonly: { type: Boolean },
|
|
maxitems: { default: null, type: Number },
|
|
},
|
|
emits: ['update:modelValue'],
|
|
data() {
|
|
const validateUserCache = {};
|
|
for (const connection of this.modelValue) {
|
|
validateUserCache[connection.username] = [connection.locale];
|
|
}
|
|
|
|
return {
|
|
v: this.modelValue,
|
|
validateUserHandle: undefined,
|
|
validateUserCache,
|
|
updateKey: 0,
|
|
};
|
|
},
|
|
watch: {
|
|
v() {
|
|
this.$emit('update:modelValue', this.v);
|
|
},
|
|
modelValue(v) {
|
|
this.v = v;
|
|
},
|
|
},
|
|
methods: {
|
|
prototype() {
|
|
return { username: '', relationship: '' };
|
|
},
|
|
validation(v) {
|
|
if (JSON.stringify(v) === JSON.stringify(this.prototype())) {
|
|
return null;
|
|
}
|
|
|
|
if (this.accountStatus(v.username).value === false) {
|
|
return 'profile.circles.validation.userNotFound';
|
|
}
|
|
|
|
if (!v.relationship) {
|
|
return 'profile.circles.validation.required';
|
|
}
|
|
|
|
return null;
|
|
},
|
|
validateUser(v) {
|
|
if (this.validateUserHandle) {
|
|
clearTimeout(this.validateUserHandle);
|
|
}
|
|
if (!v || Object.hasOwn(this.validateUserCache, v)) {
|
|
return;
|
|
}
|
|
this.validateUserHandle = setTimeout(async () => {
|
|
let res = await $fetch(`/api/profile/versions/${encodeURIComponent(normaliseWithLink(v))}`);
|
|
if (!Array.isArray(res)) {
|
|
console.error(res);
|
|
res = [];
|
|
}
|
|
this.validateUserCache[v] = res;
|
|
this.updateKey++;
|
|
}, 500);
|
|
},
|
|
accountStatus(v) {
|
|
if (this.validateUserCache[v] === undefined) {
|
|
return {
|
|
value: undefined,
|
|
btn: 'btn-secondary text-white border',
|
|
icon: 'spinner',
|
|
};
|
|
}
|
|
if (this.validateUserCache[v].length) {
|
|
return {
|
|
value: true,
|
|
btn: 'btn-outline-success',
|
|
icon: 'check-circle',
|
|
};
|
|
}
|
|
return {
|
|
value: false,
|
|
btn: 'btn-outline-danger',
|
|
icon: 'times-circle',
|
|
text: 'profile.circles.validation.userNotFound',
|
|
};
|
|
},
|
|
},
|
|
};
|
|
</script>
|