Merge pull request 'Worker descriptor menu' (!433) from hyervoni/salix-front-mindshore:feature/WorkerDescriptorMenu into dev
Reviewed-on: #433 Reviewed-by: Javier Segarra <jsegarra@verdnatura.es> Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
fde004af3c
|
@ -13,6 +13,10 @@ const $props = defineProps({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
info: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -83,6 +87,11 @@ const inputRules = [
|
||||||
v-if="hover && value && !$attrs.disabled"
|
v-if="hover && value && !$attrs.disabled"
|
||||||
@click="value = null"
|
@click="value = null"
|
||||||
></QIcon>
|
></QIcon>
|
||||||
|
<QIcon v-if="info" name="info">
|
||||||
|
<QTooltip max-width="350px">
|
||||||
|
{{ info }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
</template>
|
</template>
|
||||||
</QInput>
|
</QInput>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
|
import FormPopup from 'src/components/FormPopup.vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['onSubmit']);
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { notify } = useNotify();
|
||||||
|
|
||||||
|
const formData = reactive({
|
||||||
|
newPassword: null,
|
||||||
|
repeatPassword: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const passRequirements = ref([]);
|
||||||
|
|
||||||
|
const setPassword = async () => {
|
||||||
|
try {
|
||||||
|
if (!formData.newPassword) {
|
||||||
|
notify(t('You must enter a new password'), 'negative');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData.newPassword != formData.repeatPassword) {
|
||||||
|
notify(t(`Passwords don't match`), 'negative');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await axios.patch(`Workers/${$props.id}/setPassword`, {
|
||||||
|
newPass: formData.newPassword,
|
||||||
|
});
|
||||||
|
notify(t('Password changed!'), 'positive');
|
||||||
|
emit('onSubmit');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error setting password', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getPassRequirements = async () => {
|
||||||
|
const { data } = await axios.get('UserPasswords/findOne');
|
||||||
|
passRequirements.value = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => await getPassRequirements());
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<FormPopup :title="t('Reset password')" @on-submit="setPassword()">
|
||||||
|
<template #form-inputs>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<VnInput
|
||||||
|
:label="t('New password')"
|
||||||
|
v-model="formData.newPassword"
|
||||||
|
type="password"
|
||||||
|
:required="true"
|
||||||
|
:info="
|
||||||
|
t('passwordRequirements', {
|
||||||
|
length: passRequirements.length,
|
||||||
|
nAlpha: passRequirements.nAlpha,
|
||||||
|
nUpper: passRequirements.nUpper,
|
||||||
|
nDigits: passRequirements.nDigits,
|
||||||
|
nPunct: passRequirements.nPunct,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow class="row q-gutter-md q-mb-md">
|
||||||
|
<VnInput
|
||||||
|
:label="t('Repeat password')"
|
||||||
|
v-model="formData.repeatPassword"
|
||||||
|
type="password"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
</template>
|
||||||
|
</FormPopup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Reset password: Restablecer contraseña
|
||||||
|
New password: Nueva contraseña
|
||||||
|
Repeat password: Repetir contraseña
|
||||||
|
You must enter a new password: Debes introducir la nueva contraseña
|
||||||
|
Passwords don't match: Las contraseñas no coinciden
|
||||||
|
</i18n>
|
|
@ -6,8 +6,10 @@ import { useSession } from 'src/composables/useSession';
|
||||||
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
||||||
|
import WorkerChangePasswordForm from 'src/pages/Worker/Card/WorkerChangePasswordForm.vue';
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -25,12 +27,16 @@ const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { getTokenMultimedia } = useSession();
|
const { getTokenMultimedia } = useSession();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
|
const user = state.getUser();
|
||||||
|
const changePasswordFormDialog = ref(null);
|
||||||
|
const cardDescriptorRef = ref(null);
|
||||||
|
|
||||||
const entityId = computed(() => {
|
const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const worker = ref();
|
const worker = ref();
|
||||||
|
const workerExcluded = ref(false);
|
||||||
const filter = {
|
const filter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -71,14 +77,44 @@ function getWorkerAvatar() {
|
||||||
const token = getTokenMultimedia();
|
const token = getTokenMultimedia();
|
||||||
return `/api/Images/user/160x160/${entityId.value}/download?access_token=${token}`;
|
return `/api/Images/user/160x160/${entityId.value}/download?access_token=${token}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = (entity) => {
|
const setData = (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
data.value = useCardDescription(entity.user.nickname, entity.id);
|
data.value = useCardDescription(entity.user.nickname, entity.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openChangePasswordForm = () => changePasswordFormDialog.value.show();
|
||||||
|
|
||||||
|
const getIsExcluded = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await axios.get(
|
||||||
|
`WorkerDisableExcludeds/${entityId.value}/exists`
|
||||||
|
);
|
||||||
|
if (!data) return;
|
||||||
|
workerExcluded.value = data.exists;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error getting worker excluded: ', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExcluded = async () => {
|
||||||
|
if (workerExcluded.value)
|
||||||
|
await axios.delete(`WorkerDisableExcludeds/${entityId.value}`);
|
||||||
|
else
|
||||||
|
await axios.post(`WorkerDisableExcludeds`, {
|
||||||
|
workerFk: entityId.value,
|
||||||
|
dated: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
workerExcluded.value = !workerExcluded.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const refetch = async () => await cardDescriptorRef.value.getData();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
|
ref="cardDescriptorRef"
|
||||||
module="Worker"
|
module="Worker"
|
||||||
data-key="workerData"
|
data-key="workerData"
|
||||||
:url="`Workers/${entityId}`"
|
:url="`Workers/${entityId}`"
|
||||||
|
@ -90,9 +126,34 @@ const setData = (entity) => {
|
||||||
(data) => {
|
(data) => {
|
||||||
worker = data;
|
worker = data;
|
||||||
setData(data);
|
setData(data);
|
||||||
|
getIsExcluded();
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<template #menu="{}">
|
||||||
|
<QItem v-ripple clickable @click="handleExcluded()">
|
||||||
|
<QItemSection>
|
||||||
|
{{
|
||||||
|
workerExcluded
|
||||||
|
? t('Click to allow the user to be disabled')
|
||||||
|
: t('Click to exclude the user from getting disabled')
|
||||||
|
}}
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="!worker.user.emailVerified && user.id != worker.id"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="openChangePasswordForm()"
|
||||||
|
>
|
||||||
|
<QItemSection>
|
||||||
|
{{ t('Change password') }}
|
||||||
|
<QDialog ref="changePasswordFormDialog">
|
||||||
|
<WorkerChangePasswordForm @on-submit="refetch()" :id="entityId" />
|
||||||
|
</QDialog>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
<template #before>
|
<template #before>
|
||||||
<QImg :src="getWorkerAvatar()" class="photo">
|
<QImg :src="getWorkerAvatar()" class="photo">
|
||||||
<template #error>
|
<template #error>
|
||||||
|
@ -139,3 +200,10 @@ const setData = (entity) => {
|
||||||
height: 256px;
|
height: 256px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Click to allow the user to be disabled: Marcar para deshabilitar
|
||||||
|
Click to exclude the user from getting disabled: Marcar para no deshabilitar
|
||||||
|
Change password: Cambiar contraseña
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
passwordRequirements: 'The password must have at least { length } length characters, {nAlpha} alphabetic characters, {nUpper} capital letters, {nDigits} digits and {nPunct} symbols (Ex: $%&.)\n'
|
|
@ -3,3 +3,4 @@ You can search by worker id or name: Puedes buscar por id o nombre del trabajado
|
||||||
Locker: Taquilla
|
Locker: Taquilla
|
||||||
Internal: Interno
|
Internal: Interno
|
||||||
External: Externo
|
External: Externo
|
||||||
|
passwordRequirements: 'La contraseña debe tener al menos { length } caracteres de longitud, {nAlpha} caracteres alfabéticos, {nUpper} letras mayúsculas, {nDigits} dígitos y {nPunct} símbolos (Ej: $%&.)'
|
||||||
|
|
Loading…
Reference in New Issue