Merge pull request 'fixes #3302 log front modificaciones' (!1198) from 3302-logFormat into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #1198 Reviewed-by: Javi Gallego <jgallego@verdnatura.es> Reviewed-by: Juan Ferrer <juan@verdnatura.es>
This commit is contained in:
commit
bd6935c28e
|
@ -1335,9 +1335,9 @@ INSERT INTO `vn`.`itemTypeTag`(`id`, `itemTypeFk`, `tagFk`, `priority`)
|
|||
|
||||
CALL `vn`.`itemRefreshTags`(NULL);
|
||||
|
||||
INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`)
|
||||
INSERT INTO `vn`.`itemLog` (`id`, `originFk`, `userFk`, `action`, `description`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`, `changedModelValue`)
|
||||
VALUES
|
||||
('1', '1', '1', 'insert', 'We made a change!');
|
||||
('1', '1', '1', 'insert', 'We made a change!', 'Item', '{}', '{}', 1, '1');
|
||||
|
||||
INSERT INTO `vn`.`recovery`(`id`, `clientFk`, `started`, `finished`, `amount`, `period`)
|
||||
VALUES
|
||||
|
@ -2754,6 +2754,7 @@ INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedMode
|
|||
VALUES
|
||||
(1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1);
|
||||
|
||||
|
||||
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
|
||||
VALUES
|
||||
('lilium', 'dev', 'http://localhost:8080/#/'),
|
||||
|
|
|
@ -311,10 +311,12 @@ export default {
|
|||
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
|
||||
},
|
||||
clientLog: {
|
||||
lastModificationPreviousValue: 'vn-client-log vn-table vn-td.before',
|
||||
lastModificationCurrentValue: 'vn-client-log vn-table vn-td.after',
|
||||
penultimateModificationPreviousValue: 'vn-client-log vn-table vn-tr:nth-child(2) vn-td.before',
|
||||
penultimateModificationCurrentValue: 'vn-client-log vn-table vn-tr:nth-child(2) vn-td.after'
|
||||
lastModificationPreviousValue: 'vn-client-log vn-tr table tr td.before',
|
||||
lastModificationCurrentValue: 'vn-client-log vn-tr table tr td.after',
|
||||
namePreviousValue: 'vn-client-log vn-tr table tr:nth-child(1) td.before',
|
||||
nameCurrentValue: 'vn-client-log vn-tr table tr:nth-child(1) td.after',
|
||||
activePreviousValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.before',
|
||||
activeCurrentValue: 'vn-client-log vn-tr:nth-child(2) table tr:nth-child(2) td.after'
|
||||
|
||||
},
|
||||
clientBalance: {
|
||||
|
@ -518,7 +520,7 @@ export default {
|
|||
},
|
||||
itemLog: {
|
||||
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) > vn-td > vn-one:nth-child(3) > div span:nth-child(2)',
|
||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(3) td.after',
|
||||
},
|
||||
ticketSummary: {
|
||||
header: 'vn-ticket-summary > vn-card > h5',
|
||||
|
@ -711,9 +713,10 @@ export default {
|
|||
ticketLog: {
|
||||
firstTD: 'vn-ticket-log vn-table vn-td:nth-child(1)',
|
||||
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
|
||||
firstLogEntry: 'vn-ticket-log vn-data-viewer vn-tbody vn-tr',
|
||||
changes: 'vn-ticket-log vn-data-viewer vn-tbody > vn-tr > vn-td:nth-child(7)',
|
||||
id: 'vn-ticket-log vn-tr:nth-child(1) vn-one:nth-child(1) span'
|
||||
user: 'vn-ticket-log vn-tbody vn-tr vn-td:nth-child(2)',
|
||||
action: 'vn-ticket-log vn-tbody vn-tr vn-td:nth-child(4)',
|
||||
changes: 'vn-ticket-log vn-data-viewer vn-tbody vn-tr table tr:nth-child(2) td.after',
|
||||
id: 'vn-ticket-log vn-tr:nth-child(1) table tr:nth-child(1) td.before'
|
||||
},
|
||||
ticketService: {
|
||||
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
|
||||
|
@ -1123,7 +1126,7 @@ export default {
|
|||
undoChanges: 'vn-travel-basic-data vn-button[label="Undo changes"]'
|
||||
},
|
||||
travelLog: {
|
||||
firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(1) > div'
|
||||
firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(5)'
|
||||
},
|
||||
travelThermograph: {
|
||||
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
||||
|
|
|
@ -67,22 +67,22 @@ describe('Client Edit web access path', () => {
|
|||
});
|
||||
|
||||
it(`should confirm the last log shows the updated client name and no modifications on active checkbox`, async() => {
|
||||
let lastModificationPreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText');
|
||||
let lastModificationCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');
|
||||
let namePreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.namePreviousValue, 'innerText');
|
||||
let nameCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.nameCurrentValue, 'innerText');
|
||||
|
||||
expect(lastModificationPreviousValue).toEqual('name MaxEisenhardt active false');
|
||||
expect(lastModificationCurrentValue).toEqual('name Legion active false');
|
||||
expect(namePreviousValue).toEqual('MaxEisenhardt');
|
||||
expect(nameCurrentValue).toEqual('Legion');
|
||||
});
|
||||
|
||||
it(`should confirm the penultimate log shows the updated active and no modifications on client name`, async() => {
|
||||
let penultimateModificationPreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.penultimateModificationPreviousValue, 'innerText');
|
||||
let penultimateModificationCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.penultimateModificationCurrentValue, 'innerText');
|
||||
let activePreviousValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.activePreviousValue, 'innerText');
|
||||
let activeCurrentValue = await page
|
||||
.waitToGetProperty(selectors.clientLog.activeCurrentValue, 'innerText');
|
||||
|
||||
expect(penultimateModificationPreviousValue).toEqual('name MaxEisenhardt active true');
|
||||
expect(penultimateModificationCurrentValue).toEqual('name MaxEisenhardt active false');
|
||||
expect(activePreviousValue).toEqual('✓');
|
||||
expect(activeCurrentValue).toEqual('✗');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -43,7 +43,7 @@ describe('Client log path', () => {
|
|||
let lastModificationCurrentValue = await page.
|
||||
waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');
|
||||
|
||||
expect(lastModificationPreviousValue).toEqual('name DavidCharlesHaller');
|
||||
expect(lastModificationCurrentValue).toEqual('name this is a test');
|
||||
expect(lastModificationPreviousValue).toEqual('DavidCharlesHaller');
|
||||
expect(lastModificationCurrentValue).toEqual('this is a test');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -32,14 +32,17 @@ describe('Ticket expeditions and log path', () => {
|
|||
|
||||
it(`should confirm the expedition deleted is shown now in the ticket log`, async() => {
|
||||
await page.accessToSection('ticket.card.log');
|
||||
const firstLogEntry = await page
|
||||
.waitToGetProperty(selectors.ticketLog.firstLogEntry, 'innerText');
|
||||
const user = await page
|
||||
.waitToGetProperty(selectors.ticketLog.user, 'innerText');
|
||||
|
||||
const action = await page
|
||||
.waitToGetProperty(selectors.ticketLog.action, 'innerText');
|
||||
|
||||
const id = await page
|
||||
.waitToGetProperty(selectors.ticketLog.id, 'innerText');
|
||||
|
||||
expect(firstLogEntry).toContain('production');
|
||||
expect(firstLogEntry).toContain('Deletes');
|
||||
expect(user).toContain('production');
|
||||
expect(action).toContain('Deletes');
|
||||
expect(id).toEqual('2');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -55,6 +55,6 @@ describe('Ticket log path', () => {
|
|||
|
||||
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
|
||||
|
||||
expect(result.length).toBeGreaterThan('20');
|
||||
expect(result.length).toBeGreaterThan('15');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -70,8 +70,8 @@ describe('Supplier basic data path', () => {
|
|||
});
|
||||
|
||||
it('should check the changes have been recorded', async() => {
|
||||
const result = await page.waitToGetProperty('#newInstance:nth-child(3)', 'innerText');
|
||||
const result = await page.waitToGetProperty('vn-tr table tr:nth-child(3) td.after', 'innerText');
|
||||
|
||||
expect(result).toEqual('note Some notes');
|
||||
expect(result).toEqual('Some notes');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
url="{{$ctrl.url}}"
|
||||
filter="$ctrl.filter"
|
||||
link="{originFk: $ctrl.originId}"
|
||||
where="{changedModel: $ctrl.changedModel,
|
||||
changedModelId: $ctrl.changedModelId}"
|
||||
data="$ctrl.logs"
|
||||
limit="20"
|
||||
auto-load="true">
|
||||
|
@ -13,81 +15,53 @@
|
|||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="creationDate">Date</vn-th>
|
||||
<vn-th field="userFk" class="expendable" shrink>Author</vn-th>
|
||||
<vn-th field="changedModel" class="expendable">Model</vn-th>
|
||||
<vn-th field="action" class="expendable" shrink>Action</vn-th>
|
||||
<vn-th field="changedModelValue" class="expendable">Name</vn-th>
|
||||
<vn-th expand>Before</vn-th>
|
||||
<vn-th expand>After</vn-th>
|
||||
<vn-th field="userFk" shrink>User</vn-th>
|
||||
<vn-th field="changedModel" ng-if="$ctrl.showModelName" shrink>Model</vn-th>
|
||||
<vn-th field="action" shrink>Action</vn-th>
|
||||
<vn-th field="changedModelValue" ng-if="$ctrl.showModelName">Name</vn-th>
|
||||
<vn-th expand>Changes</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="log in $ctrl.logs">
|
||||
<vn-td shrink-datetime>
|
||||
{{::log.creationDate | date:'dd/MM/yyyy HH:mm'}}
|
||||
<div class="changes">
|
||||
<div>
|
||||
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||
<span ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
|
||||
translate>{{::log.user.name || 'System' | translate}}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Model</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModel | dashIfEmpty}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Action</span><span class="label">: </span>
|
||||
<span translate class="value">{{::$ctrl.actionsText[log.action] | dashIfEmpty}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Name</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModelValue | dashIfEmpty}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
<vn-td>
|
||||
<span ng-class="{'link': log.user.worker.id, 'value': !log.user.worker.id}"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
|
||||
translate>{{::log.user.name || 'System' | translate}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
<vn-td ng-if="$ctrl.showModelName">
|
||||
{{::log.changedModel}}
|
||||
</vn-td>
|
||||
<vn-td translate class="expendable">
|
||||
<vn-td shrink translate>
|
||||
{{::$ctrl.actionsText[log.action]}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable" expand>
|
||||
<vn-td ng-if="$ctrl.showModelName">
|
||||
{{::log.changedModelValue}}
|
||||
</vn-td>
|
||||
<vn-td expand class="before">
|
||||
<vn-one ng-repeat="old in log.oldProperties">
|
||||
<div>
|
||||
<vn-label-value
|
||||
no-ellipsize
|
||||
label="{{::old.key}}"
|
||||
value="{{::old.value}}">
|
||||
</vn-label-value>
|
||||
<vn-td expand>
|
||||
<table class="attributes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th translate class="field">Field</th>
|
||||
<th translate>Before</th>
|
||||
<th translate>After</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="prop in ::log.props">
|
||||
<td class="field">{{prop.name}}</td>
|
||||
<td class="before">{{prop.old}}</td>
|
||||
<td class="after">{{prop.new}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div ng-if="log.description != null">
|
||||
{{::log.description}}
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
<vn-td expand class="after">
|
||||
<vn-one ng-repeat="new in log.newProperties" ng-if="!log.description" id="newInstance">
|
||||
<div>
|
||||
<vn-label-value
|
||||
no-ellipsize
|
||||
label="{{::new.key}}"
|
||||
value="{{::new.value}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</vn-one>
|
||||
<vn-one ng-if="!log.newProperties" id="description">
|
||||
<div>
|
||||
<span no-ellipsize>{{::log.description}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
|
|
|
@ -2,15 +2,17 @@ import ngModule from '../../module';
|
|||
import Section from '../section';
|
||||
import './style.scss';
|
||||
|
||||
const validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.actionsText = {
|
||||
'insert': 'Creates',
|
||||
'update': 'Updates',
|
||||
'delete': 'Deletes',
|
||||
'select': 'Views'
|
||||
}; ``;
|
||||
insert: 'Creates',
|
||||
update: 'Updates',
|
||||
delete: 'Deletes',
|
||||
select: 'Views'
|
||||
};
|
||||
this.filter = {
|
||||
include: [{
|
||||
relation: 'user',
|
||||
|
@ -33,32 +35,57 @@ export default class Controller extends Section {
|
|||
|
||||
set logs(value) {
|
||||
this._logs = value;
|
||||
if (!value) return;
|
||||
|
||||
if (!this.logs) return;
|
||||
const empty = {};
|
||||
const validations = window.validations;
|
||||
value.forEach(log => {
|
||||
const locale = validations[log.changedModel] && validations[log.changedModel].locale ? validations[log.changedModel].locale : {};
|
||||
for (const log of value) {
|
||||
const oldValues = log.oldInstance || empty;
|
||||
const newValues = log.newInstance || empty;
|
||||
const locale = validations[log.changedModel]?.locale || empty;
|
||||
|
||||
log.oldProperties = this.getInstance(log.oldInstance, locale);
|
||||
log.newProperties = this.getInstance(log.newInstance, locale);
|
||||
let props = Object.keys(oldValues).concat(Object.keys(newValues));
|
||||
props = [...new Set(props)];
|
||||
|
||||
log.props = [];
|
||||
for (const prop of props) {
|
||||
log.props.push({
|
||||
name: locale[prop] || prop,
|
||||
old: this.formatValue(oldValues[prop]),
|
||||
new: this.formatValue(newValues[prop])
|
||||
});
|
||||
}
|
||||
|
||||
getInstance(instance, locale) {
|
||||
const properties = [];
|
||||
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
|
||||
|
||||
if (typeof instance == 'object' && instance != null) {
|
||||
Object.keys(instance).forEach(property => {
|
||||
if (validDate.test(instance[property]))
|
||||
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
|
||||
|
||||
const key = locale[property] || property;
|
||||
properties.push({key, value: instance[property]});
|
||||
});
|
||||
return properties;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
get showModelName() {
|
||||
return !(this.changedModel && this.changedModelId);
|
||||
}
|
||||
|
||||
formatValue(value) {
|
||||
let type = typeof value;
|
||||
|
||||
if (type === 'string' && validDate.test(value)) {
|
||||
value = new Date(value);
|
||||
type = typeof value;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'boolean':
|
||||
return value ? '✓' : '✗';
|
||||
case 'object':
|
||||
if (value instanceof Date) {
|
||||
const hasZeroTime =
|
||||
value.getHours() === 0 &&
|
||||
value.getMinutes() === 0 &&
|
||||
value.getSeconds() === 0;
|
||||
const format = hasZeroTime ? 'dd/MM/yyyy' : 'dd/MM/yyyy HH:mm:ss';
|
||||
return this.$filter('date')(value, format);
|
||||
}
|
||||
else
|
||||
return value;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
showWorkerDescriptor(event, workerId) {
|
||||
|
@ -73,6 +100,8 @@ ngModule.vnComponent('vnLog', {
|
|||
bindings: {
|
||||
model: '<',
|
||||
originId: '<',
|
||||
changedModel: '<?',
|
||||
changedModelId: '<?',
|
||||
url: '@'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,3 +12,4 @@ Deletes: Elimina
|
|||
Views: Visualiza
|
||||
System: Sistema
|
||||
note: nota
|
||||
Changes: Cambios
|
||||
|
|
|
@ -23,6 +23,28 @@ vn-log {
|
|||
display: block;
|
||||
}
|
||||
}
|
||||
.attributes {
|
||||
width: 100%;
|
||||
|
||||
tr {
|
||||
height: 10px;
|
||||
|
||||
& > td {
|
||||
padding: 2px;
|
||||
}
|
||||
& > td.field,
|
||||
& > th.field {
|
||||
width: 20%;
|
||||
color: gray;
|
||||
}
|
||||
& > td.before,
|
||||
& > th.before,
|
||||
& > td.after,
|
||||
& > th.after {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ellipsis {
|
||||
white-space: nowrap;
|
||||
|
|
Loading…
Reference in New Issue