Merge pull request 'fixes #6153 desplegar test-master' (!1721) from test into master
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #1721 Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
This commit is contained in:
commit
28be9ec6a6
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [2334.01] - 2023-08-24
|
||||
|
||||
### Added
|
||||
- (General -> Errores) Botón para enviar cau con los datos del error
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
## [2332.01] - 2023-08-10
|
||||
|
||||
### Added
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
const smtp = require('vn-print/core/smtp');
|
||||
const config = require('vn-print/core/config');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('sendToSupport', {
|
||||
description: 'Send mail to support',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'reason',
|
||||
type: 'string',
|
||||
description: 'The reason'
|
||||
},
|
||||
{
|
||||
arg: 'additionalData',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'The additional data'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/send-to-support`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.sendToSupport = async(ctx, reason, additionalData) => {
|
||||
const emailUser =
|
||||
await Self.app.models.EmailUser.findById(ctx.req.accessToken.userId, {fields: ['email']});
|
||||
|
||||
let html = `<strong>Motivo</strong>:<br/>${reason}<br/>`;
|
||||
html += `<strong>Usuario</strong>:<br/>${ctx.req.accessToken.userId} ${emailUser.email}<br/>`;
|
||||
|
||||
for (const data in additionalData)
|
||||
html += `<strong>${data}</strong>:<br/>${tryParse(additionalData[data])}<br/>`;
|
||||
|
||||
const subjectReason = JSON.parse(additionalData?.httpRequest)?.data?.error;
|
||||
smtp.send({
|
||||
to: `${config.app.reportEmail}, ${emailUser.email}`,
|
||||
subject:
|
||||
'[Support-Salix] ' +
|
||||
additionalData?.frontPath + ' ' +
|
||||
subjectReason?.name + ':' +
|
||||
subjectReason?.message,
|
||||
html
|
||||
});
|
||||
};
|
||||
|
||||
function tryParse(value) {
|
||||
try {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch {}
|
||||
return JSON.stringify(value, null, ' ').split('\n').join('<br>');
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -7,6 +7,11 @@ module.exports = Self => {
|
|||
type: 'string',
|
||||
description: 'The user name or email',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'app',
|
||||
type: 'string',
|
||||
description: 'The directory for mail'
|
||||
}
|
||||
],
|
||||
http: {
|
||||
|
@ -15,7 +20,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.recoverPassword = async function(user) {
|
||||
Self.recoverPassword = async function(user, app) {
|
||||
const models = Self.app.models;
|
||||
|
||||
const usesEmail = user.indexOf('@') !== -1;
|
||||
|
@ -29,7 +34,7 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
try {
|
||||
await Self.resetPassword({email: user, emailTemplate: 'recover-password'});
|
||||
await Self.resetPassword({email: user, emailTemplate: 'recover-password', app});
|
||||
} catch (err) {
|
||||
if (err.code === 'EMAIL_NOT_FOUND')
|
||||
return;
|
||||
|
|
|
@ -53,19 +53,13 @@ module.exports = Self => {
|
|||
return Self.validateLogin(user, password);
|
||||
};
|
||||
|
||||
Self.passExpired = async(vnUser, myOptions) => {
|
||||
Self.passExpired = async vnUser => {
|
||||
const today = Date.vnNew();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) {
|
||||
const $ = Self.app.models;
|
||||
const changePasswordToken = await $.AccessToken.create({
|
||||
scopes: ['changePassword'],
|
||||
userId: vnUser.id
|
||||
}, myOptions);
|
||||
const err = new UserError('Pass expired', 'passExpired');
|
||||
changePasswordToken.twoFactor = vnUser.twoFactor ? true : false;
|
||||
err.details = {token: changePasswordToken};
|
||||
err.details = {userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false};
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/osticket/osTicketReportEmail')(Self);
|
||||
require('../methods/osticket/closeTicket')(Self);
|
||||
require('../methods/osticket/sendToSupport')(Self);
|
||||
};
|
||||
|
|
|
@ -96,11 +96,21 @@ module.exports = function(Self) {
|
|||
const headers = httpRequest.headers;
|
||||
const origin = headers.origin;
|
||||
|
||||
const defaultHash = '/reset-password?access_token=$token$';
|
||||
const recoverHashes = {
|
||||
hedera: 'verificationToken=$token$'
|
||||
};
|
||||
|
||||
const app = info.options?.app;
|
||||
let recoverHash = app ? recoverHashes[app] : defaultHash;
|
||||
recoverHash = recoverHash.replace('$token$', info.accessToken.id);
|
||||
|
||||
const user = await Self.app.models.VnUser.findById(info.user.id);
|
||||
|
||||
const params = {
|
||||
recipient: info.email,
|
||||
lang: user.lang,
|
||||
url: `${origin}/#!/reset-password?access_token=${info.accessToken.id}`
|
||||
url: origin + '/#!' + recoverHash
|
||||
};
|
||||
|
||||
const options = Object.assign({}, info.options);
|
||||
|
|
|
@ -31,7 +31,6 @@ RUN sed -i -e 's/@mockDate/'"$MOCKDATE"'/g' mockDate.sql \
|
|||
&& gosu mysql docker-structure.sh
|
||||
COPY changes ./changes
|
||||
COPY dump/fixtures.sql ./
|
||||
ARG STAMP=unknown
|
||||
RUN gosu mysql docker-fixtures.sh
|
||||
|
||||
RUN echo "[INFO] -> Import finished" \
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* Hay una versión en salix que machacará toda esta función/procedimiento avisa
|
||||
* a ___ de los cambios que quieres hacer.
|
||||
*/
|
|
@ -0,0 +1,6 @@
|
|||
UPDATE `salix`.`ACL`
|
||||
SET principalId='salesPerson'
|
||||
WHERE
|
||||
model='Ticket'
|
||||
AND property='setDeleted'
|
||||
AND accessType='WRITE';
|
|
@ -22,12 +22,8 @@ module.exports = class Docker {
|
|||
* @param {String} networkName Name of the container network
|
||||
*/
|
||||
async run(ci, networkName = 'jenkins') {
|
||||
let d = new Date();
|
||||
let pad = v => v < 10 ? '0' + v : v;
|
||||
let stamp = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||||
|
||||
log('Building container image...');
|
||||
await this.execP(`docker build --build-arg STAMP=${stamp} -t salix-db ./db`);
|
||||
await this.execP(`docker build -t salix-db ./db`);
|
||||
log('Image built.');
|
||||
|
||||
let dockerArgs;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -362,16 +362,16 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
|
|||
VALUES
|
||||
(1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street, Apartament 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist'),
|
||||
(1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist'),
|
||||
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist'),
|
||||
(1108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist'),
|
||||
(1109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'),
|
||||
(1110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'),
|
||||
(1111, 'Missing', NULL, 'Missing man', 'Anton', 'The space, Universe far away', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others'),
|
||||
(1112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city, Underground', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others');
|
||||
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist'),
|
||||
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'),
|
||||
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'),
|
||||
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others'),
|
||||
(1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, 'others');
|
||||
|
||||
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
|
||||
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1
|
||||
|
@ -2955,6 +2955,6 @@ INSERT INTO `vn`.`invoiceInSerial` (`code`, `description`, `cplusTerIdNifFk`, `t
|
|||
('W', 'Vanaheim', 1, 'WORLD');
|
||||
|
||||
|
||||
INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`)
|
||||
INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`)
|
||||
VALUES
|
||||
(1, 0, 0, 'marvel.com');
|
||||
|
|
|
@ -65,7 +65,6 @@ TABLES=(
|
|||
sample
|
||||
state
|
||||
ticketUpdateAction
|
||||
time
|
||||
volumeConfig
|
||||
workCenter
|
||||
companyI18n
|
||||
|
|
|
@ -10,7 +10,7 @@ describe('Ticket create path', () => {
|
|||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('employee', 'ticket');
|
||||
await page.loginAndModule('salesPerson', 'ticket');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
|
|
|
@ -55,3 +55,4 @@ import './datalist';
|
|||
import './contextmenu';
|
||||
import './rating';
|
||||
import './smart-table';
|
||||
import './support-dialog';
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
<div id="shapes"></div>
|
||||
<div id="shapes"></div>
|
||||
<vn-support-dialog
|
||||
vn-id="support-dialog"
|
||||
additional-data="$ctrl.additionalData">
|
||||
</vn-support-dialog>
|
||||
|
|
|
@ -27,6 +27,18 @@ export default class Controller extends Component {
|
|||
setTimeout(() => element.classList.add('shown'), 30);
|
||||
shape.element = element;
|
||||
|
||||
if (data.additionalData && this.vnToken.token) {
|
||||
this.additionalData = data.additionalData;
|
||||
let supportButton = document.createElement('i');
|
||||
supportButton.setAttribute('class', 'material-icons clickable');
|
||||
supportButton.addEventListener('click', () => this.$.supportDialog.show());
|
||||
element.appendChild(supportButton);
|
||||
|
||||
let buttonIcon = 'support_agent';
|
||||
buttonIcon = document.createTextNode(buttonIcon);
|
||||
supportButton.appendChild(buttonIcon);
|
||||
}
|
||||
|
||||
if (shape.type)
|
||||
element.classList.add(shape.type);
|
||||
|
||||
|
@ -95,7 +107,7 @@ export default class Controller extends Component {
|
|||
|
||||
clearTimeout(shape.hideTimeout);
|
||||
shape.hideTimeout = setTimeout(
|
||||
() => this.hide(shape), shape.timeout || 3000);
|
||||
() => this.hide(shape), shape.timeout || 5000);
|
||||
|
||||
this.lastShape = shape;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,15 @@ vn-snackbar .shape {
|
|||
margin-bottom: 15px;
|
||||
color: white;
|
||||
padding: 12px 25px 12px 12px;
|
||||
|
||||
display: flex ;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
& > .text {
|
||||
text-align: center;
|
||||
|
||||
vn-chip {
|
||||
vn-chip {
|
||||
position: absolute;
|
||||
left: -16px;
|
||||
top: -16px;
|
||||
|
@ -64,4 +68,12 @@ vn-snackbar .shape {
|
|||
top: 0;
|
||||
right: 0
|
||||
}
|
||||
}
|
||||
|
||||
.clickable{
|
||||
background-color: $color-main;
|
||||
padding: 6px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
margin-right: 7px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<tpl-body>
|
||||
<section>
|
||||
<h5 class="vn-py-sm" translate>Send cau</h5>
|
||||
<vn-horizontal>
|
||||
<vn-textarea vn-one
|
||||
label="ExplainReason"
|
||||
ng-model="$ctrl.reason"
|
||||
rows="2"
|
||||
required="true">
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<span>
|
||||
{{'By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.' | translate}}
|
||||
</span>
|
||||
</vn-horizontal>
|
||||
</section>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Send</button>
|
||||
</tpl-buttons>
|
|
@ -0,0 +1,30 @@
|
|||
import ngModule from '../../module';
|
||||
import Dialog from '../dialog';
|
||||
|
||||
export default class Controller extends Dialog {
|
||||
constructor($element, $, $transclude) {
|
||||
super($element, $, $transclude);
|
||||
}
|
||||
|
||||
responseHandler(response) {
|
||||
if (response !== 'accept')
|
||||
return super.responseHandler(response);
|
||||
|
||||
this.$http.post('Ostickets/send-to-support', {
|
||||
reason: this.reason,
|
||||
additionalData: this.additionalData
|
||||
})
|
||||
.then(() => super.responseHandler(response))
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Email sended!')));
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$transclude'];
|
||||
|
||||
ngModule.vnComponent('vnSupportDialog', {
|
||||
slotTemplate: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
additionalData: '<?'
|
||||
}
|
||||
});
|
|
@ -13,4 +13,5 @@ Finalize: Finalize
|
|||
Previous: Back
|
||||
Load more: Load more
|
||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search
|
||||
General search: General search
|
||||
General search: General search
|
||||
ExplainReason: Explain the reason why this error should not occur
|
||||
|
|
|
@ -64,3 +64,6 @@ No results found: Sin resultados
|
|||
No data: Sin datos
|
||||
Undo changes: Deshacer cambios
|
||||
Load more results: Cargar más resultados
|
||||
Send cau: Enviar cau
|
||||
By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
||||
ExplainReason: Explique el motivo por el que no deberia aparecer este fallo
|
||||
|
|
|
@ -23,9 +23,9 @@ export default class App {
|
|||
this.logger.showSuccess(message);
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
showError(message, additionalData) {
|
||||
if (this.logger)
|
||||
this.logger.showError(message);
|
||||
this.logger.showError(message, additionalData);
|
||||
}
|
||||
|
||||
pushLoader() {
|
||||
|
|
|
@ -60,7 +60,7 @@ export default class Token {
|
|||
if (!this.token) return;
|
||||
const created = storage.getItem('vnTokenCreated');
|
||||
this.created = created && new Date(created);
|
||||
this.renewPeriod = storage.getItem('vnTokenRenewPeriod');
|
||||
this.ttl = storage.getItem('vnTokenTtl');
|
||||
}
|
||||
|
||||
setStorage(storage, token, created, ttl) {
|
||||
|
|
|
@ -25,15 +25,15 @@ export default class App extends Component {
|
|||
}
|
||||
|
||||
showMessage(message) {
|
||||
this.$.snackbar.show({message: message});
|
||||
this.$.snackbar.show({message});
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this.$.snackbar.showSuccess({message: message});
|
||||
this.$.snackbar.showSuccess({message});
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
this.$.snackbar.showError({message: message});
|
||||
showError(message, additionalData) {
|
||||
this.$.snackbar.showError({message, additionalData});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,6 @@ export default class Controller {
|
|||
}
|
||||
|
||||
$onInit() {
|
||||
if (!this.$state.params.id)
|
||||
this.$state.go('login');
|
||||
|
||||
this.$http.get('UserPasswords/findOne')
|
||||
.then(res => {
|
||||
this.passRequirements = res.data;
|
||||
|
@ -25,7 +22,7 @@ export default class Controller {
|
|||
}
|
||||
|
||||
submit() {
|
||||
const userId = this.$state.params.userId;
|
||||
const userId = parseInt(this.$state.params.userId);
|
||||
const oldPassword = this.oldPassword;
|
||||
const newPassword = this.newPassword;
|
||||
const repeatPassword = this.repeatPassword;
|
||||
|
@ -36,18 +33,13 @@ export default class Controller {
|
|||
if (newPassword != this.repeatPassword)
|
||||
throw new UserError(`Passwords don't match`);
|
||||
|
||||
const headers = {
|
||||
Authorization: this.$state.params.id
|
||||
};
|
||||
|
||||
this.$http.patch('Accounts/change-password',
|
||||
{
|
||||
id: userId,
|
||||
userId,
|
||||
oldPassword,
|
||||
newPassword,
|
||||
code
|
||||
},
|
||||
{headers}
|
||||
}
|
||||
).then(() => {
|
||||
this.vnApp.showSuccess(this.$translate.instant('Password updated!'));
|
||||
this.$state.go('login');
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class Controller {
|
|||
|
||||
const err = req.data?.error;
|
||||
if (err?.code == 'passExpired')
|
||||
this.$state.go('change-password', err.details.token);
|
||||
this.$state.go('change-password', err.details);
|
||||
|
||||
this.loading = false;
|
||||
this.password = '';
|
||||
|
|
|
@ -148,7 +148,13 @@ function $exceptionHandler(vnApp, $window, $state, $injector) {
|
|||
|
||||
if (messageT)
|
||||
message = $translate.instant(messageT);
|
||||
vnApp.showError(message);
|
||||
|
||||
const additonalData = {
|
||||
frontPath: $state.current.name,
|
||||
httpRequest: cause?.replace('Possibly unhandled rejection: ', ''),
|
||||
backError: exception
|
||||
};
|
||||
vnApp.showError(message, additonalData);
|
||||
};
|
||||
}
|
||||
ngModule.factory('$exceptionHandler', $exceptionHandler);
|
||||
|
|
|
@ -45,7 +45,7 @@ function config($stateProvider, $urlRouterProvider) {
|
|||
})
|
||||
.state('change-password', {
|
||||
parent: 'outLayout',
|
||||
url: '/change-password?id&userId&twoFactor',
|
||||
url: '/change-password?userId&twoFactor',
|
||||
description: 'Change password',
|
||||
template: '<vn-change-password></vn-change-password>'
|
||||
})
|
||||
|
|
|
@ -179,6 +179,7 @@
|
|||
"You can not use the same password": "You can not use the same password",
|
||||
"Valid priorities": "Valid priorities: %d",
|
||||
"Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}",
|
||||
"This ticket cannot be left empty.": "This ticket cannot be left empty. %s",
|
||||
"Social name should be uppercase": "Social name should be uppercase",
|
||||
"Street should be uppercase": "Street should be uppercase",
|
||||
"You don't have enough privileges.": "You don't have enough privileges.",
|
||||
|
|
|
@ -306,6 +306,7 @@
|
|||
"Valid priorities": "Prioridades válidas: %d",
|
||||
"Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}",
|
||||
"You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado",
|
||||
"This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s",
|
||||
"The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias",
|
||||
"You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado",
|
||||
"This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado",
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('changePassword', {
|
||||
Self.remoteMethod('changePassword', {
|
||||
description: 'Changes the user password',
|
||||
accessType: 'WRITE',
|
||||
accessScopes: ['changePassword'],
|
||||
accepts: [
|
||||
{
|
||||
arg: 'userId',
|
||||
type: 'integer',
|
||||
description: 'The user id',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'oldPassword',
|
||||
type: 'string',
|
||||
description: 'The old password',
|
||||
|
@ -28,9 +31,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.changePassword = async function(ctx, oldPassword, newPassword, code, options) {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
|
||||
Self.changePassword = async function(userId, oldPassword, newPassword, code, options) {
|
||||
const myOptions = {};
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const {models} = require('vn-loopback/server/server');
|
||||
|
||||
describe('account changePassword()', () => {
|
||||
const ctx = {req: {accessToken: {userId: 70}}};
|
||||
const userId = 70;
|
||||
const unauthCtx = {
|
||||
req: {
|
||||
headers: {},
|
||||
|
@ -20,7 +20,7 @@ describe('account changePassword()', () => {
|
|||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
await models.Account.changePassword(ctx, 'wrongPassword', 'nightmare.9999', null, options);
|
||||
await models.Account.changePassword(userId, 'wrongPassword', 'nightmare.9999', null, options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
@ -37,8 +37,8 @@ describe('account changePassword()', () => {
|
|||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', null, options);
|
||||
await models.Account.changePassword(ctx, 'nightmare.9999', 'nightmare.9999', null, options);
|
||||
await models.Account.changePassword(userId, 'nightmare', 'nightmare.9999', null, options);
|
||||
await models.Account.changePassword(userId, 'nightmare.9999', 'nightmare.9999', null, options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
@ -54,7 +54,7 @@ describe('account changePassword()', () => {
|
|||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', null, options);
|
||||
await models.Account.changePassword(userId, 'nightmare', 'nightmare.9999', null, options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
@ -86,8 +86,8 @@ describe('account changePassword()', () => {
|
|||
}
|
||||
|
||||
try {
|
||||
const authCode = await models.AuthCode.findOne({where: {userFk: 70}}, options);
|
||||
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', authCode.code, options);
|
||||
const authCode = await models.AuthCode.findOne({where: {userFk: userId}}, options);
|
||||
await models.Account.changePassword(userId, 'nightmare', 'nightmare.9999', authCode.code, options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Client last active tickets', () => {
|
||||
it('should receive an array of last active tickets of Bruce Wayne', async() => {
|
||||
it('should receive an array of last active tickets of BRUCE WAYNE', async() => {
|
||||
const tx = await models.Client.beginTransaction({});
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Client transactions', () => {
|
||||
it('should call transactions() method to receive a list of Web Payments from Bruce Wayne', async() => {
|
||||
it('should call transactions() method to receive a list of Web Payments from BRUCE WAYNE', async() => {
|
||||
const tx = await models.Client.beginTransaction({});
|
||||
|
||||
try {
|
||||
|
|
|
@ -46,8 +46,6 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
deleteRoadmaps() {
|
||||
console.log(this.checked);
|
||||
|
||||
for (const roadmap of this.checked) {
|
||||
this.$http.delete(`Roadmaps/${roadmap.id}`)
|
||||
.then(() => this.$.model.refresh())
|
||||
|
|
|
@ -248,6 +248,7 @@ module.exports = Self => {
|
|||
am.name AS agencyMode,
|
||||
am.id AS agencyModeFk,
|
||||
st.name AS state,
|
||||
st.classColor,
|
||||
wk.lastName AS salesPerson,
|
||||
ts.stateFk AS stateFk,
|
||||
ts.alertLevel AS alertLevel,
|
||||
|
|
|
@ -5,6 +5,8 @@ describe('sale transferSales()', () => {
|
|||
const userId = 1101;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: userId},
|
||||
headers: {origin: ''},
|
||||
__: value => value
|
||||
};
|
||||
const ctx = {req: activeCtx};
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ module.exports = Self => {
|
|||
const userId = ctx.req.accessToken.userId;
|
||||
const models = Self.app.models;
|
||||
const myOptions = {userId};
|
||||
const $t = ctx.req.__; // $translate
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
|
@ -95,9 +96,18 @@ module.exports = Self => {
|
|||
|
||||
const isTicketEmpty = await models.Ticket.isEmpty(id, myOptions);
|
||||
if (isTicketEmpty) {
|
||||
await originalTicket.updateAttributes({
|
||||
isDeleted: true
|
||||
}, myOptions);
|
||||
try {
|
||||
await models.Ticket.setDeleted(ctx, id, myOptions);
|
||||
} catch (e) {
|
||||
if (e.statusCode === 400) {
|
||||
throw new UserError(
|
||||
`This ticket cannot be left empty.`,
|
||||
'TRANSFER_SET_DELETED',
|
||||
$t(e.message, ...e.translateArgs)
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
"code": {
|
||||
"type": "string",
|
||||
"required": false
|
||||
},
|
||||
"classColor": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "salix-back",
|
||||
"version": "23.32.02",
|
||||
"version": "23.34.01",
|
||||
"author": "Verdnatura Levante SL",
|
||||
"description": "Salix backend",
|
||||
"license": "GPL-3.0",
|
||||
|
|
Loading…
Reference in New Issue