#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-body>
<h6 translate>{{::$ctrl.message}}</h6>
<span translate>{{::$ctrl.question}}</span>
</tpl-body>
<tpl-buttons>
<button response="cancel" translate>Cancel</button>
<button response="accept" translate vn-focus>Accept</button>
</tpl-buttons>
</div>
<tpl-title translate>
{{::$ctrl.message}}
</tpl-title>
<tpl-body translate>
{{::$ctrl.question}}
</tpl-body>
<tpl-buttons>
<button response="cancel" translate>Cancel</button>
<button response="accept" translate vn-focus>Accept</button>
</tpl-buttons>

View File

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

View File

@ -1,22 +1,28 @@
<div
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>
<default>
<div
class="body"
ng-transclude="body">
ng-if="$ctrl.loading"
class="loading-overlap shown">
<vn-spinner enable="true"></vn-spinner>
</div>
<div
class="buttons"
ng-click="$ctrl.onButtonClick($event)"
ng-transclude="buttons">
</div>
</form>
<vn-button
ng-click="$ctrl.hide()"
translate-attr="{title: 'Close'}"
icon="clear"
class="flat close">
</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 Popup from '../popup';
import template from './index.html';
import './style.scss';
/**
@ -16,22 +15,6 @@ import './style.scss';
* @slot buttons The dialog HTML buttons
*/
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.
*
@ -149,9 +132,11 @@ export default class Dialog extends Popup {
}
ngModule.vnComponent('vnDialog', {
slotTemplate: require('./index.html'),
controller: Dialog,
transclude: {
body: 'tplBody',
title: '?tplTitle',
body: '?tplBody',
buttons: '?tplButtons'
},
bindings: {

View File

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

View File

@ -1,22 +1,24 @@
<div ng-show="$ctrl.showFilter" class="filter">
<vn-textfield
ng-model="$ctrl.search"
class="dense search"
ng-blur="$ctrl.onFocusOut()"
placeholder="{{::'Search' | translate}}"
autocomplete="off">
</vn-textfield>
</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}}
<default>
<div ng-show="$ctrl.showFilter" class="filter">
<vn-textfield
ng-model="$ctrl.search"
class="dense search"
ng-blur="$ctrl.onFocusOut()"
placeholder="{{::'Search' | translate}}"
autocomplete="off">
</vn-textfield>
</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 ngModule from '../../module';
import Popover from '../popover';
import template from './index.html';
import ArrayModel from '../array-model/array-model';
import CrudModel from '../crud-model/crud-model';
import {mergeWhere} from 'vn-loopback/util/filter';
@ -21,7 +20,6 @@ export default class DropDown extends Popover {
this.showLoadMore = true;
this.showFilter = true;
this.searchDelay = 300;
this.fillDefaultSlot(template);
}
get search() {
@ -458,6 +456,7 @@ function getPosition(parent, event) {
}
ngModule.vnComponent('vnDropDown', {
slotTemplate: require('./index.html'),
controller: DropDown,
transclude: {
tplItem: '?tplItem'

View File

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

View File

@ -13,8 +13,8 @@ import './style.scss';
* @event close Thrown when popover is hidden
*/
export default class Popover extends Popup {
constructor($element, $, $transclude) {
super($element, $, $transclude);
constructor(...args) {
super(...args);
this.displayMode = isMobile ? 'centered' : 'relative';
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
* 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) {
if (parent instanceof Event)
parent = event.target;
if (parent) this.parent = parent;
super.show();
this.content = this.popup.querySelector('.content');

View File

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

View File

@ -11,14 +11,29 @@ export default class Component extends EventEmitter {
*
* @param {HTMLElement} $element The main component element
* @param {$rootScope.Scope} $scope The element scope
* @param {Function} $transclude The transclusion function
*/
constructor($element, $scope) {
constructor($element, $scope, $transclude) {
super();
this.$ = $scope;
if (!$element) return;
this.element = $element[0];
this.element.$ctrl = this;
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() {
@ -26,7 +41,7 @@ export default class Component extends EventEmitter {
let attrs = this.$element[0].attributes;
let $scope = this.$;
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 callback = locals => $scope.$parent.$eval(attr.nodeValue, locals);
this.on(eventName, callback);
@ -58,6 +73,72 @@ export default class Component extends EventEmitter {
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) {
let scope = this.$;
let previousBoundTranscludeFn = this.$transclude.$$boundTransclude;
@ -78,17 +159,6 @@ export default class Component extends EventEmitter {
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) {
this.$transclude.$$boundTransclude.$$slots[slot] =
$transclude.$$boundTransclude.$$slots[slot];
@ -96,38 +166,18 @@ export default class Component extends EventEmitter {
}
Component.$inject = ['$element', '$scope'];
function runFn(
$translate,
$q,
$http,
$state,
$stateParams,
$timeout,
$transitions,
$compile,
$filter,
$interpolate,
$window,
vnApp,
vnToken,
vnConfig,
aclService) {
Object.assign(Component.prototype, {
$translate,
$q,
$http,
$state,
$params: $stateParams,
$timeout,
$transitions,
$compile,
$filter,
$interpolate,
$window,
vnApp,
vnToken,
vnConfig,
aclService
/*
* Automatically adds the most used services to the prototype, so they are
* available as component properties.
*/
function runFn(...args) {
const proto = Component.prototype;
for (let i = 0; i < runFn.$inject.length; i++)
proto[runFn.$inject[i]] = args[i];
Object.assign(proto, {
$params: proto.$stateParams
});
}
runFn.$inject = [

View File

@ -1,6 +1,16 @@
import {ng, ngDeps} from './vendor';
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
* with parent component options. This method establishes the $options property
@ -17,7 +27,7 @@ import {camelToKebab} from './lib/string';
function vnComponent(name, options) {
let controller = options.controller;
let parent = Object.getPrototypeOf(controller);
let parentOptions = parent.$options || {};
let parentOptions = parent.$options || defaultOptions;
let parentTransclude = parentOptions.transclude;
let transclude = parentTransclude instanceof Object
@ -32,10 +42,11 @@ function vnComponent(name, options) {
} else if (options.transclude !== undefined)
transclude = options.transclude;
let mergedOptions = Object.assign({},
let $options = Object.assign({},
parentOptions,
options,
{
name,
transclude,
bindings: Object.assign({},
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)];
if (parent.$classNames) classNames = classNames.concat(parent.$classNames);
controller.$classNames = classNames;
return this.component(name, mergedOptions);
controller.$options = $options;
return this.component(name, $options);
}
const ngModuleFn = ng.module;
@ -72,33 +87,12 @@ export function config($translateProvider, $translatePartialLoaderProvider, $ani
// For CSS browser targeting
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
.useSanitizeValueStrategy('escape')
.useLoader('$translatePartialLoader', conf)
.registerAvailableLanguageKeys(langs, langAliases)
// 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;
.useLoader('$translatePartialLoader', {
urlTemplate: '/locale/{part}/{lang}.json'
});
$translatePartialLoaderProvider.addPart('core');
$animateProvider.customFilter(
node => node.tagName == 'UI-VIEW');

View File

@ -4,17 +4,19 @@
html [vn-horizontal], vn-horizontal, .vn-horizontal,
html [vn-vertical], vn-vertical, .vn-vertical {
display: flex;
& > * {
flex: 1;
}
}
html [vn-horizontal], vn-horizontal, .vn-horizontal {
flex-direction: row;
}
vn-horizontal[reverse] {
flex-direction: row-reverse;
}
html [vn-vertical], vn-vertical, .vn-vertical {
flex-direction: column;
}
vn-vertical[reverse] {
html [reverse] {
flex-direction: column-reverse;
}
html [wrap] {
@ -26,27 +28,12 @@ html [wrap-reverse] {
/* 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 {
flex-basis: auto;
}
html [vn-none], vn-none, .vn-none {
flex: none;
flex-basis: .1px;
}
html [vn-one], vn-one, .vn-one {
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 Component from 'core/lib/component';
import './quick-links';
import './style.scss';
export default class QuickLinks {}
ngModule.component('vnQuickLinks', {
template: require('./index.html'),
controller: QuickLinks,
bindings: {
links: '<?'
export default class Descriptor extends Component {
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
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 './background/background';
import './descriptor';
import './descriptor-popover';
import './home/home';
import './layout';
import './left-menu/left-menu';

View File

@ -74,4 +74,5 @@
</a>
</vn-list>
</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;
white-space: nowrap;
overflow: hidden;
padding-left: 6px;
padding-left: 10px;
}
& > vn-spinner {
padding: 0 6px;
@ -80,7 +80,7 @@ vn-layout {
padding-right: $menu-width;
}
[fixed-bottom-right] {
right: 64px + $menu-width;
right: 32px + $menu-width;
}
}
& > .main-view {

View File

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

View File

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

View File

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

View File

@ -1,15 +1,6 @@
import ngModule from '../../module';
import './style.scss';
let languages = {
es: 'Español',
en: 'English',
ca: 'Català',
pt: 'Português',
fr: 'Français',
nl: 'Nederlands',
mn: 'Монгол хэл'
};
import config from '../../config.json';
class Controller {
constructor($, $translate, vnConfig, vnAuth) {
@ -25,7 +16,7 @@ class Controller {
for (let code of $translate.getAvailableLanguageKeys()) {
this.langs.push({
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 appConfig from './config.json';
import 'core';
export const appName = 'salix';
@ -8,6 +9,8 @@ export default ngModule;
run.$inject = ['$window', '$rootScope', 'vnAuth', 'vnApp', '$state'];
export function run($window, $rootScope, vnAuth, vnApp, $state) {
$rootScope.imagePath = appConfig.imagePath;
$window.validations = {};
vnApp.name = appName;
@ -57,8 +60,22 @@ export function run($window, $rootScope, vnAuth, vnApp, $state) {
}
ngModule.run(run);
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider', '$compileProvider'];
export function config($translatePartialLoaderProvider, $httpProvider, $compileProvider) {
config.$inject = ['$translateProvider', '$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);
$httpProvider.interceptors.push('vnInterceptor');

View File

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

View File

@ -1,7 +1,7 @@
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) {
super($element, $);
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() {
const params = {
clientId: this.claim.clientFk,
@ -80,7 +72,7 @@ class Controller extends Component {
claimId: this.claim.id
};
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'];
ngModule.component('vnClaimDescriptor', {
ngModule.vnComponent('vnClaimDescriptor', {
template: require('./index.html'),
controller: Controller,
bindings: {
claim: '<',
tags: '<',
quicklinks: '<'
tags: '<'
}
});

View File

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

View File

@ -109,13 +109,6 @@ class Controller extends Section {
return total;
}
showItemDescriptor(event, itemFk) {
event.stopImmediatePropagation();
this.$.descriptor.itemFk = itemFk;
this.$.descriptor.parent = event.target;
this.$.descriptor.show();
}
showEditPopover(event, saleClaimed) {
if (this.isEditable) {
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()', () => {
it('should check if the claim is editable', () => {
controller.isClaimEditable();

View File

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

View File

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

View File

@ -13,31 +13,9 @@ export default class Controller extends Section {
}
}
showClientDescriptor(event, clientFk) {
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) {
preview(claim) {
this.claimSelected = claim;
this.$.dialogSummaryClaim.show();
event.preventDefault();
event.stopImmediatePropagation();
}
onDescriptorLoad() {
this.$.popover.relocate();
this.$.summary.show();
}
}

View File

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

View File

@ -32,24 +32,6 @@ class Controller extends Section {
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', {

View File

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

View File

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

View File

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

View File

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

View File

@ -1,67 +1,18 @@
import ngModule from '../module';
import Component from 'core/lib/component';
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());
}
import DescriptorPopover from 'salix/components/descriptor-popover';
class Controller extends DescriptorPopover {
get client() {
return this._client;
return this.entity;
}
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();
}
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;
}
);
loadData() {
return this.getData(`Clients/${this.id}/getCard`)
.then(res => this.entity = res.data);
}
}
ngModule.component('vnClientDescriptorPopover', {
template: require('./index.html'),
controller: Controller,
bindings: {
clientFk: '<',
quicklinks: '<'
}
ngModule.vnComponent('vnClientDescriptorPopover', {
slotTemplate: require('./index.html'),
controller: Controller
});

View File

@ -1,80 +1,29 @@
import './index';
describe('Client', () => {
describe('Component vnClientDescriptorPopover', () => {
let $httpBackend;
let $scope;
let controller;
let $element;
let $timeout;
describe('vnClientDescriptorPopover', () => {
let controller;
let $httpBackend;
beforeEach(ngModule('client'));
beforeEach(ngModule('client'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => {
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
$element = angular.element(`<div></div>`);
$scope = $rootScope.$new();
$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();
});
beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
controller = $componentController('vnClientDescriptorPopover', {
$element: null,
$transclude: null
});
}));
describe('client()', () => {
it(`should save the client into _client and then call relocate()`, () => {
jest.spyOn(controller.$.popover, 'relocate');
controller.client = `i'm the client!`;
$timeout.flush();
describe('loadData()', () => {
it(`should perform a get query to store the client data into the controller`, () => {
const id = 1;
const response = 'foo';
expect(controller._client).toEqual(`i'm the client!`);
expect(controller.$.popover.relocate).toHaveBeenCalledWith();
});
});
$httpBackend.expectGET(`Clients/${id}/getCard`).respond(response);
controller.id = id;
$httpBackend.flush();
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 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);
});
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})">
<vn-icon icon="desktop_windows"></vn-icon>
</a>
<vn-icon-menu
vn-id="more-button"
<vn-icon-button
icon="more_vert"
show-filter="false"
value-field="callback"
translate-fields="['name']"
data="$ctrl.moreOptions"
on-change="$ctrl.onMoreChange(value)"
on-open="$ctrl.onMoreOpen()">
</vn-icon-menu>
vn-popover="menu">
</vn-icon-button>
</div>
<div class="body">
<div class="attributes">
<h5>{{$ctrl.client.name}}</h5>
<vn-label-value label="Id"
<vn-label-value
label="Id"
value="{{$ctrl.client.id}}">
</vn-label-value>
<vn-label-value label="Phone"
<vn-label-value
label="Phone"
value="{{$ctrl.client.phone | phone}}">
</vn-label-value>
<vn-label-value label="Credit"
<vn-label-value
label="Credit"
value="{{$ctrl.client.credit | currency: 'EUR': 2}}">
</vn-label-value>
<vn-label-value label="Secured credit"
<vn-label-value
label="Secured credit"
value="{{$ctrl.client.creditInsurance | currency: 'EUR': 2}}">
</vn-label-value>
<vn-label-value label="Sales person"
<vn-label-value
label="Sales person"
value="{{$ctrl.client.salesPerson.user.nickname}}">
</vn-label-value>
</div>
@ -63,17 +62,57 @@
ng-class="{bright: $ctrl.client.isTaxDataChecked == false}">
</vn-icon>
</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
links="$ctrl.quicklinks">
</vn-quick-links>
-->
</div>
</div>
<!-- SMS Dialog -->
<vn-client-sms vn-id="sms" sms="$ctrl.newSMS"></vn-client-sms>
<!-- SMS Dialog -->
<vn-menu vn-id="menu">
<ul class="vn-list">
<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-id="consumerReportDialog"
on-response="$ctrl.sendConsumerReport($response)">
on-accept="$ctrl.onConsumerReportAccept()">
<tpl-body>
<div>
<h5 style="text-align: center">

View File

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

View File

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

View File

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

View File

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

View File

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

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 Component from 'core/lib/component';
import Descriptor from 'salix/components/descriptor';
class Controller extends Component {
class Controller extends Descriptor {
constructor($element, $) {
super($element, $);
this.moreOptions = [
@ -82,21 +82,12 @@ class Controller extends Component {
.then(() => this.$state.reload())
.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'),
controller: Controller,
bindings: {
invoiceOut: '<',
quicklinks: '<'
},
controller: Controller
invoiceOut: '<'
}
});

View File

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

View File

@ -2,30 +2,14 @@ import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
showClientDescriptor(event, clientFk) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
event.preventDefault();
event.stopImmediatePropagation();
}
preview(event, invoiceOut) {
preview(invoiceOut) {
this.selectedInvoiceOut = invoiceOut;
this.$.summary.show();
event.preventDefault();
event.stopImmediatePropagation();
}
onDescriptorLoad() {
this.$.popover.relocate();
}
openPdf(id, event) {
openPdf(id) {
let url = `api/InvoiceOuts/${id}/download?access_token=${this.vnToken.token}`;
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-td number>
<span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)"
ng-click="ticketDescriptor.show($event, ticket.id)"
class="link">
{{ticket.id}}
</span>
</vn-td>
<vn-td>
<span
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"
ng-click="clientDescriptor.show($event, ticket.clientFk)"
class="link">
{{ticket.nickname}}
</span>

View File

@ -14,29 +14,8 @@ class Controller extends Section {
}
getSummary() {
this.$http.get(`InvoiceOuts/${this.invoiceOut.id}/summary`).then(response => {
this.summary = response.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();
return this.$http.get(`InvoiceOuts/${this.invoiceOut.id}/summary`)
.then(res => this.summary = res.data);
}
}

View File

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

View File

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

View File

@ -1,79 +1,29 @@
import './index.js';
import './index';
describe('Item', () => {
describe('Component vnItemDescriptorPopover', () => {
let $httpBackend;
let $scope;
let controller;
let $timeout;
describe('vnItemDescriptorPopover', () => {
let controller;
let $httpBackend;
beforeEach(ngModule('item'));
beforeEach(ngModule('item'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => {
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
$scope = $rootScope.$new();
$scope.popover = {relocate: () => {}, show: () => {}};
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();
});
beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
controller = $componentController('vnItemDescriptorPopover', {
$element: null,
$transclude: null
});
}));
describe('item()', () => {
it(`should save the item into _item and then call relocate()`, () => {
jest.spyOn(controller.$.popover, 'relocate');
controller.item = `i'm the item!`;
$timeout.flush();
describe('loadData()', () => {
it(`should perform a get query to store the item data into the controller`, () => {
const id = 1;
const response = 'foo';
expect(controller._item).toEqual(`i'm the item!`);
expect(controller.$.popover.relocate).toHaveBeenCalledWith();
});
});
$httpBackend.expectGET(`Items/${id}/getCard`).respond(response);
controller.id = id;
$httpBackend.flush();
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 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);
});
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 style="position: relative" text-center>
<img
ng-src="//verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}"
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{$ctrl.item.image}}"
ng-src="{{::$root.imagePath}}/catalog/200x200/{{$ctrl.item.image}}"
zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{$ctrl.item.image}}"
on-error-src/>
<a href="//verdnatura.es/#!form=admin/items&filter={{$ctrl.item.id}}" target="_blank">
<vn-float-button

View File

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

View File

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

View File

@ -119,10 +119,10 @@ class Controller extends Section {
}
/**
* Compares a date with the current one
* @param {Object} date - Date to compare
* @return {Boolean} - Returns true if the two dates equals
*/
* Compares a date with the current one
* @param {Object} date - Date to compare
* @return {Boolean} - Returns true if the two dates equals
*/
isToday(date) {
let today = new Date();
today.setHours(0, 0, 0, 0);
@ -133,30 +133,6 @@ class Controller extends Section {
if (!(today - comparedDate))
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', {

View File

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

View File

@ -5,68 +5,25 @@ import './style.scss';
class Controller extends Section {
constructor($element, $) {
super($element, $);
this.itemSelected = null;
this.imagesPath = '//verdnatura.es/vn-image-data/catalog';
this.showFields = {
id: false,
actions: false
};
}
stopEvent(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
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)
onCloneAccept(itemFk) {
return this.$http.post(`Items/${itemFk}/clone`)
.then(res => {
this.$state.go('item.card.tags', {id: res.data.id});
});
this.itemSelected = null;
});
}
preview(event, item) {
this.stopEvent(event);
preview(item) {
this.itemSelected = item;
this.$.preview.show();
}
}
Controller.$inject = ['$element', '$scope'];
ngModule.component('vnItemIndex', {
template: require('./index.html'),
controller: Controller

View File

@ -16,43 +16,14 @@ describe('Item', () => {
}));
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', () => {
jest.spyOn(controller.$state, 'go');
let response = 'accept';
controller.itemSelected = {id: 1};
$httpBackend.when('POST', `Items/1/clone`).respond({id: 99});
$httpBackend.expect('POST', `Items/1/clone`);
controller.onCloneAccept(response);
$httpBackend.expectRoute('POST', `Items/:id/clone`).respond({id: 99});
controller.onCloneAccept(1);
$httpBackend.flush();
expect(controller.$state.go).toHaveBeenCalledWith('item.card.tags', {id: 99});
expect(controller.itemSelected).toBeNull();
});
});
});

View File

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

View File

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

View File

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

View File

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

View File

@ -2,29 +2,7 @@ import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
showClientDescriptor(event, clientFk) {
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();
preview(order) {
this.selectedOrder = order;
this.$.summary.show();
}

View File

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

View File

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

View File

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

View File

@ -1,74 +1,26 @@
import './index';
describe('vnRouteDescriptorPopover', () => {
let $httpBackend;
let $scope;
let controller;
let $element;
let $timeout;
let $httpBackend;
beforeEach(ngModule('route'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => {
beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
$element = angular.element(`<div></div>`);
$scope = $rootScope.$new();
$scope.popover = {relocate: () => {}, show: () => {}};
controller = $componentController('vnRouteDescriptorPopover', {$scope, $element});
controller = $componentController('vnRouteDescriptorPopover', {
$element: null,
$transclude: null
});
}));
describe('routeFk()', () => {
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()', () => {
describe('loadData()', () => {
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);
controller.routeFk = 1;
$httpBackend.expectGET(`Routes/${id}`).respond(response);
controller.id = id;
$httpBackend.flush();
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 Component from 'core/lib/component';
import Descriptor from 'salix/components/descriptor';
class Controller extends Component {
class Controller extends Descriptor {
constructor($element, $, $httpParamSerializer) {
super($element, $);
@ -22,14 +22,6 @@ class Controller extends Component {
this.$.moreButton.data = options;
}
set quicklinks(value = {}) {
this._quicklinks = Object.assign(value, this._quicklinks);
}
get quicklinks() {
return this._quicklinks;
}
onMoreChange(callback) {
callback.call(this);
}
@ -73,12 +65,11 @@ class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnRouteDescriptor', {
ngModule.vnComponent('vnRouteDescriptor', {
template: require('./index.html'),
controller: Controller,
bindings: {
route: '<',
cardReload: '&?',
quicklinks: '<'
},
controller: Controller
cardReload: '&?'
}
});

View File

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

View File

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

View File

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

View File

@ -60,14 +60,14 @@
</vn-td>
<vn-td number>
<span
ng-click="$ctrl.showTicketDescriptor($event, ticket.id)"
ng-click="ticketDescriptor.show($event, ticket.id)"
class="link">
{{ticket.id}}
</span>
</vn-td>
<vn-td>
<span
ng-click="$ctrl.showClientDescriptor($event, ticket.clientFk)"
ng-click="clientDescriptor.show($event, ticket.clientFk)"
class="link">
{{ticket.nickname}}
</span>
@ -118,10 +118,10 @@
<vn-dialog
vn-id="possibleTicketsDialog"
on-response="$ctrl.setTicketsRoute($response)">
<tpl-title translate>
Tickets to add
</tpl-title>
<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-table model="possibleTicketsModel" auto-load="false">
<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() {
this.$.possibleTicketsModel.refresh();
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()', () => {
it('should call both refresh and show methods in posible tickets model and dialog', () => {
controller.$.possibleTicketsModel = {refresh: () => {}};

View File

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

View File

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

View File

@ -1,121 +1,26 @@
import './index.js';
describe('ticket Component vnTicketDescriptorPopover', () => {
let $httpBackend;
let $scope;
describe('vnTicketDescriptorPopover', () => {
let controller;
let $element;
let $timeout;
let $httpBackend;
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$timeout_) => {
beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
$element = angular.element(`<div></div>`);
$scope = $rootScope.$new();
$scope.popover = {relocate: () => {}, show: () => {}};
controller = $componentController('vnTicketDescriptorPopover', {$scope, $element});
controller = $componentController('vnTicketDescriptorPopover', {
$element: null,
$transclude: null
});
}));
describe('ticketFk()', () => {
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()', () => {
describe('loadData()', () => {
it(`should perform a get query to store the ticket data into the controller`, () => {
controller.ticketFk = 1;
controller.canceler = null;
let response = {};
const id = 1;
const response = 'foo';
let filter = {
include: [
{
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.expectGET(`Tickets/${id}`).respond(response);
controller.id = id;
$httpBackend.flush();
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) {
let params = {id: stowaway.id, shipFk: this.ticket.id};
this.$http.post(`Stowaways/`, params)
.then(() => this.cardReload())
.then(() => {
this.cardReload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.dialog.hide();
});

View File

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

View File

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

View File

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

View File

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

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