Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3291-entryLatestBuys-buscador
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
141ae7b11c
|
@ -3,9 +3,9 @@ module.exports = Self => {
|
||||||
description: 'Send email to the user',
|
description: 'Send email to the user',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'email',
|
arg: 'user',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'The email of user',
|
description: 'The user name or email',
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -15,11 +15,20 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.recoverPassword = async function(email) {
|
Self.recoverPassword = async function(user) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
|
||||||
|
const usesEmail = user.indexOf('@') !== -1;
|
||||||
|
if (!usesEmail) {
|
||||||
|
const account = await models.Account.findOne({
|
||||||
|
fields: ['email'],
|
||||||
|
where: {name: user}
|
||||||
|
});
|
||||||
|
user = account.email;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await models.user.resetPassword({email, emailTemplate: 'recover-password'});
|
await models.user.resetPassword({email: user, emailTemplate: 'recover-password'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code === 'EMAIL_NOT_FOUND')
|
if (err.code === 'EMAIL_NOT_FOUND')
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -31,7 +31,7 @@ export default {
|
||||||
},
|
},
|
||||||
recoverPassword: {
|
recoverPassword: {
|
||||||
recoverPasswordButton: 'vn-login a[ui-sref="recover-password"]',
|
recoverPasswordButton: 'vn-login a[ui-sref="recover-password"]',
|
||||||
email: 'vn-recover-password vn-textfield[ng-model="$ctrl.email"]',
|
email: 'vn-recover-password vn-textfield[ng-model="$ctrl.user"]',
|
||||||
sendEmailButton: 'vn-recover-password vn-submit',
|
sendEmailButton: 'vn-recover-password vn-submit',
|
||||||
},
|
},
|
||||||
accountIndex: {
|
accountIndex: {
|
||||||
|
@ -562,15 +562,15 @@ export default {
|
||||||
payoutBank: '.vn-dialog vn-autocomplete[ng-model="$ctrl.bankFk"]',
|
payoutBank: '.vn-dialog vn-autocomplete[ng-model="$ctrl.bankFk"]',
|
||||||
payoutDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]',
|
payoutDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]',
|
||||||
submitPayout: '.vn-dialog button[response="accept"]',
|
submitPayout: '.vn-dialog button[response="accept"]',
|
||||||
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
searchWeeklyResult: 'vn-ticket-weekly-index vn-card smart-table slot-table table tbody tr',
|
||||||
searchResultDate: 'vn-ticket-summary [label=Landed] span',
|
searchResultDate: 'vn-ticket-summary [label=Landed] span',
|
||||||
topbarSearch: 'vn-searchbar',
|
topbarSearch: 'vn-searchbar',
|
||||||
moreMenu: 'vn-ticket-index vn-icon-button[icon=more_vert]',
|
moreMenu: 'vn-ticket-index vn-icon-button[icon=more_vert]',
|
||||||
fourthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tbody vn-tr:nth-child(4)',
|
fourthWeeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(4)',
|
||||||
fiveWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tbody vn-tr:nth-child(5)',
|
fiveWeeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(5)',
|
||||||
weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr',
|
weeklyTicket: 'vn-ticket-weekly-index vn-card smart-table slot-table table tbody tr',
|
||||||
firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||||
firstWeeklyTicketAgency: 'vn-ticket-weekly-index vn-tr:nth-child(1) [ng-model="weekly.agencyModeFk"]',
|
firstWeeklyTicketAgency: 'vn-ticket-weekly-index vn-card smart-table slot-table tr:nth-child(1) [ng-model="weekly.agencyModeFk"]',
|
||||||
acceptDeleteTurn: '.vn-confirm.shown button[response="accept"]'
|
acceptDeleteTurn: '.vn-confirm.shown button[response="accept"]'
|
||||||
},
|
},
|
||||||
createTicketView: {
|
createTicketView: {
|
||||||
|
|
|
@ -26,7 +26,7 @@ describe('RecoverPassword path', async() => {
|
||||||
expect(message.text).toContain('Notification sent!');
|
expect(message.text).toContain('Notification sent!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send email', async() => {
|
it('should send email using email', async() => {
|
||||||
await page.waitForState('login');
|
await page.waitForState('login');
|
||||||
await page.waitToClick(selectors.recoverPassword.recoverPasswordButton);
|
await page.waitToClick(selectors.recoverPassword.recoverPasswordButton);
|
||||||
|
|
||||||
|
@ -37,4 +37,16 @@ describe('RecoverPassword path', async() => {
|
||||||
|
|
||||||
expect(message.text).toContain('Notification sent!');
|
expect(message.text).toContain('Notification sent!');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send email using username', async() => {
|
||||||
|
await page.waitForState('login');
|
||||||
|
await page.waitToClick(selectors.recoverPassword.recoverPasswordButton);
|
||||||
|
|
||||||
|
await page.write(selectors.recoverPassword.email, 'BruceWayne');
|
||||||
|
await page.waitToClick(selectors.recoverPassword.sendEmailButton);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
await page.waitForState('login');
|
||||||
|
|
||||||
|
expect(message.text).toContain('Notification sent!');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -478,8 +478,8 @@ export default class SmartTable extends Component {
|
||||||
|
|
||||||
const params = {q: JSON.stringify(stateFilter)};
|
const params = {q: JSON.stringify(stateFilter)};
|
||||||
|
|
||||||
this.$state.go(this.$state.current.name, params, {location: 'replace'});
|
this.$state.go(this.$state.current.name, params, {location: 'replace'})
|
||||||
this.refresh();
|
.then(() => this.refresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
applySort() {
|
applySort() {
|
||||||
|
@ -499,8 +499,8 @@ export default class SmartTable extends Component {
|
||||||
stateFilter.tableOrder = order;
|
stateFilter.tableOrder = order;
|
||||||
|
|
||||||
const params = {q: JSON.stringify(stateFilter)};
|
const params = {q: JSON.stringify(stateFilter)};
|
||||||
this.$state.go(this.$state.current.name, params, {location: 'replace'});
|
this.$state.go(this.$state.current.name, params, {location: 'replace'})
|
||||||
this.refresh();
|
.then(() => this.refresh());
|
||||||
}
|
}
|
||||||
|
|
||||||
filterSanitizer(field) {
|
filterSanitizer(field) {
|
||||||
|
@ -589,7 +589,7 @@ export default class SmartTable extends Component {
|
||||||
refresh() {
|
refresh() {
|
||||||
this.isRefreshing = true;
|
this.isRefreshing = true;
|
||||||
this.model.refresh()
|
this.model.refresh()
|
||||||
.then(() => this.isRefreshing = false);
|
.finally(() => this.isRefreshing = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ describe('Component smartTable', () => {
|
||||||
describe('applySort()', () => {
|
describe('applySort()', () => {
|
||||||
it('should call the $state go and model refresh without making changes on the model order', () => {
|
it('should call the $state go and model refresh without making changes on the model order', () => {
|
||||||
controller.$state = {
|
controller.$state = {
|
||||||
go: jest.fn(),
|
go: jest.fn().mockReturnValue(new Promise(resolve => resolve())),
|
||||||
current: {
|
current: {
|
||||||
name: 'section'
|
name: 'section'
|
||||||
}
|
}
|
||||||
|
@ -171,13 +171,12 @@ describe('Component smartTable', () => {
|
||||||
|
|
||||||
expect(controller.model.order).toBeUndefined();
|
expect(controller.model.order).toBeUndefined();
|
||||||
expect(controller.$state.go).toHaveBeenCalled();
|
expect(controller.$state.go).toHaveBeenCalled();
|
||||||
expect(controller.refresh).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call the $state go and model refresh after setting model order according to the controller sortCriteria', () => {
|
it('should call the $state go and model refresh after setting model order according to the controller sortCriteria', () => {
|
||||||
const orderBy = {field: 'myField', sortType: 'ASC'};
|
const orderBy = {field: 'myField', sortType: 'ASC'};
|
||||||
controller.$state = {
|
controller.$state = {
|
||||||
go: jest.fn(),
|
go: jest.fn().mockReturnValue(new Promise(resolve => resolve())),
|
||||||
current: {
|
current: {
|
||||||
name: 'section'
|
name: 'section'
|
||||||
}
|
}
|
||||||
|
@ -190,7 +189,6 @@ describe('Component smartTable', () => {
|
||||||
|
|
||||||
expect(controller.model.order).toEqual(`${orderBy.field} ${orderBy.sortType}`);
|
expect(controller.model.order).toEqual(`${orderBy.field} ${orderBy.sortType}`);
|
||||||
expect(controller.$state.go).toHaveBeenCalled();
|
expect(controller.$state.go).toHaveBeenCalled();
|
||||||
expect(controller.refresh).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -293,12 +291,10 @@ describe('Component smartTable', () => {
|
||||||
controller.$inputsScope = {
|
controller.$inputsScope = {
|
||||||
searchProps: {}
|
searchProps: {}
|
||||||
};
|
};
|
||||||
jest.spyOn(controller, 'refresh');
|
|
||||||
|
|
||||||
controller.defaultFilter();
|
controller.defaultFilter();
|
||||||
|
|
||||||
expect(controller.model.addFilter).toHaveBeenCalled();
|
expect(controller.model.addFilter).toHaveBeenCalled();
|
||||||
expect(controller.refresh).toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<h5 class="vn-mb-md vn-mt-lg" translate>Recover password</h5>
|
<h5 class="vn-mb-md vn-mt-lg" translate>Recover password</h5>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
label="Email"
|
label="User or recovery email"
|
||||||
ng-model="$ctrl.email"
|
ng-model="$ctrl.user"
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default class Controller {
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
const params = {
|
const params = {
|
||||||
email: this.email
|
user: this.user
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$http.post('Accounts/recoverPassword', params)
|
this.$http.post('Accounts/recoverPassword', params)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Recover password: Recuperar contraseña
|
Recover password: Recuperar contraseña
|
||||||
We will sent you an email to recover your password: Te enviaremos un correo para restablecer tu contraseña
|
We will sent you an email to recover your password: Te enviaremos un correo para restablecer tu contraseña
|
||||||
Notification sent!: ¡Notificación enviada!
|
Notification sent!: ¡Notificación enviada!
|
||||||
|
User or recovery email: Usuario o correo de recuperación
|
||||||
|
|
|
@ -17,87 +17,110 @@
|
||||||
model="model">
|
model="model">
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-portal>
|
</vn-portal>
|
||||||
<vn-data-viewer
|
<vn-card>
|
||||||
model="model"
|
<smart-table
|
||||||
class="vn-w-xl">
|
model="model"
|
||||||
<vn-card>
|
options="$ctrl.smartTableOptions"
|
||||||
<vn-table model="model">
|
view-config-id="ticketsMonitor"
|
||||||
<vn-thead>
|
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||||
<vn-tr>
|
>
|
||||||
<vn-th field="ticketFk" number>Ticket ID</vn-th>
|
<slot-actions>
|
||||||
<vn-th field="clientName">Client</vn-th>
|
<vn-check
|
||||||
<vn-th>Shipment</vn-th>
|
label="Auto-refresh"
|
||||||
<vn-th>Agency</vn-th>
|
vn-tooltip="Toggle auto-refresh every 2 minutes"
|
||||||
<vn-th>Warehouse</vn-th>
|
on-change="$ctrl.autoRefresh(value)">
|
||||||
<vn-th>Salesperson</vn-th>
|
</vn-check>
|
||||||
<vn-th shrink></vn-th>
|
</slot-actions>
|
||||||
</vn-tr>
|
<slot-table>
|
||||||
</vn-thead>
|
<table>
|
||||||
<vn-tbody>
|
<thead>
|
||||||
<vn-tr
|
<tr>
|
||||||
ng-repeat="weekly in weeklies"
|
<th field="ticketFk">
|
||||||
ui-sref="ticket.card.summary({id: {{::weekly.ticketFk}}})"
|
<span translate>Ticket ID</span>
|
||||||
class="clickable">
|
</th>
|
||||||
<vn-td number>
|
<th field="clientName">
|
||||||
<span
|
<span translate>Client</span>
|
||||||
vn-click-stop="ticketDescriptor.show($event, weekly.ticketFk)"
|
</th>
|
||||||
class="link">
|
<th field="weekDay">
|
||||||
{{weekly.ticketFk}}
|
<span translate>Shipment</span>
|
||||||
</span>
|
</th>
|
||||||
</vn-td>
|
<th field="agencyModeFk">
|
||||||
<vn-td>
|
<span translate>Agency</span>
|
||||||
<span
|
</th>
|
||||||
vn-click-stop="clientDescriptor.show($event, weekly.clientFk)"
|
<th field="warehouseFk">
|
||||||
title ="{{::weekly.clientName}}"
|
<span translate>Warehouse</span>
|
||||||
class="link">
|
</th>
|
||||||
{{::weekly.clientName}}
|
<th field="nickName">
|
||||||
</span>
|
<span translate>Salesperson</span>
|
||||||
</vn-td>
|
</th>
|
||||||
<vn-td vn-click-stop>
|
</tr>
|
||||||
<vn-autocomplete
|
</thead>
|
||||||
vn-id="weekday"
|
<tbody>
|
||||||
ng-model="weekly.weekDay"
|
<tr
|
||||||
data="$ctrl.weekdays"
|
ng-repeat="weekly in weeklies"
|
||||||
show-field="name"
|
ui-sref="ticket.card.summary({id: {{::weekly.ticketFk}}})"
|
||||||
translate-fields="['name']"
|
class="clickable">
|
||||||
value-field="id"
|
<td number>
|
||||||
on-change="$ctrl.onUpdate(weekly.ticketFk, 'weekDay', value)"
|
<span
|
||||||
order="id"
|
vn-click-stop="ticketDescriptor.show($event, weekly.ticketFk)"
|
||||||
class="dense">
|
class="link">
|
||||||
</vn-autocomplete>
|
{{weekly.ticketFk}}
|
||||||
</vn-td>
|
</span>
|
||||||
<vn-td vn-click-stop>
|
</td>
|
||||||
<vn-autocomplete
|
<td>
|
||||||
vn-id="agencyMode"
|
<span
|
||||||
ng-model="weekly.agencyModeFk"
|
vn-click-stop="clientDescriptor.show($event, weekly.clientFk)"
|
||||||
url="AgencyModes/isActive"
|
title ="{{::weekly.clientName}}"
|
||||||
show-field="name"
|
class="link">
|
||||||
value-field="id"
|
{{::weekly.clientName}}
|
||||||
on-change="$ctrl.onUpdate(weekly.ticketFk, 'agencyModeFk', value)"
|
</span>
|
||||||
order="name"
|
</td>
|
||||||
class="dense">
|
<td vn-click-stop>
|
||||||
</vn-autocomplete>
|
<vn-autocomplete
|
||||||
</vn-td>
|
vn-id="weekday"
|
||||||
<vn-td>{{::weekly.warehouseName}}</vn-td>
|
ng-model="weekly.weekDay"
|
||||||
<vn-td>
|
data="$ctrl.weekdays"
|
||||||
<span
|
show-field="name"
|
||||||
vn-click-stop="workerDescriptor.show($event, weekly.workerFk)"
|
translate-fields="['name']"
|
||||||
class="link" >
|
value-field="id"
|
||||||
{{::weekly.userName}}
|
on-change="$ctrl.onUpdate(weekly.ticketFk, 'weekDay', value)"
|
||||||
</span>
|
order="id"
|
||||||
</vn-td>
|
class="dense">
|
||||||
<vn-td shrink>
|
</vn-autocomplete>
|
||||||
<vn-icon-button
|
</td>
|
||||||
icon="delete"
|
<td vn-click-stop>
|
||||||
vn-click-stop="deleteWeekly.show(weekly.ticketFk)"
|
<vn-autocomplete
|
||||||
vn-tooltip="Delete">
|
vn-id="agencyMode"
|
||||||
</vn-icon-button>
|
ng-model="weekly.agencyModeFk"
|
||||||
</vn-td>
|
url="AgencyModes/isActive"
|
||||||
</vn-tr>
|
show-field="name"
|
||||||
</vn-tbody>
|
value-field="id"
|
||||||
</vn-table>
|
on-change="$ctrl.onUpdate(weekly.ticketFk, 'agencyModeFk', value)"
|
||||||
</vn-card>
|
order="name"
|
||||||
</vn-data-viewer>
|
class="dense">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</td>
|
||||||
|
<td vn-click-stop>{{weekly.warehouseName}}</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
vn-click-stop="workerDescriptor.show($event, weekly.workerFk)"
|
||||||
|
class="link" >
|
||||||
|
{{::weekly.userName}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td shrink>
|
||||||
|
<vn-icon-button
|
||||||
|
icon="delete"
|
||||||
|
vn-click-stop="deleteWeekly.show(weekly.ticketFk)"
|
||||||
|
vn-tooltip="Delete">
|
||||||
|
</vn-icon-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</slot-table>
|
||||||
|
</smart-table>
|
||||||
|
</vn-card>
|
||||||
<vn-client-descriptor-popover
|
<vn-client-descriptor-popover
|
||||||
vn-id="clientDescriptor">
|
vn-id="clientDescriptor">
|
||||||
</vn-client-descriptor-popover>
|
</vn-client-descriptor-popover>
|
||||||
|
@ -112,4 +135,4 @@
|
||||||
on-accept="$ctrl.onDeleteWeeklyAccept($data)"
|
on-accept="$ctrl.onDeleteWeeklyAccept($data)"
|
||||||
question="This ticket will be removed from weekly tickets! Continue anyway?"
|
question="This ticket will be removed from weekly tickets! Continue anyway?"
|
||||||
message="You are going to delete this weekly ticket">
|
message="You are going to delete this weekly ticket">
|
||||||
</vn-confirm>
|
</vn-confirm>
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
|
@ -15,6 +16,44 @@ export default class Controller extends Section {
|
||||||
{id: 5, name: 'Saturday'},
|
{id: 5, name: 'Saturday'},
|
||||||
{id: 6, name: 'Sunday'}
|
{id: 6, name: 'Sunday'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.smartTableOptions = {
|
||||||
|
activeButtons: {
|
||||||
|
search: true,
|
||||||
|
shownColumns: true,
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'ticketFk',
|
||||||
|
searchable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'clientName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'weekDay',
|
||||||
|
searchable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'agencyModeFk',
|
||||||
|
searchable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'warehouseFk',
|
||||||
|
searchable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'nickname',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exprBuilder(param, value) {
|
||||||
|
switch (param) {
|
||||||
|
case 'clientName': return {'c.name': value};
|
||||||
|
case 'nickName': return {'u.name': value};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdate(ticketFk, field, value) {
|
onUpdate(ticketFk, field, value) {
|
||||||
|
|
Loading…
Reference in New Issue