Watchers performance fixes

This commit is contained in:
Juan Ferrer 2019-10-26 12:04:48 +02:00
parent 5fdfda47b2
commit 5ae558e965
18 changed files with 185 additions and 182 deletions

View File

@ -309,7 +309,7 @@ export default {
ticketSummary: {
header: 'vn-ticket-summary > vn-card > h5',
state: 'vn-ticket-summary vn-label-value[label="State"] > section > span',
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > a',
route: 'vn-ticket-summary vn-label-value[label="Route"] > section > span > a',
total: 'vn-ticket-summary vn-one.taxes > p:nth-child(3) > strong',
sale: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr',
firstSaleItemId: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',

View File

@ -1,13 +1,13 @@
describe('Component vnCheck', () => {
let $element;
let $ctrl;
let controller;
let element;
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-check></vn-check>`)($rootScope);
$ctrl = $element.controller('vnCheck');
controller = $element.controller('vnCheck');
element = $element[0];
}));
@ -17,46 +17,46 @@ describe('Component vnCheck', () => {
describe('field() setter', () => {
it(`should set model value`, () => {
$ctrl.field = true;
controller.field = true;
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should uncheck value and change to true when clicked`, () => {
$ctrl.field = false;
controller.field = false;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
controller.field = true;
element.click();
expect($ctrl.field).toEqual(false);
expect(controller.field).toEqual(false);
});
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
$ctrl.tripleState = true;
controller.field = true;
controller.tripleState = true;
element.click();
expect($ctrl.field).toEqual(false);
expect(controller.field).toEqual(false);
});
it(`should set value to null and change to true when clicked`, () => {
$ctrl.field = null;
$ctrl.tripleState = true;
controller.field = null;
controller.tripleState = true;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
it(`should cast value to boolean when clicked`, () => {
$ctrl.field = 0;
controller.field = 0;
element.click();
expect($ctrl.field).toEqual(true);
expect(controller.field).toEqual(true);
});
});
});

View File

@ -25,13 +25,10 @@ export default class DropDown extends Component {
this._activeOption = -1;
this.showLoadMore = true;
this.showFilter = true;
this.docKeyDownHandler = e => this.onDocKeyDown(e);
}
$postLink() {
super.$postLink();
this.$.list.addEventListener('scroll', e => this.onScroll(e));
}
get shown() {
@ -191,14 +188,24 @@ export default class DropDown extends Component {
}
onOpen() {
this.docKeyDownHandler = e => this.onDocKeyDown(e);
this.document.addEventListener('keydown', this.docKeyDownHandler);
this.listScrollHandler = e => this.onScroll(e);
this.$.list.addEventListener('scroll', this.listScrollHandler);
this.$.list.scrollTop = 0;
setTimeout(() => this.$.input.focus());
this.emit('open');
}
onClose() {
this.document.removeEventListener('keydown', this.docKeyDownHandler);
this.docKeyDownHandler = null;
this.$.list.removeEventListener('scroll', this.listScrollHandler);
this.listScrollHandler = null;
this.emit('close');
}

View File

@ -16,7 +16,6 @@ import './menu/menu';
import './multi-check/multi-check';
import './card/card';
import './step-control/step-control';
import './label-value/label-value';
import './pagination/pagination';
import './searchbar/searchbar';
import './scroll-up/scroll-up';
@ -34,9 +33,11 @@ import './float-button';
import './icon-menu';
import './icon-button';
import './input-number';
import './label-value';
import './range';
import './input-time';
import './input-file';
import './label';
import './list';
import './radio';
import './submit';

View File

@ -0,0 +1,9 @@
<section class="ellipsize">
<vn-label></vn-label>
<span ng-transclude></span>
<vn-icon
ng-if="::$ctrl.info != null"
icon="info_outline"
vn-tooltip="{{::$ctrl.info}}">
</vn-icon>
</section>

View File

@ -0,0 +1,54 @@
import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss';
/**
* Simple component to display a label with it's correspoding value. If @info
* property is provided it displays an aditional icon with the provided
* information.
*
* IMPORTANT!
*
* Please keep this component as simple as possible and without persistent
* watchers because it's used a lot of times in the application and could cause
* performance issues.
*
* @property {String} label The label
* @property {*} value The value
* @property {String} info Aditional information to display
*/
export default class Controller extends Component {
get label() {
return this._label;
}
set label(value) {
this._label = value;
let label = this.element.querySelector('vn-label');
label.textContent = this.$t(value);
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
let span = this.element.querySelector('span');
span.title = value;
span.textContent = value != null && value != '' ? value : '-';
}
}
ngModule.component('vnLabelValue', {
controller: Controller,
template: require('./index.html'),
transclude: true,
bindings: {
label: '@',
value: '@?',
info: '@?'
}
});

View File

@ -0,0 +1,36 @@
import './index.js';
describe('Component vnLabelValue', () => {
let $element;
let controller;
let element;
beforeEach(ngModule('vnCore'));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-label-value></vn-label-value>`)($rootScope);
controller = $element.controller('vnLabelValue');
element = $element[0];
}));
afterEach(() => {
$element.remove();
});
describe('value() setter', () => {
it(`should set the value on the span element`, () => {
const value = 'I am the value';
controller.value = value;
expect(element.querySelector('span').textContent).toEqual(value);
expect(element.querySelector('span').title).toEqual(value);
});
it(`should set a dash when no value is provided`, () => {
const value = null;
controller.value = value;
expect(element.querySelector('span').textContent).toEqual('-');
});
});
});

View File

@ -1,15 +0,0 @@
<section class="ellipsize">
<vn-label></vn-label>
<a
ng-show="$ctrl.state"
ui-sref="{{$ctrl.state}}($ctrl.stateParams)">
</a>
<span
ng-show="!$ctrl.state">
</span>
<vn-icon
ng-if="$ctrl.hasInfo"
vn-tooltip="{{$ctrl.info}}"
icon="info_outline">
</vn-icon>
</section>

View File

@ -1,70 +0,0 @@
import ngModule from '../../module';
import Component from 'core/lib/component';
import './style.scss';
export default class Controller extends Component {
constructor($element, $, $attrs) {
super($element, $);
this.hasInfo = Boolean($attrs.info);
this.info = $attrs.info || null;
}
set label(value) {
let label = this.element.querySelector('vn-label');
label.textContent = this.$t(value);
this._label = value;
}
get label() {
return this._label;
}
get state() {
return this._state;
}
set state(value) {
this._state = value;
this.applyTextContent();
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
this.applyTextContent();
}
get title() {
return this._title;
}
set title(value) {
let span = this.element.querySelector('span');
span.title = value;
this._title = value;
}
applyTextContent() {
const targetElement = this.state ? 'a' : 'span';
const element = this.element.querySelector(targetElement);
const hasValue = this.value && this.value != '';
element.title = this.value;
element.textContent = hasValue ? this.value : '-';
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnLabelValue', {
controller: Controller,
template: require('./label-value.html'),
bindings: {
title: '@?',
label: '@',
value: '@',
state: '@?',
stateParams: '<?'
}
});

View File

@ -1,38 +0,0 @@
import './label-value.js';
import template from './label-value.html';
describe('Component vnInputTime', () => {
let $element;
let controller;
beforeEach(ngModule('vnCore'));
beforeEach(angular.mock.inject($componentController => {
const $attrs = {};
$element = angular.element(`${template}`);
controller = $componentController('vnLabelValue', {$element, $attrs});
}));
describe('applyTextContent()', () => {
it(`should set the value on the span element as there's no navigation setted`, () => {
const value = 'I am the value';
controller.value = value;
controller.title = value;
controller.applyTextContent();
expect(controller.element.querySelector('span').textContent).toEqual(value);
expect(controller.element.querySelector('span').title).toEqual(value);
});
it(`should set the value on the anchor element as there's a navigation setted`, () => {
const value = 'I am the value';
controller.value = value;
controller.title = value;
controller.state = 'some.state.to.go';
controller.applyTextContent();
expect(controller.element.querySelector('a').textContent).toEqual(value);
expect(controller.element.querySelector('a').title).toEqual(value);
});
});
});

View File

@ -1,13 +1,6 @@
@import "variables";
vn-label-value > section {
& > vn-label {
color: $color-font-secondary;
&::after {
content: ':';
}
}
& > vn-icon {
vertical-align: middle;
color: $color-font-secondary;

View File

@ -0,0 +1 @@
import './style.scss';

View File

@ -0,0 +1,9 @@
@import "variables";
vn-label {
color: $color-font-secondary;
&::after {
content: ':';
}
}

View File

@ -59,16 +59,29 @@ export default class Component extends EventEmitter {
}
Component.$inject = ['$element', '$scope'];
function runFn($translate, $q, $http, vnApp, $state, $stateParams) {
function runFn($translate, $q, $http, $state, $stateParams, $timeout, $transitions, $compile, vnApp) {
Object.assign(Component.prototype, {
$translate,
$q,
$http,
vnApp,
$state,
$params: $stateParams
$params: $stateParams,
$timeout,
$transitions,
$compile,
vnApp
});
}
runFn.$inject = ['$translate', '$q', '$http', 'vnApp', '$state', '$stateParams'];
runFn.$inject = [
'$translate',
'$q',
'$http',
'$state',
'$stateParams',
'$timeout',
'$transitions',
'$compile',
'vnApp'
];
ngModule.run(runFn);

View File

@ -1,21 +1,20 @@
<div ng-if="$ctrl.$state.current.name === 'home'">
<div class="modules">
<a
ng-repeat="mod in ::$ctrl.modules"
ui-sref="{{::mod.route.state}}"
translate-attr="::{title: mod.name}"
class="vn-shadow">
<div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div>
<h4 ng-bind-html="$ctrl.getModuleName(mod)"></h4>
<span
ng-show='mod.keyBind'
vn-tooltip="Ctrl + Alt + {{mod.keyBind}}">
({{::mod.keyBind}})
</span>
<span ng-show='!mod.keyBind'>&nbsp;</span>
</a>
<a
ng-repeat="mod in ::$ctrl.modules"
ui-sref="{{::mod.route.state}}"
translate-attr="{title: mod.name}"
class="vn-shadow">
<div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div>
<h4 ng-bind-html="::$ctrl.getModuleName(mod)"></h4>
<span
ng-show="::mod.keyBind"
vn-tooltip="Ctrl + Alt + {{::mod.keyBind}}">
({{::mod.keyBind}})
</span>
<span ng-show="::!mod.keyBind">&nbsp;</span>
</a>
</div>
</div>

View File

@ -20,7 +20,7 @@
{{$root.user.nickname}}
</div>
<div class="text-secondary text-caption ellipsize">
{{$root.user.name}}
{{::$root.user.name}}
</div>
</div>
<a ui-sref="worker.card.summary({id: $root.user.workerId})">

View File

@ -22,22 +22,26 @@
<div class="vn-list">
<a
ng-repeat="client in clients track by client.id"
ui-sref="client.card.summary({ id: {{::client.id}} })"
ui-sref="client.card.summary(::{id: client.id})"
translate-attr="{title: 'View client'}"
class="vn-list-item searchResult">
<vn-horizontal ng-click="$ctrl.onClick($event)">
<vn-one>
<h6>{{::client.name}}</h6>
<vn-label-value label="Id"
<vn-label-value
label="Id"
value="{{::client.id}}">
</vn-label-value>
<vn-label-value label="Phone"
<vn-label-value
label="Phone"
value="{{::client.phone | phone}}">
</vn-label-value>
<vn-label-value label="Town/City"
<vn-label-value
label="Town/City"
value="{{::client.city}}">
</vn-label-value>
<vn-label-value label="Email"
<vn-label-value
label="Email"
value="{{::client.email}}">
</vn-label-value>
</vn-one>

View File

@ -41,10 +41,10 @@
<vn-label-value label="Landed"
value="{{$ctrl.summary.landed | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Route"
value="{{$ctrl.summary.routeFk}}"
state="route.card.summary"
state-params="{id: $ctrl.summary.routeFk}">
<vn-label-value label="Route">
<a ui-sref="route.card.summary({id: $ctrl.summary.routeFk})">
{{$ctrl.summary.routeFk}}
</a>
</vn-label-value>
<vn-label-value label="Address"
value="{{$ctrl.formattedAddress}}">