#1882 First step, front tests passed
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Juan Ferrer 2020-04-25 11:50:04 +02:00
parent 139fb786d6
commit 5826099601
130 changed files with 1039 additions and 2112 deletions

View File

@ -1,10 +1,10 @@
<div> <tpl-title translate>
<tpl-body> {{::$ctrl.message}}
<h6 translate>{{::$ctrl.message}}</h6> </tpl-title>
<span translate>{{::$ctrl.question}}</span> <tpl-body translate>
</tpl-body> {{::$ctrl.question}}
<tpl-buttons> </tpl-body>
<button response="cancel" translate>Cancel</button> <tpl-buttons>
<button response="accept" translate vn-focus>Accept</button> <button response="cancel" translate>Cancel</button>
</tpl-buttons> <button response="accept" translate vn-focus>Accept</button>
</div> </tpl-buttons>

View File

@ -1,18 +1,12 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Dialog from '../dialog'; import Dialog from '../dialog';
import template from './confirm.html';
import './style.scss'; import './style.scss';
export default class Confirm extends Dialog { export default class Confirm extends Dialog {}
constructor($element, $, $transclude) {
super($element, $, $transclude);
this.fillSlots(template);
}
}
ngModule.vnComponent('vnConfirm', { ngModule.vnComponent('vnConfirm', {
slotTemplate: require('./confirm.html'),
controller: Confirm, controller: Confirm,
transclude: true,
bindings: { bindings: {
question: '@', question: '@',
message: '@?' message: '@?'

View File

@ -1,22 +1,28 @@
<div <default>
ng-if="$ctrl.loading"
class="loading-overlap shown">
<vn-spinner enable="true"></vn-spinner>
</div>
<vn-button
ng-click="$ctrl.hide()"
translate-attr="{title: 'Close'}"
icon="clear"
class="flat close">
</vn-button>
<form>
<div <div
class="body" ng-if="$ctrl.loading"
ng-transclude="body"> class="loading-overlap shown">
<vn-spinner enable="true"></vn-spinner>
</div> </div>
<div <vn-button
class="buttons" ng-click="$ctrl.hide()"
ng-click="$ctrl.onButtonClick($event)" translate-attr="{title: 'Close'}"
ng-transclude="buttons"> icon="clear"
</div> class="flat close">
</form> </vn-button>
<form>
<h6
ng-if="::$ctrl.$transclude.isSlotFilled('title')"
ng-transclude="title">
</h6>
<div
class="body"
ng-transclude="body">
</div>
<div
class="buttons"
ng-click="$ctrl.onButtonClick($event)"
ng-transclude="buttons">
</div>
</form>
</default>

View File

@ -1,6 +1,5 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Popup from '../popup'; import Popup from '../popup';
import template from './index.html';
import './style.scss'; import './style.scss';
/** /**
@ -16,22 +15,6 @@ import './style.scss';
* @slot buttons The dialog HTML buttons * @slot buttons The dialog HTML buttons
*/ */
export default class Dialog extends Popup { export default class Dialog extends Popup {
constructor($element, $, $transclude) {
super($element, $, $transclude);
this.fillDefaultSlot(template);
}
/**
* Fills the dialog slots, it is intended to be used by child classes.
*
* @param {String} template The HTML template string
*/
fillSlots(template) {
let $template = angular.element(template);
this.fillSlot('body', $template.find('tpl-body'));
this.fillSlot('buttons', $template.find('tpl-buttons'));
}
/** /**
* Shows the dialog and optionally registers a handler for the response. * Shows the dialog and optionally registers a handler for the response.
* *
@ -149,9 +132,11 @@ export default class Dialog extends Popup {
} }
ngModule.vnComponent('vnDialog', { ngModule.vnComponent('vnDialog', {
slotTemplate: require('./index.html'),
controller: Dialog, controller: Dialog,
transclude: { transclude: {
body: 'tplBody', title: '?tplTitle',
body: '?tplBody',
buttons: '?tplButtons' buttons: '?tplButtons'
}, },
bindings: { bindings: {

View File

@ -18,6 +18,9 @@
& > form { & > form {
padding: $spacing-lg; padding: $spacing-lg;
& > h6 {
margin-bottom: $spacing-md;
}
& > .body > tpl-body { & > .body > tpl-body {
display: block; display: block;
min-width: 256px; min-width: 256px;

View File

@ -1,22 +1,24 @@
<div ng-show="$ctrl.showFilter" class="filter"> <default>
<vn-textfield <div ng-show="$ctrl.showFilter" class="filter">
ng-model="$ctrl.search" <vn-textfield
class="dense search" ng-model="$ctrl.search"
ng-blur="$ctrl.onFocusOut()" class="dense search"
placeholder="{{::'Search' | translate}}" ng-blur="$ctrl.onFocusOut()"
autocomplete="off"> placeholder="{{::'Search' | translate}}"
</vn-textfield> autocomplete="off">
</div> </vn-textfield>
<div class="list" tabindex="-1">
<ul
class="dropdown"
ng-click="$ctrl.onContainerClick($event)">
</ul>
<div
ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div> </div>
</div> <div class="list" tabindex="-1">
<ul
class="dropdown"
ng-click="$ctrl.onContainerClick($event)">
</ul>
<div
ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div>
</div>
</default>

View File

@ -1,7 +1,6 @@
import './style.scss'; import './style.scss';
import ngModule from '../../module'; import ngModule from '../../module';
import Popover from '../popover'; import Popover from '../popover';
import template from './index.html';
import ArrayModel from '../array-model/array-model'; import ArrayModel from '../array-model/array-model';
import CrudModel from '../crud-model/crud-model'; import CrudModel from '../crud-model/crud-model';
import {mergeWhere} from 'vn-loopback/util/filter'; import {mergeWhere} from 'vn-loopback/util/filter';
@ -21,7 +20,6 @@ export default class DropDown extends Popover {
this.showLoadMore = true; this.showLoadMore = true;
this.showFilter = true; this.showFilter = true;
this.searchDelay = 300; this.searchDelay = 300;
this.fillDefaultSlot(template);
} }
get search() { get search() {
@ -458,6 +456,7 @@ function getPosition(parent, event) {
} }
ngModule.vnComponent('vnDropDown', { ngModule.vnComponent('vnDropDown', {
slotTemplate: require('./index.html'),
controller: DropDown, controller: DropDown,
transclude: { transclude: {
tplItem: '?tplItem' tplItem: '?tplItem'

View File

@ -9,12 +9,6 @@ import Component from '../../lib/component';
* @property {Boolean} disabled Put component in disabled mode * @property {Boolean} disabled Put component in disabled mode
*/ */
export default class FormInput extends Component { export default class FormInput extends Component {
constructor($element, $scope) {
super($element, $scope);
this.classList = this.element.classList;
this.classList.add(...this.constructor.$classNames);
}
$onInit() { $onInit() {
// XXX: Compatibility with old inputs // XXX: Compatibility with old inputs
let attrs = this.$element[0].attributes; let attrs = this.$element[0].attributes;

View File

@ -13,8 +13,8 @@ import './style.scss';
* @event close Thrown when popover is hidden * @event close Thrown when popover is hidden
*/ */
export default class Popover extends Popup { export default class Popover extends Popup {
constructor($element, $, $transclude) { constructor(...args) {
super($element, $, $transclude); super(...args);
this.displayMode = isMobile ? 'centered' : 'relative'; this.displayMode = isMobile ? 'centered' : 'relative';
this.template = template; this.template = template;
} }
@ -23,9 +23,12 @@ export default class Popover extends Popup {
* Shows the popover emitting the open signal. If a parent is specified * Shows the popover emitting the open signal. If a parent is specified
* it is shown in a visible relative position to it. * it is shown in a visible relative position to it.
* *
* @param {HTMLElement} parent Overrides the parent property * @param {HTMLElement|Event} parent Overrides the parent property
*/ */
show(parent) { show(parent) {
if (parent instanceof Event)
parent = event.target;
if (parent) this.parent = parent; if (parent) this.parent = parent;
super.show(); super.show();
this.content = this.popup.querySelector('.content'); this.content = this.popup.querySelector('.content');

View File

@ -7,9 +7,8 @@ import './style.scss';
* Base class for windows displayed over application content. * Base class for windows displayed over application content.
*/ */
export default class Popup extends Component { export default class Popup extends Component {
constructor($element, $scope, $transclude) { constructor(...args) {
super($element, $scope); super(...args);
this.$transclude = $transclude;
this._shown = false; this._shown = false;
this.displayMode = 'centered'; this.displayMode = 'centered';
this.template = template; this.template = template;
@ -45,11 +44,13 @@ export default class Popup extends Component {
this.onClose(); this.onClose();
} }
let linkFn = this.$compile(this.template);
this.$contentScope = this.$.$new(); this.$contentScope = this.$.$new();
let linkFn = this.$compile(this.template);
this.popup = linkFn(this.$contentScope, null, this.popup = linkFn(this.$contentScope, null,
{parentBoundTranscludeFn: this.$transclude} {parentBoundTranscludeFn: this.$transclude}
)[0]; )[0];
this.windowEl = this.popup.querySelector('.window'); this.windowEl = this.popup.querySelector('.window');
this.windowEl.focus(); this.windowEl.focus();
@ -127,5 +128,6 @@ ngModule.vnComponent('vnPopup', {
transclude: true, transclude: true,
bindings: { bindings: {
shown: '=?' shown: '=?'
} },
installClasses: false
}); });

View File

@ -0,0 +1,23 @@
import ngModule from '../module';
/*
* Registers a handler for the click event and stops propagation when event
* is thrown, mainly when nesting clickable elements wich ignore the
* Event.defaultPrevented property, like ui-sref.
*/
export function directive($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
const fn = $parse(attrs.vnClickStop);
element.on('click', function(event) {
fn(scope, {$event: event});
event.stopPropagation();
event.preventDefault();
});
}
};
}
directive.$inject = ['$parse'];
ngModule.directive('vnClickStop', directive);

View File

@ -2,6 +2,7 @@ import './id';
import './focus'; import './focus';
import './dialog'; import './dialog';
import './popover'; import './popover';
import './click-stop';
import './rule'; import './rule';
import './acl'; import './acl';
import './on-error-src'; import './on-error-src';

View File

@ -11,14 +11,29 @@ export default class Component extends EventEmitter {
* *
* @param {HTMLElement} $element The main component element * @param {HTMLElement} $element The main component element
* @param {$rootScope.Scope} $scope The element scope * @param {$rootScope.Scope} $scope The element scope
* @param {Function} $transclude The transclusion function
*/ */
constructor($element, $scope) { constructor($element, $scope, $transclude) {
super(); super();
this.$ = $scope;
if (!$element) return; if (!$element) return;
this.element = $element[0]; this.element = $element[0];
this.element.$ctrl = this; this.element.$ctrl = this;
this.$element = $element; this.$element = $element;
this.$ = $scope; this.$transclude = $transclude;
this.classList = this.element.classList;
const constructor = this.constructor;
const $options = constructor.$options;
if ($options && $options.installClasses)
this.classList.add(...this.constructor.$classNames);
if ($transclude && constructor.slotTemplates) {
for (let slotTemplate of constructor.slotTemplates)
this.fillSlots(slotTemplate);
}
} }
$postLink() { $postLink() {
@ -26,7 +41,7 @@ export default class Component extends EventEmitter {
let attrs = this.$element[0].attributes; let attrs = this.$element[0].attributes;
let $scope = this.$; let $scope = this.$;
for (let attr of attrs) { for (let attr of attrs) {
if (attr.name.substr(0, 2) !== 'on') continue; if (!attr.name.startsWith('on-')) continue;
let eventName = kebabToCamel(attr.name.substr(3)); let eventName = kebabToCamel(attr.name.substr(3));
let callback = locals => $scope.$parent.$eval(attr.nodeValue, locals); let callback = locals => $scope.$parent.$eval(attr.nodeValue, locals);
this.on(eventName, callback); this.on(eventName, callback);
@ -58,6 +73,72 @@ export default class Component extends EventEmitter {
return this.$translate.instant(string, params); return this.$translate.instant(string, params);
} }
/**
* Fills the default transclude slot.
*
* @param {JQElement|String} template The slot template
*/
fillDefaultSlot(template) {
const linkFn = this.$compile(template);
this.$transclude.$$boundTransclude = this.createBoundTranscludeFn(linkFn);
}
/**
* Fills a named transclude slot.
*
* @param {String} slot The trasnclude slot name
* @param {JQElement|String} template The slot name
*/
fillSlot(slot, template) {
const linkFn = this.$compile(template);
const slots = this.$transclude.$$boundTransclude.$$slots;
slots[slot] = this.createBoundTranscludeFn(linkFn);
}
/**
* Fills component transclude slots using the passed HTML template string
* as source.
*
* @param {String} template The HTML template string
*/
fillSlots(template) {
const name = this.constructor.$options.name;
const transclude = this.constructor.$options.transclude;
if (!transclude)
throw new Error(`No transclusion option defined in '${name}'`);
if (!this.$transclude)
throw new Error(`No $transclude injected in '${name}'`);
let slotMap = {};
for (let slotName in transclude) {
let slotTag = transclude[slotName].match(/\w+$/)[0];
slotMap[slotTag] = slotName;
}
const $template = angular.element(template);
for (let i = 0; i < $template.length; i++) {
let slotElement = $template[i];
if (slotElement.nodeType != Node.ELEMENT_NODE) continue;
let tagName = kebabToCamel(slotElement.tagName.toLowerCase());
if (tagName == 'default')
this.fillDefaultSlot(slotElement.childNodes);
else {
let slotName = slotMap[tagName];
if (!slotName)
throw new Error(`No slot found for '${tagName}' in '${name}'`);
this.fillSlot(slotName, slotElement);
}
}
}
/**
* Creates a bounded transclude function from a linking function.
*
* @param {Function} linkFn The linking function
* @return {Function} The bounded transclude function
*/
createBoundTranscludeFn(linkFn) { createBoundTranscludeFn(linkFn) {
let scope = this.$; let scope = this.$;
let previousBoundTranscludeFn = this.$transclude.$$boundTransclude; let previousBoundTranscludeFn = this.$transclude.$$boundTransclude;
@ -78,17 +159,6 @@ export default class Component extends EventEmitter {
return vnBoundTranscludeFn; return vnBoundTranscludeFn;
} }
fillDefaultSlot(template) {
let linkFn = this.$compile(template);
this.$transclude.$$boundTransclude = this.createBoundTranscludeFn(linkFn);
}
fillSlot(slot, template) {
let slots = this.$transclude.$$boundTransclude.$$slots;
let linkFn = this.$compile(template);
slots[slot] = this.createBoundTranscludeFn(linkFn);
}
copySlot(slot, $transclude) { copySlot(slot, $transclude) {
this.$transclude.$$boundTransclude.$$slots[slot] = this.$transclude.$$boundTransclude.$$slots[slot] =
$transclude.$$boundTransclude.$$slots[slot]; $transclude.$$boundTransclude.$$slots[slot];
@ -96,38 +166,18 @@ export default class Component extends EventEmitter {
} }
Component.$inject = ['$element', '$scope']; Component.$inject = ['$element', '$scope'];
function runFn( /*
$translate, * Automatically adds the most used services to the prototype, so they are
$q, * available as component properties.
$http, */
$state, function runFn(...args) {
$stateParams, const proto = Component.prototype;
$timeout,
$transitions, for (let i = 0; i < runFn.$inject.length; i++)
$compile, proto[runFn.$inject[i]] = args[i];
$filter,
$interpolate, Object.assign(proto, {
$window, $params: proto.$stateParams
vnApp,
vnToken,
vnConfig,
aclService) {
Object.assign(Component.prototype, {
$translate,
$q,
$http,
$state,
$params: $stateParams,
$timeout,
$transitions,
$compile,
$filter,
$interpolate,
$window,
vnApp,
vnToken,
vnConfig,
aclService
}); });
} }
runFn.$inject = [ runFn.$inject = [

View File

@ -1,6 +1,16 @@
import {ng, ngDeps} from './vendor'; import {ng, ngDeps} from './vendor';
import {camelToKebab} from './lib/string'; import {camelToKebab} from './lib/string';
/**
* Extended component options.
*
* @property {Boolean} installClassses Whether to install CSS classes equivalent to the component's and parents name
* @property {String} slotTemplate HTML template used to fill component transclude slots
*/
const defaultOptions = {
installClasses: true
};
/** /**
* Acts like native Module.component() function but merging component options * Acts like native Module.component() function but merging component options
* with parent component options. This method establishes the $options property * with parent component options. This method establishes the $options property
@ -17,7 +27,7 @@ import {camelToKebab} from './lib/string';
function vnComponent(name, options) { function vnComponent(name, options) {
let controller = options.controller; let controller = options.controller;
let parent = Object.getPrototypeOf(controller); let parent = Object.getPrototypeOf(controller);
let parentOptions = parent.$options || {}; let parentOptions = parent.$options || defaultOptions;
let parentTransclude = parentOptions.transclude; let parentTransclude = parentOptions.transclude;
let transclude = parentTransclude instanceof Object let transclude = parentTransclude instanceof Object
@ -32,10 +42,11 @@ function vnComponent(name, options) {
} else if (options.transclude !== undefined) } else if (options.transclude !== undefined)
transclude = options.transclude; transclude = options.transclude;
let mergedOptions = Object.assign({}, let $options = Object.assign({},
parentOptions, parentOptions,
options, options,
{ {
name,
transclude, transclude,
bindings: Object.assign({}, bindings: Object.assign({},
parentOptions.bindings, parentOptions.bindings,
@ -47,13 +58,17 @@ function vnComponent(name, options) {
) )
} }
); );
controller.$options = mergedOptions;
let parentSlotTemplates = parent.slotTemplates || [];
if (options.slotTemplate)
controller.slotTemplates = parentSlotTemplates.concat([options.slotTemplate]);
let classNames = [camelToKebab(name)]; let classNames = [camelToKebab(name)];
if (parent.$classNames) classNames = classNames.concat(parent.$classNames); if (parent.$classNames) classNames = classNames.concat(parent.$classNames);
controller.$classNames = classNames; controller.$classNames = classNames;
return this.component(name, mergedOptions); controller.$options = $options;
return this.component(name, $options);
} }
const ngModuleFn = ng.module; const ngModuleFn = ng.module;
@ -72,33 +87,12 @@ export function config($translateProvider, $translatePartialLoaderProvider, $ani
// For CSS browser targeting // For CSS browser targeting
document.documentElement.setAttribute('data-browser', navigator.userAgent); document.documentElement.setAttribute('data-browser', navigator.userAgent);
$translatePartialLoaderProvider.addPart('core');
let conf = {urlTemplate: '/locale/{part}/{lang}.json'};
let fallbackLang = 'es';
let langs = ['en', 'es'];
let langAliases = {
en_US: 'en',
en_GB: 'en',
es_ES: 'es',
es_AR: 'es'
};
$translateProvider $translateProvider
.useSanitizeValueStrategy('escape') .useSanitizeValueStrategy('escape')
.useLoader('$translatePartialLoader', conf) .useLoader('$translatePartialLoader', {
.registerAvailableLanguageKeys(langs, langAliases) urlTemplate: '/locale/{part}/{lang}.json'
// FIXME: Circular dependency due to vnInterceptor
// .fallbackLanguage(fallbackLang)
.determinePreferredLanguage(() => {
let locale = $translateProvider.resolveClientLocale();
if (langs.indexOf(locale) !== -1)
return locale;
if (langAliases[locale])
return langAliases[locale];
return fallbackLang;
}); });
$translatePartialLoaderProvider.addPart('core');
$animateProvider.customFilter( $animateProvider.customFilter(
node => node.tagName == 'UI-VIEW'); node => node.tagName == 'UI-VIEW');

View File

@ -4,17 +4,19 @@
html [vn-horizontal], vn-horizontal, .vn-horizontal, html [vn-horizontal], vn-horizontal, .vn-horizontal,
html [vn-vertical], vn-vertical, .vn-vertical { html [vn-vertical], vn-vertical, .vn-vertical {
display: flex; display: flex;
& > * {
flex: 1;
}
} }
html [vn-horizontal], vn-horizontal, .vn-horizontal { html [vn-horizontal], vn-horizontal, .vn-horizontal {
flex-direction: row; flex-direction: row;
} }
vn-horizontal[reverse] {
flex-direction: row-reverse;
}
html [vn-vertical], vn-vertical, .vn-vertical { html [vn-vertical], vn-vertical, .vn-vertical {
flex-direction: column; flex-direction: column;
} }
vn-vertical[reverse] {
html [reverse] {
flex-direction: column-reverse; flex-direction: column-reverse;
} }
html [wrap] { html [wrap] {
@ -26,27 +28,12 @@ html [wrap-reverse] {
/* Horizontal & vertical childs */ /* Horizontal & vertical childs */
html [vn-auto],
html [vn-none],
html [vn-one],
html [vn-two],
html [vn-three],
html [vn-four],
html [vn-five],
html [vn-six],
html [vn-seven],
html [vn-eight],
html [vn-nine],
html [vn-ten],
html [vn-eleven],
html [vn-twelve]{
flex-basis: .1px;
}
html [vn-auto], vn-auto, .vn-auto { html [vn-auto], vn-auto, .vn-auto {
flex-basis: auto; flex-basis: auto;
} }
html [vn-none], vn-none, .vn-none { html [vn-none], vn-none, .vn-none {
flex: none; flex: none;
flex-basis: .1px;
} }
html [vn-one], vn-one, .vn-one { html [vn-one], vn-one, .vn-one {
flex: 1; flex: 1;

View File

@ -0,0 +1,11 @@
<default>
<vn-spinner
ng-if="$ctrl.canceler"
enable="true">
</vn-spinner>
<div
ng-if="$ctrl.entity"
ng-transclude="descriptor"
class="descriptor-wrapper">
</div>
</default>

View File

@ -0,0 +1,83 @@
import ngModule from '../../module';
import Popover from 'core/components/popover';
import './style.scss';
export default class DescriptorPopover extends Popover {
constructor(...args) {
super(...args);
this._quicklinks = {};
this.entity = null;
}
get id() {
return this._id;
}
set id(value) {
if (value == this._id) return;
this._id = value;
this.loadData();
}
get entity() {
return this._entity;
}
set entity(value) {
this._entity = value;
}
get quicklinks() {
return this._quicklinks;
}
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show(parent, id) {
if (id !== undefined)
this.id = id;
super.show(parent);
}
/**
* Reloads the descriptor data. Should be implemented or overriden by child
* classes.
*/
loadData() {
throw new Error('DescriptorPopover::loadData() method not implemented');
}
getData(url, options) {
if (this.canceler) this.canceler.resolve();
this.canceler = this.$q.defer();
this.entity = null;
options = Object.assign(options || {}, {
timeout: this.canceler.promise
});
this.relocate();
return this.$http.get(url, options)
.then(res => {
this.canceler = null;
this.$.$applyAsync(() => this.relocate());
return res;
});
}
}
ngModule.vnComponent('vnDescriptorPopover', {
slotTemplate: require('./index.html'),
controller: DescriptorPopover,
bindings: {
id: '<?',
entity: '<?',
},
transclude: {
descriptor: '?slotDescriptor'
}
});

View File

@ -0,0 +1,13 @@
@import "variables";
.vn-descriptor-popover {
.content > vn-spinner {
padding: $spacing-md;
display: block;
margin: 0 auto;
height: 45px;
}
.descriptor-wrapper {
width: 260px;
}
}

View File

@ -1,12 +1,21 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Component from 'core/lib/component';
import './quick-links';
import './style.scss'; import './style.scss';
export default class QuickLinks {} export default class Descriptor extends Component {
set quicklinks(value = {}) {
ngModule.component('vnQuickLinks', { this._quicklinks = Object.assign(value, this._quicklinks);
template: require('./index.html'),
controller: QuickLinks,
bindings: {
links: '<?'
} }
get quicklinks() {
return this._quicklinks;
}
}
ngModule.vnComponent('vnDescriptor', {
controller: Descriptor,
bindings: {
quicklinks: '<'
},
}); });

View File

@ -0,0 +1,8 @@
<a ng-repeat="button in $ctrl.links"
vn-tooltip="{{::button.tooltip}}"
class="vn-button colored"
ui-sref="{{::button.state}}">
<vn-icon
icon="{{::button.icon}}">
</vn-icon>
</a>

View File

@ -0,0 +1,11 @@
import ngModule from '../../module';
export default class QuickLinks {}
ngModule.component('vnQuickLinks', {
template: require('./quick-links.html'),
controller: QuickLinks,
bindings: {
links: '<?'
}
});

View File

@ -1,6 +1,7 @@
import './app/app'; import './app/app';
import './background/background'; import './background/background';
import './descriptor'; import './descriptor';
import './descriptor-popover';
import './home/home'; import './home/home';
import './layout'; import './layout';
import './left-menu/left-menu'; import './left-menu/left-menu';

View File

@ -74,4 +74,5 @@
</a> </a>
</vn-list> </vn-list>
</vn-portal> </vn-portal>
<ui-view class="main-view"></ui-view> <ui-view class="main-view"></ui-view>
<vn-scroll-up></vn-scroll-up>

View File

@ -32,7 +32,7 @@ vn-layout {
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
padding-left: 6px; padding-left: 10px;
} }
& > vn-spinner { & > vn-spinner {
padding: 0 6px; padding: 0 6px;
@ -80,7 +80,7 @@ vn-layout {
padding-right: $menu-width; padding-right: $menu-width;
} }
[fixed-bottom-right] { [fixed-bottom-right] {
right: 64px + $menu-width; right: 32px + $menu-width;
} }
} }
& > .main-view { & > .main-view {

View File

@ -6,11 +6,6 @@ import './style.scss';
* Base class for module cards. * Base class for module cards.
*/ */
export default class ModuleCard extends Component { export default class ModuleCard extends Component {
constructor($element, $) {
super($element, $);
this.element.classList.add('vn-module-card');
}
$onInit() { $onInit() {
this.reload(); this.reload();
} }

View File

@ -2,12 +2,7 @@ import ngModule from '../../module';
import Component from 'core/lib/component'; import Component from 'core/lib/component';
import './style.scss'; import './style.scss';
export default class ModuleMain extends Component { export default class ModuleMain extends Component {}
constructor($element, $) {
super($element, $);
this.element.classList.add('vn-module-main');
}
}
ngModule.vnComponent('vnModuleMain', { ngModule.vnComponent('vnModuleMain', {
template: require('./index.html'), template: require('./index.html'),

View File

@ -2,17 +2,7 @@ import ngModule from '../../module';
import Component from 'core/lib/component'; import Component from 'core/lib/component';
import './style.scss'; import './style.scss';
export default class Section extends Component { export default class Section extends Component {}
constructor($element, $) {
super($element, $);
this.element.classList.add('vn-section');
}
stopEvent(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
ngModule.vnComponent('vnSection', { ngModule.vnComponent('vnSection', {
controller: Section controller: Section

View File

@ -1,15 +1,6 @@
import ngModule from '../../module'; import ngModule from '../../module';
import './style.scss'; import './style.scss';
import config from '../../config.json';
let languages = {
es: 'Español',
en: 'English',
ca: 'Català',
pt: 'Português',
fr: 'Français',
nl: 'Nederlands',
mn: 'Монгол хэл'
};
class Controller { class Controller {
constructor($, $translate, vnConfig, vnAuth) { constructor($, $translate, vnConfig, vnAuth) {
@ -25,7 +16,7 @@ class Controller {
for (let code of $translate.getAvailableLanguageKeys()) { for (let code of $translate.getAvailableLanguageKeys()) {
this.langs.push({ this.langs.push({
code: code, code: code,
name: languages[code] ? languages[code] : code name: config.languages[code] ? config.languages[code] : code
}); });
} }

25
front/salix/config.json Normal file
View File

@ -0,0 +1,25 @@
{
"imagePath": "//verdnatura.es/vn-image-data",
"langOptions": {
"fallbackLang": "es",
"langs": [
"en",
"es"
],
"langAliases": {
"en_US": "en",
"en_GB": "en",
"es_ES": "es",
"es_AR": "es"
}
},
"languages": {
"es": "Español",
"en": "English",
"ca": "Català",
"pt": "Português",
"fr": "Français",
"nl": "Nederlands",
"mn": "Монгол хэл"
}
}

View File

@ -1,4 +1,5 @@
import {ng} from 'core/vendor'; import {ng} from 'core/vendor';
import appConfig from './config.json';
import 'core'; import 'core';
export const appName = 'salix'; export const appName = 'salix';
@ -8,6 +9,8 @@ export default ngModule;
run.$inject = ['$window', '$rootScope', 'vnAuth', 'vnApp', '$state']; run.$inject = ['$window', '$rootScope', 'vnAuth', 'vnApp', '$state'];
export function run($window, $rootScope, vnAuth, vnApp, $state) { export function run($window, $rootScope, vnAuth, vnApp, $state) {
$rootScope.imagePath = appConfig.imagePath;
$window.validations = {}; $window.validations = {};
vnApp.name = appName; vnApp.name = appName;
@ -57,8 +60,22 @@ export function run($window, $rootScope, vnAuth, vnApp, $state) {
} }
ngModule.run(run); ngModule.run(run);
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider', '$compileProvider']; config.$inject = ['$translateProvider', '$translatePartialLoaderProvider', '$httpProvider', '$compileProvider'];
export function config($translatePartialLoaderProvider, $httpProvider, $compileProvider) { export function config($translateProvider, $translatePartialLoaderProvider, $httpProvider, $compileProvider) {
const langOptions = appConfig.langOptions;
$translateProvider
.registerAvailableLanguageKeys(langOptions.langs, langOptions.langAliases)
// TODO: Circular dependency due to vnInterceptor
// .fallbackLanguage(langOptions.fallbackLang)
.determinePreferredLanguage(() => {
const locale = $translateProvider.resolveClientLocale();
if (langOptions.langs.indexOf(locale) !== -1)
return locale;
if (langOptions.langAliases[locale])
return langOptions.langAliases[locale];
return fallbackLang;
});
$translatePartialLoaderProvider.addPart(appName); $translatePartialLoaderProvider.addPart(appName);
$httpProvider.interceptors.push('vnInterceptor'); $httpProvider.interceptors.push('vnInterceptor');

View File

@ -6,19 +6,16 @@
auto-save="true" auto-save="true"
on-save="$ctrl.onSave()"> on-save="$ctrl.onSave()">
</vn-crud-model> </vn-crud-model>
<vn-crud-model auto-load="true" <vn-crud-model auto-load="true"
url="ClaimDestinations" url="ClaimDestinations"
data="claimDestinations"> data="claimDestinations">
</vn-crud-model> </vn-crud-model>
<vn-card class="vn-mb-md vn-pa-lg vn-w-lg" style="text-align: right" <vn-card class="vn-mb-md vn-pa-lg vn-w-lg" style="text-align: right"
ng-if="$ctrl.salesClaimed.length > 0"> ng-if="$ctrl.salesClaimed.length > 0">
<vn-label-value label="Total claimed" <vn-label-value label="Total claimed"
value="{{$ctrl.claimedTotal | currency: 'EUR':2}}"> value="{{$ctrl.claimedTotal | currency: 'EUR':2}}">
</vn-label-value> </vn-label-value>
</vn-card> </vn-card>
<vn-card class="vn-pa-lg vn-w-lg"> <vn-card class="vn-pa-lg vn-w-lg">
<section class="header"> <section class="header">
<vn-tool-bar class="vn-mb-md"> <vn-tool-bar class="vn-mb-md">
@ -53,7 +50,6 @@
on-change="$ctrl.saveMana(value)"> on-change="$ctrl.saveMana(value)">
</vn-check> </vn-check>
</section> </section>
<vn-data-viewer model="model"> <vn-data-viewer model="model">
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
@ -75,7 +71,7 @@
vn-repeat-last on-last="$ctrl.focusLastInput()"> vn-repeat-last on-last="$ctrl.focusLastInput()">
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showDescriptor($event, saleClaimed.sale.itemFk)" ng-click="descriptor.show($event, saleClaimed.sale.itemFk)"
class="link"> class="link">
{{::saleClaimed.sale.itemFk | zeroFill:6}} {{::saleClaimed.sale.itemFk | zeroFill:6}}
</span> </span>
@ -83,7 +79,7 @@
<vn-td number> <vn-td number>
<span <span
class="link" class="link"
ng-click="$ctrl.showTicketDescriptor($event, saleClaimed.sale.ticketFk)"> ng-click="ticketDescriptor.show($event, saleClaimed.sale.ticketFk)">
{{::saleClaimed.sale.ticketFk}} {{::saleClaimed.sale.ticketFk}}
</span> </span>
</vn-td> </vn-td>
@ -117,7 +113,6 @@
</vn-tbody> </vn-tbody>
</vn-table> </vn-table>
</vn-data-viewer> </vn-data-viewer>
<vn-button-bar> <vn-button-bar>
<vn-button <vn-button
label="Regularize" label="Regularize"
@ -126,7 +121,6 @@
</vn-button> </vn-button>
</vn-button-bar> </vn-button-bar>
</vn-card> </vn-card>
<!-- Add Lines Dialog --> <!-- Add Lines Dialog -->
<vn-dialog vn-id="addSales"> <vn-dialog vn-id="addSales">
<tpl-body> <tpl-body>

View File

@ -63,14 +63,6 @@ export default class Controller extends Section {
}); });
} }
showTicketDescriptor(event, ticketFk) {
this.$.ticketDescriptor.ticketFk = ticketFk;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
event.preventDefault();
}
focusLastInput() { focusLastInput() {
let inputs = document.querySelectorAll('#claimDestinationFk'); let inputs = document.querySelectorAll('#claimDestinationFk');
inputs[inputs.length - 1].querySelector('input').focus(); inputs[inputs.length - 1].querySelector('input').focus();
@ -172,13 +164,6 @@ export default class Controller extends Section {
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
} }
// Item Descriptor
showDescriptor(event, itemFk) {
this.$.descriptor.itemFk = itemFk;
this.$.descriptor.parent = event.target;
this.$.descriptor.show();
}
saveResponsibility(value) { saveResponsibility(value) {
let query = `Claims/${this.$params.id}/updateClaimAction`; let query = `Claims/${this.$params.id}/updateClaimAction`;

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) { constructor($element, $, $httpParamSerializer) {
super($element, $); super($element, $);
this.$httpParamSerializer = $httpParamSerializer; this.$httpParamSerializer = $httpParamSerializer;
@ -49,14 +49,6 @@ class Controller extends Component {
}; };
} }
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
get quicklinks() {
return this._quicklinks;
}
showPickupOrder() { showPickupOrder() {
const params = { const params = {
clientId: this.claim.clientFk, clientId: this.claim.clientFk,
@ -80,7 +72,7 @@ class Controller extends Component {
claimId: this.claim.id claimId: this.claim.id
}; };
this.$http.get(`email/claim-pickup-order`, {params}).then( this.$http.get(`email/claim-pickup-order`, {params}).then(
() => this.vnApp.showMessage(this.$translate.instant('Notification sent!')) () => this.vnApp.showMessage(this.$t('Notification sent!'))
); );
} }
} }
@ -101,12 +93,11 @@ class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$httpParamSerializer']; Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnClaimDescriptor', { ngModule.vnComponent('vnClaimDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
claim: '<', claim: '<',
tags: '<', tags: '<'
quicklinks: '<'
} }
}); });

View File

@ -46,9 +46,9 @@
</vn-input-number> </vn-input-number>
</vn-td> </vn-td>
<vn-td expand title="{{::saleClaimed.sale.concept}}"> <vn-td expand title="{{::saleClaimed.sale.concept}}">
<span <span
class="link" ng-click="itemDescriptor.show($event, saleClaimed.sale.itemFk)"
ng-click="$ctrl.showItemDescriptor($event, saleClaimed.sale.itemFk)"> class="link">
{{::saleClaimed.sale.concept}} {{::saleClaimed.sale.concept}}
</span> </span>
</vn-td> </vn-td>
@ -98,14 +98,17 @@
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>
<vn-tr ng-repeat="sale in $ctrl.salesToClaim" class="clickable" ng-click="$ctrl.addClaimedSale($index)"> <vn-tr
ng-repeat="sale in $ctrl.salesToClaim"
ng-click="$ctrl.addClaimedSale($index)"
class="clickable">
<vn-td number>{{sale.landed | date: 'dd/MM/yyyy'}}</vn-td> <vn-td number>{{sale.landed | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{sale.quantity}}</vn-td> <vn-td number>{{sale.quantity}}</vn-td>
<vn-td expand title="{{::sale.concept}}"> <vn-td expand title="{{::sale.concept}}">
<span <span
class="link" vn-click-stop="itemDescriptor.show($event, sale.itemFk)"
ng-click="$ctrl.showItemDescriptor($event, sale.itemFk)"> class="link">
{{sale.concept}} {{sale.itemFk}} - {{sale.concept}}
</span> </span>
</vn-td> </vn-td>
<vn-td number>{{sale.price | currency: 'EUR':2}}</vn-td> <vn-td number>{{sale.price | currency: 'EUR':2}}</vn-td>
@ -120,7 +123,7 @@
</tpl-body> </tpl-body>
</vn-dialog> </vn-dialog>
<vn-item-descriptor-popover <vn-item-descriptor-popover
vn-id="descriptor"> vn-id="itemDescriptor">
</vn-item-descriptor-popover> </vn-item-descriptor-popover>
<vn-popover <vn-popover
class="edit" class="edit"

View File

@ -109,13 +109,6 @@ class Controller extends Section {
return total; return total;
} }
showItemDescriptor(event, itemFk) {
event.stopImmediatePropagation();
this.$.descriptor.itemFk = itemFk;
this.$.descriptor.parent = event.target;
this.$.descriptor.show();
}
showEditPopover(event, saleClaimed) { showEditPopover(event, saleClaimed) {
if (this.isEditable) { if (this.isEditable) {
if (!this.aclService.hasAny(['salesAssistant'])) if (!this.aclService.hasAny(['salesAssistant']))

View File

@ -125,25 +125,6 @@ describe('claim', () => {
}); });
}); });
describe('showItemDescriptor()', () => {
it('should configure the descriptor then show it', () => {
const itemId = 500;
const event = {
stopImmediatePropagation: () => {},
target: 'the target element'
};
jest.spyOn(event, 'stopImmediatePropagation');
jest.spyOn(controller.$.descriptor, 'show');
controller.showItemDescriptor(event, itemId);
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
expect(controller.$.descriptor.itemFk).toEqual(itemId);
expect(controller.$.descriptor.parent).toEqual(event.target);
expect(controller.$.descriptor.show).toHaveBeenCalledWith();
});
});
describe('isClaimEditable()', () => { describe('isClaimEditable()', () => {
it('should check if the claim is editable', () => { it('should check if the claim is editable', () => {
controller.isClaimEditable(); controller.isClaimEditable();

View File

@ -42,7 +42,6 @@
<form name="form"> <form name="form">
<vn-horizontal ng-repeat="claimDevelopment in claimDevelopments"> <vn-horizontal ng-repeat="claimDevelopment in claimDevelopments">
<vn-autocomplete <vn-autocomplete
vn-one
vn-focus vn-focus
label="Reason" label="Reason"
ng-model="claimDevelopment.claimReasonFk" ng-model="claimDevelopment.claimReasonFk"
@ -52,7 +51,6 @@
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete <vn-autocomplete
vn-one
label="Result" label="Result"
ng-model="claimDevelopment.claimResultFk" ng-model="claimDevelopment.claimResultFk"
data="claimResults" data="claimResults"
@ -61,7 +59,6 @@
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete <vn-autocomplete
vn-one
label="Responsible" label="Responsible"
ng-model="claimDevelopment.claimResponsibleFk" ng-model="claimDevelopment.claimResponsibleFk"
data="claimResponsibles" data="claimResponsibles"
@ -69,8 +66,7 @@
show-field="description" show-field="description"
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete <vn-autocomplete
vn-one
ng-model="claimDevelopment.workerFk" ng-model="claimDevelopment.workerFk"
url="Clients/activeWorkersWithRole" url="Clients/activeWorkersWithRole"
show-field="nickname" show-field="nickname"
@ -81,7 +77,6 @@
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete <vn-autocomplete
vn-one
label="Redelivery" label="Redelivery"
ng-model="claimDevelopment.claimRedeliveryFk" ng-model="claimDevelopment.claimRedeliveryFk"
data="claimRedeliveries" data="claimRedeliveries"
@ -90,6 +85,7 @@
rule> rule>
</vn-autocomplete> </vn-autocomplete>
<vn-icon-button <vn-icon-button
vn-none
class="vn-my-md" class="vn-my-md"
vn-tooltip="Remove sale" vn-tooltip="Remove sale"
icon="delete" icon="delete"

View File

@ -23,15 +23,17 @@
ui-sref="claim.card.summary({id: claim.id})"> ui-sref="claim.card.summary({id: claim.id})">
<vn-td number>{{::claim.id}}</vn-td> <vn-td number>{{::claim.id}}</vn-td>
<vn-td expand> <vn-td expand>
<span class="link" ng-click="$ctrl.showClientDescriptor($event, claim.clientFk)"> <span
vn-click-stop="clientDescriptor.show($event, claim.clientFk)"
class="link">
{{::claim.name}} {{::claim.name}}
</span> </span>
</vn-td> </vn-td>
<vn-td center>{{::claim.created | date:'dd/MM/yyyy'}}</vn-td> <vn-td center>{{::claim.created | date:'dd/MM/yyyy'}}</vn-td>
<vn-td expand> <vn-td expand>
<span <span
class="link" vn-click-stop="workerDescriptor.show($event, claim.workerFk)"
ng-click="$ctrl.showWorkerDescriptor($event, claim.workerFk)"> class="link" >
{{::claim.nickName}} {{::claim.nickName}}
</span> </span>
</vn-td> </vn-td>
@ -42,7 +44,7 @@
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.preview($event, claim)" vn-click-stop="$ctrl.preview(claim)"
vn-tooltip="Preview" vn-tooltip="Preview"
icon="desktop_windows"> icon="desktop_windows">
</vn-icon-button> </vn-icon-button>
@ -56,10 +58,11 @@
vn-id="clientDescriptor"> vn-id="clientDescriptor">
</vn-client-descriptor-popover> </vn-client-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-popup vn-id="dialog-summary-claim"> <vn-popup vn-id="summary">
<vn-claim-summary claim="$ctrl.claimSelected"></vn-claim-summary> <vn-claim-summary
claim="$ctrl.claimSelected">
</vn-claim-summary>
</vn-popup> </vn-popup>
<vn-scroll-up></vn-scroll-up> <vn-scroll-up></vn-scroll-up>

View File

@ -13,31 +13,9 @@ export default class Controller extends Section {
} }
} }
showClientDescriptor(event, clientFk) { preview(claim) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
event.stopImmediatePropagation();
}
showWorkerDescriptor(event, workerFk) {
event.preventDefault();
event.stopImmediatePropagation();
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
preview(event, claim) {
this.claimSelected = claim; this.claimSelected = claim;
this.$.dialogSummaryClaim.show(); this.$.summary.show();
event.preventDefault();
event.stopImmediatePropagation();
}
onDescriptorLoad() {
this.$.popover.relocate();
} }
} }

View File

@ -6,16 +6,20 @@
<h5>{{::$ctrl.summary.claim.id}} - {{::$ctrl.summary.claim.client.name}}</h5> <h5>{{::$ctrl.summary.claim.id}} - {{::$ctrl.summary.claim.client.name}}</h5>
<vn-horizontal> <vn-horizontal>
<vn-one> <vn-one>
<vn-label-value label="Created" <vn-label-value
label="Created"
value="{{$ctrl.summary.claim.created | date: 'dd/MM/yyyy'}}"> value="{{$ctrl.summary.claim.created | date: 'dd/MM/yyyy'}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="State" <vn-label-value
label="State"
value="{{$ctrl.summary.claim.claimState.description}}"> value="{{$ctrl.summary.claim.claimState.description}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Salesperson" <vn-label-value
label="Salesperson"
value="{{$ctrl.summary.claim.client.salesPerson.user.nickname}}"> value="{{$ctrl.summary.claim.client.salesPerson.user.nickname}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Attended by" <vn-label-value
label="Attended by"
value="{{$ctrl.summary.claim.worker.user.nickname}}"> value="{{$ctrl.summary.claim.worker.user.nickname}}">
</vn-label-value> </vn-label-value>
</vn-one> </vn-one>
@ -61,7 +65,7 @@
<vn-tr ng-repeat="saleClaimed in $ctrl.summary.salesClaimed"> <vn-tr ng-repeat="saleClaimed in $ctrl.summary.salesClaimed">
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showItemDescriptor($event, saleClaimed.sale.itemFk)" ng-click="itemDescriptor.show($event, saleClaimed.sale.itemFk)"
class="link"> class="link">
{{::saleClaimed.sale.itemFk | zeroFill:6}} {{::saleClaimed.sale.itemFk | zeroFill:6}}
</span> </span>
@ -113,7 +117,7 @@
<vn-td expand> <vn-td expand>
<span <span
class="link" class="link"
ng-click="$ctrl.showWorkerDescriptor($event, development.workerFk)"> ng-click="workerDescriptor.show($event, development.workerFk)">
{{::development.worker.user.nickname}} {{::development.worker.user.nickname}}
</span> </span>
</vn-td> </vn-td>
@ -144,14 +148,14 @@
<vn-tr ng-repeat="action in $ctrl.summary.actions"> <vn-tr ng-repeat="action in $ctrl.summary.actions">
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showItemDescriptor($event, action.sale.itemFk)" ng-click="itemDescriptor.show($event, action.sale.itemFk)"
class="link"> class="link">
{{::action.sale.itemFk | zeroFill:6}} {{::action.sale.itemFk | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showTicketDescriptor($event, action.sale.ticket.id)" ng-click="ticketDescriptor.show($event, action.sale.ticket.id)"
class="link"> class="link">
{{::action.sale.ticket.id | zeroFill:6}} {{::action.sale.ticket.id | zeroFill:6}}
</span> </span>
@ -177,8 +181,7 @@
vn-id="itemDescriptor"> vn-id="itemDescriptor">
</vn-item-descriptor-popover> </vn-item-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-ticket-descriptor-popover <vn-ticket-descriptor-popover
vn-id="ticketDescriptor"> vn-id="ticketDescriptor">

View File

@ -32,24 +32,6 @@ class Controller extends Section {
this.summary = response.data; this.summary = response.data;
}); });
} }
showItemDescriptor(event, itemFk) {
this.$.itemDescriptor.itemFk = itemFk;
this.$.itemDescriptor.parent = event.target;
this.$.itemDescriptor.show();
}
showWorkerDescriptor(event, workerFk) {
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
showTicketDescriptor(event, ticketId) {
this.$.ticketDescriptor.ticketFk = ticketId;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
}
} }
ngModule.component('vnClaimSummary', { ngModule.component('vnClaimSummary', {

View File

@ -1,44 +1,38 @@
<div> <tpl-title translate>
<tpl-body> New payment
<h6 translate>New payment</h6> </tpl-title>
<div class="vn-pa-md"> <tpl-body>
<vn-horizontal> <vn-horizontal>
<vn-date-picker <vn-date-picker
vn-one label="Date"
label="Date" ng-model="$ctrl.receipt.payed">
ng-model="$ctrl.receipt.payed"> </vn-date-picker>
</vn-date-picker> <vn-autocomplete
<vn-autocomplete url="Companies"
vn-one label="Company"
url="Companies" show-field="code"
label="Company" value-field="id"
show-field="code" ng-model="$ctrl.receipt.companyFk">
value-field="id" </vn-autocomplete>
ng-model="$ctrl.receipt.companyFk"> </vn-horizontal>
</vn-autocomplete> <vn-horizontal>
</vn-horizontal> <vn-autocomplete
<vn-horizontal> url="Banks"
<vn-autocomplete label="Bank"
vn-one show-field="bank"
url="Banks" value-field="id"
label="Bank" ng-model="$ctrl.receipt.bankFk">
show-field="bank" </vn-autocomplete>
value-field="id" <vn-input-number
ng-model="$ctrl.receipt.bankFk"> vn-focus
</vn-autocomplete> label="Amount"
<vn-input-number ng-model="$ctrl.receipt.amountPaid"
vn-one step="0.01"
vn-focus rule>
label="Amount" </vn-input-number>
ng-model="$ctrl.receipt.amountPaid" </vn-horizontal>
step="0.01" </tpl-body>
rule> <tpl-buttons>
</vn-input-number> <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
</vn-horizontal> <button response="accept" translate vn-focus>Accept</button>
</div> </tpl-buttons>
</tpl-body>
<tpl-buttons>
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
<button response="accept" translate vn-focus>Accept</button>
</tpl-buttons>
</div>

View File

@ -1,11 +1,9 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Dialog from 'core/components/dialog'; import Dialog from 'core/components/dialog';
import template from './index.html';
class Controller extends Dialog { class Controller extends Dialog {
constructor($element, $, $transclude) { constructor($element, $, $transclude) {
super($element, $, $transclude); super($element, $, $transclude);
this.fillSlots(template);
this.receipt = { this.receipt = {
payed: new Date(), payed: new Date(),
@ -76,8 +74,8 @@ class Controller extends Dialog {
} }
ngModule.vnComponent('vnClientBalanceCreate', { ngModule.vnComponent('vnClientBalanceCreate', {
slotTemplate: require('./index.html'),
controller: Controller, controller: Controller,
transclude: true,
bindings: { bindings: {
payed: '<?', payed: '<?',
bankFk: '<?', bankFk: '<?',

View File

@ -1,6 +1,6 @@
<vn-crud-model <vn-crud-model
vn-id="model" vn-id="model"
url="receipts/filter" url="Receipts/filter"
limit="20" limit="20"
data="$ctrl.balances"> data="$ctrl.balances">
</vn-crud-model> </vn-crud-model>
@ -66,19 +66,26 @@
</vn-td> </vn-td>
<vn-td> <vn-td>
<span <span
class="link" vn-click-stop="workerDescriptor.show($event, balance.workerFk)"
ng-click="$ctrl.showWorkerDescriptor($event, balance.workerFk)"> class="link">
{{::balance.userNickname}} {{::balance.userNickname}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand>
<span <div ng-show="::balance.ref">
title="{{balance.isInvoice ? 'BILL' : balance.ref | translate: {ref: balance.ref} }}" <span
ng-class="{'link': balance.isInvoice}" ng-if="balance.isInvoice"
ng-click="$ctrl.showInvoiceOutDescriptor($event, balance)" title="{{'BILL' | translate: {ref: balance.ref} }}"
ng-show="balance.ref"> vn-click-stop="invoiceOutDescriptor.show($event, balance)"
{{balance.isInvoice ? 'BILL' : balance.ref | translate: {ref: balance.ref} }} ng-class="link">
</span> {{'BILL' | translate: {ref: balance.ref} }}
</span>
<span
ng-if="!balance.isInvoice"
title="{{::balance.ref}}">
{{::balance.ref}}
</span>
</div>
</vn-td> </vn-td>
<vn-td number>{{::balance.bankFk}}</vn-td> <vn-td number>{{::balance.bankFk}}</vn-td>
<vn-td number expand>{{::balance.debit | currency: 'EUR':2}}</vn-td> <vn-td number expand>{{::balance.debit | currency: 'EUR':2}}</vn-td>
@ -121,10 +128,8 @@
company-fk="$ctrl.companyId"> company-fk="$ctrl.companyId">
</vn-client-balance-create> </vn-client-balance-create>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-invoice-out-descriptor-popover <vn-invoice-out-descriptor-popover
vn-id="invoiceOutDescriptor" vn-id="invoiceOutDescriptor">
invoice-out-id="$ctrl.selectedInvoiceOut">
</vn-invoice-out-descriptor-popover> </vn-invoice-out-descriptor-popover>

View File

@ -72,29 +72,6 @@ class Controller extends Section {
} }
}); });
} }
showWorkerDescriptor(event, workerFk) {
if (event.defaultPrevented) return;
event.preventDefault();
event.stopPropagation();
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
showInvoiceOutDescriptor(event, balance) {
if (!balance.isInvoice) return;
if (event.defaultPrevented) return;
event.preventDefault();
event.stopPropagation();
this.selectedInvoiceOut = balance.id;
this.$.invoiceOutDescriptor.parent = event.target;
this.$.invoiceOutDescriptor.show();
}
} }
Controller.$inject = ['$element', '$scope']; Controller.$inject = ['$element', '$scope'];

View File

@ -1,12 +1,6 @@
<vn-popover vn-id="popover"> <slot-descriptor>
<vn-spinner <vn-client-descriptor
ng-if="$ctrl.client == null"
style="padding: 1em;"
enable="true">
</vn-spinner>
<vn-client-descriptor
ng-if="$ctrl.client"
client="$ctrl.client" client="$ctrl.client"
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-client-descriptor> </vn-client-descriptor>
</vn-popover> </slot-descriptor>

View File

@ -1,67 +1,18 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import DescriptorPopover from 'salix/components/descriptor-popover';
import './style.scss';
class Controller extends Component {
constructor($element, $) {
super($element, $);
this.client = null;
this._quicklinks = {};
}
set clientFk(id) {
if (id == this._clientFk) return;
this._clientFk = id;
this.client = null;
this.getCard();
}
set client(value) {
this._client = value;
this.$timeout(() => this.$.popover.relocate());
}
class Controller extends DescriptorPopover {
get client() { get client() {
return this._client; return this.entity;
} }
get quicklinks() { loadData() {
return this._quicklinks; return this.getData(`Clients/${this.id}/getCard`)
} .then(res => this.entity = res.data);
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show() {
this.$.popover.parent = this.parent;
this.$.popover.show();
}
getCard() {
if (this.canceler)
this.canceler.resolve();
this.canceler = this.$q.defer();
let options = {timeout: this.canceler.promise};
this.$http.get(`Clients/${this._clientFk}/getCard`, options).then(
response => {
this.client = response.data;
this.canceler = null;
}
);
} }
} }
ngModule.component('vnClientDescriptorPopover', { ngModule.vnComponent('vnClientDescriptorPopover', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller
bindings: {
clientFk: '<',
quicklinks: '<'
}
}); });

View File

@ -1,80 +1,29 @@
import './index'; import './index';
describe('Client', () => { describe('vnClientDescriptorPopover', () => {
describe('Component vnClientDescriptorPopover', () => { let controller;
let $httpBackend; let $httpBackend;
let $scope;
let controller;
let $element;
let $timeout;
beforeEach(ngModule('client')); beforeEach(ngModule('client'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => { beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$timeout = _$timeout_; controller = $componentController('vnClientDescriptorPopover', {
$element = angular.element(`<div></div>`); $element: null,
$scope = $rootScope.$new(); $transclude: null
$scope.popover = {relocate: () => {}, show: () => {}};
controller = $componentController('vnClientDescriptorPopover', {$scope, $element});
}));
describe('clientFk()', () => {
it(`should not apply any changes if the received id is the same stored in _clientFk`, () => {
controller.client = 'I exist!';
controller._clientFk = 1;
jest.spyOn(controller, 'getCard');
controller.clientFk = 1;
expect(controller.client).toEqual('I exist!');
expect(controller._clientFk).toEqual(1);
expect(controller.getCard).not.toHaveBeenCalled();
});
it(`should set the received id into _clientFk, set the client to null and then call getCard()`, () => {
controller.client = `Please don't`;
controller._clientFk = 1;
jest.spyOn(controller, 'getCard');
controller.clientFk = 999;
expect(controller.client).toBeNull();
expect(controller._clientFk).toEqual(999);
expect(controller.getCard).toHaveBeenCalledWith();
});
}); });
}));
describe('client()', () => { describe('loadData()', () => {
it(`should save the client into _client and then call relocate()`, () => { it(`should perform a get query to store the client data into the controller`, () => {
jest.spyOn(controller.$.popover, 'relocate'); const id = 1;
controller.client = `i'm the client!`; const response = 'foo';
$timeout.flush();
expect(controller._client).toEqual(`i'm the client!`); $httpBackend.expectGET(`Clients/${id}/getCard`).respond(response);
expect(controller.$.popover.relocate).toHaveBeenCalledWith(); controller.id = id;
}); $httpBackend.flush();
});
describe('show()', () => { expect(controller.client).toEqual(response);
it(`should call the show()`, () => {
jest.spyOn(controller.$.popover, 'show');
controller.show();
expect(controller.$.popover.show).toHaveBeenCalledWith();
});
});
describe('getCard()', () => {
it(`should perform a get query to store the client data into the controller`, () => {
controller.clientFk = 1;
controller.canceler = null;
let response = {};
$httpBackend.when('GET', `Clients/${controller._clientFk}/getCard`).respond(response);
$httpBackend.expect('GET', `Clients/${controller._clientFk}/getCard`);
controller.getCard();
$httpBackend.flush();
expect(controller.client).toEqual(response);
});
}); });
}); });
}); });

View File

@ -1,9 +0,0 @@
vn-client-descriptor-popover {
vn-client-descriptor {
display: block;
width: 256px;
& > vn-card{
margin: 0!important;
}
}
}

View File

@ -6,33 +6,32 @@
<a translate-attr="{title: 'Preview'}" ui-sref="client.card.summary({id: $ctrl.client.id})"> <a translate-attr="{title: 'Preview'}" ui-sref="client.card.summary({id: $ctrl.client.id})">
<vn-icon icon="desktop_windows"></vn-icon> <vn-icon icon="desktop_windows"></vn-icon>
</a> </a>
<vn-icon-menu <vn-icon-button
vn-id="more-button"
icon="more_vert" icon="more_vert"
show-filter="false" vn-popover="menu">
value-field="callback" </vn-icon-button>
translate-fields="['name']"
data="$ctrl.moreOptions"
on-change="$ctrl.onMoreChange(value)"
on-open="$ctrl.onMoreOpen()">
</vn-icon-menu>
</div> </div>
<div class="body"> <div class="body">
<div class="attributes"> <div class="attributes">
<h5>{{$ctrl.client.name}}</h5> <h5>{{$ctrl.client.name}}</h5>
<vn-label-value label="Id" <vn-label-value
label="Id"
value="{{$ctrl.client.id}}"> value="{{$ctrl.client.id}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Phone" <vn-label-value
label="Phone"
value="{{$ctrl.client.phone | phone}}"> value="{{$ctrl.client.phone | phone}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Credit" <vn-label-value
label="Credit"
value="{{$ctrl.client.credit | currency: 'EUR': 2}}"> value="{{$ctrl.client.credit | currency: 'EUR': 2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Secured credit" <vn-label-value
label="Secured credit"
value="{{$ctrl.client.creditInsurance | currency: 'EUR': 2}}"> value="{{$ctrl.client.creditInsurance | currency: 'EUR': 2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Sales person" <vn-label-value
label="Sales person"
value="{{$ctrl.client.salesPerson.user.nickname}}"> value="{{$ctrl.client.salesPerson.user.nickname}}">
</vn-label-value> </vn-label-value>
</div> </div>
@ -63,17 +62,57 @@
ng-class="{bright: $ctrl.client.isTaxDataChecked == false}"> ng-class="{bright: $ctrl.client.isTaxDataChecked == false}">
</vn-icon> </vn-icon>
</div> </div>
<div class="quicklinks">
<a class="vn-button colored"
vn-tooltip="Client ticket list"
ui-sref="ticket.index({q: $ctrl.filter})">
<vn-icon icon="icon-ticket"></vn-icon>
</a>
<a class="vn-button colored"
vn-tooltip="New order"
ui-sref="order.create({clientFk: $ctrl.client.id})">
<vn-icon icon="icon-basketadd"></vn-icon>
</a>
</div>
<!--
<vn-quick-links <vn-quick-links
links="$ctrl.quicklinks"> links="$ctrl.quicklinks">
</vn-quick-links> </vn-quick-links>
-->
</div> </div>
</div> </div>
<!-- SMS Dialog --> <vn-menu vn-id="menu">
<vn-client-sms vn-id="sms" sms="$ctrl.newSMS"></vn-client-sms> <ul class="vn-list">
<!-- SMS Dialog --> <li>
<a class="vn-item"
ui-sref="ticket.create({clientFk: $ctrl.client.id})"
translate>
Simple ticket
</a>
</li>
<li>
<div class="vn-item"
ng-click="$ctrl.showSMSDialog()"
translate>
Send SMS
</div>
</li>
<li>
<div class="vn-item"
ng-click="consumerReportDialog.show()"
translate>
Send consumer report
</div>
</li>
</ul>
</vn-menu>
<vn-client-sms
vn-id="sms"
sms="$ctrl.newSMS">
</vn-client-sms>
<vn-dialog <vn-dialog
vn-id="consumerReportDialog" vn-id="consumerReportDialog"
on-response="$ctrl.sendConsumerReport($response)"> on-accept="$ctrl.onConsumerReportAccept()">
<tpl-body> <tpl-body>
<div> <div>
<h5 style="text-align: center"> <h5 style="text-align: center">

View File

@ -1,20 +1,10 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) { constructor($element, $, $httpParamSerializer) {
super($element, $); super($element, $);
this.$httpParamSerializer = $httpParamSerializer; this.$httpParamSerializer = $httpParamSerializer;
this.moreOptions = [
{name: 'Simple ticket', callback: this.newTicket},
{name: 'Send SMS', callback: this.showSMSDialog},
{name: 'Send consumer report', callback: this.showConsumerReportDialog}
];
}
onMoreChange(callback) {
callback.call(this);
} }
get client() { get client() {
@ -23,7 +13,6 @@ class Controller extends Component {
set client(value) { set client(value) {
this._client = value; this._client = value;
if (!value) return; if (!value) return;
if (this.$params.sendSMS) if (this.$params.sendSMS)
@ -43,56 +32,37 @@ class Controller extends Component {
}; };
} }
set quicklinks(value = {}) { get filter() {
this._quicklinks = Object.assign(value, this._quicklinks); return this.client ? JSON.stringify({clientFk: this.client.id}) : null;
}
get quicklinks() {
return this._quicklinks;
}
newTicket() {
this.$state.go('ticket.create', {clientFk: this.client.id});
} }
showSMSDialog() { showSMSDialog() {
const client = this.client; const client = this.client || {};
const phone = this.$params.phone || client.mobile || client.phone;
const message = this.$params.message || '';
this.newSMS = { this.newSMS = {
destinationFk: client.id, destinationFk: client.id,
destination: phone, destination: this.$params.phone || client.mobile || client.phone,
message: message message: this.$params.message || ''
}; };
this.$.sms.open(); this.$.sms.open();
} }
showConsumerReportDialog() { onConsumerReportAccept() {
this.$.consumerReportDialog.show(); const params = this.$httpParamSerializer({
} authorization: this.vnToken.token,
clientId: this.client.id,
sendConsumerReport(response) { from: this.from,
if (response === 'accept') { to: this.to,
const params = { });
authorization: this.vnToken.token, window.open(`api/report/campaign-metrics?${params}`);
clientId: this.client.id,
from: this.from,
to: this.to,
};
const serializedParams = this.$httpParamSerializer(params);
const url = `api/report/campaign-metrics?${serializedParams}`;
window.open(url);
}
} }
} }
Controller.$inject = ['$element', '$scope', '$httpParamSerializer']; Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnClientDescriptor', { ngModule.vnComponent('vnClientDescriptor', {
template: require('./index.html'), template: require('./index.html'),
bindings: { bindings: {
client: '<', client: '<'
quicklinks: '<'
}, },
controller: Controller controller: Controller
}); });

View File

@ -41,8 +41,7 @@
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<a <a
ui-sref="client.card.sample.create" ui-sref="client.card.sample.create"

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) { constructor($element, $, $httpParamSerializer) {
super($element, $); super($element, $);
this.$httpParamSerializer = $httpParamSerializer; this.$httpParamSerializer = $httpParamSerializer;
@ -49,14 +49,6 @@ class Controller extends Component {
this._quicklinks = links; this._quicklinks = links;
} }
get quicklinks() {
return this._quicklinks;
}
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
showEntryReport() { showEntryReport() {
const params = { const params = {
authorization: this.vnToken.token, authorization: this.vnToken.token,
@ -71,14 +63,13 @@ class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$httpParamSerializer']; Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnEntryDescriptor', { ngModule.vnComponent('vnEntryDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller,
bindings: { bindings: {
entry: '<', entry: '<'
quicklinks: '<'
}, },
require: { require: {
card: '^?vnEntryCard' card: '^?vnEntryCard'
}, }
controller: Controller
}); });

View File

@ -1,12 +1,6 @@
<vn-popover vn-id="popover"> <slot-descriptor>
<vn-spinner <vn-invoice-out-descriptor
ng-if="$ctrl.invoiceOut == null"
style="padding: 1em;"
enable="true">
</vn-spinner>
<vn-invoice-out-descriptor
ng-if="$ctrl.invoiceOut"
invoice-out="$ctrl.invoiceOut" invoice-out="$ctrl.invoiceOut"
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-invoice-out-descriptor> </vn-invoice-out-descriptor>
</vn-popover> </slot-descriptor>

View File

@ -1,55 +1,20 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import DescriptorPopover from 'salix/components/descriptor-popover';
import './style.scss';
class Controller extends Component { class Controller extends DescriptorPopover {
constructor($element, $,) { get invoiceOut() {
super($element, $); return this.entity;
this.worker = null;
this._quicklinks = {};
}
set invoiceOutId(id) {
if (id == this._invoiceOutId) return;
this._invoiceOutId = id;
this.invoiceOut = null;
this.loadData();
}
get invoiceOutId() {
return this._invoiceOutId;
}
get quicklinks() {
return this._quicklinks;
}
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show() {
this.$.popover.parent = this.parent;
this.$.popover.show();
} }
loadData() { loadData() {
let query = `InvoiceOuts/findOne`; const filter = {
let filter = {
where: {
id: this._invoiceOutId
},
include: [ include: [
{ {
relation: 'company', relation: 'company',
scope: { scope: {
fields: ['id', 'code'] fields: ['id', 'code']
} }
}, }, {
{
relation: 'client', relation: 'client',
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
@ -58,20 +23,12 @@ class Controller extends Component {
] ]
}; };
this.$http.get(query, {params: {filter}}).then(res => { return this.getData(`InvoiceOuts/${this.id}`, {filter})
this.invoiceOut = res.data; .then(res => this.entity = res.data);
this.$.$applyAsync(() => {
this.$.popover.relocate();
});
});
} }
} }
ngModule.component('vnInvoiceOutDescriptorPopover', { ngModule.vnComponent('vnInvoiceOutDescriptorPopover', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller
bindings: {
invoiceOutId: '<',
quicklinks: '<'
}
}); });

View File

@ -1,11 +0,0 @@
vn-ticket-descriptor-popover {
vn-ticket-descriptor {
display: block;
width: 256px;
max-height: 448px;
& > vn-card {
margin: 0!important;
}
}
}

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.moreOptions = [ this.moreOptions = [
@ -82,21 +82,12 @@ class Controller extends Component {
.then(() => this.$state.reload()) .then(() => this.$state.reload())
.then(() => this.vnApp.showSuccess(this.$t('InvoiceOut booked'))); .then(() => this.vnApp.showSuccess(this.$t('InvoiceOut booked')));
} }
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
get quicklinks() {
return this._quicklinks;
}
} }
ngModule.component('vnInvoiceOutDescriptor', { ngModule.vnComponent('vnInvoiceOutDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller,
bindings: { bindings: {
invoiceOut: '<', invoiceOut: '<'
quicklinks: '<' }
},
controller: Controller
}); });

View File

@ -29,7 +29,7 @@
<vn-td> <vn-td>
<span <span
class="link" class="link"
ng-click="$ctrl.showClientDescriptor($event, invoiceOut.clientFk)"> vn-click-stop="clientDescriptor.show($event, invoiceOut.clientFk)">
{{::invoiceOut.clientSocialName | dashIfEmpty}} {{::invoiceOut.clientSocialName | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
@ -39,7 +39,7 @@
<vn-td> <vn-td>
<vn-icon-button <vn-icon-button
ng-show="invoiceOut.hasPdf" ng-show="invoiceOut.hasPdf"
ng-click="$ctrl.openPdf(invoiceOut.id, $event)" vn-click-stop="$ctrl.openPdf(invoiceOut.id)"
icon="cloud_download" icon="cloud_download"
title="Download PDF" title="Download PDF"
vn-tooltip="Download PDF"> vn-tooltip="Download PDF">
@ -47,7 +47,7 @@
</vn-td> </vn-td>
<vn-td> <vn-td>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.preview($event, invoiceOut)" vn-click-stop="$ctrl.preview(invoiceOut)"
vn-tooltip="Preview" vn-tooltip="Preview"
icon="desktop_windows"> icon="desktop_windows">
</vn-icon-button> </vn-icon-button>

View File

@ -2,30 +2,14 @@ import ngModule from '../module';
import Section from 'salix/components/section'; import Section from 'salix/components/section';
export default class Controller extends Section { export default class Controller extends Section {
showClientDescriptor(event, clientFk) { preview(invoiceOut) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
event.stopImmediatePropagation();
}
preview(event, invoiceOut) {
this.selectedInvoiceOut = invoiceOut; this.selectedInvoiceOut = invoiceOut;
this.$.summary.show(); this.$.summary.show();
event.preventDefault();
event.stopImmediatePropagation();
} }
onDescriptorLoad() { openPdf(id) {
this.$.popover.relocate();
}
openPdf(id, event) {
let url = `api/InvoiceOuts/${id}/download?access_token=${this.vnToken.token}`; let url = `api/InvoiceOuts/${id}/download?access_token=${this.vnToken.token}`;
window.open(url, '_blank'); window.open(url, '_blank');
event.preventDefault();
event.stopImmediatePropagation();
} }
} }

View File

@ -54,14 +54,14 @@
<vn-tr ng-repeat="ticket in $ctrl.summary.invoiceOut.tickets"> <vn-tr ng-repeat="ticket in $ctrl.summary.invoiceOut.tickets">
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)" ng-click="ticketDescriptor.show($event, ticket.id)"
class="link"> class="link">
{{ticket.id}} {{ticket.id}}
</span> </span>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span <span
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)" ng-click="clientDescriptor.show($event, ticket.clientFk)"
class="link"> class="link">
{{ticket.nickname}} {{ticket.nickname}}
</span> </span>

View File

@ -14,29 +14,8 @@ class Controller extends Section {
} }
getSummary() { getSummary() {
this.$http.get(`InvoiceOuts/${this.invoiceOut.id}/summary`).then(response => { return this.$http.get(`InvoiceOuts/${this.invoiceOut.id}/summary`)
this.summary = response.data; .then(res => this.summary = res.data);
});
}
showClientDescriptor(event, clientFk) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
}
showTicketDescriptor(event, ticketFk) {
this.$.ticketDescriptor.ticketFk = ticketFk;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
event.preventDefault();
}
preview(event, invoiceOut) {
this.selectedInvoiceOut = invoiceOut;
this.$.invoiceOutSummaryDialog.show();
event.preventDefault();
} }
} }

View File

@ -1,12 +1,6 @@
<vn-popover vn-id="popover"> <slot-descriptor>
<vn-spinner
ng-if="$ctrl.item == null"
style="padding: 1em;"
enable="true">
</vn-spinner>
<vn-item-descriptor <vn-item-descriptor
ng-if="$ctrl.item"
item="$ctrl.item" item="$ctrl.item"
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-item-descriptor> </vn-item-descriptor>
</vn-popover> </slot-descriptor>

View File

@ -1,77 +1,29 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import DescriptorPopover from 'salix/components/descriptor-popover';
import './style.scss';
class Controller extends Component { class Controller extends DescriptorPopover {
constructor($element, $) { constructor(...args) {
super($element, $); super(...args);
this.item = null;
this._quicklinks = {};
}
set itemFk(id) {
if (id == this._itemFk) return;
this._itemFk = id;
this.item = null;
this._quicklinks = { this._quicklinks = {
btnThree: { btnThree: {
icon: 'icon-transaction', icon: 'icon-transaction',
state: `item.card.diary({ state: `item.card.diary({id: $ctrl.id})`,
id: ${id},
})`,
tooltip: 'Item diary' tooltip: 'Item diary'
} }
}; };
this.getCard();
}
set item(value) {
this._item = value;
this.$timeout(() => this.$.popover.relocate());
} }
get item() { get item() {
return this._item; return this.entity;
} }
get quicklinks() { loadData() {
return this._quicklinks; return this.getData(`Items/${this.id}/getCard`)
} .then(res => this.entity = res.data);
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show() {
this.$.popover.parent = this.parent;
this.$.popover.show();
}
getCard() {
if (this.canceler)
this.canceler.resolve();
this.canceler = this.$q.defer();
let options = {timeout: this.canceler.promise};
this.$http.get(`Items/${this._itemFk}/getCard`, options).then(
response => {
this.item = response.data;
this.canceler = null;
}
);
} }
} }
Controller.$inject = ['$element', '$scope'];
ngModule.component('vnItemDescriptorPopover', { ngModule.vnComponent('vnItemDescriptorPopover', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller
bindings: {
itemFk: '<',
quicklinks: '<'
}
}); });

View File

@ -1,79 +1,29 @@
import './index.js'; import './index';
describe('Item', () => { describe('vnItemDescriptorPopover', () => {
describe('Component vnItemDescriptorPopover', () => { let controller;
let $httpBackend; let $httpBackend;
let $scope;
let controller;
let $timeout;
beforeEach(ngModule('item')); beforeEach(ngModule('item'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => { beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$timeout = _$timeout_; controller = $componentController('vnItemDescriptorPopover', {
$scope = $rootScope.$new(); $element: null,
$scope.popover = {relocate: () => {}, show: () => {}}; $transclude: null
const $element = angular.element('<vn-item-descriptor-popover></vn-item-descriptor-popover>');
controller = $componentController('vnItemDescriptorPopover', {$element, $scope});
}));
describe('itemFk()', () => {
it(`should not apply any changes if the received id is the same stored in _itemFk`, () => {
controller.item = 'I exist!';
controller._itemFk = 1;
jest.spyOn(controller, 'getCard');
controller.itemFk = 1;
expect(controller.item).toEqual('I exist!');
expect(controller._itemFk).toEqual(1);
expect(controller.getCard).not.toHaveBeenCalled();
});
it(`should set the received id into _itemFk, set the item to null and then call getCard()`, () => {
controller.item = `Please don't`;
controller._itemFk = 1;
jest.spyOn(controller, 'getCard');
controller.itemFk = 999;
expect(controller.item).toBeNull();
expect(controller._itemFk).toEqual(999);
expect(controller.getCard).toHaveBeenCalledWith();
});
}); });
}));
describe('item()', () => { describe('loadData()', () => {
it(`should save the item into _item and then call relocate()`, () => { it(`should perform a get query to store the item data into the controller`, () => {
jest.spyOn(controller.$.popover, 'relocate'); const id = 1;
controller.item = `i'm the item!`; const response = 'foo';
$timeout.flush();
expect(controller._item).toEqual(`i'm the item!`); $httpBackend.expectGET(`Items/${id}/getCard`).respond(response);
expect(controller.$.popover.relocate).toHaveBeenCalledWith(); controller.id = id;
}); $httpBackend.flush();
});
describe('show()', () => { expect(controller.item).toEqual(response);
it(`should call the show()`, () => {
jest.spyOn(controller.$.popover, 'show');
controller.show();
expect(controller.$.popover.show).toHaveBeenCalledWith();
});
});
describe('getCard()', () => {
it(`should perform a get query to store the item data into the controller`, () => {
controller.itemFk = 1;
controller.canceler = null;
let response = {};
$httpBackend.when('GET', `Items/${controller._itemFk}/getCard`).respond(response);
$httpBackend.expect('GET', `Items/${controller._itemFk}/getCard`);
controller.getCard();
$httpBackend.flush();
expect(controller.item).toEqual(response);
});
}); });
}); });
}); });

View File

@ -1,5 +0,0 @@
body > .vn-popover vn-item-descriptor {
display: block;
width: 256px;
min-height: 448px;
}

View File

@ -20,8 +20,8 @@
<div> <div>
<div style="position: relative" text-center> <div style="position: relative" text-center>
<img <img
ng-src="//verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}" ng-src="{{::$root.imagePath}}/catalog/200x200/{{$ctrl.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{$ctrl.item.image}}" zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{$ctrl.item.image}}"
on-error-src/> on-error-src/>
<a href="//verdnatura.es/#!form=admin/items&filter={{$ctrl.item.id}}" target="_blank"> <a href="//verdnatura.es/#!form=admin/items&filter={{$ctrl.item.id}}" target="_blank">
<vn-float-button <vn-float-button

View File

@ -1,8 +1,8 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
import './style.scss'; import './style.scss';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.moreOptions = [ this.moreOptions = [
@ -90,13 +90,10 @@ class Controller extends Component {
} }
} }
Controller.$inject = ['$element', '$scope']; ngModule.vnComponent('vnItemDescriptor', {
ngModule.component('vnItemDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
item: '<', item: '<'
quicklinks: '<'
} }
}); });

View File

@ -49,7 +49,7 @@
<vn-td number> <vn-td number>
<span class="chip" <span class="chip"
ng-class="::{link: sale.isTicket}" ng-class="::{link: sale.isTicket}"
ng-click="$ctrl.showDescriptor($event, sale)" vn-click-stop="descriptor.show($event, sale.origin)"
name="origin"> name="origin">
{{::sale.origin | dashIfEmpty}} {{::sale.origin | dashIfEmpty}}
</span> </span>
@ -57,9 +57,13 @@
<vn-td>{{::sale.stateName | dashIfEmpty}}</vn-td> <vn-td>{{::sale.stateName | dashIfEmpty}}</vn-td>
<vn-td>{{::sale.reference | dashIfEmpty}}</vn-td> <vn-td>{{::sale.reference | dashIfEmpty}}</vn-td>
<vn-td class="truncate"> <vn-td class="truncate">
<span <span ng-if="::!sale.isTicket">
ng-class="::{link: sale.isTicket}" {{::sale.name | dashIfEmpty}}
ng-click="$ctrl.showClientDescriptor($event, sale)"> </span>
<span
ng-if="::sale.isTicket"
vn-click-stop="clientDescriptor.show($event, sale.clientFk)"
class="link">
{{::sale.name | dashIfEmpty}} {{::sale.name | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>

View File

@ -119,10 +119,10 @@ class Controller extends Section {
} }
/** /**
* Compares a date with the current one * Compares a date with the current one
* @param {Object} date - Date to compare * @param {Object} date - Date to compare
* @return {Boolean} - Returns true if the two dates equals * @return {Boolean} - Returns true if the two dates equals
*/ */
isToday(date) { isToday(date) {
let today = new Date(); let today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
@ -133,30 +133,6 @@ class Controller extends Section {
if (!(today - comparedDate)) if (!(today - comparedDate))
return true; return true;
} }
showDescriptor(event, sale) {
if (!sale.isTicket) return;
this.$.descriptor.ticketFk = sale.origin;
this.$.descriptor.parent = event.target;
this.$.descriptor.show();
event.preventDefault();
}
showClientDescriptor(event, sale) {
if (!sale.isTicket) return;
this.$.clientDescriptor.clientFk = sale.clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
}
onDescriptorLoad() {
this.$.popover.relocate();
}
} }
ngModule.component('vnItemDiary', { ngModule.component('vnItemDiary', {

View File

@ -35,15 +35,15 @@
ui-sref="item.card.summary({id: item.id})"> ui-sref="item.card.summary({id: item.id})">
<vn-td shrink> <vn-td shrink>
<img <img
ng-src="{{::$ctrl.imagesPath}}/50x50/{{::item.image}}" ng-src="{{::$root.imagePath}}/catalog/50x50/{{::item.image}}"
zoom-image="{{::$ctrl.imagesPath}}/1600x900/{{::item.image}}" zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{::item.image}}"
ng-click="$ctrl.stopEvent($event)" vn-click-stop
on-error-src/> on-error-src/>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<span <span
class="link" vn-click-stop="itemDescriptor.show($event, item.id)"
ng-click="$ctrl.showItemDescriptor($event, item.id)"> class="link">
{{::item.id | zeroFill:6}} {{::item.id | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
@ -73,7 +73,7 @@
<vn-td shrink title="{{::item.userNickname}}"> <vn-td shrink title="{{::item.userNickname}}">
<span <span
class="link" class="link"
ng-click="$ctrl.showWorkerDescriptor($event, item.buyerFk)"> vn-click-stop="workerDescriptor.show($event, item.buyerFk)">
{{::item.userNickname}} {{::item.userNickname}}
</span> </span>
</vn-td> </vn-td>
@ -87,12 +87,12 @@
<vn-td shrink> <vn-td shrink>
<vn-horizontal class="buttons"> <vn-horizontal class="buttons">
<vn-icon-button <vn-icon-button
ng-click="$ctrl.cloneItem($event, item)" vn-click-stop="clone.show(item.id)"
vn-tooltip="Clone" vn-tooltip="Clone"
icon="icon-clone"> icon="icon-clone">
</vn-icon-button> </vn-icon-button>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.preview($event, item)" vn-click-stop="$ctrl.preview(item)"
vn-tooltip="Preview" vn-tooltip="Preview"
icon="desktop_windows"> icon="desktop_windows">
</vn-icon-button> </vn-icon-button>
@ -106,18 +106,20 @@
<a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right> <a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button> <vn-float-button icon="add"></vn-float-button>
</a> </a>
<vn-popup vn-id="preview"> <vn-item-descriptor-popover
<vn-item-summary item="$ctrl.itemSelected"></vn-item-summary> vn-id="itemDescriptor">
</vn-popup> </vn-item-descriptor-popover>
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>
<vn-confirm <vn-confirm
vn-id="clone" vn-id="clone"
on-response="$ctrl.onCloneAccept($response)" on-accept="$ctrl.onCloneAccept($data)"
question="Do you want to clone this item?" question="Do you want to clone this item?"
message="All it's properties will be copied"> message="All it's properties will be copied">
</vn-confirm> </vn-confirm>
<vn-item-descriptor-popover vn-id="itemDescriptor"></vn-item-descriptor-popover> <vn-popup vn-id="preview">
<vn-worker-descriptor-popover <vn-item-summary
vn-id="workerDescriptor" item="$ctrl.itemSelected">
worker-fk="$ctrl.selectedWorker"> </vn-item-summary>
</vn-worker-descriptor-popover> </vn-popup>
<vn-scroll-up></vn-scroll-up>

View File

@ -5,68 +5,25 @@ import './style.scss';
class Controller extends Section { class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.itemSelected = null;
this.imagesPath = '//verdnatura.es/vn-image-data/catalog';
this.showFields = { this.showFields = {
id: false, id: false,
actions: false actions: false
}; };
} }
stopEvent(event) { onCloneAccept(itemFk) {
event.preventDefault(); return this.$http.post(`Items/${itemFk}/clone`)
event.stopImmediatePropagation(); .then(res => {
}
showItemDescriptor(event, itemFk) {
if (event.defaultPrevented) return;
event.preventDefault();
event.stopPropagation();
this.$.itemDescriptor.itemFk = itemFk;
this.$.itemDescriptor.parent = event.target;
this.$.itemDescriptor.show();
}
showWorkerDescriptor(event, workerFk) {
if (event.defaltPrevented) return;
event.preventDefault();
event.stopPropagation();
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
cloneItem(event, item) {
this.stopEvent(event);
this.itemSelected = item;
this.$.clone.show();
}
onCloneAccept(response) {
if (!(response == 'accept' && this.itemSelected))
return;
this.$http.post(`Items/${this.itemSelected.id}/clone`).then(res => {
if (res && res.data && res.data.id)
this.$state.go('item.card.tags', {id: res.data.id}); this.$state.go('item.card.tags', {id: res.data.id});
}); });
this.itemSelected = null;
} }
preview(event, item) { preview(item) {
this.stopEvent(event);
this.itemSelected = item; this.itemSelected = item;
this.$.preview.show(); this.$.preview.show();
} }
} }
Controller.$inject = ['$element', '$scope'];
ngModule.component('vnItemIndex', { ngModule.component('vnItemIndex', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller controller: Controller

View File

@ -16,43 +16,14 @@ describe('Item', () => {
})); }));
describe('onCloneAccept()', () => { describe('onCloneAccept()', () => {
it('should do nothing if response is not accept', () => {
jest.spyOn(controller.$state, 'go');
let response = 'ERROR!';
controller.itemSelected = 'check me';
controller.onCloneAccept(response);
expect(controller.$state.go).not.toHaveBeenCalledWith();
expect(controller.itemSelected).toEqual('check me');
});
it('should do nothing if response is accept but itemSelected is not defined in the controller', () => {
jest.spyOn(controller.$state, 'go');
let response = 'accept';
controller.itemSelected = undefined;
controller.onCloneAccept(response);
expect(controller.$state.go).not.toHaveBeenCalledWith();
expect(controller.itemSelected).toBeUndefined();
});
it('should perform a post query and then call go() then update itemSelected in the controller', () => { it('should perform a post query and then call go() then update itemSelected in the controller', () => {
jest.spyOn(controller.$state, 'go'); jest.spyOn(controller.$state, 'go');
let response = 'accept'; $httpBackend.expectRoute('POST', `Items/:id/clone`).respond({id: 99});
controller.itemSelected = {id: 1}; controller.onCloneAccept(1);
$httpBackend.when('POST', `Items/1/clone`).respond({id: 99});
$httpBackend.expect('POST', `Items/1/clone`);
controller.onCloneAccept(response);
$httpBackend.flush(); $httpBackend.flush();
expect(controller.$state.go).toHaveBeenCalledWith('item.card.tags', {id: 99}); expect(controller.$state.go).toHaveBeenCalledWith('item.card.tags', {id: 99});
expect(controller.itemSelected).toBeNull();
}); });
}); });
}); });

View File

@ -3,8 +3,8 @@
<vn-horizontal> <vn-horizontal>
<vn-one> <vn-one>
<img style="width: 100%; display: block;" <img style="width: 100%; display: block;"
ng-src="//verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}" ng-src="{{::$root.imagePath}}/catalog/200x200/{{$ctrl.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{$ctrl.item.image}}" on-error-src/> zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{$ctrl.item.image}}" on-error-src/>
<vn-horizontal class="item-state"> <vn-horizontal class="item-state">
<vn-one> <vn-one>
<p translate>Visible</p> <p translate>Visible</p>

View File

@ -5,8 +5,8 @@
<vn-card> <vn-card>
<div class="image"> <div class="image">
<img <img
ng-src="//verdnatura.es/vn-image-data/catalog/200x200/{{::item.image}}" ng-src="{{::$root.imagePath}}/catalog/200x200/{{::item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{::item.image}}" zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{::item.image}}"
on-error-src/> on-error-src/>
</div> </div>
<div class="description"> <div class="description">

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.moreOptions = [ this.moreOptions = [
@ -33,14 +33,6 @@ class Controller extends Component {
return this._order; return this._order;
} }
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
get quicklinks() {
return this._quicklinks;
}
deleteOrder(response) { deleteOrder(response) {
if (response === 'accept') { if (response === 'accept') {
const params = {id: this.order.id}; const params = {id: this.order.id};
@ -56,10 +48,10 @@ class Controller extends Component {
} }
} }
ngModule.component('vnOrderDescriptor', { ngModule.vnComponent('vnOrderDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller,
bindings: { bindings: {
order: '<' order: '<'
}, }
controller: Controller
}); });

View File

@ -27,14 +27,16 @@
ui-sref="order.card.summary({id: {{::order.id}}})"> ui-sref="order.card.summary({id: {{::order.id}}})">
<vn-td number>{{::order.id}}</vn-td> <vn-td number>{{::order.id}}</vn-td>
<vn-td expand> <vn-td expand>
<span class="link" ng-click="$ctrl.showClientDescriptor($event, order.clientFk)"> <span
vn-click-stop="clientDescriptor.show($event, order.clientFk)"
class="link">
{{::order.clientName}} {{::order.clientName}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand>
<span <span
class="link" vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
ng-click="$ctrl.showWorkerDescriptor($event, order.salesPersonFk)"> class="link" >
{{::order.workerNickname | dashIfEmpty}} {{::order.workerNickname | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
@ -51,9 +53,9 @@
<vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td> <vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td>
<vn-td shrink> <vn-td shrink>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.preview($event, order)" vn-click-stop="$ctrl.preview(order)"
vn-tooltip="Preview" icon="desktop_windows"
icon="desktop_windows"> vn-tooltip="Preview">
</vn-icon-button> </vn-icon-button>
</vn-td> </vn-td>
</vn-tr> </vn-tr>
@ -72,10 +74,11 @@
vn-id="clientDescriptor"> vn-id="clientDescriptor">
</vn-client-descriptor-popover> </vn-client-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-popup vn-id="summary"> <vn-popup vn-id="summary">
<vn-order-summary order="$ctrl.selectedOrder"></vn-order-summary> <vn-order-summary
order="$ctrl.selectedOrder">
</vn-order-summary>
</vn-popup> </vn-popup>
<vn-scroll-up></vn-scroll-up> <vn-scroll-up></vn-scroll-up>

View File

@ -2,29 +2,7 @@ import ngModule from '../module';
import Section from 'salix/components/section'; import Section from 'salix/components/section';
export default class Controller extends Section { export default class Controller extends Section {
showClientDescriptor(event, clientFk) { preview(order) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
event.stopImmediatePropagation();
}
showWorkerDescriptor(event, workerFk) {
event.preventDefault();
event.stopImmediatePropagation();
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
onDescriptorLoad() {
this.$.popover.relocate();
}
preview(event, order) {
event.preventDefault();
event.stopImmediatePropagation();
this.selectedOrder = order; this.selectedOrder = order;
this.$.summary.show(); this.$.summary.show();
} }

View File

@ -32,8 +32,8 @@
<vn-tr ng-repeat="row in $ctrl.rows"> <vn-tr ng-repeat="row in $ctrl.rows">
<vn-td shrink> <vn-td shrink>
<img <img
ng-src="//verdnatura.es/vn-image-data/catalog/50x50/{{::row.item.image}}" ng-src="{{::$root.imagePath}}/catalog/50x50/{{::row.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{::row.item.image}}" zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{::row.item.image}}"
on-error-src/> on-error-src/>
</vn-td> </vn-td>
<vn-td number> <vn-td number>

View File

@ -1,12 +1,6 @@
<vn-popover vn-id="popover"> <slot-descriptor>
<vn-spinner <vn-route-descriptor
ng-if="$ctrl.route == null"
style="padding: 1em;"
enable="true">
</vn-spinner>
<vn-route-descriptor
ng-if="$ctrl.route"
route="$ctrl.route" route="$ctrl.route"
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-route-descriptor> </vn-route-descriptor>
</vn-popover> </slot-descriptor>

View File

@ -1,59 +1,13 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import DescriptorPopover from 'salix/components/descriptor-popover';
import './style.scss';
class Controller extends Component {
constructor($element, $) {
super($element, $);
this.route = null;
this._quicklinks = {};
}
set routeFk(id) {
if (id == this._routeFk) return;
this._routeFk = id;
this.route = null;
this.getCard();
}
get routeFk() {
return this._routeFk;
}
set route(value) {
this._route = value;
this.$timeout(() => this.$.popover.relocate());
}
class Controller extends DescriptorPopover {
get route() { get route() {
return this._route; return this.entity;
} }
get quicklinks() { loadData() {
return this._quicklinks; const filter = {
}
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show() {
this.$.popover.parent = this.parent;
this.$.popover.show();
}
getCard() {
if (this.canceler)
this.canceler.resolve();
this.canceler = this.$q.defer();
let query = 'Routes/findOne';
let filter = {
fields: [ fields: [
'id', 'id',
'workerFk', 'workerFk',
@ -86,8 +40,7 @@ class Controller extends Component {
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
} }
}, }, {
{
relation: 'worker', relation: 'worker',
scope: { scope: {
fields: ['userFk'], fields: ['userFk'],
@ -107,20 +60,13 @@ class Controller extends Component {
} }
] ]
}; };
this.$http.get(query, {params: {filter}}).then(res => {
this.route = res.data; return this.getData(`Routes/${this.id}`, {filter})
this.$.$applyAsync(() => { .then(res => this.entity = res.data);
this.$.popover.relocate();
});
});
} }
} }
ngModule.component('vnRouteDescriptorPopover', { ngModule.vnComponent('vnRouteDescriptorPopover', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller
bindings: {
routeFk: '<',
quicklinks: '<'
}
}); });

View File

@ -1,74 +1,26 @@
import './index'; import './index';
describe('vnRouteDescriptorPopover', () => { describe('vnRouteDescriptorPopover', () => {
let $httpBackend;
let $scope;
let controller; let controller;
let $element; let $httpBackend;
let $timeout;
beforeEach(ngModule('route')); beforeEach(ngModule('route'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => { beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$timeout = _$timeout_; controller = $componentController('vnRouteDescriptorPopover', {
$element = angular.element(`<div></div>`); $element: null,
$scope = $rootScope.$new(); $transclude: null
$scope.popover = {relocate: () => {}, show: () => {}}; });
controller = $componentController('vnRouteDescriptorPopover', {$scope, $element});
})); }));
describe('routeFk()', () => { describe('loadData()', () => {
it(`should do nothing if the received id isn't a new one`, () => {
controller.route = 'I exist!';
controller._routeFk = 1;
jest.spyOn(controller, 'getCard');
controller.routeFk = 1;
expect(controller.route).toEqual('I exist!');
expect(controller._routeFk).toEqual(1);
expect(controller.getCard).not.toHaveBeenCalled();
});
it(`should set the received id, set the route null and then call getCard()`, () => {
controller.route = `Please don't`;
controller._routeFk = 1;
jest.spyOn(controller, 'getCard');
controller.routeFk = 999;
expect(controller.route).toBeNull();
expect(controller._routeFk).toEqual(999);
expect(controller.getCard).toHaveBeenCalledWith();
});
});
describe('route()', () => {
it(`should save the client on the controller and then call relocate()`, () => {
jest.spyOn(controller.$.popover, 'relocate');
let route = `i'm the route!`;
controller.route = route;
$timeout.flush();
expect(controller.route).toEqual(route);
expect(controller.$.popover.relocate).toHaveBeenCalledWith();
});
});
describe('show()', () => {
it(`should call the popover show() method`, () => {
jest.spyOn(controller.$.popover, 'show');
controller.show();
expect(controller.$.popover.show).toHaveBeenCalledWith();
});
});
describe('getCard()', () => {
it(`should perform a get query to store the client data into the controller`, () => { it(`should perform a get query to store the client data into the controller`, () => {
let response = {the: 'route'}; const id = 1;
const response = 'foo';
$httpBackend.whenRoute('GET', 'Routes/findOne').respond(response); $httpBackend.expectGET(`Routes/${id}`).respond(response);
controller.routeFk = 1; controller.id = id;
$httpBackend.flush(); $httpBackend.flush();
expect(controller.route).toEqual(response); expect(controller.route).toEqual(response);

View File

@ -1,9 +0,0 @@
vn-route-descriptor-popover {
vn-route-descriptor {
display: block;
width: 256px;
& > vn-card{
margin: 0!important;
}
}
}

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) { constructor($element, $, $httpParamSerializer) {
super($element, $); super($element, $);
@ -22,14 +22,6 @@ class Controller extends Component {
this.$.moreButton.data = options; this.$.moreButton.data = options;
} }
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
get quicklinks() {
return this._quicklinks;
}
onMoreChange(callback) { onMoreChange(callback) {
callback.call(this); callback.call(this);
} }
@ -73,12 +65,11 @@ class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$httpParamSerializer']; Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnRouteDescriptor', { ngModule.vnComponent('vnRouteDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller,
bindings: { bindings: {
route: '<', route: '<',
cardReload: '&?', cardReload: '&?'
quicklinks: '<' }
},
controller: Controller
}); });

View File

@ -53,8 +53,7 @@
</vn-route-summary> </vn-route-summary>
</vn-popup> </vn-popup>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<a ui-sref="route.create" <a ui-sref="route.create"
vn-tooltip="New route" vn-tooltip="New route"

View File

@ -2,11 +2,6 @@ import ngModule from '../module';
import ModuleMain from 'salix/components/module-main'; import ModuleMain from 'salix/components/module-main';
export default class Route extends ModuleMain { export default class Route extends ModuleMain {
constructor($element, $, vnConfig) {
super($element, $);
this.vnConfig = vnConfig;
}
$postLink() { $postLink() {
let to = new Date(); let to = new Date();
to.setDate(to.getDate() + 1); to.setDate(to.getDate() + 1);
@ -18,7 +13,6 @@ export default class Route extends ModuleMain {
this.filter = {from, to, warehouseFk: this.vnConfig.warehouseFk}; this.filter = {from, to, warehouseFk: this.vnConfig.warehouseFk};
} }
} }
Route.$inject = ['$element', '$scope', 'vnConfig'];
ngModule.vnComponent('vnRoute', { ngModule.vnComponent('vnRoute', {
controller: Route, controller: Route,

View File

@ -69,14 +69,14 @@
<vn-td shrink>{{ticket.priority | dashIfEmpty}}</vn-td> <vn-td shrink>{{ticket.priority | dashIfEmpty}}</vn-td>
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)" ng-click="ticketDescriptor.show($event, ticket.id)"
class="link"> class="link">
{{ticket.id | zeroFill:6}} {{ticket.id | zeroFill:6}}
</span> </span>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span <span
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)" ng-click="clientDescriptor.show($event, ticket.clientFk)"
class="link"> class="link">
{{ticket.nickname}} {{ticket.nickname}}
</span> </span>

View File

@ -16,20 +16,6 @@ class Controller extends Section {
}); });
} }
showTicketDescriptor(event, ticketFk) {
this.$.ticketDescriptor.ticketFk = ticketFk;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
event.preventDefault();
}
showClientDescriptor(event, clientFk) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
}
get route() { get route() {
return this._route; return this._route;
} }

View File

@ -60,14 +60,14 @@
</vn-td> </vn-td>
<vn-td number> <vn-td number>
<span <span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)" ng-click="ticketDescriptor.show($event, ticket.id)"
class="link"> class="link">
{{ticket.id}} {{ticket.id}}
</span> </span>
</vn-td> </vn-td>
<vn-td> <vn-td>
<span <span
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)" ng-click="clientDescriptor.show($event, ticket.clientFk)"
class="link"> class="link">
{{ticket.nickname}} {{ticket.nickname}}
</span> </span>
@ -118,10 +118,10 @@
<vn-dialog <vn-dialog
vn-id="possibleTicketsDialog" vn-id="possibleTicketsDialog"
on-response="$ctrl.setTicketsRoute($response)"> on-response="$ctrl.setTicketsRoute($response)">
<tpl-title translate>
Tickets to add
</tpl-title>
<tpl-body> <tpl-body>
<section class="header vn-pa-md">
<h5><span translate>Tickets to add</span></h5>
</section>
<vn-data-viewer class="vn-pa-md" model="possibleTicketsModel"> <vn-data-viewer class="vn-pa-md" model="possibleTicketsModel">
<vn-table model="possibleTicketsModel" auto-load="false"> <vn-table model="possibleTicketsModel" auto-load="false">
<vn-thead> <vn-thead>

View File

@ -128,20 +128,6 @@ class Controller extends Section {
}); });
} }
showTicketDescriptor(event, ticketFk) {
this.$.ticketDescriptor.ticketFk = ticketFk;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
event.preventDefault();
}
showClientDescriptor(event, clientFk) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
}
openPossibleTicketsDialog() { openPossibleTicketsDialog() {
this.$.possibleTicketsModel.refresh(); this.$.possibleTicketsModel.refresh();
this.$.possibleTicketsDialog.show(); this.$.possibleTicketsDialog.show();

View File

@ -213,36 +213,6 @@ describe('Route', () => {
}); });
}); });
describe('showTicketDescriptor()', () => {
it('should call the descriptor show function after setting the parent and the ticket id', () => {
controller.$.ticketDescriptor = {show: () => {}};
jest.spyOn(controller.$.ticketDescriptor, 'show');
const event = {target: {}, preventDefault: () => {}};
jest.spyOn(event, 'preventDefault');
const ticketId = 999;
controller.showTicketDescriptor(event, ticketId);
expect(controller.$.ticketDescriptor.ticketFk).toEqual(ticketId);
expect(controller.$.ticketDescriptor.show).toHaveBeenCalledWith();
expect(event.preventDefault).toHaveBeenCalledWith();
});
});
describe('showClientDescriptor()', () => {
it('should call the descriptor show method after setting the parent and the client id', () => {
controller.$.clientDescriptor = {show: () => {}};
jest.spyOn(controller.$.clientDescriptor, 'show');
const event = {target: {}, preventDefault: () => {}};
jest.spyOn(event, 'preventDefault');
const clientId = 999;
controller.showClientDescriptor(event, clientId);
expect(controller.$.clientDescriptor.clientFk).toEqual(clientId);
expect(controller.$.clientDescriptor.show).toHaveBeenCalledWith();
expect(event.preventDefault).toHaveBeenCalledWith();
});
});
describe('openPossibleTicketsDialog()', () => { describe('openPossibleTicketsDialog()', () => {
it('should call both refresh and show methods in posible tickets model and dialog', () => { it('should call both refresh and show methods in posible tickets model and dialog', () => {
controller.$.possibleTicketsModel = {refresh: () => {}}; controller.$.possibleTicketsModel = {refresh: () => {}};

View File

@ -1,12 +1,6 @@
<vn-popover vn-id="popover"> <slot-descriptor>
<vn-spinner
ng-if="$ctrl.ticket == null"
style="padding: 1em;"
enable="true">
</vn-spinner>
<vn-ticket-descriptor <vn-ticket-descriptor
ng-if="$ctrl.ticket"
ticket="$ctrl.ticket" ticket="$ctrl.ticket"
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-ticket-descriptor> </vn-ticket-descriptor>
</vn-popover> </slot-descriptor>

View File

@ -1,72 +1,34 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import DescriptorPopover from 'salix/components/descriptor-popover';
import './style.scss';
class Controller extends Component {
constructor($element, $) {
super($element, $);
this.ticket = null;
this._quicklinks = {};
}
set ticketFk(id) {
if (id == this._ticketFk) return;
this._ticketFk = id;
this.ticket = null;
this.getCard();
}
set ticket(value) {
this._ticket = value;
this.$timeout(() => this.$.popover.relocate());
}
class Controller extends DescriptorPopover {
get ticket() { get ticket() {
return this._ticket; return this.entity;
} }
get quicklinks() { loadData() {
return this._quicklinks; const filter = {
}
set quicklinks(value = {}) {
Object.keys(value).forEach(key => {
this._quicklinks[key] = value[key];
});
}
show() {
this.$.popover.parent = this.parent;
this.$.popover.show();
}
getCard() {
if (this.canceler)
this.canceler.resolve();
this.canceler = this.$q.defer();
let options = {timeout: this.canceler.promise};
let filter = {
include: [ include: [
{ {
relation: 'warehouse', relation: 'warehouse',
scope: { scope: {
fields: ['name'] fields: ['name']
} }
}, }, {
{
relation: 'agencyMode', relation: 'agencyMode',
scope: { scope: {
fields: ['name'] fields: ['name']
} }
}, }, {
{
relation: 'client', relation: 'client',
scope: { scope: {
fields: ['salesPersonFk', 'name', 'isActive', 'isFreezed', 'isTaxDataChecked'], fields: [
'salesPersonFk',
'name',
'isActive',
'isFreezed',
'isTaxDataChecked'
],
include: { include: {
relation: 'salesPerson', relation: 'salesPerson',
scope: { scope: {
@ -80,8 +42,7 @@ class Controller extends Component {
} }
} }
} }
}, }, {
{
relation: 'state', relation: 'state',
scope: { scope: {
fields: ['stateFk'], fields: ['stateFk'],
@ -93,22 +54,13 @@ class Controller extends Component {
} }
] ]
}; };
let json = encodeURIComponent(JSON.stringify(filter));
let query = `Tickets/${this._ticketFk}?filter=${json}`; return this.getData(`Tickets/${this.id}`, {filter})
this.$http.get(query, options).then( .then(res => this.entity = res.data);
response => {
this.ticket = response.data;
this.canceler = null;
}
);
} }
} }
ngModule.component('vnTicketDescriptorPopover', { ngModule.vnComponent('vnTicketDescriptorPopover', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller
bindings: {
ticketFk: '<',
quicklinks: '<'
}
}); });

View File

@ -1,121 +1,26 @@
import './index.js'; import './index.js';
describe('ticket Component vnTicketDescriptorPopover', () => { describe('vnTicketDescriptorPopover', () => {
let $httpBackend;
let $scope;
let controller; let controller;
let $element; let $httpBackend;
let $timeout;
beforeEach(ngModule('ticket')); beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => { beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$timeout = _$timeout_; controller = $componentController('vnTicketDescriptorPopover', {
$element = angular.element(`<div></div>`); $element: null,
$scope = $rootScope.$new(); $transclude: null
$scope.popover = {relocate: () => {}, show: () => {}}; });
controller = $componentController('vnTicketDescriptorPopover', {$scope, $element});
})); }));
describe('ticketFk()', () => { describe('loadData()', () => {
it(`should not apply any changes if the received id is the same stored in _ticketFk`, () => {
controller.ticket = 'I exist!';
controller._ticketFk = 1;
jest.spyOn(controller, 'getCard');
controller.ticketFk = 1;
expect(controller.ticket).toEqual('I exist!');
expect(controller._ticketFk).toEqual(1);
expect(controller.getCard).not.toHaveBeenCalled();
});
it(`should set the received id into _ticketFk, set the ticket to null and then call getCard()`, () => {
controller.ticket = `Please don't`;
controller._ticketFk = 1;
jest.spyOn(controller, 'getCard');
controller.ticketFk = 999;
expect(controller.ticket).toBeNull();
expect(controller._ticketFk).toEqual(999);
expect(controller.getCard).toHaveBeenCalledWith();
});
});
describe('ticket()', () => {
it(`should save the ticket into _ticket and then call relocate()`, () => {
jest.spyOn(controller.$.popover, 'relocate');
controller.ticket = `i'm the ticket!`;
$timeout.flush();
expect(controller._ticket).toEqual(`i'm the ticket!`);
expect(controller.$.popover.relocate).toHaveBeenCalledWith();
});
});
describe('show()', () => {
it(`should call the show()`, () => {
jest.spyOn(controller.$.popover, 'show');
controller.show();
expect(controller.$.popover.show).toHaveBeenCalledWith();
});
});
describe('getCard()', () => {
it(`should perform a get query to store the ticket data into the controller`, () => { it(`should perform a get query to store the ticket data into the controller`, () => {
controller.ticketFk = 1; const id = 1;
controller.canceler = null; const response = 'foo';
let response = {};
let filter = { $httpBackend.expectGET(`Tickets/${id}`).respond(response);
include: [ controller.id = id;
{
relation: 'warehouse',
scope: {
fields: ['name']
}
},
{
relation: 'agencyMode',
scope: {
fields: ['name']
}
},
{
relation: 'client',
scope: {
fields: ['salesPersonFk', 'name', 'isActive', 'isFreezed', 'isTaxDataChecked'],
include: {
relation: 'salesPerson',
scope: {
fields: ['userFk'],
include: {
relation: 'user',
scope: {
fields: ['nickname']
}
}
}
}
}
},
{
relation: 'state',
scope: {
fields: ['stateFk'],
include: {
relation: 'state',
fields: ['id', 'name'],
}
}
}
]
};
let json = encodeURIComponent(JSON.stringify(filter));
$httpBackend.when('GET', `Tickets/${controller._ticketFk}?filter=${json}`).respond(response);
$httpBackend.expect('GET', `Tickets/${controller._ticketFk}?filter=${json}`);
controller.getCard();
$httpBackend.flush(); $httpBackend.flush();
expect(controller.ticket).toEqual(response); expect(controller.ticket).toEqual(response);

View File

@ -1,11 +0,0 @@
vn-ticket-descriptor-popover {
vn-ticket-descriptor {
display: block;
width: 256px;
max-height: 448px;
& > vn-card {
margin: 0!important;
}
}
}

View File

@ -6,8 +6,8 @@ class Controller extends Component {
addStowaway(stowaway) { addStowaway(stowaway) {
let params = {id: stowaway.id, shipFk: this.ticket.id}; let params = {id: stowaway.id, shipFk: this.ticket.id};
this.$http.post(`Stowaways/`, params) this.$http.post(`Stowaways/`, params)
.then(() => this.cardReload())
.then(() => { .then(() => {
this.cardReload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.dialog.hide(); this.$.dialog.hide();
}); });

View File

@ -1,7 +1,7 @@
import ngModule from '../module'; import ngModule from '../module';
import Component from 'core/lib/component'; import Descriptor from 'salix/components/descriptor';
class Controller extends Component { class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) { constructor($element, $, $httpParamSerializer) {
super($element, $); super($element, $);
this.$httpParamSerializer = $httpParamSerializer; this.$httpParamSerializer = $httpParamSerializer;
@ -95,14 +95,6 @@ class Controller extends Component {
this._quicklinks = links; this._quicklinks = links;
} }
get quicklinks() {
return this._quicklinks;
}
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
showChangeShipped() { showChangeShipped() {
if (!this.isEditable) { if (!this.isEditable) {
this.vnApp.showError(this.$t(`This ticket can't be modified`)); this.vnApp.showError(this.$t(`This ticket can't be modified`));
@ -356,11 +348,11 @@ class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$httpParamSerializer']; Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnTicketDescriptor', { ngModule.vnComponent('vnTicketDescriptor', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller,
bindings: { bindings: {
ticket: '<', ticket: '<',
cardReload: '&' cardReload: '&'
}, }
controller: Controller
}); });

View File

@ -63,8 +63,7 @@
quicklinks="$ctrl.quicklinks"> quicklinks="$ctrl.quicklinks">
</vn-item-descriptor-popover> </vn-item-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-confirm <vn-confirm
vn-id="delete-expedition" vn-id="delete-expedition"

View File

@ -36,7 +36,7 @@
<vn-td shrink> <vn-td shrink>
<vn-check <vn-check
ng-model="ticket.checked" ng-model="ticket.checked"
ng-click="$ctrl.preventDefault($event)"> vn-click-stop>
</vn-check> </vn-check>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
@ -67,9 +67,9 @@
</vn-td> </vn-td>
<vn-td number>{{::ticket.id}}</vn-td> <vn-td number>{{::ticket.id}}</vn-td>
<vn-td expand class="expendable"> <vn-td expand class="expendable">
<span <span
class="link" vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)"
ng-click="$ctrl.showWorkerDescriptor($event, ticket.salesPersonFk)"> class="link">
{{::ticket.userNickname | dashIfEmpty}} {{::ticket.userNickname | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
@ -80,9 +80,9 @@
</vn-td> </vn-td>
<vn-td>{{::ticket.shipped | date: 'HH:mm'}}</vn-td> <vn-td>{{::ticket.shipped | date: 'HH:mm'}}</vn-td>
<vn-td expand> <vn-td expand>
<span <span
class="link" vn-click-stop="clientDescriptor.show($event, ticket.clientFk)"
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"> class="link">
{{::ticket.nickname}} {{::ticket.nickname}}
</span> </span>
</vn-td> </vn-td>
@ -103,12 +103,12 @@
</vn-td> </vn-td>
<vn-td actions> <vn-td actions>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.goToLines($event, ticket.id)" vn-click-stop="$ctrl.goToLines(ticket.id)"
vn-tooltip="Go to lines" vn-tooltip="Go to lines"
icon="icon-lines"> icon="icon-lines">
</vn-icon-button> </vn-icon-button>
<vn-icon-button <vn-icon-button
ng-click="$ctrl.preview($event, ticket)" vn-click-stop="$ctrl.preview(ticket)"
vn-tooltip="Preview" vn-tooltip="Preview"
icon="desktop_windows"> icon="desktop_windows">
</vn-icon-button> </vn-icon-button>
@ -118,7 +118,6 @@
</vn-table> </vn-table>
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
<div fixed-bottom-right> <div fixed-bottom-right>
<vn-vertical style="align-items: center;"> <vn-vertical style="align-items: center;">
<vn-button class="round sm vn-mb-sm" <vn-button class="round sm vn-mb-sm"
@ -128,7 +127,6 @@
vn-tooltip="Payment on account..." vn-tooltip="Payment on account..."
tooltip-position="left"> tooltip-position="left">
</vn-button> </vn-button>
<a ui-sref="ticket.create"> <a ui-sref="ticket.create">
<vn-button class="round md vn-mb-sm" <vn-button class="round md vn-mb-sm"
icon="add" icon="add"
@ -139,16 +137,16 @@
</a> </a>
</vn-vertical> </vn-vertical>
</div> </div>
<vn-popup vn-id="summary"> <vn-popup vn-id="summary">
<vn-ticket-summary ticket="$ctrl.selectedTicket"></vn-ticket-summary> <vn-ticket-summary
ticket="$ctrl.selectedTicket">
</vn-ticket-summary>
</vn-popup> </vn-popup>
<vn-client-descriptor-popover <vn-client-descriptor-popover
vn-id="clientDescriptor"> vn-id="clientDescriptor">
</vn-client-descriptor-popover> </vn-client-descriptor-popover>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover
vn-id="workerDescriptor" vn-id="workerDescriptor">
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover> </vn-worker-descriptor-popover>
<vn-client-balance-create <vn-client-balance-create
vn-id="balanceCreateDialog"> vn-id="balanceCreateDialog">

View File

@ -43,12 +43,6 @@ export default class Controller extends Section {
return this.checked.length; return this.checked.length;
} }
goToLines(event, ticketFk) {
this.preventDefault(event);
let url = this.$state.href('ticket.card.sale', {id: ticketFk}, {absolute: true});
window.open(url, '_blank');
}
onMoreOpen() { onMoreOpen() {
let options = this.moreOptions.filter(o => o.always || this.isChecked); let options = this.moreOptions.filter(o => o.always || this.isChecked);
this.$.moreButton.data = options; this.$.moreButton.data = options;
@ -89,30 +83,15 @@ export default class Controller extends Section {
return 'warning'; return 'warning';
} }
showClientDescriptor(event, clientFk) { goToLines(ticketFk) {
this.preventDefault(event); let url = this.$state.href('ticket.card.sale', {id: ticketFk}, {absolute: true});
this.$.clientDescriptor.clientFk = clientFk; window.open(url, '_blank');
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
} }
showWorkerDescriptor(event, workerFk) { preview(ticket) {
this.preventDefault(event);
this.selectedWorker = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
preview(event, ticket) {
this.preventDefault(event);
this.selectedTicket = ticket; this.selectedTicket = ticket;
this.$.summary.show(); this.$.summary.show();
} }
preventDefault(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
} }
ngModule.component('vnTicketIndex', { ngModule.component('vnTicketIndex', {

View File

@ -52,21 +52,6 @@ describe('Component vnTicketIndex', () => {
}); });
}); });
describe('showClientDescriptor()', () => {
it('should show the client descriptor popover', () => {
controller.$.clientDescriptor = {show: () => {}};
controller.$.clientDescriptor.show = jasmine.createSpy('show');
let event = new MouseEvent('click', {
view: $window,
bubbles: true,
cancelable: true
});
controller.showClientDescriptor(event, tickets[0].clientFk);
expect(controller.$.clientDescriptor.show).toHaveBeenCalledWith();
});
});
describe('preview()', () => { describe('preview()', () => {
it('should show the dialog summary', () => { it('should show the dialog summary', () => {
controller.$.summary = {show: () => {}}; controller.$.summary = {show: () => {}};

Some files were not shown because too many files have changed in this diff Show More