Integración con MySQL, errores solucionados

This commit is contained in:
Juan Ferrer Toribio 2017-04-28 15:04:29 +02:00
parent 1eb0fb9c8d
commit ce2d7936af
37 changed files with 269 additions and 175 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ spliting.js
build build
npm-debug.log npm-debug.log
debug.log debug.log
datasources.development.json

View File

@ -23,7 +23,7 @@
<vn-textfield vn-one label="Email" field="$ctrl.client.email"></vn-textfield> <vn-textfield vn-one label="Email" field="$ctrl.client.email"></vn-textfield>
<vn-autocomplete vn-one <vn-autocomplete vn-one
field="$ctrl.client.salesPerson" field="$ctrl.client.salesPerson"
url="/client/api/SalesPeople" url="/client/api/Employees"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Comercial"> label="Comercial">

View File

@ -43,7 +43,7 @@
<vn-textfield vn-two label="IBAN" field="fiscal.client.iban"></vn-textfield> <vn-textfield vn-two label="IBAN" field="fiscal.client.iban"></vn-textfield>
<vn-autocomplete vn-two <vn-autocomplete vn-two
field="fiscal.client.payMethod" field="fiscal.client.payMethod"
url="/client/api/PaymentMethods" url="/client/api/PayMethods"
show-field="name" show-field="name"
value-field="id" value-field="id"
label="Forma de pago"> label="Forma de pago">

View File

@ -3,8 +3,7 @@ import Component from '../lib/component';
import './style.scss'; import './style.scss';
/** /**
* Combobox like component with search and partial data loading * Combobox like component with search and partial data loading features.
* features.
*/ */
export default class Autocomplete extends Component { export default class Autocomplete extends Component {
constructor($element, $scope, $http, vnPopover) { constructor($element, $scope, $http, vnPopover) {

View File

@ -1,7 +1,7 @@
import {module as _module} from '../module'; import {module as _module} from '../module';
import * as resolveFactory from '../lib/resolveDefaultComponents'; import * as resolveFactory from '../lib/resolveDefaultComponents';
import * as util from '../lib/util'; import * as util from '../lib/util';
require ('./style.css'); require('./style.css');
const _NAME = 'card'; const _NAME = 'card';
export const NAME = util.getName(_NAME); export const NAME = util.getName(_NAME);

View File

@ -1,6 +1,7 @@
import './mdl-override.css'; import './mdl-override.css';
import './styles/fonts/mdi-override.css'; import './styles/fonts/mdi-override.css';
import './textfield/index';
import './watcher/index'; import './watcher/index';
import './paging/index'; import './paging/index';
import './icon/index'; import './icon/index';
@ -20,8 +21,6 @@ export {NAME as RADIO, directive as RadioDirective} from './radio/radio';
export {NAME as RADIO_MDL, factory as radionMdl} from './radio/radio.mdl'; export {NAME as RADIO_MDL, factory as radionMdl} from './radio/radio.mdl';
export {NAME as TEXTAREA, directive as TextareaDirective} from './textarea/textarea'; export {NAME as TEXTAREA, directive as TextareaDirective} from './textarea/textarea';
export {NAME as TEXTAREA_MDL, factory as textareaMdl} from './textarea/textarea.mdl'; export {NAME as TEXTAREA_MDL, factory as textareaMdl} from './textarea/textarea.mdl';
export {NAME as TEXTFIELD, directive as TextfieldDirective} from './textfield/textfield';
export {NAME as TEXTFIELD_MDL, factory as textfieldMdl} from './textfield/textfield.mdl';
export {NAME as LABEL, directive as LabelDirective} from './label/label'; export {NAME as LABEL, directive as LabelDirective} from './label/label';
export {NAME as LABEL_MDL, factory as labelMdl} from './label/label.mdl'; export {NAME as LABEL_MDL, factory as labelMdl} from './label/label.mdl';
export {NAME as ICON_BUTTON, directive as IconButtonDirective} from './icon-button/icon-button'; export {NAME as ICON_BUTTON, directive as IconButtonDirective} from './icon-button/icon-button';

View File

@ -33,20 +33,19 @@ export function directive(interpolate, compile, $window) {
if (!validations || validations.length == 0) if (!validations || validations.length == 0)
return; return;
let errorMsg = angular.element('<span class="mdl-textfield__error"></span>');
element.after(errorMsg);
let input = ctrl[0]; let input = ctrl[0];
let form = ctrl[1]; let form = ctrl[1];
let parent = element.parent(); let errorSpan = angular.element('<span class="mdl-textfield__error"></span>');
let errorMsg;
let errorShown = false;
input.$validators.entity = function(value) { input.$validators.entity = function(value) {
try { try {
validateAll(value, validations); validateAll(value, validations);
return true; return true;
} catch (e) { } catch (e) {
errorMsg.text(e.message); errorMsg = e.message;
parent.attr('title', e.message); if (errorShown) changeError();
return false; return false;
} }
}; };
@ -54,14 +53,27 @@ export function directive(interpolate, compile, $window) {
scope.$watch(function() { scope.$watch(function() {
return (form.$submitted || input.$dirty) && input.$invalid; return (form.$submitted || input.$dirty) && input.$invalid;
}, function(value) { }, function(value) {
let parent = element.parent();
if (value) { if (value) {
changeError();
parent.addClass('invalid'); parent.addClass('invalid');
errorMsg[0].style.display = 'block'; element.after(errorSpan);
} else { } else if (errorShown) {
parent.removeClass('invalid'); parent.removeClass('invalid');
errorMsg[0].style.display = 'none'; parent.removeAttr('title');
errorSpan.remove();
errorSpan.empty();
} }
errorShown = value;
}); });
function changeError() {
let parent = element.parent();
errorSpan.text(errorMsg);
parent.attr('title', errorMsg);
}
} }
} }
module.directive('vnValidation', directive); module.directive('vnValidation', directive);

View File

@ -1 +1 @@
import './phone'; import './phone';

View File

@ -2,15 +2,17 @@ import {module} from '../module';
/** /**
* Formats a phone number putting a space every three digits. * Formats a phone number putting a space every three digits.
*
* @return {String} The formated number
*/ */
export default function phone() { export default function phone() {
return function(input) { return function(input) {
input = input || ''; input = input || '';
let out = ''; let out = '';
for(let i = 0; i < input.length; i++) { for (let i = 0; i < input.length; i++) {
out = out + input.charAt(i); out += input.charAt(i);
if((i+1) % 3 == 0) if ((i + 1) % 3 == 0)
out = out +' '; out += ' ';
} }
return out; return out;
}; };

View File

@ -1,7 +1,7 @@
import {module} from '../module'; import {module} from '../module';
export {factory as mdlFactory} from './index.mdl'; import './index.mdl';
import './style.css';
import * as resolveFactory from '../lib/resolveDefaultComponents'; import * as resolveFactory from '../lib/resolveDefaultComponents';
require('./style.css');
const _NAME = 'icon'; const _NAME = 'icon';
export const NAME = 'vnIcon'; export const NAME = 'vnIcon';
@ -12,7 +12,7 @@ export function directive(resolver) {
template: function(_, attrs) { template: function(_, attrs) {
return resolver.getTemplate(_NAME, attrs); return resolver.getTemplate(_NAME, attrs);
} }
} };
} }
directive.$inject = [resolveFactory.NAME]; directive.$inject = [resolveFactory.NAME];

View File

@ -3,20 +3,25 @@
*/ */
export default class Component { export default class Component {
/** /**
* The element window. * The component owner window.
*/ */
get window() { get window() {
return this.document.defaultView; return this.document.defaultView;
} }
/**
* The component owner document.
*/
get document() {
return this.element.ownerDocument;
}
/** /**
* Contructor. * Contructor.
* *
* @param {HTMLElement} $element The main component element * @param {HTMLElement} $element The main component element
*/ */
constructor($element) { constructor($element) {
this.element = $element[0]; this.element = $element[0];
this.element.$ctrl = this; this.element.$ctrl = this;
this.document = $element[0].ownerDocument;
} }
} }
Component.$inject = ['$element']; Component.$inject = ['$element'];

View File

@ -3,14 +3,14 @@ import {module} from '../module';
export const NAME = 'vnInputAttrsNormalizer'; export const NAME = 'vnInputAttrsNormalizer';
export class InputAttrsNormalizer { export class InputAttrsNormalizer {
normalize(attrs) { normalize(attrs) {
if(attrs.field) { if (attrs.field) {
let split = attrs.field.split('.'); let split = attrs.field.split('.');
let len = split.length; let len = split.length;
if(len == 0) if (len == 0)
throw new Error (`Attribute 'field' can not be empty`); throw new Error(`Attribute 'field' can not be empty`);
if(len > 3) if (len > 3)
throw new Error (`Attribute 'field' must have this syntax: [ctrl].[entity].[field]`); throw new Error(`Attribute 'field' must have this syntax: [ctrl].[entity].[field]`);
let i = len - 1; let i = len - 1;
let field = split[i--]; let field = split[i--];

View File

@ -0,0 +1,69 @@
import {module} from '../module';
import Component from '../lib/component';
import * as resolveFactory from '../lib/resolveDefaultComponents';
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
import './style.scss';
import './index.mdl';
export default class Textfield extends Component {
constructor($element, $scope, $attrs) {
super($element);
let input = this.input = this.element.querySelector('input');
input.addEventListener('input',
() => this.checkValue());
input.addEventListener('focus',
() => this.checkValue());
input.addEventListener('blur',
() => this.showClear(false));
let clearButton = this.element.querySelector('button');
clearButton.addEventListener('click',
() => this.onClearClick());
clearButton.addEventListener('mousedown',
event => event.preventDefault());
// input.value = ' ';
let div = this.element.firstChild;
componentHandler.upgradeElement(div);
}
link($scope, $attrs) {
let mdlTextField = this.element.firstChild.MaterialTextfield;
$scope.$watch($attrs.model,
() => mdlTextField.updateClasses_());
mdlTextField.updateClasses_();
}
onClearClick() {
this.input.value = '';
this.checkValue();
let event = this.document.createEvent('HTMLEvents');
event.initEvent('change', false, true);
this.input.dispatchEvent(event);
}
checkValue() {
this.showClear(this.input.value);
}
showClear(show) {
let clearButton = this.element.querySelector('button');
clearButton.style.visibility = show ? 'visible' : 'hidden';
}
}
Textfield.$inject = ['$element', '$scope', '$attrs'];
directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME];
export function directive(resolve, normalizer) {
return {
restrict: 'E',
template: function(_, attrs) {
normalizer.normalize(attrs);
return resolve.getTemplate('textfield', attrs);
},
link: function($scope, $element, $attrs, $ctrl) {
$ctrl.link($scope, $attrs);
},
controller: Textfield
};
}
module.directive('vnTextfield', directive);

View File

@ -5,11 +5,8 @@
name="*[name]*" name="*[name]*"
ng-model="*[model]*" ng-model="*[model]*"
vn-validation="*[rule]*" vn-validation="*[rule]*"
*[enabled]* *[enabled]*/>
ng-focus="onFocusInput(*[model]*, $event)" <button type="button" class="mdl-chip__action" title="Clear text">
ng-blur="onBlurInput($event)"
/>
<button type="button" class="mdl-chip__action" ng-click="clickClear('*[model]*')">
<i class="material-icons">clear</i> <i class="material-icons">clear</i>
</button> </button>
<label class="mdl-textfield__label" translate>*[label]*</label> <label class="mdl-textfield__label" translate>*[label]*</label>

View File

@ -0,0 +1,16 @@
import {module} from '../module';
export const NAME = 'vnTextfieldMdlFactory';
export function factory() {
return {
template: require('./index.mdl.html'),
default: {
label: 'text',
className: 'mdl-textfield--floating-label',
type: 'text'
}
};
}
module.factory(NAME, factory);

View File

@ -1,11 +0,0 @@
.mdl-chip__action{
position: absolute;
top: 0px;
right: -6px;
margin: 22px 0px;
visibility: hidden;
}
.material-icons{
font-size: 18px;
}

View File

@ -0,0 +1,12 @@
vn-textfield {
.mdl-chip__action{
position: absolute;
top: 0px;
right: -6px;
margin: 22px 0px;
visibility: hidden;
}
.material-icons{
font-size: 18px;
}
}

View File

@ -1,59 +0,0 @@
import {module as _module} from '../module';
import * as resolveFactory from '../lib/resolveDefaultComponents';
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
import * as util from '../lib/util';
require('./style.css');
const _NAME = 'textfield';
export const NAME = util.getName(_NAME);
directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME, '$parse'];
export function directive(resolve, normalizer, $parse) {
return {
restrict: 'E',
template: function(_, attrs) {
normalizer.normalize(attrs);
return resolve.getTemplate(_NAME, attrs);
},
link: function(scope, element, attrs) {
scope.$watch(attrs.model, () => {
let mdlField = element[0].firstChild.MaterialTextfield;
if (mdlField)
mdlField.updateClasses_();
});
componentHandler.upgradeElement(element[0].firstChild);
scope.clickClear = function(model) {
setTimeout(() => {
scope.$apply(function() {
$parse(model).assign(scope, "");
});
});
};
scope.onFocusInput = function(model, event) {
var buttonClear = event.target.parentNode.querySelector("button");
checkModelValue(buttonClear, model);
};
scope.onBlurInput = function(event) {
var buttonClear = event.target.parentNode.querySelector("button");
setTimeout(() => {
buttonClear.style.visibility = "hidden";
}, 80);
};
element.on('input', function() {
var buttonClear = this.querySelector("button");
var model = this.querySelector("input").value;
checkModelValue(buttonClear, model);
});
function checkModelValue(buttonClear, model) {
if (model !== undefined && model !== "")
buttonClear.style.visibility = "visible";
else
buttonClear.style.visibility = "hidden";
}
}
};
}
_module.directive(NAME, directive);

View File

@ -1,24 +0,0 @@
import {module as _module} from '../module';
import * as util from '../lib/util';
import * as constant from '../lib/constants';
import template from './textfield.mdl.html';
const _NAME = 'textfield';
const DEFAULT_LABEL = 'text';
const DEFAULT_CLASS = 'mdl-textfield--floating-label';
const DEFAULT_TYPE = 'text';
export const NAME = util.getFactoryName(_NAME + constant.MATERIAL_DESIGN_FRAMEWORK);
export function factory() {
return {
template: template,
default: {
label: DEFAULT_LABEL,
className: DEFAULT_CLASS,
type: DEFAULT_TYPE
}
};
}
_module.factory(NAME, factory);

View File

@ -2,7 +2,7 @@
"ids": { "ids": {
"User": 2, "User": 2,
"AccessToken": 4, "AccessToken": 4,
"Client": 23, "Client": 24,
"PaymentMethod": 4, "PaymentMethod": 4,
"SalesPerson": 11, "SalesPerson": 11,
"Address": 87, "Address": 87,
@ -28,7 +28,8 @@
"16": "{\"name\":\"Floristeria Antonieta\",\"fi\":\"2345234523d\",\"socialName\":\"23452345assdfgsdfgt\",\"active\":true,\"dueDay\":5,\"id\":16,\"modify\":\"FiscalData\",\"email\":\"antonieta@gmail.com\",\"phone\":\"654654654\",\"mobile\":\"654456456\",\"fax\":\"456456456\",\"street\":\"asdfasdf\",\"salesPerson\":8,\"city\":\"Albalat de la Ribera\",\"postcode\":\"46532\"}", "16": "{\"name\":\"Floristeria Antonieta\",\"fi\":\"2345234523d\",\"socialName\":\"23452345assdfgsdfgt\",\"active\":true,\"dueDay\":5,\"id\":16,\"modify\":\"FiscalData\",\"email\":\"antonieta@gmail.com\",\"phone\":\"654654654\",\"mobile\":\"654456456\",\"fax\":\"456456456\",\"street\":\"asdfasdf\",\"salesPerson\":8,\"city\":\"Albalat de la Ribera\",\"postcode\":\"46532\"}",
"19": "{\"name\":\"Planticas Eustaquio\",\"fi\":\"789456123B\",\"socialName\":\"Eustaquio Martinez\",\"active\":true,\"dueDay\":5,\"id\":19,\"email\":\"peustaquio@hotmail.es\",\"city\":\"Polinya\",\"postcode\":\"46231\",\"phone\":\"963215486\"}", "19": "{\"name\":\"Planticas Eustaquio\",\"fi\":\"789456123B\",\"socialName\":\"Eustaquio Martinez\",\"active\":true,\"dueDay\":5,\"id\":19,\"email\":\"peustaquio@hotmail.es\",\"city\":\"Polinya\",\"postcode\":\"46231\",\"phone\":\"963215486\"}",
"21": "{\"name\":\"Ramos Antonieta\",\"fi\":\"B89564289\",\"socialName\":\"Antonia SL\",\"active\":true,\"dueDay\":5,\"id\":21,\"email\":\"ramos@rantonieta.es\",\"salesPerson\":8,\"phone\":\"986574232\"}", "21": "{\"name\":\"Ramos Antonieta\",\"fi\":\"B89564289\",\"socialName\":\"Antonia SL\",\"active\":true,\"dueDay\":5,\"id\":21,\"email\":\"ramos@rantonieta.es\",\"salesPerson\":8,\"phone\":\"986574232\"}",
"22": "{\"name\":\"Plantas Raimundo\",\"fi\":\"2536418B\",\"socialName\":\"Plantas Raimundo SL\",\"dueDay\":5,\"id\":22,\"email\":\"jose@plantasraimundo.com\",\"phone\":\"963254289\",\"mobile\":\"641967586\",\"salesPerson\":3,\"city\":\"Sueca\",\"postcode\":\"46985\"}" "22": "{\"name\":\"Plantas Raimundo\",\"fi\":\"2536418B\",\"socialName\":\"Plantas Raimundo SL\",\"dueDay\":5,\"id\":22,\"email\":\"jose@plantasraimundo.com\",\"phone\":\"963254289\",\"mobile\":\"641967586\",\"salesPerson\":3,\"city\":\"Sueca\",\"postcode\":\"46985\"}",
"23": "{\"name\":\"ddddddddd\",\"fi\":\"sdsdsd\",\"socialName\":\"sdsdsd\",\"dueDay\":5,\"id\":23}"
}, },
"PaymentMethod": { "PaymentMethod": {
"1": "{\"name\":\"Tarjeta\",\"id\":1}", "1": "{\"name\":\"Tarjeta\",\"id\":1}",

View File

@ -11,12 +11,13 @@
"compression": "^1.0.3", "compression": "^1.0.3",
"cors": "^2.5.2", "cors": "^2.5.2",
"helmet": "^1.3.0", "helmet": "^1.3.0",
"loopback": "^2.22.0",
"loopback-boot": "^2.6.5", "loopback-boot": "^2.6.5",
"loopback-component-explorer": "^2.4.0", "loopback-component-explorer": "^2.4.0",
"serve-favicon": "^2.0.1", "loopback-connector-mysql": "^3.0.0",
"strong-error-handler": "^1.0.1",
"loopback-datasource-juggler": "^2.39.0", "loopback-datasource-juggler": "^2.39.0",
"loopback": "^2.22.0" "serve-favicon": "^2.0.1",
"strong-error-handler": "^1.0.1"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^2.13.1", "eslint": "^2.13.1",

View File

@ -1,7 +1,9 @@
module.exports = function(app) { module.exports = function(app) {
/*
var User = app.models.User; var User = app.models.User;
User.create ({ User.create ({
email: 'admin@admin.com', email: 'admin@admin.com',
password: '1234' password: '1234'
}, function (err, user) {}); }, function (err, user) {});
*/
}; };

View File

@ -1,4 +1,3 @@
'use strict';
module.exports = function(server) { module.exports = function(server) {
// Install a `/` route that returns server status // Install a `/` route that returns server status

View File

@ -1,6 +1,16 @@
{ {
"db": { "db": {
"name": "db", "name": "db",
"connector": "memory" "connector": "memory"
},
"auth": {
"name": "mysql",
"connector": "mysql",
"database": "auth",
"debug": false,
"host": "localhost",
"port": 3306,
"username": "root",
"password": ""
} }
} }

View File

@ -14,12 +14,24 @@
] ]
}, },
"User": { "User": {
"dataSource": "db", "dataSource": "auth",
"public": false "public": true
}, },
"AccessToken": { "AccessToken": {
"dataSource": "db", "dataSource": "auth",
"public": false, "public": true,
"strict": true "strict": true
},
"ACL": {
"dataSource": "auth",
"public": true
},
"RoleMapping": {
"dataSource": "auth",
"public": true
},
"Role": {
"dataSource": "auth",
"public": true
} }
} }

View File

@ -8,11 +8,11 @@
"id": true, "id": true,
"description": "Identifier" "description": "Identifier"
}, },
"street": { "consignee": {
"type": "string", "type": "string",
"required": true "required": true
}, },
"consignee": { "street": {
"type": "string", "type": "string",
"required": true "required": true
}, },
@ -23,8 +23,8 @@
"postcode": { "postcode": {
"type": "string" "type": "string"
}, },
"enabled": { "province": {
"type": "boolean" "type": "Number"
}, },
"phone": { "phone": {
"type": "string" "type": "string"
@ -32,6 +32,9 @@
"mobile": { "mobile": {
"type": "string" "type": "string"
}, },
"enabled": {
"type": "boolean"
},
"default": { "default": {
"type": "boolean" "type": "boolean"
} }

View File

@ -2,8 +2,8 @@
module.exports = function(Client) { module.exports = function(Client) {
// Validations // Validations
Client.validatesUniquenessOf('name', {message: 'El nombre debe ser unico'}); Client.validatesUniquenessOf('name', {message: 'El nombre debe ser único'});
Client.validatesUniquenessOf('fi', {message: 'El nif/cif debe ser unico'}); Client.validatesUniquenessOf('fi', {message: 'El NIF/CIF debe ser único'});
Client.validatesPresenceOf('socialName', {message: 'Debe especificarse la razón social'}); Client.validatesPresenceOf('socialName', {message: 'Debe especificarse la razón social'});
Client.validatesFormatOf('postcode', {allowNull: true, with: /^\d+$/, message: 'El código postal solo debe contener números'}); Client.validatesFormatOf('postcode', {allowNull: true, with: /^\d+$/, message: 'El código postal solo debe contener números'});
Client.validatesLengthOf('postcode', {allowNull: true, min: 3, max: 10}); Client.validatesLengthOf('postcode', {allowNull: true, min: 3, max: 10});

View File

@ -35,12 +35,15 @@
"street": { "street": {
"type": "string" "type": "string"
}, },
"consignee": {
"type": "string"
},
"city": { "city": {
"type": "string" "type": "string"
}, },
"province": {
"type": "Number"
},
"country": {
"type": "Number"
},
"postcode": { "postcode": {
"type": "string" "type": "string"
}, },
@ -71,7 +74,7 @@
"dueDay": { "dueDay": {
"type": "Number" "type": "Number"
}, },
"gestdoc": { "dms": {
"type": "Number" "type": "Number"
}, },
"surcharge": { "surcharge": {
@ -94,6 +97,16 @@
"model": "Account", "model": "Account",
"foreignKey": "id" "foreignKey": "id"
}, },
"payMethod": {
"type": "hasOne",
"model": "PayMethod",
"foreignKey": "id"
},
"salesPerson": {
"type": "hasOne",
"model": "Employee",
"foreignKey": "id"
},
"addresses": { "addresses": {
"type": "hasMany", "type": "hasMany",
"model": "Address", "model": "Address",

View File

@ -20,11 +20,11 @@
}, },
"relations": { "relations": {
"salesPerson": { "salesPerson": {
"type": "belongsTo", "type": "hasOne",
"model": "SalesPerson", "model": "Employee",
"foreignKey": "id" "foreignKey": "id"
}, },
"clients": { "client": {
"type": "hasOne", "type": "hasOne",
"model": "Client", "model": "Client",
"foreignKey": "id" "foreignKey": "id"

View File

@ -1,5 +1,5 @@
{ {
"name": "SalesPerson", "name": "Employee",
"base": "PersistedModel", "base": "PersistedModel",
"validateUpsert": true, "validateUpsert": true,
"properties": { "properties": {

View File

@ -1,5 +1,5 @@
{ {
"name": "PaymentMethod", "name": "PayMethod",
"base": "PersistedModel", "base": "PersistedModel",
"validateUpsert": true, "validateUpsert": true,
"properties": { "properties": {

View File

@ -13,6 +13,13 @@
"required": true "required": true
} }
}, },
"relations": {
"country": {
"type": "hasOne",
"model": "Country",
"foreignKey": "id"
}
},
"acls": [ "acls": [
{ {
"accessType": "*", "accessType": "*",

View File

@ -14,6 +14,7 @@
"loopback": "^2.38.0", "loopback": "^2.38.0",
"loopback-boot": "^2.6.5", "loopback-boot": "^2.6.5",
"loopback-component-explorer": "^2.7.0", "loopback-component-explorer": "^2.7.0",
"loopback-connector-mysql": "^3.0.0",
"loopback-datasource-juggler": "^2.54.0", "loopback-datasource-juggler": "^2.54.0",
"serve-favicon": "^2.0.1", "serve-favicon": "^2.0.1",
"strong-error-handler": "^1.2.1" "strong-error-handler": "^1.2.1"

View File

@ -1,4 +1,4 @@
module.exports = function(server) { module.exports = function(server) {
server.enableAuth(); //server.enableAuth();
}; };

View File

@ -1,6 +1,13 @@
module.exports = function(server) { module.exports = function(server) {
var router = server.loopback.Router(); let router = server.loopback.Router();
router.get('/status', server.loopback.status()); router.get('/status', server.loopback.status());
server.use(router); server.use(router);
/*
let ds = server.dataSources.auth;
//ds.automigrate(function() {
ds.autoupdate(function() {
console.log('Tables migrated!');
});
*/
}; };

View File

@ -3,5 +3,25 @@
"name": "db", "name": "db",
"connector": "memory", "connector": "memory",
"file": "db.json" "file": "db.json"
},
"auth": {
"name": "mysql",
"connector": "mysql",
"database": "auth",
"debug": false,
"host": "localhost",
"port": 3306,
"username": "root",
"password": ""
},
"vn": {
"name": "mysql",
"connector": "mysql",
"database": "vn",
"debug": false,
"host": "localhost",
"port": 3306,
"username": "root",
"password": ""
} }
} }

View File

@ -14,60 +14,60 @@
] ]
}, },
"User": { "User": {
"dataSource": "db", "dataSource": "auth",
"public": true "public": true
}, },
"AccessToken": { "AccessToken": {
"dataSource": "db", "dataSource": "auth",
"public": true, "public": true,
"strict": true "strict": true
}, },
"ACL": { "ACL": {
"dataSource": "db", "dataSource": "auth",
"public": true "public": true
}, },
"RoleMapping": { "RoleMapping": {
"dataSource": "db", "dataSource": "auth",
"public": true "public": true
}, },
"Role": { "Role": {
"dataSource": "db", "dataSource": "auth",
"public": true "public": true
}, },
"Client": { "Client": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"PaymentMethod": { "PayMethod": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"SalesPerson": { "Employee": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"Address": { "Address": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"Agency": { "Agency": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"Province": { "Province": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"Country": { "Country": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"ClientObservation": { "ClientObservation": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
}, },
"Account": { "Account": {
"dataSource": "db", "dataSource": "vn",
"public": true "public": true
} }
} }