forked from verdnatura/salix-front
Merge branch 'dev' into 6825-vnTable
This commit is contained in:
commit
048685277f
|
@ -1178,6 +1178,7 @@ item:
|
|||
available: Available
|
||||
warehouseText: 'Calculated on the warehouse of { warehouseName }'
|
||||
itemDiary: Item diary
|
||||
producer: Producer
|
||||
list:
|
||||
id: Identifier
|
||||
grouping: Grouping
|
||||
|
|
|
@ -1167,6 +1167,7 @@ item:
|
|||
available: Disponible
|
||||
warehouseText: 'Calculado sobre el almacén de { warehouseName }'
|
||||
itemDiary: Registro de compra-venta
|
||||
producer: Productor
|
||||
list:
|
||||
id: Identificador
|
||||
grouping: Grouping
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<script setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const onSynchronizeAll = async () => {
|
||||
try {
|
||||
notify(t('Synchronizing in the background'), 'positive');
|
||||
await axios.patch(`Accounts/syncAll`);
|
||||
} catch (error) {
|
||||
console.error('Error synchronizing all accounts', error);
|
||||
}
|
||||
};
|
||||
|
||||
const onSynchronizeRoles = async () => {
|
||||
try {
|
||||
await axios.patch(`RoleInherits/sync`);
|
||||
notify(t('Roles synchronized!'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error synchronizing roles', error);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage>
|
||||
<VnSubToolbar />
|
||||
<FormModel
|
||||
:url="`AccountConfigs/${1}`"
|
||||
:url-update="`AccountConfigs/${1}`"
|
||||
model="AccountAccounts"
|
||||
auto-load
|
||||
>
|
||||
<template #moreActions>
|
||||
<QBtn
|
||||
class="q-ml-none"
|
||||
color="primary"
|
||||
:label="t('accounts.syncAll')"
|
||||
@click="onSynchronizeAll()"
|
||||
/>
|
||||
<QBtn
|
||||
color="primary"
|
||||
:label="t('accounts.syncRoles')"
|
||||
@click="onSynchronizeRoles()"
|
||||
/>
|
||||
</template>
|
||||
<template #form="{ data }">
|
||||
<div class="q-gutter-y-sm">
|
||||
<VnInput :label="t('accounts.homedir')" v-model="data.homedir" />
|
||||
<VnInput :label="t('accounts.shell')" v-model="data.shell" />
|
||||
<VnInput
|
||||
:label="t('accounts.idBase')"
|
||||
v-model="data.idBase"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('accounts.min')"
|
||||
v-model="data.min"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('accounts.max')"
|
||||
v-model="data.max"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('accounts.warn')"
|
||||
v-model="data.warn"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('accounts.inact')"
|
||||
v-model="data.inact"
|
||||
type="number"
|
||||
min="0"
|
||||
/>
|
||||
</VnRow>
|
||||
</div>
|
||||
</template>
|
||||
</FormModel>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Roles synchronized!: ¡Roles sincronizados!
|
||||
Synchronizing in the background: Sincronizando en segundo plano
|
||||
</i18n>
|
|
@ -8,12 +8,12 @@ import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
|||
import CardList from 'src/components/ui/CardList.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import AclFilter from './Acls/AclFilter.vue';
|
||||
import AclFormView from './Acls/AclFormView.vue';
|
||||
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import AclFormView from './Acls/AclFormView.vue';
|
||||
|
||||
defineProps({
|
||||
id: {
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const arrayData = useArrayData('AccountLdap');
|
||||
|
||||
const URL_UPDATE = `LdapConfigs/${1}`;
|
||||
const URL_CREATE = `LdapConfigs`;
|
||||
const DEFAULT_DATA = {
|
||||
id: 1,
|
||||
hasData: false,
|
||||
groupDn: null,
|
||||
password: null,
|
||||
rdn: null,
|
||||
server: null,
|
||||
userDn: null,
|
||||
};
|
||||
|
||||
const initialData = ref({
|
||||
...DEFAULT_DATA,
|
||||
});
|
||||
|
||||
const hasData = computed({
|
||||
get: () => initialData.value.hasData,
|
||||
set: (val) => {
|
||||
initialData.value.hasData = val;
|
||||
if (!val) formCustomFn.value = deleteMailForward;
|
||||
else formCustomFn.value = null;
|
||||
},
|
||||
});
|
||||
|
||||
const initialDataLoaded = ref(false);
|
||||
const formUrlCreate = ref(null);
|
||||
const formUrlUpdate = ref(null);
|
||||
const formCustomFn = ref(null);
|
||||
|
||||
const onTestConection = async () => {
|
||||
try {
|
||||
await axios.get(`LdapConfigs/test`);
|
||||
notify(t('LDAP connection established!'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error testing connection', error);
|
||||
}
|
||||
};
|
||||
|
||||
const getInitialLdapConfig = async () => {
|
||||
try {
|
||||
initialDataLoaded.value = false;
|
||||
const { data } = await axios.get(URL_UPDATE);
|
||||
initialData.value = data;
|
||||
hasData.value = true;
|
||||
return data;
|
||||
} catch (error) {
|
||||
hasData.value = false;
|
||||
arrayData.destroy();
|
||||
console.error('Error fetching initial LDAP config', error);
|
||||
return null;
|
||||
} finally {
|
||||
// Si asignamos un valor a urlUpdate, debemos asignar null a urlCreate y viceversa, ya puede causar problemas en formModel
|
||||
if (hasData.value) {
|
||||
formUrlUpdate.value = URL_UPDATE;
|
||||
formUrlCreate.value = null;
|
||||
} else {
|
||||
formUrlUpdate.value = null;
|
||||
formUrlCreate.value = URL_CREATE;
|
||||
}
|
||||
initialDataLoaded.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteMailForward = async () => {
|
||||
try {
|
||||
await axios.delete(URL_UPDATE);
|
||||
initialData.value = { ...DEFAULT_DATA };
|
||||
hasData.value = false;
|
||||
notify(t('globals.dataSaved'), 'positive');
|
||||
} catch (err) {
|
||||
console.error('Error deleting mail forward', err);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => await getInitialLdapConfig());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage>
|
||||
<VnSubToolbar />
|
||||
<FormModel
|
||||
:key="initialDataLoaded"
|
||||
model="AccountLdap"
|
||||
:form-initial-data="initialData"
|
||||
:url-create="formUrlCreate"
|
||||
:url-update="formUrlUpdate"
|
||||
:save-fn="formCustomFn"
|
||||
auto-load
|
||||
@on-data-saved="getInitialLdapConfig()"
|
||||
>
|
||||
<template #moreActions>
|
||||
<QBtn
|
||||
class="q-ml-none"
|
||||
color="primary"
|
||||
:label="t('ldap.testConnection')"
|
||||
@click="onTestConection()"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('ldap.testConnection') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow class="row q-gutter-md">
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('ldap.enableSync')"
|
||||
v-model="data.hasData"
|
||||
@update:model-value="($event) => (hasData = $event)"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<template v-if="hasData">
|
||||
<VnInput
|
||||
:label="t('ldap.server')"
|
||||
clearable
|
||||
v-model="data.server"
|
||||
:required="true"
|
||||
:rules="validate('LdapConfig.server')"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ldap.rdn')"
|
||||
clearable
|
||||
v-model="data.rdn"
|
||||
:required="true"
|
||||
:rules="validate('LdapConfig.rdn')"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('ldap.password')"
|
||||
clearable
|
||||
type="password"
|
||||
v-model="data.password"
|
||||
:required="true"
|
||||
:rules="validate('LdapConfig.password')"
|
||||
/>
|
||||
<VnInput :label="t('ldap.userDN')" clearable v-model="data.userDn" />
|
||||
<VnInput
|
||||
:label="t('ldap.groupDN')"
|
||||
clearable
|
||||
v-model="data.groupDn"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</FormModel>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
LDAP connection established!: ¡Conexión con LDAP establecida!
|
||||
</i18n>
|
|
@ -0,0 +1,187 @@
|
|||
<script setup>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
|
||||
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import axios from 'axios';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const arrayData = useArrayData('AccountSamba');
|
||||
|
||||
const formModel = ref(null);
|
||||
|
||||
const URL_UPDATE = `SambaConfigs/${1}`;
|
||||
const URL_CREATE = `SambaConfigs`;
|
||||
|
||||
const DEFAULT_DATA = {
|
||||
id: 1,
|
||||
hasData: false,
|
||||
adDomain: null,
|
||||
adController: null,
|
||||
adUser: null,
|
||||
adPassword: null,
|
||||
userDn: null,
|
||||
verifyCert: false,
|
||||
};
|
||||
|
||||
const initialData = ref({
|
||||
...DEFAULT_DATA,
|
||||
});
|
||||
|
||||
const hasData = computed({
|
||||
get: () => initialData.value.hasData,
|
||||
set: (val) => {
|
||||
initialData.value.hasData = val;
|
||||
if (!val) formCustomFn.value = deleteMailForward;
|
||||
else formCustomFn.value = null;
|
||||
},
|
||||
});
|
||||
|
||||
const initialDataLoaded = ref(false);
|
||||
const formUrlCreate = ref(null);
|
||||
const formUrlUpdate = ref(null);
|
||||
const formCustomFn = ref(null);
|
||||
|
||||
const onTestConection = async () => {
|
||||
try {
|
||||
await axios.get(`SambaConfigs/test`);
|
||||
notify(t('Samba connection established!'), 'positive');
|
||||
} catch (error) {
|
||||
console.error('Error testing connection', error);
|
||||
}
|
||||
};
|
||||
|
||||
const getInitialSambaConfig = async () => {
|
||||
try {
|
||||
initialDataLoaded.value = false;
|
||||
const { data } = await axios.get(URL_UPDATE);
|
||||
initialData.value = data;
|
||||
hasData.value = true;
|
||||
return data;
|
||||
} catch (error) {
|
||||
hasData.value = false;
|
||||
arrayData.destroy();
|
||||
console.error('Error fetching initial Samba config', error);
|
||||
return null;
|
||||
} finally {
|
||||
if (hasData.value) {
|
||||
formUrlUpdate.value = URL_UPDATE;
|
||||
formUrlCreate.value = null;
|
||||
} else {
|
||||
formUrlUpdate.value = null;
|
||||
formUrlCreate.value = URL_CREATE;
|
||||
}
|
||||
initialDataLoaded.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteMailForward = async () => {
|
||||
try {
|
||||
await axios.delete(URL_UPDATE);
|
||||
initialData.value = { ...DEFAULT_DATA };
|
||||
hasData.value = false;
|
||||
notify(t('globals.dataSaved'), 'positive');
|
||||
} catch (err) {
|
||||
console.error('Error deleting mail forward', err);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => await getInitialSambaConfig());
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage>
|
||||
<VnSubToolbar />
|
||||
<FormModel
|
||||
ref="formModel"
|
||||
:key="initialDataLoaded"
|
||||
model="AccountSamba"
|
||||
:form-initial-data="initialData"
|
||||
:url-create="formUrlCreate"
|
||||
:url-update="formUrlUpdate"
|
||||
:save-fn="formCustomFn"
|
||||
auto-load
|
||||
@on-data-saved="getInitialSambaConfig()"
|
||||
>
|
||||
<template #moreActions>
|
||||
<QBtn
|
||||
class="q-ml-none"
|
||||
color="primary"
|
||||
:label="t('samba.testConnection')"
|
||||
:disable="formModel.hasChanges"
|
||||
@click="onTestConection()"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('samba.testConnection') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
<template #form="{ data, validate }">
|
||||
<VnRow class="row q-gutter-md">
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('samba.enableSync')"
|
||||
v-model="data.hasData"
|
||||
@update:model-value="($event) => (hasData = $event)"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<template v-if="hasData">
|
||||
<VnInput
|
||||
:label="t('samba.domainAD')"
|
||||
clearable
|
||||
v-model="data.adDomain"
|
||||
:required="true"
|
||||
:rules="validate('SambaConfigs.server')"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('samba.domainController')"
|
||||
clearable
|
||||
v-model="data.adController"
|
||||
:required="true"
|
||||
:rules="validate('SambaConfigs.adController')"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('samba.userAD')"
|
||||
clearable
|
||||
v-model="data.adUser"
|
||||
:rules="validate('SambaConfigs.adUser')"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('samba.passwordAD')"
|
||||
clearable
|
||||
type="password"
|
||||
v-model="data.adPassword"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('samba.domainPart')"
|
||||
clearable
|
||||
v-model="data.userDn"
|
||||
:required="true"
|
||||
:rules="validate('SambaConfigs.userDn')"
|
||||
/>
|
||||
<QCheckbox
|
||||
:label="t('samba.verifyCertificate')"
|
||||
v-model="data.verifyCert"
|
||||
:rules="validate('SambaConfigs.groupDn')"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</FormModel>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
Samba connection established!: ¡Conexión con LDAP establecida!
|
||||
</i18n>
|
|
@ -1,11 +1,9 @@
|
|||
<script setup>
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ ldap:
|
|||
groupDN: Group DN
|
||||
testConnection: Test connection
|
||||
success: LDAP connection established!
|
||||
password: Password
|
||||
samba:
|
||||
enableSync: Enable synchronization
|
||||
domainController: Domain controller
|
||||
|
@ -78,6 +79,16 @@ samba:
|
|||
verifyCertificate: Verify certificate
|
||||
testConnection: Test connection
|
||||
success: Samba connection established!
|
||||
accounts:
|
||||
homedir: Homedir base
|
||||
shell: Shell
|
||||
idBase: User and role base id
|
||||
min: Min
|
||||
max: Max
|
||||
warn: Warn
|
||||
inact: Inact
|
||||
syncAll: Synchronize all
|
||||
syncRoles: Synchronize roles
|
||||
connections:
|
||||
refresh: Refresh
|
||||
username: Username
|
||||
|
|
|
@ -70,6 +70,7 @@ mailAlias:
|
|||
name: Nombre
|
||||
isPublic: Público
|
||||
ldap:
|
||||
password: Contraseña
|
||||
enableSync: Habilitar sincronización
|
||||
server: Servidor
|
||||
rdn: RDN
|
||||
|
@ -86,9 +87,19 @@ samba:
|
|||
userAD: Usuario AD
|
||||
passwordAD: Contraseña AD
|
||||
domainPart: DN usuarios (sin la parte del dominio)
|
||||
Verify certificate: Verificar certificado
|
||||
verifyCertificate: Verificar certificado
|
||||
testConnection: Probar conexión
|
||||
success: ¡Conexión con Samba establecida!
|
||||
accounts:
|
||||
homedir: Directorio base para carpetas de usuario
|
||||
shell: Intérprete de línea de comandos
|
||||
idBase: Id base usuarios y roles
|
||||
min: Min
|
||||
max: Max
|
||||
warn: Warn
|
||||
inact: Inact
|
||||
syncAll: Sincronizar todo
|
||||
syncRoles: Sincronizar roles
|
||||
connections:
|
||||
refresh: Actualizar
|
||||
username: Nombre de usuario
|
||||
|
|
|
@ -16,6 +16,7 @@ import useCardDescription from 'src/composables/useCardDescription';
|
|||
import { useSession } from 'src/composables/useSession';
|
||||
import { getUrl } from 'src/composables/getUrl';
|
||||
import axios from 'axios';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
|
@ -182,6 +183,10 @@ const openCloneDialog = async () => {
|
|||
</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
:label="t('item.descriptor.producer')"
|
||||
:value="dashIfEmpty(entity.subName)"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="entity.value5"
|
||||
:label="t('item.descriptor.color')"
|
||||
|
|
|
@ -460,7 +460,7 @@ onMounted(async () => {
|
|||
style="margin-left: 1px"
|
||||
/>
|
||||
</QBtnGroup>
|
||||
<QBtnGroup push class="q-gutter-x-sm" flat style="margin-left: 0px">
|
||||
<QBtnGroup push class="q-gutter-x-sm q-ml-none" flat>
|
||||
<QBtn
|
||||
v-if="reason && state && (isHimSelf || isHr)"
|
||||
:label="t('Reason')"
|
||||
|
|
|
@ -15,6 +15,9 @@ export default {
|
|||
'AccountList',
|
||||
'AccountAliasList',
|
||||
'AccountRoles',
|
||||
'AccountAccounts',
|
||||
'AccountLdap',
|
||||
'AccountSamba',
|
||||
'AccountAcls',
|
||||
'AccountConnections',
|
||||
],
|
||||
|
@ -36,6 +39,15 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Account/AccountList.vue'),
|
||||
},
|
||||
{
|
||||
path: 'role-list',
|
||||
name: 'AccountRoles',
|
||||
meta: {
|
||||
title: 'roles',
|
||||
icon: 'group',
|
||||
},
|
||||
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
|
||||
},
|
||||
{
|
||||
path: 'alias-list',
|
||||
name: 'AccountAliasList',
|
||||
|
@ -54,6 +66,36 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Account/AccountConnections.vue'),
|
||||
},
|
||||
{
|
||||
path: 'accounts',
|
||||
name: 'AccountAccounts',
|
||||
meta: {
|
||||
title: 'accounts',
|
||||
icon: 'accessibility',
|
||||
roles: ['itManagement'],
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountAccounts.vue'),
|
||||
},
|
||||
{
|
||||
path: 'ldap',
|
||||
name: 'AccountLdap',
|
||||
meta: {
|
||||
title: 'ldap',
|
||||
icon: 'account_tree',
|
||||
roles: ['itManagement'],
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountLdap.vue'),
|
||||
},
|
||||
{
|
||||
path: 'samba',
|
||||
name: 'AccountSamba',
|
||||
meta: {
|
||||
title: 'samba',
|
||||
icon: 'preview',
|
||||
roles: ['itManagement'],
|
||||
},
|
||||
component: () => import('src/pages/Account/AccountSamba.vue'),
|
||||
},
|
||||
{
|
||||
path: 'acls',
|
||||
name: 'AccountAcls',
|
||||
|
@ -68,15 +110,6 @@ export default {
|
|||
name: 'AccountAclForm',
|
||||
component: () => import('src/pages/Account/Acls/AclFormView.vue'),
|
||||
},
|
||||
{
|
||||
path: 'role-list',
|
||||
name: 'AccountRoles',
|
||||
meta: {
|
||||
title: 'roles',
|
||||
icon: 'group',
|
||||
},
|
||||
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue