This commit is contained in:
Javi Gallego 2019-02-06 07:58:43 +01:00
commit f9982047aa
125 changed files with 1499 additions and 918 deletions

View File

@ -38,7 +38,7 @@
"Vehicle": { "Vehicle": {
"dataSource": "vn" "dataSource": "vn"
}, },
"UserTableConfiguration": { "UserConfigView": {
"dataSource": "vn" "dataSource": "vn"
} }
} }

View File

@ -1,9 +1,9 @@
{ {
"name": "UserTableConfiguration", "name": "UserConfigView",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "salix.userTableConfiguration" "table": "salix.userConfigView"
} }
}, },
"properties": { "properties": {
@ -21,10 +21,10 @@
} }
}, },
"relations": { "relations": {
"worker": { "user": {
"type": "belongsTo", "type": "belongsTo",
"model": "Worker", "model": "Account",
"foreignKey": "workerFk" "foreignKey": "userFk"
} }
} }
} }

View File

@ -190,6 +190,19 @@ let actions = {
}, done, selector); }, done, selector);
}, },
clickIfVisible: function(selector, done) {
this.wait(selector)
.isVisible(selector)
.then(visible => {
if (visible)
return this.click(selector);
throw new Error(`invisible selector: ${selector}`);
})
.then(done)
.catch(done);
},
countElement: function(selector, done) { countElement: function(selector, done) {
this.evaluate_now(selector => { this.evaluate_now(selector => {
return document.querySelectorAll(selector).length; return document.querySelectorAll(selector).length;

View File

@ -164,7 +164,7 @@ export default {
newPaymentButton: `${components.vnFloatButton}`, newPaymentButton: `${components.vnFloatButton}`,
newPaymentBankInut: `vn-client-risk-create vn-textfield[field="$ctrl.receipt.bankFk"] input`, newPaymentBankInut: `vn-client-risk-create vn-textfield[field="$ctrl.receipt.bankFk"] input`,
newPaymentAmountInput: `vn-client-risk-create vn-textfield[field="$ctrl.receipt.amountPaid"] input`, newPaymentAmountInput: `vn-client-risk-create vn-textfield[field="$ctrl.receipt.amountPaid"] input`,
saveButton: `${components.vnSubmit}`, saveButton: `vn-client-risk-create vn-button[label="Save"]`,
firstRiskLineBalance: 'vn-client-risk-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)' firstRiskLineBalance: 'vn-client-risk-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)'
}, },
@ -191,7 +191,8 @@ export default {
moreMenu: `vn-item-descriptor vn-icon-menu > div > vn-icon`, moreMenu: `vn-item-descriptor vn-icon-menu > div > vn-icon`,
moreMenuRegularizeButton: `vn-item-descriptor vn-icon-menu > div > vn-drop-down > vn-popover ul > li:nth-child(1)`, moreMenuRegularizeButton: `vn-item-descriptor vn-icon-menu > div > vn-drop-down > vn-popover ul > li:nth-child(1)`,
regularizeQuantityInput: `vn-item-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-textfield > div > div > div.infix > input`, regularizeQuantityInput: `vn-item-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-textfield > div > div > div.infix > input`,
regularizeWarehouseAutocomplete: 'vn-item-descriptor > vn-dialog vn-autocomplete[field="$ctrl.warehouseFk"]', regularizeWarehouseAutocomplete: 'vn-item-descriptor vn-dialog vn-autocomplete[field="$ctrl.warehouseFk"]',
editButton: 'vn-item-card vn-item-descriptor vn-float-button[icon="edit"]',
regularizeSaveButton: `vn-item-descriptor > vn-dialog > div > form > div.buttons > tpl-buttons > button` regularizeSaveButton: `vn-item-descriptor > vn-dialog > div > form > div.buttons > tpl-buttons > button`
}, },
itemBasicData: { itemBasicData: {
@ -335,7 +336,7 @@ export default {
descriptorItemDiaryButton: `vn-item-descriptor .quicklinks.ng-scope > vn-horizontal > a > vn-icon > i`, descriptorItemDiaryButton: `vn-item-descriptor .quicklinks.ng-scope > vn-horizontal > a > vn-icon > i`,
newItemButton: 'vn-float-button[icon="add"]', newItemButton: 'vn-float-button[icon="add"]',
firstSaleText: `vn-table div > vn-tbody > vn-tr:nth-child(1)`, firstSaleText: `vn-table div > vn-tbody > vn-tr:nth-child(1)`,
firstSaleThumbnailImage: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(3) > img', firstSaleThumbnailImage: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) vn-td:nth-child(3) > img',
firstSaleZoomedImage: 'body > div > div > img', firstSaleZoomedImage: 'body > div > div > img',
firstSaleQuantity: `vn-textfield[model="sale.quantity"]:nth-child(1) input`, firstSaleQuantity: `vn-textfield[model="sale.quantity"]:nth-child(1) input`,
firstSaleQuantityClearInput: `vn-textfield[model="sale.quantity"] div.suffix > i`, firstSaleQuantityClearInput: `vn-textfield[model="sale.quantity"] div.suffix > i`,

View File

@ -163,6 +163,13 @@ describe('Item summary path', () => {
expect(url.hash).toContain('summary'); expect(url.hash).toContain('summary');
}); });
it(`should check the descritor edit button is not visible for employee`, async() => {
const visibleButton = await nightmare
.isVisible(selectors.itemDescriptor.editButton);
expect(visibleButton).toBeFalsy();
});
it(`should check the item summary shows fields from basic data section`, async() => { it(`should check the item summary shows fields from basic data section`, async() => {
const result = await nightmare const result = await nightmare
.waitForTextInElement(selectors.itemSummary.basicData, 'Object2 Gem2 3') .waitForTextInElement(selectors.itemSummary.basicData, 'Object2 Gem2 3')

View File

@ -11,6 +11,13 @@ describe('Item Edit basic data path', () => {
.accessToSection('item.card.data'); .accessToSection('item.card.data');
}); });
it(`should check the descritor edit button is visible for buyer`, async() => {
const visibleButton = await nightmare
.isVisible(selectors.itemDescriptor.editButton);
expect(visibleButton).toBeTruthy();
});
it(`should edit the item basic data`, async() => { it(`should edit the item basic data`, async() => {
const result = await nightmare const result = await nightmare
.clearInput(selectors.itemBasicData.nameInput) .clearInput(selectors.itemBasicData.nameInput)

View File

@ -14,10 +14,11 @@ describe('Ticket Create new tracking state path', () => {
it('should access to the create state view by clicking the create floating button', async() => { it('should access to the create state view by clicking the create floating button', async() => {
let url = await nightmare let url = await nightmare
.waitToClick(selectors.ticketTracking.createStateButton) .clickIfVisible(selectors.ticketTracking.createStateButton)
.wait(selectors.createStateView.stateAutocomplete) .wait(selectors.createStateView.stateAutocomplete)
.parsedUrl(); .parsedUrl();
expect(url.hash).toContain('tracking/edit'); expect(url.hash).toContain('tracking/edit');
}); });

View File

@ -62,7 +62,7 @@ describe('Ticket Edit sale path', () => {
it(`should click on the thumbnail image of the 1st sale and see the zoomed image`, async() => { it(`should click on the thumbnail image of the 1st sale and see the zoomed image`, async() => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleThumbnailImage) .clickIfVisible(selectors.ticketSales.firstSaleThumbnailImage)
.countElement(selectors.ticketSales.firstSaleZoomedImage); .countElement(selectors.ticketSales.firstSaleZoomedImage);
expect(result).toEqual(1); expect(result).toEqual(1);
@ -70,7 +70,8 @@ describe('Ticket Edit sale path', () => {
it(`should click on the zoomed image to close it`, async() => { it(`should click on the zoomed image to close it`, async() => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleZoomedImage) .wait(1000)
.clickIfVisible(selectors.ticketSales.firstSaleZoomedImage)
.countElement(selectors.ticketSales.firstSaleZoomedImage); .countElement(selectors.ticketSales.firstSaleZoomedImage);
expect(result).toEqual(0); expect(result).toEqual(0);
@ -94,15 +95,15 @@ describe('Ticket Edit sale path', () => {
it(`should click on the descriptor image of the 1st sale and see the zoomed image`, async() => { it(`should click on the descriptor image of the 1st sale and see the zoomed image`, async() => {
const result = await nightmare const result = await nightmare
.waitToClick('vn-item-descriptor img') .clickIfVisible('vn-item-descriptor img')
.countElement(selectors.ticketSales.firstSaleZoomedImage); .countElement(selectors.ticketSales.firstSaleZoomedImage);
expect(result).toEqual(1); expect(result).toEqual(1);
}); });
it(`should click on the zoomed image to close it`, async() => { it(`should now click on the zoomed image to close it`, async() => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.ticketSales.firstSaleZoomedImage) .clickIfVisible(selectors.ticketSales.firstSaleZoomedImage)
.countElement(selectors.ticketSales.firstSaleZoomedImage); .countElement(selectors.ticketSales.firstSaleZoomedImage);
expect(result).toEqual(0); expect(result).toEqual(0);

View File

@ -1,7 +1,8 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare'; import createNightmare from '../../helpers/nightmare';
describe('Ticket descriptor path', () => { // #1051 Traducciones que fallan
xdescribe('Ticket descriptor path', () => {
const nightmare = createNightmare(); const nightmare = createNightmare();
beforeAll(() => { beforeAll(() => {

View File

@ -13,6 +13,5 @@ COPY front/nginx.conf sites-available/salix
RUN rm sites-enabled/default && ln -s ../sites-available/salix sites-enabled/salix RUN rm sites-enabled/default && ln -s ../sites-available/salix sites-enabled/salix
COPY dist /salix/dist COPY dist /salix/dist
COPY front/salix/manifest.json /salix/dist/
CMD ["nginx", "-g", "daemon off;"] CMD ["nginx", "-g", "daemon off;"]

View File

@ -47,9 +47,6 @@ export default class Dialog extends Component {
if (this.onOpen) if (this.onOpen)
this.onOpen(); this.onOpen();
let firstFocusable = this.element.querySelector('input, textarea');
if (firstFocusable) firstFocusable.focus();
} }
/** /**

View File

@ -5,7 +5,7 @@
<vn-icon icon="keyboard_arrow_up" ng-if="item.childs.length" <vn-icon icon="keyboard_arrow_up" ng-if="item.childs.length"
ng-click="$ctrl.toggle(item, $event)"> ng-click="$ctrl.toggle(item, $event)">
</vn-icon> </vn-icon>
<vn-icon icon="keyboard_arrow_down" ng-if="!item.childs" <vn-icon icon="keyboard_arrow_down" ng-if="item.sons > 0 && !item.childs"
ng-click="$ctrl.toggle(item, $event)"> ng-click="$ctrl.toggle(item, $event)">
</vn-icon> </vn-icon>
</vn-auto> </vn-auto>

View File

@ -20,6 +20,7 @@ export default class Treeview extends Component {
refresh() { refresh() {
this.model.refresh().then(() => { this.model.refresh().then(() => {
this.data = this.model.data; this.data = this.model.data;
console.log(this.data);
this.repaintAll(); this.repaintAll();
}); });
} }

View File

@ -38,3 +38,4 @@ October: Octubre
November: Noviembre November: Noviembre
December: Diciembre December: Diciembre
Has delivery: Hay reparto Has delivery: Hay reparto
Loading: Cargando

View File

@ -3,10 +3,10 @@
<img src="./logo.svg" alt="Logo"></img> <img src="./logo.svg" alt="Logo"></img>
</a> </a>
<vn-icon <vn-icon
ng-if="$ctrl.showLeftMenuButton"
class="show-menu"
icon="menu" icon="menu"
ng-click="$ctrl.showLeftMenu()"> class="show-menu"
ng-if="$ctrl.leftMenu"
ng-click="$ctrl.leftMenu.show()">
</vn-icon> </vn-icon>
<div class="main-title" translate> <div class="main-title" translate>
{{$ctrl.$state.current.description}} {{$ctrl.$state.current.description}}
@ -14,20 +14,15 @@
<vn-spinner enable="$ctrl.vnApp.loading"></vn-spinner> <vn-spinner enable="$ctrl.vnApp.loading"></vn-spinner>
<vn-main-menu></vn-main-menu> <vn-main-menu></vn-main-menu>
<vn-icon <vn-icon
ng-if="$ctrl.rightMenu"
class="show-menu"
icon="menu" icon="menu"
ng-click="$ctrl.showRightMenu()"> class="show-menu"
ng-if="$ctrl.rightMenu"
ng-click="$ctrl.rightMenu.show()">
</vn-icon> </vn-icon>
</vn-topbar> </vn-topbar>
<div ui-view <div ui-view
class="main-view" class="main-view"
ng-class="{'padding': $ctrl.showTopbar}"> ng-class="{padding: $ctrl.showTopbar}">
<vn-home></vn-home> <vn-home></vn-home>
</div> </div>
<div
class="background"
ng-class="{shown: $ctrl.leftMenuShown || $ctrl.rightMenuShown}"
ng-click="$ctrl.hideMenus()">
</div>
<vn-snackbar vn-id="snackbar"></vn-snackbar> <vn-snackbar vn-id="snackbar"></vn-snackbar>

View File

@ -1,19 +1,18 @@
import ngModule from '../../module'; import ngModule from '../../module';
import './style.scss'; import './style.scss';
/**
* The main graphical application component.
*
* @property {SideMenu} leftMenu The left menu, if it's present
* @property {SideMenu} rightMenu The left menu, if it's present
*/
export default class App { export default class App {
constructor($, $element, vnApp, $state, $transitions) { constructor($, $state, vnApp) {
Object.assign(this, { Object.assign(this, {
$, $,
$element, $state,
vnApp, vnApp
$state
});
$transitions.onStart({}, transition => {
let state = transition.targetState().name();
this.showLeftMenuButton = state.split('.').length >= 3;
this.hideMenus();
}); });
} }
@ -30,33 +29,6 @@ export default class App {
return state && state != 'login'; return state && state != 'login';
} }
get leftMenu() {
return this.$element[0].querySelector('.left-menu');
}
showLeftMenu() {
if (!this.leftMenu) return;
this.leftMenu.classList.add('shown');
this.leftMenuShown = true;
}
showRightMenu() {
if (!this.rightMenu) return;
this.rightMenu.classList.add('shown');
this.rightMenuShown = true;
}
hideMenus() {
if (this.leftMenuShown) {
this.leftMenu.classList.remove('shown');
this.leftMenuShown = false;
}
if (this.rightMenuShown) {
this.rightMenu.classList.remove('shown');
this.rightMenuShown = false;
}
}
showMessage(message) { showMessage(message) {
this.$.snackbar.show({message: message}); this.$.snackbar.show({message: message});
} }
@ -69,7 +41,7 @@ export default class App {
this.$.snackbar.showError({message: message}); this.$.snackbar.showError({message: message});
} }
} }
App.$inject = ['$scope', '$element', 'vnApp', '$state', '$transitions']; App.$inject = ['$scope', '$state', 'vnApp'];
ngModule.component('vnApp', { ngModule.component('vnApp', {
template: require('./app.html'), template: require('./app.html'),

View File

@ -1,9 +1,6 @@
@import "background"; @import "background";
@import "margin"; @import "margin";
@import "variables";
$menu-width: 16em;
$topbar-height: 4em;
$mobile-width: 800px;
body { body {
@extend .bg-content; @extend .bg-content;
@ -72,27 +69,6 @@ vn-app {
margin: 0 auto; margin: 0 auto;
padding-left: $menu-width; padding-left: $menu-width;
%side-menu {
display: block;
position: fixed;
z-index: 5;
bottom: 0;
width: $menu-width;
min-width: $menu-width;
background-color: white;
box-shadow: 0 .1em .2em rgba(1, 1, 1, .2);
overflow: auto;
}
.left-menu {
@extend %side-menu;
top: $topbar-height;
left: 0;
}
.right-menu {
@extend %side-menu;
top: $topbar-height;
right: 0;
}
} }
.main-with-right-menu { .main-with-right-menu {
padding-right: $menu-width; padding-right: $menu-width;
@ -102,18 +78,6 @@ vn-app {
} }
} }
} }
& > .background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
z-index: 14;
opacity: 0;
transition: opacity 200ms ease-out;
}
@media screen and (max-width: $mobile-width) { @media screen and (max-width: $mobile-width) {
& > vn-topbar > header { & > vn-topbar > header {
@ -135,32 +99,10 @@ vn-app {
} }
vn-main-block { vn-main-block {
padding-left: 0; padding-left: 0;
%side-menu-mobile {
top: 0;
transition: transform 200ms ease-out;
z-index: 15;
&.shown {
transform: translateZ(0) translateX(0);
}
}
.left-menu {
@extend %side-menu-mobile;
transform: translateZ(0) translateX(-$menu-width);
}
.right-menu {
@extend %side-menu-mobile;
transform: translateZ(0) translateX($menu-width);
}
} }
.main-with-right-menu { .main-with-right-menu {
padding-right: 0; padding-right: 0;
} }
} }
& > .background.shown {
display: block;
opacity: .3;
}
} }
} }

View File

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

View File

@ -0,0 +1,26 @@
@import "variables";
@keyframes fadein {
from {
opacity: 0;
}
}
vn-background {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
z-index: 14;
@media screen and (max-width: $mobile-width) {
&.shown {
display: block;
opacity: .3;
animation: 500ms ease-out fadein;
}
}
}

View File

@ -2,6 +2,8 @@ import './app/app';
import './login/login'; import './login/login';
import './home/home'; import './home/home';
import './main-menu/main-menu'; import './main-menu/main-menu';
import './background/background';
import './side-menu/side-menu';
import './left-menu/left-menu'; import './left-menu/left-menu';
import './topbar/topbar'; import './topbar/topbar';
import './user-configuration-popover'; import './user-configuration-popover';

View File

@ -5,6 +5,7 @@
class="unselectable"> class="unselectable">
{{currentUserName}} {{currentUserName}}
</div> </div>
<div>
<vn-icon <vn-icon
id="apps" id="apps"
icon="apps" icon="apps"
@ -19,6 +20,8 @@
</li> </li>
</ul> </ul>
</vn-menu> </vn-menu>
</div>
<div>
<vn-icon <vn-icon
id="logout" id="logout"
icon="exit_to_app" icon="exit_to_app"
@ -26,5 +29,7 @@
ng-click="$ctrl.onLogoutClick()"> ng-click="$ctrl.onLogoutClick()">
</vn-icon> </vn-icon>
</div> </div>
<vn-user-configuration-popover vn-id="popover"> </div>
<vn-user-configuration-popover
vn-id="popover">
</vn-user-configuration-popover> </vn-user-configuration-popover>

View File

@ -2,13 +2,13 @@ import ngModule from '../../module';
import './style.scss'; import './style.scss';
export default class MainMenu { export default class MainMenu {
constructor($translate, $scope, $http, $window, vnModules, vnAuth) { constructor($, $http, vnAuth, vnModules) {
this.$ = $scope; Object.assign(this, {
this.$http = $http; $,
this.$translate = $translate; $http,
this.$window = $window; vnAuth,
this.modules = vnModules.get(); modules: vnModules.get()
this.vnAuth = vnAuth; });
} }
$onInit() { $onInit() {
@ -30,7 +30,7 @@ export default class MainMenu {
this.vnAuth.logout(); this.vnAuth.logout();
} }
} }
MainMenu.$inject = ['$translate', '$scope', '$http', '$window', 'vnModules', 'vnAuth']; MainMenu.$inject = ['$scope', '$http', 'vnAuth', 'vnModules'];
ngModule.component('vnMainMenu', { ngModule.component('vnMainMenu', {
template: require('./main-menu.html'), template: require('./main-menu.html'),

View File

@ -12,7 +12,7 @@ vn-main-menu {
& > * { & > * {
cursor: pointer; cursor: pointer;
padding-left: .3em; padding-left: .6em;
&:hover { &:hover {
color: $main-01; color: $main-01;
@ -21,10 +21,9 @@ vn-main-menu {
& > #user { & > #user {
vertical-align: middle; vertical-align: middle;
font-weight: bold; font-weight: bold;
padding-right: .4em; margin-right: .2em;
} }
& > vn-icon, & > div > vn-icon {
& > a > vn-icon {
display: block; display: block;
font-size: 2.1em; font-size: 2.1em;
} }

View File

@ -0,0 +1,9 @@
<vn-background
ng-class="{shown: $ctrl.shown}"
ng-click="$ctrl.hide()">
</vn-background>
<div
class="menu"
ng-class="{shown: $ctrl.shown}"
ng-transclude>
</div>

View File

@ -0,0 +1,78 @@
import ngModule from '../../module';
import './style.scss';
/**
* A side menu.
*
* @property {String} side [left|right] The side where the menu is displayed
* @property {Boolean} shown Whether the menu it's currently displayed (Only for small viewports)
*/
export default class SideMenu {
constructor($, $element, $window, $transitions) {
Object.assign(this, {
$,
$element,
$window,
$transitions,
side: 'left'
});
}
$onInit() {
this.menu = this.$element[0].querySelector('.menu');
if (this.side == 'right') {
this.menu.classList.add('right');
this.app.rightMenu = this;
} else {
this.menu.classList.add('left');
this.app.leftMenu = this;
}
}
$onDestroy() {
if (this.side == 'right')
this.app.rightMenu = null;
else
this.app.leftMenu = null;
}
onEscape(event) {
if (!event.defaultPrevented && event.key == 'Escape') {
event.preventDefault();
this.hide();
this.$.$digest();
}
}
onTransition(transition) {
if (transition.from().name !== transition.to().name)
this.hide();
}
show() {
this.shown = true;
this.handler = e => this.onEscape(e);
this.$window.addEventListener('keydown', this.handler);
this.stateHandler = this.$transitions.onStart({}, t => this.onTransition(t));
}
hide() {
this.$window.removeEventListener('keydown', this.handler);
this.stateHandler();
this.shown = false;
}
}
SideMenu.$inject = ['$scope', '$element', '$window', '$transitions'];
ngModule.component('vnSideMenu', {
template: require('./side-menu.html'),
controller: SideMenu,
transclude: true,
bindings: {
side: '@?'
},
require: {
app: '^vnApp'
}
});

View File

@ -0,0 +1,37 @@
@import "variables";
vn-side-menu > .menu {
display: block;
position: fixed;
z-index: 5;
bottom: 0;
width: $menu-width;
min-width: $menu-width;
background-color: white;
box-shadow: 0 .1em .2em rgba(1, 1, 1, .2);
overflow: auto;
top: $topbar-height;
&.left {
left: 0;
}
&.right {
right: 0;
}
@media screen and (max-width: $mobile-width) {
top: 0;
transition: transform 200ms ease-out;
z-index: 15;
&.left {
transform: translateZ(0) translateX(-$menu-width);
}
&.right {
transform: translateZ(0) translateX($menu-width);
}
&.shown {
transform: translateZ(0) translateX(0);
}
}
}

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/> <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"/> <meta name="mobile-web-app-capable" content="yes"/>
<link rel="manifest" href="manifest.json"/> <link rel="manifest" href="<%= require('./manifest.json') %>"/>
<title vn-title translate></title> <title vn-title translate></title>
</head> </head>
<body> <body>

View File

@ -1,12 +1,12 @@
{ {
"name": "Salix", "name": "Salix",
"start_url": "index.html",
"display": "standalone",
"theme_color": "#3d3d3d",
"icons": [ "icons": [
{ {
"src": "favicon.ico", "src": "favicon.ico",
"sizes": "512x512" "sizes": "512x512"
} }
], ]
"start_url": "index.html",
"display": "standalone",
"theme_color": "#3d3d3d"
} }

View File

@ -78,3 +78,8 @@
} }
} }
} }
vn-popover {
.vn-descriptor > .header > a:first-child {
visibility: hidden;
}
}

View File

@ -13,3 +13,4 @@ import './effects.scss';
import './order-product.scss'; import './order-product.scss';
import './summary.scss'; import './summary.scss';
import './descriptor.scss'; import './descriptor.scss';
import './modal-form.scss';

View File

@ -0,0 +1,38 @@
@import 'colors';
@import "./padding";
vn-dialog.modal-form {
vn-horizontal.header{
@extend .pad-small;
background-color: $main-01;
h5{
color: white;
margin: 0 auto;
}
}
tpl-body {
width: 100%;
}
table {
width: 100%
}
& > div{
padding: 0!important;
}
vn-textfield {
width: 100%;
}
.buttons{
margin-top: 0!important;
}
p{
display: none;
}
button.close > vn-icon{
color: white!important;
}
vn-ticket-sale-edit-discount > div {
padding-bottom: 0!important;
}
}

View File

@ -0,0 +1,4 @@
$menu-width: 16em;
$topbar-height: 4em;
$mobile-width: 800px;

View File

@ -65,5 +65,6 @@
"INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no esta permitido el uso de la letra ñ", "INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no esta permitido el uso de la letra ñ",
"You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado", "You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado",
"You can't create a ticket for a inactive client": "No puedes crear un ticket para un cliente inactivo", "You can't create a ticket for a inactive client": "No puedes crear un ticket para un cliente inactivo",
"Tag value cannot be blank": "El valor del tag no puede quedar en blanco" "Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
"ORDER_EMPTY": "Cesta vacía"
} }

View File

@ -17,14 +17,6 @@ class Controller {
this.ndMonth = this.$scope.ndMonth; this.ndMonth = this.$scope.ndMonth;
} }
$onInit() {
this.app.rightMenu = this.$element[0];
}
$onDestroy() {
this.app.rightMenu = null;
}
get zone() { get zone() {
return this._zone; return this._zone;
} }
@ -152,9 +144,6 @@ Controller.$inject = ['$element', '$scope', '$stateParams', '$http'];
ngModule.component('vnZoneCalendar', { ngModule.component('vnZoneCalendar', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,
require: {
app: '^vnApp'
},
bindings: { bindings: {
zone: '<' zone: '<'
} }

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor> <vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -16,7 +16,7 @@ export default class Controller {
case 'search': case 'search':
return /^\d+$/.test(value) return /^\d+$/.test(value)
? {id: value} ? {id: value}
: {name: {regexp: value}}; : {name: {like: `%${value}%`}};
case 'warehouseFk': case 'warehouseFk':
case 'agencyModeFk': case 'agencyModeFk':
return {[param]: value}; return {[param]: value};

View File

@ -16,8 +16,7 @@
on-selection="$ctrl.onSelection(item)"> on-selection="$ctrl.onSelection(item)">
</vn-treeview> </vn-treeview>
</vn-card> </vn-card>
<vn-zone-calendar <vn-side-menu side="right">
class="right-menu" <vn-zone-calendar zone="::$ctrl.zone"></vn-zone-calendar>
zone="::$ctrl.zone"> </vn-side-menu>
</vn-zone-calendar>
</div> </div>

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-claim-descriptor claim="$ctrl.claim"></vn-claim-descriptor> <vn-claim-descriptor claim="$ctrl.claim"></vn-claim-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-client-descriptor client="$ctrl.client"></vn-client-descriptor> <vn-client-descriptor client="$ctrl.client"></vn-client-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -5,8 +5,5 @@ vn-client-descriptor-popover {
& > vn-card{ & > vn-card{
margin: 0!important; margin: 0!important;
} }
.header > a:first-child {
display: none
}
} }
} }

View File

@ -1,12 +1,12 @@
<vn-dialog
vn-id="dialog"
class="modal-form">
<tpl-body>
<mg-ajax path="/client/api/receipts" options="vnPost"></mg-ajax> <mg-ajax path="/client/api/receipts" options="vnPost"></mg-ajax>
<vn-watcher <vn-horizontal class="header">
vn-id="watcher" <h5><span translate>New payment</span></h5>
data="$ctrl.receipt" </vn-horizontal>
form="form" <div pad-medium>
save="post">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large>
<vn-horizontal> <vn-horizontal>
<vn-date-picker vn-one <vn-date-picker vn-one
label="Date" label="Date"
@ -36,9 +36,10 @@
vn-focus> vn-focus>
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
</vn-card> </div>
<vn-button-bar> <vn-horizontal margin-medium class="buttons-bar">
<vn-submit label="Save"></vn-submit> <vn-button vn-one label="Save" ng-click="$ctrl.save()"></vn-button>
<vn-button ng-click="$ctrl.cancel($event)" label="Cancel"></vn-button> <vn-button vn-one ng-click="$ctrl.hide()" label="Cancel"></vn-button>
</vn-button-bar> </vn-horizontal>
</form> </tpl-body>
</vn-dialog>

View File

@ -1,11 +1,13 @@
import ngModule from '../../module'; import ngModule from '../../module';
import './style.scss';
class Controller { class Controller {
constructor($scope, $state, $http, $stateParams) { constructor($scope, $state, $http, vnApp, $translate) {
this.$http = $http; this.$http = $http;
this.$ = $scope; this.$ = $scope;
this.$state = $state; this.$state = $state;
this.$stateParams = $stateParams; this.vnApp = vnApp;
this.$translate = $translate;
this.receipt = { this.receipt = {
payed: new Date(), payed: new Date(),
@ -13,21 +15,26 @@ class Controller {
companyFk: window.localStorage.defaultCompanyFk, companyFk: window.localStorage.defaultCompanyFk,
bankFk: window.localStorage.defaultBankFk bankFk: window.localStorage.defaultBankFk
}; };
if (this.$stateParams.payed)
this.receipt.payed = this.$stateParams.payed;
if (this.$stateParams.bankFk)
this.receipt.bankFk = this.$stateParams.bankFk;
if (this.$stateParams.amountPaid)
this.receipt.amountPaid = this.$stateParams.amountPaid;
if (this.$stateParams.companyFk)
this.receipt.companyFk = this.$stateParams.companyFk;
} }
$onInit() { set payed(value) {
this.receipt.payed = value;
}
set bankFk(value) {
this.receipt.bankFk = value;
}
set amountPaid(value) {
this.receipt.amountPaid = value;
}
set companyFk(value) {
this.receipt.companyFk = value;
this.getAmountPaid();
}
getAmountPaid() {
let filter = { let filter = {
where: { where: {
clientFk: this.$state.params.id, clientFk: this.$state.params.id,
@ -41,25 +48,34 @@ class Controller {
}); });
} }
cancel() { show() {
this.goToIndex(); this.$.dialog.show();
} }
goToIndex() { hide() {
this.$state.go('client.card.risk.index'); this.$.dialog.hide();
} }
onSubmit() { save() {
this.$.watcher.submit().then( let query = `/client/api/receipts`;
() => { this.$http.post(query, this.receipt).then(() => {
this.goToIndex(); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
} this.hide();
); if (this.onResponse)
this.onResponse();
});
} }
} }
Controller.$inject = ['$scope', '$state', '$http', '$stateParams']; Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
ngModule.component('vnClientRiskCreate', { ngModule.component('vnClientRiskCreate', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller controller: Controller,
bindings: {
payed: '<?',
bankFk: '<?',
amountPaid: '<?',
onResponse: '&?',
companyFk: '<?'
}
}); });

View File

@ -0,0 +1,3 @@
vn-horizontal.buttons-bar{
text-align: center;
}

View File

@ -94,13 +94,16 @@
<vn-pagination model="model"></vn-pagination> <vn-pagination model="model"></vn-pagination>
</vn-card> </vn-card>
</vn-vertical> </vn-vertical>
<a ui-sref="client.card.risk.create"
vn-tooltip="New payment"
vn-bind="+"
fixed-bottom-right>
<vn-float-button <vn-float-button
vn-acl="administrative" vn-acl="administrative"
vn-acl-action="remove" vn-acl-action="remove"
icon="add"> icon="add"
vn-tooltip="New payment"
vn-bind="+"
fixed-bottom-right
ng-click="$ctrl.openCreateDialog()">
</vn-float-button> </vn-float-button>
</a>
<vn-client-risk-create vn-id="riskCreateDialog">
</vn-client-risk-create>

View File

@ -31,6 +31,9 @@ class Controller {
setOrder(value) { setOrder(value) {
this.params.params.companyFk = value; this.params.params.companyFk = value;
this.filter.where.companyFk = value; this.filter.where.companyFk = value;
}
refresh() {
this.$.model.refresh(); this.$.model.refresh();
this.$.riskModel.refresh(); this.$.riskModel.refresh();
} }
@ -55,6 +58,14 @@ class Controller {
return this._risks; return this._risks;
} }
openCreateDialog() {
this.$.riskCreateDialog.companyFk = this.companyFk;
this.$.riskCreateDialog.onResponse = () => {
this.refresh();
};
this.$.riskCreateDialog.show();
}
onDownload() { onDownload() {
alert('Not implemented yet'); alert('Not implemented yet');
} }

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-item-descriptor item="$ctrl.item"></vn-item-descriptor> <vn-item-descriptor item="$ctrl.item"></vn-item-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -3,9 +3,5 @@ vn-item-descriptor-popover {
display: block; display: block;
width: 16em; width: 16em;
min-height: 28em; min-height: 28em;
.header > a:first-child {
display: none
}
} }
} }

View File

@ -147,8 +147,8 @@ class Controller {
this.$scope.descriptor.ticketFk = sale.origin; this.$scope.descriptor.ticketFk = sale.origin;
this.$scope.descriptor.parent = event.target; this.$scope.descriptor.parent = event.target;
this.$scope.descriptor.show(); this.$scope.descriptor.show();
event.preventDefault(); event.preventDefault();
event.stopImmediatePropagation();
} }
showClientDescriptor(event, sale) { showClientDescriptor(event, sale) {
@ -157,8 +157,8 @@ class Controller {
this.$scope.clientDescriptor.clientFk = sale.clientFk; this.$scope.clientDescriptor.clientFk = sale.clientFk;
this.$scope.clientDescriptor.parent = event.target; this.$scope.clientDescriptor.parent = event.target;
this.$scope.clientDescriptor.show(); this.$scope.clientDescriptor.show();
event.preventDefault(); event.preventDefault();
event.stopImmediatePropagation();
} }
onDescriptorLoad() { onDescriptorLoad() {

View File

@ -39,7 +39,7 @@
<vn-tr ng-repeat="entry in entries"> <vn-tr ng-repeat="entry in entries">
<vn-td number> <vn-td number>
<vn-check <vn-check
field="entries.isIgnored" field="entry.isIgnored"
disabled="true"> disabled="true">
</vn-check> </vn-check>
</vn-td> </vn-td>

View File

@ -7,9 +7,5 @@ vn-ticket-descriptor-popover {
& > vn-card { & > vn-card {
margin: 0!important; margin: 0!important;
} }
.header > a:first-child {
display: none
}
} }
} }

View File

@ -20,7 +20,7 @@ class Controller {
let params = {id: this.possibleStowaways[index].id, shipFk: this.ticket.id}; let params = {id: this.possibleStowaways[index].id, shipFk: this.ticket.id};
this.$http.post(`/api/Stowaways/`, params) this.$http.post(`/api/Stowaways/`, params)
.then(() => { .then(() => {
this.card.reload(); this.cardReload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}); });
} }
@ -40,9 +40,7 @@ ngModule.component('vnAddStowaway', {
template: require('./addStowaway.html'), template: require('./addStowaway.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
ticket: '<' ticket: '<',
}, cardReload: '&?'
require: {
card: '^vnTicketCard'
} }
}); });

View File

@ -100,6 +100,7 @@
show-field="id" show-field="id"
value-field="id" value-field="id"
vn-tooltip="Ship stowaways" vn-tooltip="Ship stowaways"
tooltip-position="up"
data="$ctrl.ticket.ship" data="$ctrl.ticket.ship"
on-change="$ctrl.goToTicket(value)"> on-change="$ctrl.goToTicket(value)">
</vn-button-menu> </vn-button-menu>
@ -152,5 +153,5 @@
question="You are going to delete this ticket" question="You are going to delete this ticket"
message="Continue anyway?"> message="Continue anyway?">
</vn-confirm> </vn-confirm>
<vn-add-stowaway vn-id="addStowaway" ticket="$ctrl.ticket"></vn-add-stowaway> <vn-add-stowaway vn-id="addStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-add-stowaway>
<vn-remove-stowaway vn-id="removeStowaway" ticket="$ctrl.ticket"></vn-remove-stowaway> <vn-remove-stowaway vn-id="removeStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-remove-stowaway>

View File

@ -1,5 +1,4 @@
import ngModule from '../module'; import ngModule from '../module';
import './style.scss';
class Controller { class Controller {
constructor($state, $scope, $http, vnApp, $translate) { constructor($state, $scope, $http, vnApp, $translate) {
@ -11,7 +10,7 @@ class Controller {
this.moreOptions = [ this.moreOptions = [
{callback: this.showAddTurnDialog, name: 'Add turn', show: true}, {callback: this.showAddTurnDialog, name: 'Add turn', show: true},
{callback: this.showDeleteTicketDialog, name: 'Delete ticket', show: true}, {callback: this.showDeleteTicketDialog, name: 'Delete ticket', show: true},
{callback: this.showAddStowaway, name: 'Add stowaway', show: true}, {callback: this.showAddStowaway, name: 'Add stowaway', show: () => this.isTicketModule()},
{callback: this.showRemoveStowaway, name: 'Remove stowaway', show: () => this.shouldShowRemoveStowaway()}, {callback: this.showRemoveStowaway, name: 'Remove stowaway', show: () => this.shouldShowRemoveStowaway()},
/* callback: this.showChangeShipped, name: 'Change shipped hour', show: true} */ /* callback: this.showChangeShipped, name: 'Change shipped hour', show: true} */
]; ];
@ -37,8 +36,16 @@ class Controller {
} }
} }
isTicketModule() {
let path = this.$state.getCurrentPath();
if (path[1].state.name === 'ticket')
return true;
return false;
}
shouldShowRemoveStowaway() { shouldShowRemoveStowaway() {
if (!this._ticket) if (!this._ticket || !this.isTicketModule())
return false; return false;
return (this._ticket.stowaway || (this._ticket.ship && this._ticket.ship.length > 0)); return (this._ticket.stowaway || (this._ticket.ship && this._ticket.ship.length > 0));
@ -157,7 +164,8 @@ Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate'];
ngModule.component('vnTicketDescriptor', { ngModule.component('vnTicketDescriptor', {
template: require('./index.html'), template: require('./index.html'),
bindings: { bindings: {
ticket: '<' ticket: '<',
cardReload: '&'
}, },
controller: Controller controller: Controller
}); });

View File

@ -46,7 +46,7 @@ class Controller {
deleteStowaway(response) { deleteStowaway(response) {
if (response === 'ACCEPT') { if (response === 'ACCEPT') {
this.$http.delete(`/api/Stowaways/${this.stowawayToDelete.id}`).then(res => { this.$http.delete(`/api/Stowaways/${this.stowawayToDelete.id}`).then(res => {
this.card.reload(); this.cardReload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}); });
} }
@ -72,9 +72,7 @@ ngModule.component('vnRemoveStowaway', {
template: require('./removeStowaway.html'), template: require('./removeStowaway.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
ticket: '<' ticket: '<',
}, cardReload: '&?'
require: {
card: '^vnTicketCard'
} }
}); });

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-order-descriptor order="$ctrl.order"></vn-order-descriptor> <vn-order-descriptor order="$ctrl.order"></vn-order-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -97,10 +97,9 @@
</vn-card> </vn-card>
<vn-pagination margin-small-v model="model"></vn-pagination> <vn-pagination margin-small-v model="model"></vn-pagination>
</div> </div>
<vn-catalog-filter <vn-side-menu side="right">
class="right-menu" <vn-catalog-filter order="$ctrl.order"></vn-catalog-filter>
order="$ctrl.order"> </vn-side-menu>
</vn-catalog-filter>
<vn-order-prices-popover <vn-order-prices-popover
vn-id="pricesPopover" vn-id="pricesPopover"
order="$ctrl.order"> order="$ctrl.order">

View File

@ -19,9 +19,7 @@
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>
<vn-horizontal class="input"> <vn-horizontal class="input">
<vn-autocomplete <vn-autocomplete vn-id="type" vn-one
vn-one
vn-id="type"
data="$ctrl.itemTypes" data="$ctrl.itemTypes"
on-change="$ctrl.type = { on-change="$ctrl.type = {
id: value, id: value,

View File

@ -14,22 +14,19 @@ class Controller {
this.tags = []; this.tags = [];
} }
$onInit() {
this.app.rightMenu = this.$element[0];
}
$onDestroy() {
this.app.rightMenu = null;
}
get order() { get order() {
return this._order; return this._order;
} }
/**
* Sets filter values from state params
*
* @param {Object} value - Order data
*/
set order(value) { set order(value) {
this._order = value; if (!value.id || this._order) return;
if (!value.id) return; this._order = value;
this.$scope.$$postDigest(() => { this.$scope.$$postDigest(() => {
let category; let category;
@ -57,20 +54,18 @@ class Controller {
this.itemTypes = []; this.itemTypes = [];
this.type = null; this.type = null;
if (!value || (this.category && this.category.id == value.id)) { if (!value || (this.category && this.category.id == value.id))
this._category = null; this._category = null;
this.updateStateParams(); else
return;
}
this._category = value; this._category = value;
this.updateStateParams(); this.updateStateParams();
const query = `/item/api/ItemCategories/${value.id}/itemTypes`; if (this.tags.length > 0)
this.$http.get(query).then(res => { this.applyFilters();
this.itemTypes = res.data;
}); if (value)
this.updateItemTypes();
} }
get type() { get type() {
@ -91,6 +86,16 @@ class Controller {
this.applyFilters(); this.applyFilters();
} }
/**
* Refreshes item type dropdown data
*/
updateItemTypes() {
const query = `/item/api/ItemCategories/${this.category.id}/itemTypes`;
this.$http.get(query).then(res => {
this.itemTypes = res.data;
});
}
onSearch(event) { onSearch(event) {
if (event.key !== 'Enter') return; if (event.key !== 'Enter') return;
this.tags.push({ this.tags.push({
@ -153,6 +158,9 @@ class Controller {
this.$panel = null; this.$panel = null;
} }
/**
* Updates url state params from filter values
*/
updateStateParams() { updateStateParams() {
const params = {}; const params = {};
@ -174,8 +182,7 @@ ngModule.component('vnCatalogFilter', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller, controller: Controller,
require: { require: {
catalog: '^vnOrderCatalog', catalog: '^vnOrderCatalog'
app: '^vnApp'
}, },
bindings: { bindings: {
order: '<', order: '<',

View File

@ -41,4 +41,8 @@ vn-catalog-filter > div {
flex-wrap: wrap; flex-wrap: wrap;
@extend .pad-medium; @extend .pad-medium;
} }
vn-autocomplete[vn-id="type"] .list {
max-height: 20em
}
} }

View File

@ -70,7 +70,7 @@
</vn-card> </vn-card>
<vn-button-bar ng-if="!$ctrl.order.isConfirmed"> <vn-button-bar ng-if="!$ctrl.order.isConfirmed">
<vn-button <vn-button
label="Save" label="Confirm"
ng-click="$ctrl.save()"> ng-click="$ctrl.save()">
</vn-button> </vn-button>
</vn-button-bar> </vn-button-bar>

View File

@ -92,6 +92,7 @@ class Controller {
this.$http.post(query).then(() => { this.$http.post(query).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Order confirmed')); this.vnApp.showSuccess(this.$translate.instant('Order confirmed'));
this.$state.go(`ticket.index`, {clientFk: this.order.clientFk});
}); });
} }
} }

View File

@ -1,2 +1,3 @@
Remove item: Eliminar articulo Delete row: Eliminar linea
Order confirmed: Pedido confirmado Order confirmed: Pedido confirmado
Are you sure you want to delete this row?: ¿Estas seguro de que quieres borrar esta línea?

View File

@ -20,6 +20,10 @@ module.exports = Self => {
Self.getPossibleStowaways = async ticketFk => { Self.getPossibleStowaways = async ticketFk => {
let ship = await Self.app.models.Ticket.findById(ticketFk); let ship = await Self.app.models.Ticket.findById(ticketFk);
if (!ship || !ship.shipped)
return [];
let lowestDate = new Date(ship.shipped.getTime()); let lowestDate = new Date(ship.shipped.getTime());
lowestDate.setHours(0, 0, -1, 0); lowestDate.setHours(0, 0, -1, 0);

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-ticket-descriptor ticket="$ctrl.ticket"></vn-ticket-descriptor> <vn-ticket-descriptor ticket="$ctrl.ticket" card-reload="$ctrl.reload()"></vn-ticket-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -16,8 +16,10 @@
label="Address" label="Address"
show-field="nickname" show-field="nickname"
value-field="id" value-field="id"
field="$ctrl.ticket.addressFk"> field="$ctrl.ticket.addressFk"
<tpl-item>{{::nickname}} order="isActive DESC">
<tpl-item ng-class="::{notActive: isActive === false}">
<span class="inactive" translate>{{::isActive ? '' : 'INACTIVE'}}</span> {{::nickname}}
<span ng-show="city || province || street">- {{::street}} - {{::city}} - {{::province.name}} - {{::agencyMode.name}}</span> <span ng-show="city || province || street">- {{::street}} - {{::city}} - {{::province.name}} - {{::agencyMode.name}}</span>
</tpl-item> </tpl-item>
</vn-autocomplete> </vn-autocomplete>

View File

@ -1,5 +1,6 @@
import ngModule from '../../module'; import ngModule from '../../module';
import {toJsonDate} from 'core/lib/date'; import {toJsonDate} from 'core/lib/date';
import './style.scss';
class Controller { class Controller {
constructor($scope, $http, $translate, vnApp) { constructor($scope, $http, $translate, vnApp) {

View File

@ -0,0 +1,13 @@
@import 'colors';
tpl-item{
&.notActive {
background-color: $main-bg;
color: $secondary-font-color;
width: 100%;
}
& > .inactive {
text-transform: uppercase;
}
}

View File

@ -34,6 +34,6 @@
<vn-pagination model="model"></vn-pagination> <vn-pagination model="model"></vn-pagination>
</vn-card> </vn-card>
</vn-vertical> </vn-vertical>
<a ui-sref="ticket.card.tracking.edit" vn-bind="+" vn-visible-by="production, administrative, salesperson" fixed-bottom-right> <a ui-sref="ticket.card.tracking.edit" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button> <vn-float-button icon="add"></vn-float-button>
</a> </a>

View File

@ -1,7 +1,7 @@
<vn-main-block> <vn-main-block>
<div class="left-menu"> <vn-side-menu side="left">
<vn-worker-descriptor worker="$ctrl.worker"></vn-worker-descriptor> <vn-worker-descriptor worker="$ctrl.worker"></vn-worker-descriptor>
<vn-left-menu></vn-left-menu> <vn-left-menu></vn-left-menu>
</div> </vn-side-menu>
<div class="content-block" ui-view></div> <div class="content-block" ui-view></div>
</vn-main-block> </vn-main-block>

View File

@ -1,5 +1,5 @@
.container { .container {
font-family: verdana, sans-serif; font-family: arial, sans-serif;
font-size: 16px; font-size: 16px;
zoom: 0.55 zoom: 0.55
} }
@ -33,9 +33,18 @@
float: left float: left
} }
.clearfix {
overflow: hidden;
display: block;
clear: both
}
.row { .row {
white-space: nowrap; margin-bottom: 15px;
margin-bottom: 15px overflow: hidden;
display: block;
clear: both;
width: 100%
} }
.row.small { .row.small {
@ -52,13 +61,36 @@
box-sizing: border-box box-sizing: border-box
} }
.row:last-child {
margin-bottom: 0
}
.row.inline .text {
display: table-cell;
margin-bottom: 0;
width: 30%
}
.row.inline .control {
display: table-cell;
padding-left: 20px;
font-weight: bold;
color: #000;
width: 70%
}
.row.inline .description {
position: static;
overflow: visible
}
.row .description { .row .description {
position: relative; position: relative;
padding-top: 2px; padding-top: 2px;
overflow: hidden;
font-size: 9px; font-size: 9px;
overflow: hidden;
display: block; display: block;
color: #999 clear: both
} }
.row .line { .row .line {
@ -78,42 +110,17 @@
float: left float: left
} }
.row:last-child {
margin-bottom: 0
}
.row.inline .text {
display: inline-block;
margin-bottom: 0;
width: 40%;
}
.row.inline .control {
display: inline-block;
font-weight: bold;
padding-left: 20px;
color: #000;
width: 60%
}
.row.inline .description {
position: static;
overflow: visible
}
.panel { .panel {
position: relative position: relative
} }
.panel .header { .panel .header {
background-color: #FFF; background-color: #FFF;
position:absolute;
left: 17.5px;
top: -12px;
padding: 2.5px 5px; padding: 2.5px 5px;
position: absolute;
font-weight: bold; font-weight: bold;
left: 17.5px;
top: -12px
} }
.panel .body { .panel .body {
@ -127,22 +134,27 @@
margin-top: 0 margin-top: 0
} }
.box { .field {
border-top: 1px solid #CCC;
border-right: 1px solid #CCC;
border-bottom: 1px solid #CCC; border-bottom: 1px solid #CCC;
font-weight: bold; border-left: 1px solid #CCC;
text-align: center; border-top: 1px solid #CCC;
padding-top: 4px;
width: 25px;
height: 21px;
color: #000;
float: left float: left
} }
.box.crossed { .field span {
font-weight: 100; border-right: 1px solid #CCC;
font-size: 16px -webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
display: table-cell;
vertical-align: middle;
text-align: center;
font-weight: bold
}
.field.square span {
height: 35.4px;
width: 35.4px
} }
.pull-left { .pull-left {
@ -153,53 +165,89 @@
float: right float: right
} }
.verticalText { .vertical-text {
-moz-transform: rotate(90deg); -moz-transform: rotate(90deg);
-webkit-transform: rotate(90deg); -webkit-transform: rotate(90deg);
transform: rotate(90deg); transform: rotate(90deg);
position: absolute; position: absolute;
text-align: center; text-align: center;
font-size: .65em; font-size: .65em;
right: -108px;
width: 200px; width: 200px;
border: 2px solid #000;
right: -110px;
top: 50% top: 50%
} }
vn-table { table {
border-collapse: collapse; border-collapse: collapse;
margin: 20px 0; border-spacing: 0;
display: table;
width: 100%;
} }
vn-thead { .row-oriented, .column-oriented {
text-align: left;
width: 100%
}
.row-oriented .description,
.column-oriented .description {
font-size: 0.6em;
color: #888;
padding: 0 !important
}
.row-oriented .description .line,
.column-oriented .description .line {
border-bottom: 1px solid #DDD;
border-right: 1px solid #DDD;
border-left: 1px solid #DDD;
margin-top: 10px;
color: #999;
padding: 5px
}
.row-oriented .description span,
.column-oriented .description span {
background-color: #FFF;
margin: -5px 0 0 50px;
display: block;
padding: 5px;
float: left
}
.column-oriented {
margin: 20px 0
}
.column-oriented tfoot {
border-top: 1px solid #808080;
}
.column-oriented td, .column-oriented th {
padding: 5px 10px
}
.column-oriented thead {
background-color: #c0c0c0
}
.column-oriented thead tr {
border-bottom: 1px solid #808080; border-bottom: 1px solid #808080;
border-top: 1px solid #808080; border-top: 1px solid #808080;
display: table-header-group background-color: #c0c0c0
} }
vn-tbody { .column-oriented tfoot tr:first-child td {
border-top: 3px solid #888888; padding-top: 20px !important;
display: table-row-group
} }
vn-tfoot { .panel .row-oriented td, .panel .row-oriented th {
border-top: 1px solid #808080; padding: 10px 0
display: table-footer-group
} }
vn-tr { .row-oriented > tbody > tr > td {
display: table-row width: 30%
} }
vn-th { .row-oriented > tbody > tr > th {
font-weight: bold padding-left: 30px;
} width: 70%
vn-td, vn-th {
vertical-align: middle;
display: table-cell;
text-align: left;
padding: 5px 0
} }

View File

@ -10,6 +10,14 @@
text-align: right text-align: right
} }
.gray { .font.gray {
color: #555 color: #555
} }
.font.light-gray {
color: #888
}
.font.small {
font-size: 0.65em
}

View File

@ -5,8 +5,9 @@
{"type": "email", "name": "letter-debtor-st"}, {"type": "email", "name": "letter-debtor-st"},
{"type": "email", "name": "letter-debtor-nd"}, {"type": "email", "name": "letter-debtor-nd"},
{"type": "email", "name": "claim-pickup-order"}, {"type": "email", "name": "claim-pickup-order"},
{"type": "report", "name": "delivery-note"}, {"type": "email", "name": "sepa-core"},
{"type": "report", "name": "invoice"}, {"type": "report", "name": "rpt-delivery-note"},
{"type": "report", "name": "rpt-invoice"},
{"type": "report", "name": "rpt-claim-pickup-order"}, {"type": "report", "name": "rpt-claim-pickup-order"},
{"type": "report", "name": "rpt-letter-debtor"}, {"type": "report", "name": "rpt-letter-debtor"},
{"type": "report", "name": "rpt-sepa-core"}, {"type": "report", "name": "rpt-sepa-core"},

View File

@ -107,7 +107,7 @@ module.exports = {
format: 'A4', format: 'A4',
border: '1.5cm', border: '1.5cm',
footer: { footer: {
height: '80px', height: '60px',
} }
}; };

View File

@ -26,7 +26,7 @@
<p>{{$t('sections.howToBuy.stock')}}</p> <p>{{$t('sections.howToBuy.stock')}}</p>
<p>{{$t('sections.howToBuy.delivery')}}</p> --> <p>{{$t('sections.howToBuy.delivery')}}</p> -->
</section> </section>
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
</section> </section>
</body> </body>
</html> </html>

View File

@ -30,6 +30,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {

View File

@ -62,7 +62,7 @@
</section> </section>
</p> </p>
</section> </section>
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
</section> </section>
</body> </body>
</html> </html>

View File

@ -19,6 +19,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {

View File

@ -1,3 +0,0 @@
.blue {
color: blue
}

View File

@ -1,4 +0,0 @@
<div>
<span class="red">{{$t('clientId')}}: {{ id1 }} {{ id2 }}</span>
<span class="blue">heey</span>
</div>

View File

@ -1,35 +0,0 @@
const database = require(`${appPath}/lib/database`);
const UserException = require(`${appPath}/lib/exceptions/userException`);
module.exports = {
name: 'delivery-note',
async asyncData(ctx, params) {
const promises = [];
const dataIndex = promises.push(this.methods.fetchData()) - 1;
const itemsIndex = promises.push(this.methods.fetchItems()) - 1;
return Promise.all(promises).then(result => {
const [[data]] = result[dataIndex];
const [[items]] = result[itemsIndex];
return {
id1: data.id,
id2: items.id,
};
});
},
data() {
return {
id: null,
};
},
methods: {
fetchData() {
return database.pool.query('SELECT 1 AS id');
},
fetchItems() {
return database.pool.query('SELECT 2 AS id');
},
},
};

View File

@ -1,8 +0,0 @@
module.exports = {
messages: {
es: {
clientId: 'Id cliente',
},
},
}
;

View File

@ -6,6 +6,9 @@ module.exports = {
}; };
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale;
const embeded = []; const embeded = [];
this.files.map(file => { this.files.map(file => {
const src = this.isPreview ? `/api/${file}` : `cid:${file}`; const src = this.isPreview ? `/api/${file}` : `cid:${file}`;
@ -27,4 +30,5 @@ module.exports = {
], ],
}; };
}, },
props: ['locale']
}; };

View File

@ -19,5 +19,24 @@ module.exports = {
escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`, escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
}, },
}, },
/* fr: {
buttons: {
webAcccess: 'Visitez notre site web',
info: 'Ayúdanos a mejorar',
},
privacy: {
fiscalAddress: 'VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla · www.verdnatura.es · clientes@verdnatura.es',
disclaimer: `- AVISO - Ce message est privé et confidentiel et doit être utilisé.
exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje
por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier documento
adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a
ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace
responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.`,
law: `En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal,
te comunicamos que los datos personales que facilites se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,
pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por
escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
},
}, */
}, },
}; };

View File

@ -52,7 +52,7 @@
</p> </p>
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
<!-- End footer component --> <!-- End footer component -->
</section> </section>
</body> </body>

View File

@ -30,6 +30,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {

View File

@ -35,7 +35,7 @@
</p> </p>
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
<!-- End footer component --> <!-- End footer component -->
</section> </section>
</body> </body>

View File

@ -31,6 +31,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {

View File

@ -38,7 +38,7 @@
<p>{{ $t('notifyAnError') }}</p> <p>{{ $t('notifyAnError') }}</p>
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
<!-- End footer component --> <!-- End footer component -->
</section> </section>
</body> </body>

View File

@ -13,7 +13,7 @@ module.exports = {
if (!params.clientFk) if (!params.clientFk)
throw new UserException('No client id specified'); throw new UserException('No client id specified');
return this.methods.fetchClientData(params.clientFk) return this.methods.fetchClient(params.clientFk)
.then(([result]) => { .then(([result]) => {
if (!result) if (!result)
throw new UserException('No client data found'); throw new UserException('No client data found');
@ -21,10 +21,11 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {
fetchClientData(clientFk) { fetchClient(clientFk) {
return database.pool.query(` return database.pool.query(`
SELECT SELECT
u.lang locale, u.lang locale,

View File

@ -49,7 +49,7 @@
</p> </p>
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<email-footer></email-footer> <email-footer :locale="locale"></email-footer>
<!-- End footer component --> <!-- End footer component -->
</section> </section>
</body> </body>

View File

@ -1,6 +1,4 @@
const database = require(`${appPath}/lib/database`); const database = require(`${appPath}/lib/database`);
const emailHeader = require('../email-header');
const emailFooter = require('../email-footer');
const UserException = require(`${appPath}/lib/exceptions/userException`); const UserException = require(`${appPath}/lib/exceptions/userException`);
module.exports = { module.exports = {
@ -13,7 +11,7 @@ module.exports = {
if (!params.clientFk) if (!params.clientFk)
throw new UserException('No client id specified'); throw new UserException('No client id specified');
return this.methods.fetchClientData(params.clientFk) return this.methods.fetchClient(params.clientFk)
.then(([result]) => { .then(([result]) => {
if (!result) if (!result)
throw new UserException('No client data found'); throw new UserException('No client data found');
@ -21,6 +19,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
data() { data() {
@ -29,7 +28,7 @@ module.exports = {
}; };
}, },
methods: { methods: {
fetchClientData(clientFk) { fetchClient(clientFk) {
return database.pool.query(` return database.pool.query(`
SELECT SELECT
c.id, c.id,
@ -47,7 +46,7 @@ module.exports = {
}, },
}, },
components: { components: {
'email-header': emailHeader, 'email-header': require('../email-header'),
'email-footer': emailFooter, 'email-footer': require('../email-footer'),
}, },
}; };

View File

@ -1,13 +1,12 @@
footer { footer {
font-family: verdana, sans-serif; font-family: verdana, sans-serif;
font-size: 12px; font-size: 0.55em;
color: #555; color: #555;
zoom: 0.55 zoom: 0.65
} }
footer, footer p { footer, footer p {
text-align: center; text-align: center
font-size: 12px
} }
footer .page { footer .page {

View File

@ -1,4 +1,8 @@
module.exports = { module.exports = {
name: 'report-footer', name: 'report-footer',
props: ['leftText', 'centerText'] created() {
if (this.locale)
this.$i18n.locale = this.locale;
},
props: ['leftText', 'centerText', 'locale']
}; };

View File

@ -3,7 +3,7 @@ header {
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 40px; margin-bottom: 40px;
text-align: center; text-align: center;
font-size: 12px; font-size: 0.65em;
color: #555 color: #555
} }

View File

@ -1,6 +1,9 @@
module.exports = { module.exports = {
name: 'report-header', name: 'report-header',
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale;
const embeded = []; const embeded = [];
this.files.map(file => { this.files.map(file => {
embeded[file] = `file://${__dirname + file}`; embeded[file] = `file://${__dirname + file}`;
@ -12,4 +15,5 @@ module.exports = {
files: ['/assets/images/report-logo.svg'], files: ['/assets/images/report-logo.svg'],
}; };
}, },
props: ['locale']
}; };

View File

@ -9,7 +9,7 @@
font-size: 2em font-size: 2em
} }
vn-table { table.column-oriented {
margin-top: 50px !important margin-top: 50px !important
} }

View File

@ -8,18 +8,22 @@
<section class="size50"> <section class="size50">
<section class="size75"> <section class="size75">
<h1 class="title uppercase">{{$t('title')}}</h1> <h1 class="title uppercase">{{$t('title')}}</h1>
<section class="row inline small"> <table class="row-oriented">
<section class="text uppercase gray">{{$t('claimId')}}:</section> <tbody>
<section class="control">{{claimId}}</section> <tr>
</section> <td class="font gray uppercase">{{$t('claimId')}}</td>
<section class="row inline small"> <th>{{claimId}}</th>
<section class="text uppercase gray">{{$t('clientId')}}:</section> </tr>
<section class="control">{{clientId}}</section> <tr>
</section> <td class="font gray uppercase">{{$t('clientId')}}</td>
<section class="row inline small"> <th>{{clientId}}</th>
<section class="text uppercase gray">{{$t('date')}}:</section> </tr>
<section class="control">{{dated()}}</section> <tr>
</section> <td class="font gray uppercase">{{$t('date')}}</td>
<th>{{dated()}}</th>
</tr>
</tbody>
</table>
</section> </section>
</section> </section>
<section class="size50"> <section class="size50">
@ -41,24 +45,24 @@
</section> </section>
</section> </section>
<vn-table> <table class="column-oriented">
<vn-thead> <thead>
<vn-tr> <tr>
<vn-th>{{$t('reference')}}</vn-th> <th>{{$t('reference')}}</th>
<vn-th>{{$t('quantity')}}</vn-th> <th>{{$t('quantity')}}</th>
<vn-th>{{$t('claims')}}</vn-th> <th>{{$t('claims')}}</th>
<vn-th>{{$t('concept')}}</vn-th> <th>{{$t('concept')}}</th>
</vn-tr> </tr>
</vn-thead> </thead>
<vn-tbody> <tbody>
<vn-tr v-for="sale in sales" :key="sale.id"> <tr v-for="sale in sales" :key="sale.id">
<vn-td class="gray">{{sale.id}}</vn-td> <td class="font gray">{{sale.id}}</td>
<vn-td>{{sale.quantity}}</vn-td> <td>{{sale.quantity}}</td>
<vn-td>{{sale.claimQuantity}}</vn-td> <td>{{sale.claimQuantity}}</td>
<vn-td>{{sale.concept}}</vn-td> <td>{{sale.concept}}</td>
</vn-tr> </tr>
</vn-tbody> </tbody>
</vn-table> </table>
<section class="panel sign"> <section class="panel sign">
<section class="body centered"> <section class="body centered">
@ -71,7 +75,8 @@
<report-footer id="pageFooter" <report-footer id="pageFooter"
:left-text="$t('claim', [claimId])" :left-text="$t('claim', [claimId])"
:center-text="clientName"> :center-text="clientName"
:locale="locale">
</report-footer> </report-footer>
</section> </section>
</body> </body>

View File

@ -27,6 +27,7 @@ module.exports = {
}); });
}, },
created() { created() {
if (this.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.locale;
}, },
methods: { methods: {

View File

@ -0,0 +1,7 @@
const CssReader = require(`${appPath}/lib/cssReader`);
module.exports = new CssReader([
`${appPath}/common/css/layout.css`,
`${appPath}/common/css/misc.css`,
`${__dirname}/style.css`])
.mergeStyles();

View File

@ -0,0 +1,14 @@
.container {
color: #000
}
.title {
font-weight: 100;
margin-top: 0;
margin-bottom: 20px;
font-size: 2em
}
table.column-oriented {
margin-top: 50px !important
}

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