Merge branch 'dev' of https://git.verdnatura.es/salix into dev

This commit is contained in:
Juan Ferrer Toribio 2017-05-31 13:53:10 +02:00
commit b42209b2f6
110 changed files with 849 additions and 246 deletions

View File

@ -1,3 +1,3 @@
import './ngModule'; import './ngModule';
import './config'; import './config';
import './login/index'; import './login/login';

View File

View File

@ -76,6 +76,6 @@ export default class Controller {
Controller.$inject = ['$element', '$scope', '$window', '$http']; Controller.$inject = ['$element', '$scope', '$window', '$http'];
ngModule.component('vnLogin', { ngModule.component('vnLogin', {
template: require('./index.html'), template: require('./login.html'),
controller: Controller controller: Controller
}); });

View File

@ -1,5 +1,7 @@
{ {
"module": "client", "module": "client",
"name": "Clients",
"icon": "person",
"routes": [ "routes": [
{ {
"url": "/clients", "url": "/clients",

View File

@ -19,7 +19,7 @@ Controller.$inject = ['$scope', '$state'];
export const NAME = 'vnAddressCreate'; export const NAME = 'vnAddressCreate';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./address-create.html'),
controller: Controller controller: Controller
}; };
module.component(NAME, COMPONENT); module.component(NAME, COMPONENT);

View File

@ -11,7 +11,7 @@ Controller.$inject = ['$stateParams'];
export const NAME = 'vnAddressEdit'; export const NAME = 'vnAddressEdit';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./address-edit.html'),
controllerAs: 'addressData', controllerAs: 'addressData',
controller: Controller controller: Controller
}; };

View File

@ -1,6 +1,6 @@
import {module} from '../module'; import {module} from '../module';
export const component = { export const component = {
template: require('./index.html') template: require('./addresses.html')
}; };
module.component('vnClientAddresses', component); module.component('vnClientAddresses', component);

View File

@ -1,7 +1,7 @@
import {module} from '../module'; import {module} from '../module';
export const component = { export const component = {
template: require('./index.html'), template: require('./basic-data.html'),
bindings: { bindings: {
client: '<' client: '<'
} }

View File

@ -5,7 +5,7 @@
form="form" form="form"
save="put"> save="put">
</vn-watcher> </vn-watcher>
<form name="form" ng-submit="watcher.submit()" pad-medium> <form name="form" ng-submit="bill.checkChanges() && watcher.submit()" pad-medium>
<vn-card margin-small-bottom> <vn-card margin-small-bottom>
<vn-vertical pad-large> <vn-vertical pad-large>
<vn-title>Información de facturación</vn-title> <vn-title>Información de facturación</vn-title>
@ -41,3 +41,17 @@
<vn-submit label="Guardar"></vn-submit> <vn-submit label="Guardar"></vn-submit>
</vn-button-bar> </vn-button-bar>
</form> </form>
<vn-dialog
vn-id="send-mail"
on-response="bill.returnDialog(response)">
<tpl-body>
<vn-vertical>
<vn-one text-center translate>Changed terms</vn-one>
<vn-one text-center translate>Notify customer?</vn-one>
</vn-vertical>
</tpl-body>
<tpl-buttons>
<button response="CANCEL" translate>No</button>
<button response="ACCEPT" translate>Yes, notify</button>
</tpl-buttons>
</vn-dialog>

View File

@ -0,0 +1,63 @@
import {module} from '../module';
export const NAME = 'vnClientBillingData';
class billingData {
constructor($scope, $http, $timeout, vnAppLogger, $translate) {
this.$ = $scope;
this.http = $http;
this.timeout = $timeout;
this.logger = vnAppLogger;
this.translate = $translate;
this.payId = null;
this.dueDay = null;
this.copyData();
}
$onChanges(changes) {
this.copyData();
}
copyData() {
if (this.client) {
this.payId = this.client.payMethod ? this.client.payMethod.id : null;
this.dueDay = this.client.dueDay ? this.client.dueDay : null;
}
}
checkChanges() {
let payId = this.client.payMethodFk || null;
let dueDay = this.client.dueDay || null;
if (this.payId !== payId || this.dueDay !== dueDay) {
this.$.sendMail.show();
return false;
}
return true;
}
returnDialog(response) {
if (response === 'ACCEPT') {
this.sendMail().then(
() => this.logger.showMessage(this.translate.instant('Notification sent!')),
() => this.logger.showMessage(this.translate.instant('Notification error'))
);
}
this.timeout(() => this.$.watcher.submit());
}
sendMail() {
return this.http.post(`/mailer/manuscript/paymentUpdate`, {user: this.client.id});
}
}
billingData.$inject = ['$scope', '$http', '$timeout', 'vnAppLogger', '$translate'];
export const COMPONENT = {
template: require('./billing-data.html'),
controller: billingData,
controllerAs: 'bill',
bindings: {
client: '<'
}
};
module.component(NAME, COMPONENT);

View File

@ -1,11 +0,0 @@
import {module} from '../module';
export const NAME = 'vnClientBillingData';
export const COMPONENT = {
template: require('./index.html'),
controllerAs: 'bill',
bindings: {
client: '<'
}
};
module.component(NAME, COMPONENT);

View File

@ -0,0 +1,8 @@
{
"Changed terms": "Has modificado las condiciones de pago",
"Notify customer?" : "¿Deseas notificar al cliente de dichos cambios?",
"No": "No",
"Yes, notify": "Sí, notificar",
"Notification sent!": "¡Notificación enviada!",
"Notification error": "Error al enviar notificación"
}

View File

@ -11,7 +11,7 @@ export default class vnClientCard {
module.component(NAME, { module.component(NAME, {
template: require('./index.html'), template: require('./card.html'),
controllerAs: 'card', controllerAs: 'card',
controller: vnClientCard controller: vnClientCard
}); });

View File

@ -1,27 +1,27 @@
export * from './module'; export * from './module';
export {NAME as CLIENT_CARD, export {NAME as CLIENT_CARD,
COMPONENT as CLIENT_CARD_COMPONENT} from './card/index'; COMPONENT as CLIENT_CARD_COMPONENT} from './card/card';
export {NAME as CLIENTS, export {NAME as CLIENTS,
COMPONENT as CLIENTS_COMPONENT} from './index/index'; COMPONENT as CLIENTS_COMPONENT} from './index/index';
export {NAME as CLIENT_FISCAL_DATA_INDEX, export {NAME as CLIENT_FISCAL_DATA_INDEX,
COMPONENT as CLIENT_FISCAL_DATA_INDEX_COMPONENT} from './fiscal-data/index'; COMPONENT as CLIENT_FISCAL_DATA_INDEX_COMPONENT} from './fiscal-data/fiscal-data';
export {NAME as CLIENT_BILLING_DATA_INDEX, export {NAME as CLIENT_BILLING_DATA_INDEX,
COMPONENT as CLIENT_BILLINGL_DATA_INDEX_COMPONENT} from './billing-data/index'; COMPONENT as CLIENT_BILLINGL_DATA_INDEX_COMPONENT} from './billing-data/billing-data';
export {NAME as CLIENT_DESCRIPTOR, export {NAME as CLIENT_DESCRIPTOR,
COMPONENT as CLIENT_DESCRIPTOR_COMPONENT} from './descriptor/index'; COMPONENT as CLIENT_DESCRIPTOR_COMPONENT} from './descriptor/descriptor';
export {NAME as CLIENT_NOTES, export {NAME as CLIENT_NOTES,
COMPONENT as CLIENT_NOTES_COMPONENT} from './notes/index'; COMPONENT as CLIENT_NOTES_COMPONENT} from './notes/notes';
export {NAME as CLIENT_SEARCH_PANEL, export {NAME as CLIENT_SEARCH_PANEL,
COMPONENT as CLIENT_SEARCH_PANEL_COMPONENT} from './search-panel/index'; COMPONENT as CLIENT_SEARCH_PANEL_COMPONENT} from './search-panel/search-panel';
export {NAME as CLIENT_CREATE, export {NAME as CLIENT_CREATE,
COMPONENT as CLIENT_CREATE_COMPONENT} from './create/index'; COMPONENT as CLIENT_CREATE_COMPONENT} from './create/create';
export {NAME as CLIENT_ADDRESS_EDIT_INDEX, export {NAME as CLIENT_ADDRESS_EDIT_INDEX,
COMPONENT as CLIENT_ADDRESS_EDIT_INDEX_COMPONENT} from './address-edit/index'; COMPONENT as CLIENT_ADDRESS_EDIT_INDEX_COMPONENT} from './address-edit/address-edit';
export {NAME as NEW_NOTE_INDEX, export {NAME as NEW_NOTE_INDEX,
COMPONENT as NEW_NOTE_INDEX_COMPONENT} from './new-note/index'; COMPONENT as NEW_NOTE_INDEX_COMPONENT} from './new-note/new-note';
import './addresses/index'; import './addresses/addresses';
import './address-create/index'; import './address-create/address-create';
import './basic-data/index'; import './basic-data/basic-data';
import './web-access/index'; import './web-access/web-access';

View File

@ -17,7 +17,7 @@ class Controller {
Controller.$inject = ['$scope', '$state']; Controller.$inject = ['$scope', '$state'];
export const component = { export const component = {
template: require('./index.html'), template: require('./create.html'),
controller: Controller controller: Controller
}; };
module.component('vnClientCreate', component); module.component('vnClientCreate', component);

View File

@ -3,7 +3,7 @@ import './style.css';
export const NAME = 'vnDescriptor'; export const NAME = 'vnDescriptor';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./descriptor.html'),
controllerAs: 'descriptor', controllerAs: 'descriptor',
bindings: { bindings: {
client: '<', client: '<',

View File

@ -2,7 +2,7 @@ import {module} from '../module';
export const NAME = 'vnClientFiscalData'; export const NAME = 'vnClientFiscalData';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./fiscal-data.html'),
controllerAs: 'fiscal', controllerAs: 'fiscal',
bindings: { bindings: {
client: '<' client: '<'

View File

@ -3,19 +3,19 @@
<div style="max-width: 40em; margin: 0 auto;"> <div style="max-width: 40em; margin: 0 auto;">
<vn-card> <vn-card>
<vn-horizontal pad-medium> <vn-horizontal pad-medium>
<vn-searchbar <vn-searchbar vn-auto
vn-auto
index="index" index="index"
on-search="index.accept()" on-search="$ctrl.search(index)"
advanced="true" advanced="true"
search="$ctrl.model.search"
popover="vn-client-search-panel"> popover="vn-client-search-panel">
</vn-searchbar> </vn-searchbar>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>
<vn-card margin-medium-top> <vn-card margin-medium-top>
<vn-item-client ng-repeat="client in index.model" title="View client" client="client"></vn-item-client> <vn-item-client ng-repeat="client in index.model.instances" title="View client" client="client"></vn-item-client>
</vn-card> </vn-card>
<vn-paging index="index"></vn-paging> <vn-paging index="index" total="index.model.count"></vn-paging>
</div> </div>
<a ui-sref="create" fixed-bottom-right> <a ui-sref="create" fixed-bottom-right>
<vn-float-button icon="person_add"></vn-float-button> <vn-float-button icon="person_add"></vn-float-button>

View File

@ -2,6 +2,16 @@ import {module} from '../module';
import './style.css'; import './style.css';
import './item-client'; import './item-client';
module.component('vnClientIndex', { class Controller {
template: require('./index.html') search(index) {
}); index.filter.search = this.model.search;
index.accept();
}
}
export const NAME = 'vnClientIndex';
export const COMPONENT = {
template: require('./index.html'),
controller: Controller
};
module.component(NAME, COMPONENT);

View File

@ -1,4 +1,4 @@
import template from './index.html'; import template from './new-note.html';
import {module} from '../module'; import {module} from '../module';
class Controller { class Controller {

View File

@ -1,5 +1,5 @@
import './style.css'; import './style.css';
import template from './index.html'; import template from './notes.html';
import {module} from '../module'; import {module} from '../module';
export const NAME = 'vnClientNotes'; export const NAME = 'vnClientNotes';

View File

@ -2,7 +2,7 @@ import {module} from '../module';
export const NAME = 'vnClientSearchPanel'; export const NAME = 'vnClientSearchPanel';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./search-panel.html'),
controller: function($scope, $window) { controller: function($scope, $window) {
this.filter = {id: null, fi: null, name: null, socialName: null, city: null, postcode: null, email: null, phone: null}; this.filter = {id: null, fi: null, name: null, socialName: null, city: null, postcode: null, email: null, phone: null};
this.formVisibility = true; this.formVisibility = true;

View File

@ -1,48 +0,0 @@
import {module} from '../module';
class Controller {
constructor($scope, $http, vnAppLogger) {
this.$scope = $scope;
this.$http = $http;
this.vnAppLogger = vnAppLogger;
}
$onChanges() {
if(this.client)
this.account = this.client.account;
}
onPassOpen() {
this.newPassword = '';
this.repeatPassword = '';
this.$scope.$apply();
}
onPassChange(response) {
if(response == 'ACCEPT')
try {
if(!this.newPassword)
throw new Error(`Passwords can't be empty`);
if(this.newPassword != this.repeatPassword)
throw new Error(`Passwords don't match`);
let account = {
password: this.newPassword
};
this.$http.put(`/client/api/Accounts/${this.client.id}`, account);
}
catch(e) {
this.vnAppLogger.showError(e.message);
return false;
}
return true;
}
}
Controller.$inject = ['$scope', '$http', 'vnAppLogger'];
module.component('vnClientWebAccess', {
template: require('./index.html'),
bindings: {
client: '<'
},
controller: Controller
});

View File

@ -0,0 +1,46 @@
import {module} from '../module';
class Controller {
constructor($scope, $http, vnAppLogger) {
this.$scope = $scope;
this.$http = $http;
this.vnAppLogger = vnAppLogger;
}
$onChanges() {
if (this.client)
this.account = this.client.account;
}
onPassOpen() {
this.newPassword = '';
this.repeatPassword = '';
this.$scope.$apply();
}
onPassChange(response) {
if (response == 'ACCEPT')
try {
if (!this.newPassword)
throw new Error(`Passwords can't be empty`);
if (this.newPassword != this.repeatPassword)
throw new Error(`Passwords don't match`);
let account = {
password: this.newPassword
};
this.$http.put(`/client/api/Accounts/${this.client.id}`, account);
} catch (e) {
this.vnAppLogger.showError(e.message);
return false;
}
return true;
}
}
Controller.$inject = ['$scope', '$http', 'vnAppLogger'];
module.component('vnClientWebAccess', {
template: require('./web-access.html'),
bindings: {
client: '<'
},
controller: Controller
});

View File

@ -400,7 +400,7 @@ export default class Autocomplete extends Component {
Autocomplete.$inject = ['$element', '$scope', '$http', 'vnPopover', '$transclude']; Autocomplete.$inject = ['$element', '$scope', '$http', 'vnPopover', '$transclude'];
module.component('vnAutocomplete', { module.component('vnAutocomplete', {
template: require('./index.html'), template: require('./autocomplete.html'),
bindings: { bindings: {
url: '@', url: '@',
showField: '@?', showField: '@?',

View File

@ -1,18 +1,19 @@
import './mdl-override.css'; import './mdl-override.css';
import './styles/fonts/mdi-override.css'; import './styles/fonts/mdi-override.css';
import './textfield/index'; import './textfield/textfield';
import './watcher/index'; import './watcher/watcher';
import './paging/index'; import './paging/paging';
import './icon/index'; import './icon/icon';
import './autocomplete/index'; import './autocomplete/autocomplete';
import './popover/index'; import './popover/popover';
import './dialog/index'; import './dialog/dialog';
import './confirm/index';
import './title/index'; import './confirm/confirm';
import './subtitle/index'; import './title/title';
import './spinner/index'; import './subtitle/subtitle';
import './snackbar/index'; import './spinner/spinner';
import './snackbar/snackbar';
export {NAME as BUTTON, directive as ButtonDirective} from './button/button'; export {NAME as BUTTON, directive as ButtonDirective} from './button/button';
export {NAME as BUTTON_MDL, factory as buttonMdl} from './button/button.mdl'; export {NAME as BUTTON_MDL, factory as buttonMdl} from './button/button.mdl';

View File

@ -1,12 +1,12 @@
import {module} from '../module'; import {module} from '../module';
import Dialog from '../dialog/index'; import Dialog from '../dialog/dialog';
import './style.css'; import './style.css';
export default class Confirm extends Dialog {} export default class Confirm extends Dialog {}
Dialog.$inject = ['$element']; Dialog.$inject = ['$element'];
module.component('vnConfirm', { module.component('vnConfirm', {
template: require('./index.html'), template: require('./confirm.html'),
bindings: { bindings: {
onResponse: '&', onResponse: '&',
question: '@', question: '@',

View File

@ -98,7 +98,7 @@ export default class Dialog extends Component {
Dialog.$inject = ['$element']; Dialog.$inject = ['$element'];
module.component('vnDialog', { module.component('vnDialog', {
template: require('./index.html'), template: require('./dialog.html'),
transclude: { transclude: {
tplBody: 'tplBody', tplBody: 'tplBody',
tplButtons: 'tplButtons' tplButtons: 'tplButtons'

View File

@ -1,5 +1,5 @@
import {module} from '../module'; import {module} from '../module';
import Dialog from '../dialog/index'; import Dialog from '../dialog/dialog';
import {kebabToCamel} from '../lib/string'; import {kebabToCamel} from '../lib/string';
/** /**

View File

@ -1,5 +1,5 @@
import {module} from '../module'; import {module} from '../module';
import './index.mdl'; import './icon.mdl';
import './style.css'; import './style.css';
import * as resolveFactory from '../lib/resolveDefaultComponents'; import * as resolveFactory from '../lib/resolveDefaultComponents';

View File

@ -1,5 +1,5 @@
import {module} from '../module'; import {module} from '../module';
import template from './index.mdl.html'; import template from './icon.mdl.html';
export const NAME = 'vnIconMdlFactory'; export const NAME = 'vnIconMdlFactory';
export function factory() { export function factory() {

View File

@ -1 +1 @@
<label>*[text]*</label> <label translate="*[text]*"></label>

View File

@ -36,7 +36,7 @@ Paging.$inject = ['$http', '$scope'];
export const NAME = 'vnPaging'; export const NAME = 'vnPaging';
export const COMPONENT = { export const COMPONENT = {
template: require('./index.html'), template: require('./paging.html'),
bindings: { bindings: {
index: '<', index: '<',
total: '<' total: '<'

View File

@ -20,6 +20,6 @@ export default class Controller {
Controller.$inject = ['$element']; Controller.$inject = ['$element'];
module.component('vnSnackbar', { module.component('vnSnackbar', {
template: require('./index.html'), template: require('./snackbar.html'),
controller: Controller controller: Controller
}); });

View File

@ -49,7 +49,7 @@ export default class Spinner extends Component {
Spinner.$inject = ['$element', '$scope']; Spinner.$inject = ['$element', '$scope'];
export const component = { export const component = {
template: require('./index.html'), template: require('./spinner.html'),
bindings: { bindings: {
enable: '=' enable: '='
}, },

View File

@ -1,6 +1,6 @@
import {module} from '../module'; import {module} from '../module';
module.component('vnSubtitle', { module.component('vnSubtitle', {
template: require('./index.html'), template: require('./subtitle.html'),
transclude: true transclude: true
}); });

View File

@ -3,7 +3,7 @@ import Component from '../lib/component';
import * as resolveFactory from '../lib/resolveDefaultComponents'; import * as resolveFactory from '../lib/resolveDefaultComponents';
import * as normalizerFactory from '../lib/inputAttrsNormalizer'; import * as normalizerFactory from '../lib/inputAttrsNormalizer';
import './style.scss'; import './style.scss';
import './index.mdl'; import './textfield.mdl';
export default class Textfield extends Component { export default class Textfield extends Component {
constructor($element, $scope, $attrs) { constructor($element, $scope, $attrs) {

View File

@ -4,7 +4,7 @@ export const NAME = 'vnTextfieldMdlFactory';
export function factory() { export function factory() {
return { return {
template: require('./index.mdl.html'), template: require('./textfield.mdl.html'),
default: { default: {
label: 'text', label: 'text',
className: 'mdl-textfield--floating-label', className: 'mdl-textfield--floating-label',

View File

@ -1,6 +1,6 @@
import {module} from '../module'; import {module} from '../module';
module.component('vnTitle', { module.component('vnTitle', {
template: require('./index.html'), template: require('./title.html'),
transclude: true transclude: true
}); });

View File

@ -149,7 +149,7 @@ export default class Watcher extends Component {
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnAppLogger', '$translate']; Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnAppLogger', '$translate'];
module.component('vnWatcher', { module.component('vnWatcher', {
template: require('./index.html'), template: require('./watcher.html'),
bindings: { bindings: {
url: '@?', url: '@?',
idField: '@?', idField: '@?',

View File

@ -1,10 +1,14 @@
import ngModule from './module'; import ngModule from './module';
function aclService() { aclService.$inject = ['aclConstant'];
this.roles = window.Salix.acl.roles; function aclService(aclConstant) {
this.roles = aclConstant.roles || undefined;
this.routeHasPermission = function(route) { this.routeHasPermission = function(route) {
let hasPermission; let hasPermission;
if (!route.acl) if (!this.roles)
hasPermission = false;
else if (!route.acl)
hasPermission = true; hasPermission = true;
else if (!this.roles || !Object.keys(this.roles).length) else if (!this.roles || !Object.keys(this.roles).length)
hasPermission = false; hasPermission = false;

View File

@ -6,3 +6,4 @@ import './config';
import './run'; import './run';
import './components'; import './components';
import './styles/index'; import './styles/index';
import './modulesFactory';

View File

@ -1,5 +1,5 @@
import {ng} from 'vendor'; import {ng} from 'vendor';
import './module'; import appName from './module';
export const bootstrap = () => { export const bootstrap = () => {
const selector = 'selector'; const selector = 'selector';
@ -13,5 +13,5 @@ export const bootstrap = () => {
if (!_element) { if (!_element) {
throw new Error('Element is not defined'); throw new Error('Element is not defined');
} }
ng.bootstrap(_element, ['salix']); ng.bootstrap(_element, [appName]);
}; };

View File

@ -1,4 +1,4 @@
import ngModule from '../../module'; import ngModule, {appName} from '../../module';
import './style.scss'; import './style.scss';
export const NAME = 'vnApp'; export const NAME = 'vnApp';
@ -76,4 +76,6 @@ function interceptorConfig($httpProvider) {
} }
ngModule.config(interceptorConfig); ngModule.config(interceptorConfig);
var acl = window[appName] ? window[appName].acl : {};
ngModule.constant('aclConstant', acl);

View File

@ -1,3 +1,17 @@
<vn-horizontal> <vn-vertical ng-if="$ctrl.state.current.name === 'home'">
<div class="default" translate>Push on applications menu</div> <vn-horizontal>
</vn-horizontal> <h6 vn-one translate="Modules access"></h6>
</vn-horizontal>
<vn-horizontal vn-one>
<a ng-repeat="mod in $ctrl.modules" ui-sref="{{::mod.route.state}}" class="{{::mod.name}} vn-module mdl-shadow--4dp">
<vn-vertical>
<vn-one>
<h4 translate="{{::mod.name}}"></h4>
</vn-one>
<vn-one>
<vn-icon icon="{{::mod.icon}}"></vn-icon>
</vn-one>
</vn-vertical>
</a>
</vn-horizontal>
</vn-vertical>

View File

@ -4,11 +4,12 @@ import './style.scss';
export const NAME = 'vnHome'; export const NAME = 'vnHome';
export default class vnHome { export default class vnHome {
constructor() { constructor(modulesFactory, $state) {
this.modules = []; this.modules = modulesFactory.getModules();
this.state = $state;
} }
} }
vnHome.$inject = []; vnHome.$inject = ['modulesFactory', '$state'];
export const COMPONENT = { export const COMPONENT = {
template: require('./home.html'), template: require('./home.html'),

View File

@ -1,7 +1,41 @@
vn-home { vn-home {
& > .default { padding: 2em;
text-align: center; vn-horizontal{
font-size: 1.3em; margin-bottom: 15px;
padding: 2em; }
h6{
color: #3C393B;
text-align: center;
}
a:link{
text-decoration: none;
}
.vn-module{
display: flex;
flex: none;
padding: 2em;
border-radius: 4px;
box-sizing: border-box;
transition: opacity 0.7s ease;
h4{
text-transform: capitalize;
} }
vn-one{
text-align: center;
}
i{
font-size: 50px !important;
margin: 0 auto;
}
&:hover{
opacity: 0.7;
}
&.Clients{
background-color: #ffa410;
color: #ffffff;
}
}
} }

View File

@ -6,14 +6,16 @@
<vn-icon icon="account_circle" translate-attr="{title: 'Profile'}" style="font-size: 35px;"></vn-icon> <vn-icon icon="account_circle" translate-attr="{title: 'Profile'}" style="font-size: 35px;"></vn-icon>
<ul class="mdl-menu mdl-js-menu mdl-menu--bottom-right" pad-medium for="apps"> <ul class="mdl-menu mdl-js-menu mdl-menu--bottom-right" pad-medium for="apps">
<vn-horizontal> <vn-horizontal>
<vn-vertical> <div ng-repeat="mod in $ctrl.modules">
<a ui-sref="clients"> <vn-vertical>
<button vn-one class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored popover-button"> <a ui-sref="{{::mod.route.state}}">
<vn-icon vn-one icon="person" style="font-size:40px"></vn-icon> <button vn-one class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored popover-button">
</button> <vn-icon vn-one icon="{{::mod.icon}}" style="font-size:40px"></vn-icon>
</a> </button>
<vn-label class="popover-label" text="Clientes"></vn-label> </a>
</vn-vertical> <vn-label class="popover-label" text="{{::mod.name}}"></vn-label>
</vn-vertical>
</div>
</vn-horizontal> </vn-horizontal>
</ul> </ul>
</div> </div>

View File

@ -2,9 +2,10 @@ import ngModule from '../../module';
import './style.scss'; import './style.scss';
export default class Controller { export default class Controller {
constructor($translate, $window) { constructor($translate, $window, modulesFactory) {
this.$translate = $translate; this.$translate = $translate;
this.$window = $window; this.$window = $window;
this.modules = modulesFactory.getModules();
} }
onLogoutClick() { onLogoutClick() {
this.$window.location = 'salix/logout'; this.$window.location = 'salix/logout';
@ -15,7 +16,7 @@ export default class Controller {
console.log(`Locale changed: ${lang}`); console.log(`Locale changed: ${lang}`);
} }
} }
Controller.$inject = ['$translate', '$window']; Controller.$inject = ['$translate', '$window', 'modulesFactory'];
ngModule.component('vnMainMenu', { ngModule.component('vnMainMenu', {
template: require('./main-menu.html'), template: require('./main-menu.html'),

View File

@ -1,6 +1,6 @@
<form ng-submit="$ctrl.onSubmit()"> <form ng-submit="$ctrl.onSubmit()">
<vn-horizontal> <vn-horizontal>
<vn-textfield vn-one label="Search" model="$ctrl.model.search"></vn-textfield> <vn-textfield vn-one label="Search" model="$ctrl.search"></vn-textfield>
<vn-icon <vn-icon
ng-if="$ctrl.advanced" ng-if="$ctrl.advanced"
ng-click="$ctrl.onClick($event)" ng-click="$ctrl.onClick($event)"

View File

@ -22,9 +22,10 @@ export default class Controller {
} }
onChildSubmit(filter) { onChildSubmit(filter) {
this.vnPopover.hide(); this.vnPopover.hide();
this.index.filter = filter; Object.assign(this.index.filter, filter);
this.onSubmit(); this.onSubmit();
} }
onSubmit() { onSubmit() {
if (this.onSearch) if (this.onSearch)
this.onSearch(); this.onSearch();
@ -39,6 +40,7 @@ ngModule.component('vnSearchbar', {
template: require('./searchbar.html'), template: require('./searchbar.html'),
bindings: { bindings: {
index: '<', index: '<',
search: '=',
onSearch: '&', onSearch: '&',
advanced: '=', advanced: '=',
popover: '@' popover: '@'

View File

@ -1,8 +1,8 @@
import ngModule from './module'; import ngModule, {appName} from './module';
config.$inject = ['$translatePartialLoaderProvider']; config.$inject = ['$translatePartialLoaderProvider'];
export function config($translatePartialLoaderProvider) { export function config($translatePartialLoaderProvider) {
$translatePartialLoaderProvider.addPart('salix'); $translatePartialLoaderProvider.addPart(appName);
} }
ngModule.config(config); ngModule.config(config);

View File

@ -6,5 +6,7 @@
"Profile": "Profile", "Profile": "Profile",
"Data saved!": "Data saved!", "Data saved!": "Data saved!",
"Can't contact with server": "Can't contact with server", "Can't contact with server": "Can't contact with server",
"Push on applications menu": "To open a module push on applications menu" "Push on applications menu": "To open a module push on applications menu",
"Clients": "Clients",
"Modules access": "Modules access"
} }

View File

@ -6,5 +6,7 @@
"Profile": "Perfil", "Profile": "Perfil",
"Data saved!": "¡Datos guardados!", "Data saved!": "¡Datos guardados!",
"Can't contact with server": "No se pudo contactar con el servidor", "Can't contact with server": "No se pudo contactar con el servidor",
"Push on applications menu": "Para abrir un módulo pulsa en el menú de aplicaciones" "Push on applications menu": "Para abrir un módulo pulsa en el menú de aplicaciones",
"Clients": "Clientes",
"Modules access" : "Acceso a módulos"
} }

View File

@ -1,5 +1,6 @@
import {ng} from 'vendor'; import {ng} from 'vendor';
import 'core'; import 'core';
const ngModule = ng.module('salix', ['vnCore']); export const appName = 'salix';
const ngModule = ng.module(appName, ['vnCore']);
export default ngModule; export default ngModule;

View File

@ -0,0 +1,36 @@
import ngModule from './module';
function modulesFactory(aclService) {
function _getMainRoute(routeCollection) {
let cant = routeCollection.length;
for (let i = 0; i < cant; i++) {
if (!routeCollection[i].abstract) {
return routeCollection[i];
}
}
return null;
}
function getModules() {
let modules = [];
for (let file in window.routes) {
let card = {
name: routes[file].name || routes[file].module,
icon: routes[file].icon || ''
};
let mainRoute = _getMainRoute(window.routes[file].routes);
if (mainRoute && aclService.routeHasPermission(mainRoute)) {
card.route = mainRoute;
modules.push(card);
}
}
return modules;
}
return {
getModules: getModules
};
}
modulesFactory.$inject = ['aclService'];
ngModule.factory('modulesFactory', modulesFactory);

View File

@ -27,3 +27,6 @@ vn-button-bar {
display: block; display: block;
margin-top: $margin-small; margin-top: $margin-small;
} }
html [text-center], .text-center {
text-align: center;
}

View File

@ -158,8 +158,10 @@ gulp.task('services', function() {
var auth = require('./services/auth/server/server.js'); var auth = require('./services/auth/server/server.js');
var client = require('./services/client/server/server.js'); var client = require('./services/client/server/server.js');
var server = require('./services/salix/server/server.js'); var server = require('./services/salix/server/server.js');
var mailer = require('./services/mailer/server.js');
auth.start(); auth.start();
client.start(); client.start();
server.start(); server.start();
mailer.start();
}); });

View File

@ -64,14 +64,14 @@
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$authenticated", "principalId": "$everyone",
"permission": "ALLOW" "permission": "DENY"
}, },
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "root",
"permission": "DENY" "permission": "ALLOW"
} }
] ]
} }

View File

@ -5,6 +5,8 @@ module.exports = function(Client) {
require('../scopes/client/card.js')(Client); require('../scopes/client/card.js')(Client);
require('../scopes/client/activate.js')(Client); require('../scopes/client/activate.js')(Client);
require('../scopes/client/addresses.js')(Client); require('../scopes/client/addresses.js')(Client);
require('../scopes/client/filter.js')(Client);
require('../scopes/client/before-save.js')(Client);
// Validations // Validations
@ -58,41 +60,4 @@ module.exports = function(Client) {
}); });
} }
// Hooks
Client.observe('before save', function(ctx, next) {
if (ctx.instance) {
if (!ctx.instance.dueDay)
ctx.instance.dueDay = 5;
next();
} else {
Client.findById(ctx.where.id, function(err, instance) {
if (instance
&& instance.payMethodFk != ctx.data.payMethodFk
&& instance.dueDay == ctx.data.dueDay)
ctx.data.dueDay = 5;
next();
});
}
});
// Basic filter
Client.installMethod('filter', filterClients);
function filterClients(p) {
return {
where: {
id: p.id,
name: {regexp: p.name},
cif: p.cif,
socialName: {regexp: p.socialName},
city: {regexp: p.city},
postcode: p.postcode,
email: {regexp: p.email},
phone: p.phone
},
skip: (p.page - 1) * p.size,
limit: p.size
};
}
}; };

View File

@ -144,14 +144,14 @@
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$authenticated", "principalId": "$everyone",
"permission": "ALLOW" "permission": "DENY"
}, },
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "root",
"permission": "DENY" "permission": "ALLOW"
} }
], ],
"validations": [], "validations": [],

View File

@ -37,14 +37,14 @@
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$authenticated", "principalId": "$everyone",
"permission": "ALLOW" "permission": "DENY"
}, },
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "root",
"permission": "DENY" "permission": "ALLOW"
} }
], ],
"scope": { "scope": {

View File

@ -33,10 +33,22 @@
}, },
"acls": [ "acls": [
{ {
"accessType": "*", "accessType": "READ",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "$everyone",
"permission": "ALLOW" "permission": "ALLOW"
},
{
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "root",
"permission": "ALLOW"
} }
] ]
} }

View File

@ -28,14 +28,14 @@
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$authenticated", "principalId": "$everyone",
"permission": "ALLOW" "permission": "DENY"
}, },
{ {
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "root",
"permission": "DENY" "permission": "ALLOW"
} }
] ]
} }

View File

@ -54,13 +54,41 @@ module.exports = function(self) {
} }
}); });
this.filter = (params, cb) => { this[methodName] = (params, cb) => {
let filter = removeEmpty(filterCb(params)); let filter = removeEmpty(filterCb(params));
this.find(filter, function(err, instances) { var response = {}
if(!err)
cb(null, instances); function returnValues(){
}) if(response.instances !== undefined && response.count !== undefined)
}; cb(null, response);
}
function error(){
cb(null, response);
}
this.find(filter, function(err, instances) {
if(!err){
response.instances = instances;
returnValues();
}
else{
error();
}
})
this.count(filter.where, function(err, totalCount){
if(!err){
response.count = totalCount;
returnValues();
}
else{
error();
}
})
};
}; };

View File

@ -27,6 +27,12 @@
"accessType": "*", "accessType": "*",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "root",
"permission": "ALLOW" "permission": "ALLOW"
} }
] ]

View File

@ -32,10 +32,22 @@
}, },
"acls": [ "acls": [
{ {
"accessType": "*", "accessType": "READ",
"principalType": "ROLE", "principalType": "ROLE",
"principalId": "$everyone", "principalId": "$everyone",
"permission": "ALLOW" "permission": "ALLOW"
},
{
"accessType": "WRITE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "DENY"
},
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "root",
"permission": "ALLOW"
} }
] ]
} }

View File

@ -0,0 +1,18 @@
module.exports = function(Client){
Client.observe('before save', function(ctx, next) {
if (ctx.instance) {
if (!ctx.instance.dueDay)
ctx.instance.dueDay = 5;
next();
} else {
Client.findById(ctx.where.id, function(err, instance) {
if (instance
&& instance.payMethodFk != ctx.data.payMethodFk
&& instance.dueDay == ctx.data.dueDay)
ctx.data.dueDay = 5;
next();
});
}
});
}

View File

@ -1,43 +1,57 @@
[ [
{ {
"relation": "salesPerson", "relation": "salesPerson",
"scope":{ "scope": {
"fields": { "fields": [
"id": true, "name": true "id",
} "name"
]
} }
}, },
{ {
"relation": "contactChannel", "relation": "contactChannel",
"scope":{ "scope": {
"fields": { "fields": [
"id": true, "name": true "id",
} "name"
]
} }
}, },
{ {
"relation": "province", "relation": "province",
"scope":{ "scope": {
"fields": { "fields": [
"id": true, "name": true "id",
} "name"
]
} }
}, },
{ {
"relation": "country", "relation": "country",
"scope":{ "scope": {
"fields": { "fields": [
"id": true, "name": true "id",
} "name"
]
} }
}, },
{ {
"relation": "payMethod", "relation": "payMethod",
"scope":{ "scope": {
"fields": { "fields": [
"id": true, "name": true "id",
} "name"
]
}
},
{
"relation": "account",
"scope": {
"fields": [
"id",
"name",
"active"
]
} }
} }
] ]

View File

@ -0,0 +1,39 @@
module.exports = function(Client){
Client.installMethod('filter', filterClients);
function filterClients(p) {
if(p.search && p.search !== "")
return searchWhere(p);
return andWhere(p);
}
function searchWhere(p){
return {
where: {
or:[
{id: p.search,},
{name: {regexp: p.search}}
]
},
skip: (p.page - 1) * p.size,
limit: p.size
}
}
function andWhere(p){
return {
where: {
id: p.id,
name: {regexp: p.name},
cif: p.cif,
socialName: {regexp: p.socialName},
city: {regexp: p.city},
postcode: p.postcode,
email: {regexp: p.email},
phone: p.phone
},
skip: (p.page - 1) * p.size,
limit: p.size
}
}
}

2
services/mailer/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
config.json

View File

@ -0,0 +1,30 @@
var express = require('express');
var router = new express.Router();
var mail = require('../mail.js');
var database = require('../database.js');
var template = require('../template.js');
// Escrito de cambios en méto de pago del cliente
router.post('/paymentUpdate', function(request, response) {
database.pool.query('SELECT Cliente, `e-mail` AS email FROM Clientes WHERE Id_Cliente = ?', [request.body.user], function(error, rs) {
var params = {
clientName: rs[0].Cliente
};
template.getTemplate('paymentUpdate', params, function(body) {
var data = {
recipient: rs[0].email,
subject: 'Cambios en las condiciones de pago',
body: body
};
if (mail.send(data)) {
response.json({status: "OK"});
} else {
response.json({status: "ERROR"});
}
});
});
});
module.exports = router;

View File

@ -0,0 +1,8 @@
var express = require('express');
var router = new express.Router();
router.get('/test', function(request, response) {
response.send("test");
});
module.exports = router;

View File

@ -0,0 +1,35 @@
<div style="width:600px;font-family:arial,sans-serif;font-size:16px;color:#555;margin:0 auto">
<div style="padding:20px;text-align: center;border-bottom: 1px solid #CCC">
<img class="logo" src="https://verdnatura.es/image/logo.png" style="width:307px;margin-bottom: 5px"/>
<div style="color: #CCC">
<span style="display: block;color:#555;font-size: 10px">Verdnatura Levante SL, B97367486</span>
<span style="display: block;color:#555;font-size: 10px">Avda. Espioca 100, 46460 Silla (Valencia)</span>
</div>
</div>
<div>
<div style="text-align:center">
<h1 style="color: #999;font-size: 34px;margin-top: 35px;margin-bottom: 35px">CAMBIOS EN CONDICIONES DE PAGO</h1>
</div>
<p>
Estimado cliente <strong style="font-size: 20px">{{clientName}}</strong>
</p>
<p style="text-align: justify">
Se han cambiado las condiciones de pago, estas son las nuevas:
</p>
</div>
<div style="font-size:10px;font-weight:100;border-top: 1px solid #CCC;margin-top: 35px">
<p style="text-align: justify">Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo.
Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre 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.</p>
<p style="text-align: justify">En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos
que los datos personales que facilite 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.</p>
</div>
</div>

View File

@ -0,0 +1,11 @@
module.exports = {
/**
* Obtiene las variables de entorno
* @param {String} env - Nombre de la variable de entorno
* @return {String} Valor de la variable de entorno
*/
getEnv: function(env) {
return process.env[env];
}
};

View File

@ -0,0 +1,13 @@
var Settings = require('../Settings.js');
module.exports = {
/**
* Imprimir cabecera
*/
printHeader: function() {
console.log('##########################################################');
console.log('## ' + Settings.name + ' ##');
console.log('##########################################################');
}
};

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