Merge branch 'dev' of https://git.verdnatura.es/salix
This commit is contained in:
commit
9d67a622fc
|
@ -16,3 +16,5 @@ rules:
|
|||
camelcase: 0
|
||||
default-case: 0
|
||||
no-eq-null: 0
|
||||
no-console: 0
|
||||
no-warning-comments: 0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
spliting.js
|
||||
build
|
||||
npm-debug.log
|
||||
debug.log
|
||||
datasources.development.json
|
||||
.idea
|
||||
.idea
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"name": "Iniciar",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/services/client/server/server.js",
|
||||
"program": "${workspaceRoot}/services/auth/server/server.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
|
|
|
@ -1,28 +1,25 @@
|
|||
#!/usr/bin/env groovy
|
||||
|
||||
import groovy.json.*;
|
||||
|
||||
def image;
|
||||
def branchName = "${env.BRANCH_NAME}";
|
||||
def branchNameTest = "preprod";
|
||||
def branchNameProd = "master";
|
||||
def prefixDocker = "test";
|
||||
def dockerNginxName = ["nginx", "-p 80:80 --privileged --link test-auth:auth --link test-salix:salix --link test-client:client --link test-mailer:mailer --link test-production:production"]
|
||||
def dockerAuthName = ["auth", "-p 3000:3000"]
|
||||
def dockerSalixName = ["salix", "-p 3001:3001"]
|
||||
def dockerClientName = ["client", "-p 3002:3002"]
|
||||
def dockerMailerName = ["mailer", "-p 3003:3003"]
|
||||
def dockerProductionName = ["production", "-p 3004:3004"]
|
||||
def branchProduction = "master"
|
||||
def branchTest = "test";
|
||||
def dockerHost = "${env.DOCKER_HOST}";
|
||||
|
||||
def buildNumber = "${env.BUILD_NUMBER}";
|
||||
env.NODE_ENV = branchName;
|
||||
env.BRANCH_NAME = branchName;
|
||||
env.TAG = "${env.BUILD_NUMBER}";
|
||||
|
||||
def dockers = [dockerAuthName, dockerSalixName, dockerClientName, dockerMailerName, dockerProductionName, dockerNginxName]
|
||||
if (branchName == "test")
|
||||
env.NODE_ENV = "development";
|
||||
|
||||
node {
|
||||
|
||||
if (branchName == branchNameProd)
|
||||
prefixDocker = "prod";
|
||||
if (branchName == branchProduction)
|
||||
dockerHost = "tcp://172.16.255.29:2375";
|
||||
|
||||
node
|
||||
{
|
||||
stage ('Print environment variables'){
|
||||
echo "Branch ${branchName}, Build ${env.TAG}, NODE_ENV ${env.NODE_ENV} en docker Host ${dockerHost}"
|
||||
}
|
||||
stage ('Checkout') {
|
||||
checkout scm
|
||||
}
|
||||
|
@ -31,51 +28,25 @@ node {
|
|||
sh "npm install"
|
||||
}
|
||||
|
||||
stage ('build Project Salix'){
|
||||
stage ('build Project'){
|
||||
sh "gulp build"
|
||||
}
|
||||
|
||||
for (int i = 0; i < dockers.size(); i++)
|
||||
stage ("docker")
|
||||
{
|
||||
def element = dockers[i][0]
|
||||
def ports = dockers[i][1]
|
||||
|
||||
stage ("docker ${element}")
|
||||
stage ("install modules loopback service")
|
||||
{
|
||||
stage ("Stopping ${prefixDocker}-${element} actual")
|
||||
{
|
||||
try
|
||||
{
|
||||
def returnDocker = sh (script: "docker stop ${prefixDocker}-${element}", returnStdout: true).trim();
|
||||
echo "${returnDocker}";
|
||||
returnDocker = sh (script: "docker rm ${prefixDocker}-${element}", returnStdout: false).trim();
|
||||
//echo "${returnDocker}";
|
||||
returnDocker = sh (script: "docker rmi ${prefixDocker}-${element}:${buildNumber-3}", returnStdout: true).trim();
|
||||
echo "borran ${prefixDocker}-${element}:${buildNumber-3}";
|
||||
//echo "${returnDocker}";
|
||||
}catch(Exception _){
|
||||
echo "Error Stage Stopping"
|
||||
}
|
||||
}
|
||||
stage ("Create Docker Image ${element}") {
|
||||
dir("./services/${element}"){
|
||||
stage ("Install modules service ${element}"){
|
||||
if (fileExists('./package.json'))
|
||||
sh "npm i"
|
||||
}
|
||||
stage("Build image ${element}"){
|
||||
image = docker.build("${prefixDocker}-${element}:${buildNumber}", ".")
|
||||
}
|
||||
}
|
||||
}
|
||||
stage ("Run Docker ${element}"){
|
||||
image.run ("${ports} --name ${prefixDocker}-${element}")
|
||||
}
|
||||
/*
|
||||
stage('docker registry'){
|
||||
docker.withServer('tcp://harbor.verdnatura.es','docker-registry')
|
||||
}
|
||||
*/
|
||||
sh "cd ./services/loopback && npm install"
|
||||
}
|
||||
|
||||
stage ("Stopping/Removing Docker")
|
||||
{
|
||||
sh "docker-compose down --rmi all"
|
||||
}
|
||||
|
||||
stage ("Generar dockers")
|
||||
{
|
||||
sh "docker-compose up -d --build"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,10 @@ npm run testWatch or test for single run
|
|||
|
||||
on root run:
|
||||
|
||||
gulp docker
|
||||
|
||||
wait 10 secs for db to be ready
|
||||
|
||||
npm run e2e
|
||||
|
||||
## Built With
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
{
|
||||
"url": "/clients",
|
||||
"state": "clients",
|
||||
"component": "vn-client-index"
|
||||
"component": "vn-client-index",
|
||||
"acl": ["employee"]
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "create",
|
||||
|
@ -22,7 +23,7 @@
|
|||
"state": "clientCard.basicData",
|
||||
"component": "vn-client-basic-data",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Datos básicos",
|
||||
|
@ -33,7 +34,7 @@
|
|||
"state": "clientCard.fiscalData",
|
||||
"component": "vn-client-fiscal-data",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Datos fiscales",
|
||||
|
@ -44,7 +45,7 @@
|
|||
"state": "clientCard.billingData",
|
||||
"component": "vn-client-billing-data",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Datos facturación",
|
||||
|
@ -60,7 +61,7 @@
|
|||
"state": "clientCard.addresses.list",
|
||||
"component": "vn-client-addresses",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Consignatarios",
|
||||
|
@ -79,7 +80,7 @@
|
|||
"state": "clientCard.webAccess",
|
||||
"component": "vn-client-web-access",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Acceso web",
|
||||
|
@ -95,7 +96,7 @@
|
|||
"state": "clientCard.notes.list",
|
||||
"component": "vn-client-notes",
|
||||
"params": {
|
||||
"client": "card.client"
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Notas",
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.address.agencyFk"
|
||||
url="/client/api/AgencyServices"
|
||||
url="/client/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
|
|
|
@ -2,6 +2,7 @@ import './address-create.js';
|
|||
|
||||
describe('Client', () => {
|
||||
describe('Component vnAddressCreate', () => {
|
||||
let controller;
|
||||
let $componentController;
|
||||
let $state;
|
||||
|
||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
|||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.id = '1234';
|
||||
controller = $componentController('vnAddressCreate', {$state});
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
let controller = $componentController('vnAddressCreate', {$state});
|
||||
|
||||
expect(controller.address.clientFk).toBe(1234);
|
||||
expect(controller.address.isEnabled).toBe(true);
|
||||
});
|
||||
|
|
|
@ -11,8 +11,12 @@
|
|||
<vn-vertical pad-large>
|
||||
<vn-title>Address</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="enabled" field="$ctrl.address.isEnabled"></vn-check>
|
||||
<vn-check vn-one label="Is equalizated" field="$ctrl.address.isEqualizated"></vn-check>
|
||||
<vn-one>
|
||||
<vn-check label="enabled" field="$ctrl.address.isEnabled"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Is equalizated" field="$ctrl.address.isEqualizated"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Consignee" field="$ctrl.address.consignee" vn-focus></vn-textfield>
|
||||
|
@ -33,7 +37,7 @@
|
|||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.address.defaultAgencyFk"
|
||||
url="/client/api/AgencyServices"
|
||||
url="/client/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Agency">
|
||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
|||
describe('Component vnAddressEdit', () => {
|
||||
let $componentController;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
|||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.addressId = '1234';
|
||||
controller = $componentController('vnAddressEdit', {$state: $state});
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
let controller = $componentController('vnAddressEdit', {$state: $state});
|
||||
|
||||
expect(controller.address.id).toBe(1234);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -27,8 +27,12 @@
|
|||
<vn-textfield vn-one label="Crédito asegurado" field="$ctrl.client.creditInsurance" vn-acl="administrative"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Recargo de equivalencia" field="$ctrl.client.equalizationTax" vn-acl="administrative"></vn-check>
|
||||
<vn-check vn-one label="Vies" field="$ctrl.client.vies" vn-acl="administrative"></vn-check>
|
||||
<vn-one>
|
||||
<vn-check label="Recargo de equivalencia" field="$ctrl.client.equalizationTax" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Vies" field="$ctrl.client.vies" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
|
@ -36,9 +40,15 @@
|
|||
<vn-vertical pad-large>
|
||||
<vn-title>Documentación</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Recibido core VNH" field="$ctrl.client.coreVnh" vn-acl="administrative"></vn-check>
|
||||
<vn-check vn-one label="Recibido core VNL" field="$ctrl.client.coreVnl" vn-acl="administrative"></vn-check>
|
||||
<vn-check vn-one label="Recibido B2B VNL" field="$ctrl.client.sepaVnl" vn-acl="administrative"></vn-check>
|
||||
<vn-one>
|
||||
<vn-check label="Recibido core VNH" field="$ctrl.client.coreVnh" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Recibido core VNL" field="$ctrl.client.coreVnl" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Recibido B2B VNL" field="$ctrl.client.sepaVnl" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
|
@ -59,4 +69,18 @@
|
|||
<button response="CANCEL" translate>No</button>
|
||||
<button response="ACCEPT" translate>Yes, notify</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
<vn-dialog
|
||||
vn-id="propagate-equalizationTax"
|
||||
on-response="$ctrl.returnDialogRE(response)">
|
||||
<tpl-body>
|
||||
<vn-vertical>
|
||||
<vn-one text-center translate>You changes the equivalent tax</vn-one>
|
||||
<vn-one text-center translate>Do you want to spread the change to their consignees?</vn-one>
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<button response="CANCEL" translate>No</button>
|
||||
<button response="ACCEPT" translate>Yes, propagate</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
|
@ -20,6 +20,7 @@ export default class Controller {
|
|||
this.billData.discount = this.client.discount;
|
||||
this.billData.credit = this.client.credit;
|
||||
this.billData.creditInsurance = this.client.creditInsurance;
|
||||
this.equalizationTax = this.client.equalizationTax;
|
||||
}
|
||||
}
|
||||
submit() {
|
||||
|
@ -36,13 +37,41 @@ export default class Controller {
|
|||
}
|
||||
}
|
||||
);
|
||||
if (!equals)
|
||||
|
||||
if (equals) {
|
||||
this.checkREChanges();
|
||||
} else {
|
||||
this.$.sendMail.show();
|
||||
}
|
||||
}
|
||||
returnDialog(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.post(`/mailer/manuscript/payment-update/${this.client.id}`).then(
|
||||
() => this.vnApp.showMessage(this.translate.instant('Notification sent!'))
|
||||
() => {
|
||||
this.vnApp.showMessage(this.translate.instant('Notification sent!'));
|
||||
this.checkREChanges();
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.checkREChanges();
|
||||
}
|
||||
}
|
||||
|
||||
checkREChanges() {
|
||||
let equals = this.equalizationTax == this.client.equalizationTax;
|
||||
this.equalizationTax = this.client.equalizationTax;
|
||||
|
||||
if (!equals)
|
||||
this.$.propagateEqualizationTax.show();
|
||||
}
|
||||
|
||||
returnDialogRE(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.patch(`/client/api/Clients/${this.client.id}/addressesPropagateRe`, {isEqualizated: this.client.equalizationTax}).then(
|
||||
res => {
|
||||
if (res.data)
|
||||
this.vnApp.showMessage(this.translate.instant('Equivalent tax spreaded'));
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ describe('Client', () => {
|
|||
let $componentController;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -18,11 +19,11 @@ describe('Client', () => {
|
|||
$scope.watcher = {submit};
|
||||
let show = jasmine.createSpy('show');
|
||||
$scope.sendMail = {show};
|
||||
controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('copyData()', () => {
|
||||
it(`should define billData using client's data`, () => {
|
||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
controller.client = {
|
||||
credit: 1000000000000,
|
||||
creditInsurance: null,
|
||||
|
@ -40,7 +41,6 @@ describe('Client', () => {
|
|||
|
||||
describe('submit()', () => {
|
||||
it(`should call submit() on the watcher then receive a callback`, done => {
|
||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
spyOn(controller, 'checkPaymentChanges');
|
||||
controller.submit()
|
||||
.then(() => {
|
||||
|
@ -53,7 +53,6 @@ describe('Client', () => {
|
|||
|
||||
describe('checkPaymentChanges()', () => {
|
||||
it(`should not call sendMail.show() if there are no changes on billing data`, () => {
|
||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
controller.billData = {marvelHero: 'Silver Surfer'};
|
||||
controller.client = {marvelHero: 'Silver Surfer'};
|
||||
controller.checkPaymentChanges();
|
||||
|
@ -62,7 +61,6 @@ describe('Client', () => {
|
|||
});
|
||||
|
||||
it(`should call sendMail.show() if there are changes on billing data object`, () => {
|
||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
controller.billData = {marvelHero: 'Silver Surfer'};
|
||||
controller.client = {marvelHero: 'Spider-Man'};
|
||||
controller.checkPaymentChanges();
|
||||
|
@ -73,7 +71,6 @@ describe('Client', () => {
|
|||
|
||||
describe('returnDialog()', () => {
|
||||
it('should request to send notification email', () => {
|
||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||
controller.client = {id: '123'};
|
||||
$httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done');
|
||||
$httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`);
|
||||
|
|
|
@ -4,5 +4,9 @@
|
|||
"No": "No",
|
||||
"Yes, notify": "Sí, notificar",
|
||||
"Notification sent!": "¡Notificación enviada!",
|
||||
"Notification error": "Error al enviar notificación"
|
||||
"Notification error": "Error al enviar notificación",
|
||||
"You changes the equivalent tax": "Has cambiado el recargo de equivalencia",
|
||||
"Do you want to spread the change to their consignees?" : "¿Deseas propagar el cambio a sus consignatarios?",
|
||||
"Yes, propagate": "Si, propagar",
|
||||
"Equivalent tax spreaded": "Recargo de equivalencia propagado"
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
<vn-horizontal>
|
||||
<mg-ajax
|
||||
path="/client/api/Clients/{{edit.params.id}}/card"
|
||||
actions="card.client = edit.model"
|
||||
actions="$ctrl.client = edit.model"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-empty style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
|
||||
<vn-descriptor
|
||||
client="card.client"
|
||||
active="card.client.active"
|
||||
client="$ctrl.client"
|
||||
active="$ctrl.client.active"
|
||||
class="display-block" >
|
||||
</vn-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
|
|
|
@ -9,6 +9,5 @@ export default class Controller {
|
|||
|
||||
ngModule.component('vnClientCard', {
|
||||
template: require('./card.html'),
|
||||
controller: Controller,
|
||||
controllerAs: 'card'
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
|||
describe('Component vnClientCard', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -12,11 +13,10 @@ describe('Client', () => {
|
|||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope;
|
||||
controller = $componentController('vnClientCard', {$scope: $scope});
|
||||
}));
|
||||
|
||||
it('should define and set client property to null in the module instance', () => {
|
||||
let controller = $componentController('vnClientCard', {$scope: $scope});
|
||||
|
||||
expect(controller.client).toBeDefined();
|
||||
expect(controller.client).toBe(null);
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ describe('Client', () => {
|
|||
let $componentController;
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -23,11 +24,10 @@ describe('Client', () => {
|
|||
};
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientCreate', {$scope: $scope});
|
||||
}));
|
||||
|
||||
it('should define and set scope, state and client properties', () => {
|
||||
let controller = $componentController('vnClientCreate', {$scope: $scope});
|
||||
|
||||
expect(controller.$).toBe($scope);
|
||||
expect(controller.$state).toBe($state);
|
||||
expect(controller.client.active).toBe(true);
|
||||
|
@ -35,7 +35,6 @@ describe('Client', () => {
|
|||
|
||||
describe('onSubmit()', () => {
|
||||
it(`should call submit() on the watcher then expect a callback`, () => {
|
||||
let controller = $componentController('vnClientCreate', {$scope: $scope});
|
||||
spyOn($state, 'go');
|
||||
controller.onSubmit();
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<vn-card>
|
||||
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<a vn-one ui-sref="clients">
|
||||
<i class="material-icons descriptor-icon">person</i>
|
||||
</vn-one>
|
||||
</a>
|
||||
<vn-vertical vn-two>
|
||||
<div class="margin-none">{{::$ctrl.client.id}}</div>
|
||||
<div class="margin-none">{{$ctrl.client.name}}</div>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import './style.css';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope, $http) {
|
||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
|||
describe('Component vnDescriptor', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -12,11 +13,11 @@ describe('Client', () => {
|
|||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnDescriptor', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('set active', () => {
|
||||
it('should check if active is defined and diferent from the new value', () => {
|
||||
let controller = $componentController('vnDescriptor', {$scope: $scope});
|
||||
controller.client = {id: 1};
|
||||
|
||||
expect(controller._active).toBe(undefined);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.descriptor-icon{
|
||||
font-size:60px;
|
||||
}
|
|
@ -10,8 +10,12 @@
|
|||
<vn-vertical pad-large>
|
||||
<vn-title>Fiscal data</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-check vn-one label="Facturar" field="$ctrl.client.hasToInvoice"></vn-check>
|
||||
<vn-check vn-one label="Factura impresa" field="$ctrl.client.invoiceByEmail"></vn-check>
|
||||
<vn-one>
|
||||
<vn-check label="Has to invoice" field="$ctrl.client.hasToInvoice"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Invoice by mail" field="$ctrl.client.invoiceByEmail"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-two label="Domicilio fiscal" field="$ctrl.client.street" vn-focus></vn-textfield>
|
||||
|
@ -33,7 +37,7 @@
|
|||
url="/client/api/Countries"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="País">
|
||||
label="CountryFk">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
|
|
|
@ -3,6 +3,7 @@ import './index.js';
|
|||
describe('Client', () => {
|
||||
describe('Component vnClientIndex', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -10,17 +11,15 @@ describe('Client', () => {
|
|||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnClientIndex');
|
||||
}));
|
||||
|
||||
it('should define and set model property as an empty object', () => {
|
||||
let controller = $componentController('vnClientIndex');
|
||||
|
||||
expect(controller.model).toEqual({});
|
||||
});
|
||||
|
||||
describe('search()', () => {
|
||||
it(`should set model's search to the search input`, () => {
|
||||
let controller = $componentController('vnClientIndex');
|
||||
controller.model.search = 'batman';
|
||||
let index = {
|
||||
filter: {},
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"Client": "Cliente",
|
||||
"Clients": "Clientes",
|
||||
"Fiscal data": "Datos Fiscales"
|
||||
"Fiscal data": "Datos Fiscales",
|
||||
"Has to invoice": "Factura",
|
||||
"Invoice by mail": "Factura impresa",
|
||||
"CountryFk": "País"
|
||||
}
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
|||
describe('Component vnNoteCreate', () => {
|
||||
let $componentController;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
|||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.id = '1234';
|
||||
controller = $componentController('vnNoteCreate', {$state: $state});
|
||||
}));
|
||||
|
||||
it('should define clientFk using $state.params.id', () => {
|
||||
let controller = $componentController('vnNoteCreate', {$state: $state});
|
||||
|
||||
expect(controller.note.clientFk).toBe(1234);
|
||||
expect(controller.note.client).toBe(undefined);
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ describe('Client', () => {
|
|||
let $componentController;
|
||||
let $state;
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -14,11 +15,11 @@ describe('Client', () => {
|
|||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should call getObservation() with the client id`, () => {
|
||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||
controller.client = {
|
||||
id: 1234
|
||||
};
|
||||
|
@ -31,19 +32,20 @@ describe('Client', () => {
|
|||
|
||||
describe('$getObservation()', () => {
|
||||
it(`should request to GET the client notes`, () => {
|
||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||
controller.client = {id: '1234'};
|
||||
let json = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
|
||||
$httpBackend.when('GET', `/client/api/clientObservations?filter=${json}`).respond('ok');
|
||||
$httpBackend.expectGET(`/client/api/clientObservations?filter=${json}`, {Accept: 'application/json, text/plain, */*'});
|
||||
let jsonString = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
|
||||
let json = {data: 'some data'};
|
||||
$httpBackend.when('GET', `/client/api/clientObservations?filter=${jsonString}`).respond(json);
|
||||
$httpBackend.expectGET(`/client/api/clientObservations?filter=${jsonString}`, {Accept: 'application/json, text/plain, */*'});
|
||||
controller.getObservation();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.observations).toEqual(json);
|
||||
});
|
||||
});
|
||||
|
||||
describe('$newObservation()', () => {
|
||||
it(`should redirect the user to the newObservation view`, () => {
|
||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||
controller.client = {id: '1234'};
|
||||
spyOn(controller.$state, 'go');
|
||||
controller.newObservation();
|
||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
|||
describe('Component vnClientSearchPanel', () => {
|
||||
let $componentController;
|
||||
let $window;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -12,11 +13,11 @@ describe('Client', () => {
|
|||
beforeEach(angular.mock.inject((_$componentController_, _$window_) => {
|
||||
$componentController = _$componentController_;
|
||||
$window = _$window_;
|
||||
controller = $componentController('vnClientSearchPanel', {$window: $window});
|
||||
}));
|
||||
|
||||
describe('onSearch()', () => {
|
||||
it(`should call setStorageValue() and onSubmit()`, () => {
|
||||
let controller = $componentController('vnClientSearchPanel', {$window: $window});
|
||||
spyOn(controller, 'setStorageValue');
|
||||
spyOn(controller, 'onSubmit');
|
||||
controller.setStorageValue();
|
||||
|
@ -29,8 +30,6 @@ describe('Client', () => {
|
|||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should set filter properties using the search values`, () => {
|
||||
let controller = $componentController('vnClientSearchPanel', {$window: $window});
|
||||
|
||||
expect(controller.filter).not.toBeDefined();
|
||||
spyOn(JSON, 'parse').and.returnValue({data: 'data'});
|
||||
controller.$onChanges();
|
||||
|
|
|
@ -8,9 +8,15 @@
|
|||
<form name="form" ng-submit="watcher.submit()" pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Web access</vn-title>
|
||||
<vn-check label="Enable web access" field="$ctrl.account.active"></vn-check>
|
||||
<vn-textfield label="User" class="margin-medium-top" field="$ctrl.account.name" vn-focus></vn-textfield>
|
||||
<vn-one>
|
||||
<vn-title>Web access</vn-title>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Enable web access" field="$ctrl.account.active"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-textfield label="User" class="margin-medium-top" field="$ctrl.account.name" vn-focus></vn-textfield>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
|
|
|
@ -5,6 +5,7 @@ describe('Component VnClientWebAccess', () => {
|
|||
let $httpBackend;
|
||||
let $scope;
|
||||
let vnApp;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -16,11 +17,11 @@ describe('Component VnClientWebAccess', () => {
|
|||
$httpBackend = _$httpBackend_;
|
||||
vnApp = _vnApp_;
|
||||
spyOn(vnApp, 'showError');
|
||||
controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should pass client's account data to account then call isCustomer function`, () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
spyOn(controller, 'isCustomer');
|
||||
controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
|
||||
controller.account = {};
|
||||
|
@ -33,7 +34,6 @@ describe('Component VnClientWebAccess', () => {
|
|||
|
||||
describe('isCustomer()', () => {
|
||||
it(`should perform a query if client is defined with an ID`, () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
controller.client = {id: '1234'};
|
||||
controller.isCustomer();
|
||||
|
||||
|
@ -45,7 +45,6 @@ describe('Component VnClientWebAccess', () => {
|
|||
|
||||
describe('onPassOpen()', () => {
|
||||
it('should set passwords to empty values', () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
controller.newPassword = 'm24x8';
|
||||
controller.repeatPassword = 'm24x8';
|
||||
controller.onPassOpen();
|
||||
|
@ -57,7 +56,6 @@ describe('Component VnClientWebAccess', () => {
|
|||
|
||||
describe('onPassChange()', () => {
|
||||
it('should request to update the password', () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
controller.client = {id: '1234'};
|
||||
controller.newPassword = 'm24x8';
|
||||
controller.repeatPassword = 'm24x8';
|
||||
|
@ -70,7 +68,6 @@ describe('Component VnClientWebAccess', () => {
|
|||
|
||||
describe(`when password is empty`, () => {
|
||||
it(`should throw Passwords can't be empty error`, () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
controller.client = {id: '1234'};
|
||||
controller.newPassword = '';
|
||||
controller.canChangePassword = true;
|
||||
|
@ -82,7 +79,6 @@ describe('Component VnClientWebAccess', () => {
|
|||
|
||||
describe(`when passwords don't match`, () => {
|
||||
it(`should throw Passwords don't match error`, () => {
|
||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
controller.client = {id: '1234'};
|
||||
controller.newPassword = 'm24x8';
|
||||
controller.canChangePassword = true;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
filter="true"
|
||||
load-more="$ctrl.getItems()"
|
||||
show-load-more="$ctrl.maxRow"
|
||||
remove-load-more="$ctrl.removeLoadMore"
|
||||
filter-action="$ctrl.findItems(search)"
|
||||
item-width="$ctrl.width"
|
||||
multiple="$ctrl.multiple"
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import {module} from '../module';
|
||||
import Component from '../lib/component';
|
||||
import copyObject from '../lib/copy';
|
||||
import './style.scss';
|
||||
|
||||
class Autocomplete extends Component {
|
||||
constructor($element, $scope, $http, $timeout) {
|
||||
constructor($element, $scope, $http, $timeout, $filter) {
|
||||
super($element);
|
||||
this.$element = $element;
|
||||
this.$scope = $scope;
|
||||
this.$http = $http;
|
||||
this.$timeout = $timeout;
|
||||
this.$filter = $filter;
|
||||
|
||||
this._showDropDown = false;
|
||||
this.finding = false;
|
||||
|
@ -19,10 +21,12 @@ class Autocomplete extends Component {
|
|||
this.maxRow = 10;
|
||||
this.showField = this.showField || 'name';
|
||||
this.valueField = this.valueField || 'id';
|
||||
this.items = this.data || [];
|
||||
this.order = this.order || 'name ASC';
|
||||
this.items = copyObject(this.data) || [];
|
||||
this.displayValueMultiCheck = [];
|
||||
this._multiField = [];
|
||||
this.readonly = true;
|
||||
this.removeLoadMore = false;
|
||||
}
|
||||
|
||||
get showDropDown() {
|
||||
|
@ -33,6 +37,10 @@ class Autocomplete extends Component {
|
|||
this._preLoad = true;
|
||||
this.getItems();
|
||||
}
|
||||
if (value && !this.width) {
|
||||
let rectangle = this.$element[0].getBoundingClientRect();
|
||||
this.width = Math.round(rectangle.width) - 10;
|
||||
}
|
||||
this._showDropDown = value;
|
||||
}
|
||||
|
||||
|
@ -70,28 +78,36 @@ class Autocomplete extends Component {
|
|||
return this.multiple ? this._multiField : this._field;
|
||||
}
|
||||
set field(value) {
|
||||
this.finding = true;
|
||||
if (value && value.hasOwnProperty(this.valueField)) {
|
||||
this._field = value[this.valueField];
|
||||
if (this.multiple) {
|
||||
this.setMultiField(value[this.valueField]);
|
||||
if (!angular.equals(value, this.field)) {
|
||||
this.finding = true;
|
||||
if (value && value.hasOwnProperty(this.valueField)) {
|
||||
this._field = value[this.valueField];
|
||||
if (this.multiple) {
|
||||
this.setMultiField(value[this.valueField]);
|
||||
}
|
||||
} else {
|
||||
this.setValue(value);
|
||||
}
|
||||
} else {
|
||||
this.setValue(value);
|
||||
|
||||
if (value && value.hasOwnProperty(this.showField))
|
||||
this.displayValue = value[this.showField];
|
||||
|
||||
this.finding = false;
|
||||
|
||||
if (this.onChange)
|
||||
this.onChange({item: this._field});
|
||||
}
|
||||
|
||||
if (value && value.hasOwnProperty(this.showField))
|
||||
this.displayValue = value[this.showField];
|
||||
|
||||
this.finding = false;
|
||||
|
||||
if (this.onChange)
|
||||
this.onChange({item: this._field});
|
||||
}
|
||||
|
||||
set initialData(value) {
|
||||
if (value) {
|
||||
this.field = value;
|
||||
if (value && value.hasOwnProperty(this.valueField)) {
|
||||
this._field = value[this.valueField];
|
||||
if (this.multiple) {
|
||||
this._multiField = [value[this.valueField]]
|
||||
}
|
||||
if (value.hasOwnProperty(this.showField)) {
|
||||
this.displayValue = value[this.showField];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,12 +189,12 @@ class Autocomplete extends Component {
|
|||
}
|
||||
|
||||
findItems(search) {
|
||||
if (!this.url)
|
||||
return this.items ? this.items : [];
|
||||
|
||||
if (search && !this.finding) {
|
||||
if (this.url && search && !this.finding) {
|
||||
this.maxRow = false;
|
||||
let filter = {where: {name: {regexp: search}}};
|
||||
if (this.filter && this.filter.where) {
|
||||
Object.assign(filter.where, this.filter.where);
|
||||
}
|
||||
let json = JSON.stringify(filter);
|
||||
this.finding = true;
|
||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||
|
@ -198,43 +214,65 @@ class Autocomplete extends Component {
|
|||
this.finding = false;
|
||||
}
|
||||
);
|
||||
} else if (search && !this.url && this.data) {
|
||||
this.items = this.$filter('filter')(this.data, search);
|
||||
} else if (!search && !this.finding) {
|
||||
this.maxRow = 10;
|
||||
this.items = [];
|
||||
this.getItems();
|
||||
}
|
||||
}
|
||||
|
||||
getItems() {
|
||||
let filter = {};
|
||||
if (this.url === undefined) {
|
||||
this.items = copyObject(this.data);
|
||||
this.maxRow = false;
|
||||
this.removeLoadMore = true;
|
||||
} else {
|
||||
let filter = {};
|
||||
if (!this.finding) {
|
||||
this.finding = true;
|
||||
|
||||
if (this.maxRow) {
|
||||
if (this.items) {
|
||||
filter.skip = this.items.length;
|
||||
}
|
||||
filter.limit = this.maxRow;
|
||||
filter.order = 'name ASC';
|
||||
}
|
||||
if (this.maxRow) {
|
||||
if (this.items) {
|
||||
filter.skip = this.items.length;
|
||||
}
|
||||
filter.limit = this.maxRow;
|
||||
filter.order = this.order;
|
||||
}
|
||||
if (this.filter) {
|
||||
Object.assign(filter, this.filter);
|
||||
}
|
||||
|
||||
let json = JSON.stringify(filter);
|
||||
let json = JSON.stringify(filter);
|
||||
|
||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||
json => {
|
||||
if (json.data.length)
|
||||
json.data.forEach(
|
||||
el => {
|
||||
if (this.multiple) {
|
||||
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
|
||||
this.removeLoadMore = false;
|
||||
|
||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||
json => {
|
||||
if (json.data.length) {
|
||||
json.data.forEach(
|
||||
el => {
|
||||
if (this.multiple) {
|
||||
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
|
||||
}
|
||||
this.items.push(el);
|
||||
}
|
||||
);
|
||||
if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) {
|
||||
this.removeLoadMore = true;
|
||||
}
|
||||
this.items.push(el);
|
||||
} else {
|
||||
this.maxRow = false;
|
||||
}
|
||||
);
|
||||
else
|
||||
this.maxRow = false;
|
||||
this.finding = false;
|
||||
},
|
||||
() => {
|
||||
this.finding = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.findMore = this.url && this.maxRow;
|
||||
this.mouseFocus = false;
|
||||
|
@ -265,9 +303,6 @@ class Autocomplete extends Component {
|
|||
this.showDropDown = this.mouseFocus;
|
||||
});
|
||||
});
|
||||
|
||||
let rectangle = this.$element[0].getBoundingClientRect();
|
||||
this.width = Math.round(rectangle.width) - 10;
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
|
@ -277,9 +312,17 @@ class Autocomplete extends Component {
|
|||
this.$element.unbind('focusout');
|
||||
}
|
||||
|
||||
$onChanges(objectChange) {
|
||||
if (objectChange.data && objectChange.data.currentValue && objectChange.data.currentValue.length) {
|
||||
this.items = copyObject(objectChange.data.currentValue);
|
||||
this.maxRow = false;
|
||||
this.removeLoadMore = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout'];
|
||||
Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout', '$filter'];
|
||||
|
||||
module.component('vnAutocomplete', {
|
||||
template: require('./autocomplete.html'),
|
||||
|
@ -292,11 +335,11 @@ module.component('vnAutocomplete', {
|
|||
initialData: '<?',
|
||||
onChange: '&?',
|
||||
data: '<?',
|
||||
itemAs: '@?',
|
||||
field: '=',
|
||||
label: '@',
|
||||
itemTemplate: '@?',
|
||||
multiple: '@?'
|
||||
multiple: '@?',
|
||||
order: '@?',
|
||||
filter: '<?'
|
||||
},
|
||||
transclude: {
|
||||
tplItem: '?tplItem'
|
||||
|
|
|
@ -6,6 +6,7 @@ describe('Component vnAutocomplete', () => {
|
|||
let $httpBackend;
|
||||
let $timeout;
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -17,11 +18,11 @@ describe('Component vnAutocomplete', () => {
|
|||
$httpBackend = _$httpBackend_;
|
||||
$timeout = _$timeout_;
|
||||
$element = angular.element('<div></div>');
|
||||
controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
}));
|
||||
|
||||
describe('showDropDown() setter', () => {
|
||||
it(`should set _showDropDown value`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller._showDropDown = '';
|
||||
controller.showDropDown = 'some value';
|
||||
|
||||
|
@ -29,7 +30,6 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set _showDropDown value`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller._showDropDown = '';
|
||||
controller.showDropDown = 'some value';
|
||||
|
||||
|
@ -39,7 +39,6 @@ describe('Component vnAutocomplete', () => {
|
|||
|
||||
describe('displayValue() setter', () => {
|
||||
it(`should display value in a formated way`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
let value = 'some value';
|
||||
controller.displayValue = value;
|
||||
|
||||
|
@ -48,7 +47,6 @@ describe('Component vnAutocomplete', () => {
|
|||
|
||||
describe('when the autocomeplete is multiple', () => {
|
||||
it(`should display values separated with commas`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.multiple = true;
|
||||
controller.displayValue = 'some value';
|
||||
controller.displayValue = 'another value';
|
||||
|
@ -61,14 +59,12 @@ describe('Component vnAutocomplete', () => {
|
|||
describe('field() setter', () => {
|
||||
describe('when value is an object', () => {
|
||||
it(`should set _field controllers property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
||||
|
||||
expect(controller._field).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should set _multifield controllers property `, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.multiple = true;
|
||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
||||
|
||||
|
@ -82,7 +78,6 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set _multifield value and remove it if called a second type with same value`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.multiple = true;
|
||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
||||
|
||||
|
@ -96,7 +91,6 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set displayValue finding an existing item in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.field = {id: 2, name: 'Bruce Wayne'};
|
||||
|
||||
|
@ -106,7 +100,6 @@ describe('Component vnAutocomplete', () => {
|
|||
|
||||
describe('when value is a number', () => {
|
||||
it(`should set _field controller property finding an existing item in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.field = 2;
|
||||
|
||||
|
@ -114,7 +107,6 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set _multifield value and remove it if called a second type with same value finding an existing item in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.multiple = true;
|
||||
controller.field = 2;
|
||||
|
@ -127,7 +119,7 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should perform a query if the item id isn't present in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}').respond();
|
||||
$httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
|
@ -136,7 +128,6 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set displayValue finding an existing item in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.field = 2;
|
||||
|
||||
|
@ -144,7 +135,7 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
|
||||
it(`should set field performing a query as the item id isn't present in the controller.items property`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}').respond();
|
||||
$httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
|
@ -154,25 +145,10 @@ describe('Component vnAutocomplete', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('findItem()', () => {
|
||||
it(`should return items array if the controller does not provide a url and nither it has items`, () => {
|
||||
describe('findItems()', () => {
|
||||
it(`should perform a search and store the result in controller items`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = ['Batman', 'Bruce Wayne'];
|
||||
controller.findItems('some search value');
|
||||
|
||||
expect(controller.items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it(`should perform a query with the search value if the finding flag is false`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.items = ['Batman', 'Bruce Wayne'];
|
||||
controller.findItems('Gotham');
|
||||
|
||||
expect(controller.items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it(`should perform a query with the search value if the finding flag is false`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
||||
controller.url = 'test.com';
|
||||
let search = 'The Joker';
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
||||
$httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
|
||||
|
@ -183,18 +159,37 @@ describe('Component vnAutocomplete', () => {
|
|||
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
|
||||
});
|
||||
|
||||
it(`should perform a query with the search value if the finding flag is false`, () => {
|
||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
||||
let search = 'The Joker';
|
||||
it(`should perform a search with multiple true and store the result in controller items with the checked property defined`, () => {
|
||||
controller.url = 'test.com';
|
||||
let search = 'Joker';
|
||||
controller.multiple = true;
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
||||
$httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
|
||||
$httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}, {id: 4, name: 'Joker'}]);
|
||||
$httpBackend.expectGET(`test.com?filter=${json}`);
|
||||
controller.findItems(search);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
|
||||
expect(controller.items).toEqual([{id: 3, name: 'The Joker', checked: false}, {id: 4, name: 'Joker', checked: false}]);
|
||||
});
|
||||
|
||||
// siguiente test el de Multiple!
|
||||
it(`should call getItems function if there's no search value`, () => {
|
||||
controller.url = 'test.com';
|
||||
spyOn(controller, 'getItems');
|
||||
controller.findItems();
|
||||
|
||||
expect(controller.getItems).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getItems()', () => {
|
||||
it(`should perfom a query to fill the items without filter`, () => {
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET(`test.com?filter={"skip":0,"limit":10,"order":"name ASC"}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
|
||||
$httpBackend.expectGET(`test.com?filter={"skip":0,"limit":10,"order":"name ASC"}`);
|
||||
controller.getItems();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import {module as _module} from '../module';
|
|||
import * as resolveFactory from '../lib/resolveDefaultComponents';
|
||||
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
|
||||
import * as util from '../lib/util';
|
||||
import './style.css';
|
||||
|
||||
const _NAME = 'check';
|
||||
export const NAME = util.getName(_NAME);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
vn-check {
|
||||
float: left;
|
||||
}
|
|
@ -21,6 +21,12 @@ export default class ColumnHeader {
|
|||
}
|
||||
return showArrow;
|
||||
}
|
||||
$onInit() {
|
||||
if (this.defaultOrder) {
|
||||
this.order = this.defaultOrder;
|
||||
this.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnHeader.$inject = [];
|
||||
|
||||
|
@ -29,7 +35,8 @@ module.component('vnColumnHeader', {
|
|||
bindings: {
|
||||
field: '@?',
|
||||
text: '@?',
|
||||
className: '@?'
|
||||
className: '@?',
|
||||
defaultOrder: '@?'
|
||||
},
|
||||
require: {
|
||||
gridHeader: '^^vnGridHeader'
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
import './column-header.js';
|
||||
|
||||
describe('Component vnColumnHeader', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnColumnHeader', {});
|
||||
}));
|
||||
|
||||
describe('onClick()', () => {
|
||||
it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
|
||||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.order = 'ASC';
|
||||
controller.onClick();
|
||||
|
||||
expect(controller.order).toEqual('DESC');
|
||||
});
|
||||
|
||||
it(`should change the ordenation to ASC (ascendant) if it wasnt ASC`, () => {
|
||||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.order = 'DESC or any other value that might occur';
|
||||
controller.onClick();
|
||||
|
||||
expect(controller.order).toEqual('ASC');
|
||||
});
|
||||
|
||||
it(`should call the selectColum() function after changing a value`, () => {
|
||||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.order = 'Change me!';
|
||||
spyOn(controller.gridHeader, 'selectColum');
|
||||
controller.onClick();
|
||||
|
||||
expect(controller.gridHeader.selectColum).toHaveBeenCalledWith(controller);
|
||||
});
|
||||
});
|
||||
|
||||
describe('showArrow()', () => {
|
||||
it(`should return true when the type is DESC and MouseIsOver`, () => {
|
||||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.mouseIsOver = true;
|
||||
let result = controller.showArrow('DESC');
|
||||
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should return true if many conditions are true`, () => {
|
||||
controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
|
||||
controller.field = 'fields should be identical';
|
||||
controller.order = 'ASC';
|
||||
let result = controller.showArrow('ASC');
|
||||
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should return false without type being DESC or any other values being true`, () => {
|
||||
controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
|
||||
controller.field = 'I am the controllers field';
|
||||
controller.order = 'ASC';
|
||||
let result = controller.showArrow('ASC');
|
||||
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onInit()', () => {
|
||||
it(`should never call onClick()`, () => {
|
||||
spyOn(controller, 'onClick');
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.onClick).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should define controllers order as per defaultOrder then call onClick()`, () => {
|
||||
controller.defaultOrder = 'ASC';
|
||||
spyOn(controller, 'onClick');
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.order).toEqual('ASC');
|
||||
expect(controller.onClick).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -38,8 +38,6 @@ export {NAME as SUBMIT, directive as SubmitDirective} from './submit/submit';
|
|||
export {NAME as SUBMIT_MDL, factory as submitMdl} from './submit/submit.mdl';
|
||||
export {NAME as COMBO, directive as ComboDirective} from './combo/combo';
|
||||
export {NAME as COMBO_MDL, factory as comboMdl} from './combo/combo.mdl';
|
||||
/* export {NAME as DATE_PICKER, directive as DatePickerDirective} from './date-picker/date-picker';
|
||||
export {NAME as DATE_PICKER_MDL, factory as datePickerMdl} from './date-picker/date-picker.mdl';*/
|
||||
export {NAME as CARD, directive as CardDirective} from './card/card';
|
||||
export {NAME as CARD_MDL, factory as cardMdl} from './card/card.mdl';
|
||||
export {NAME as SWITCH, directive as SwitchDirective} from './switch/switch';
|
||||
|
|
|
@ -1,51 +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';
|
||||
import Flatpickr from 'vendor/src/flatpickr';
|
||||
|
||||
const _NAME = 'datePicker';
|
||||
export const NAME = util.getName(_NAME);
|
||||
|
||||
directive.$inject = [resolveFactory.NAME, normalizerFactory.NAME, '$translate'];
|
||||
export function directive(resolve, normalizer, $translate) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: function(_, attrs) {
|
||||
normalizer.normalize(attrs);
|
||||
return resolve.getTemplate(_NAME, attrs);
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
let input = element[0];
|
||||
let flatpickrInstance;
|
||||
let initOptions = {};
|
||||
|
||||
if (attrs.iniOpts)
|
||||
initOptions = scope.$eval(attrs.iniOpts);
|
||||
|
||||
if (!initOptions.locale)
|
||||
initOptions.locale = $translate.use();
|
||||
|
||||
/*if (!initOptions.dateFormat && initOptions.locale === 'es')
|
||||
initOptions.dateFormat = 'd-m-Y';*/
|
||||
|
||||
if (!input.matches('input'))
|
||||
input = input.querySelector('input');
|
||||
|
||||
if (input)
|
||||
flatpickrInstance = new Flatpickr(input, initOptions);
|
||||
|
||||
scope.$watch(attrs.model, () => {
|
||||
let mdlField = element[0].firstChild.MaterialCheckbox;
|
||||
if (mdlField)
|
||||
mdlField.updateClasses_();
|
||||
});
|
||||
componentHandler.upgradeElement(element[0].firstChild);
|
||||
|
||||
element.on('$destroy', function() {
|
||||
flatpickrInstance.destroy();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
_module.directive(NAME, directive);
|
|
@ -1,4 +0,0 @@
|
|||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<input class="mdl-textfield__input *[className]*" type="text" name="*[name]*" ng-model="*[model]*" rule="*[rule]*" *[enabled]*/>
|
||||
<label class="mdl-textfield__label" translate>*[label]*</label>
|
||||
</div>
|
|
@ -1,14 +0,0 @@
|
|||
import {module} from '../module';
|
||||
import template from './date-picker.mdl.html';
|
||||
|
||||
export const NAME = 'vnDatePickerMdlFactory';
|
||||
export function factory() {
|
||||
return {
|
||||
template: template,
|
||||
default: {
|
||||
label: 'Label',
|
||||
enabled: 'enabled'
|
||||
}
|
||||
};
|
||||
}
|
||||
module.factory(NAME, factory);
|
|
@ -1,19 +1,21 @@
|
|||
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
|
||||
<div
|
||||
class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label"
|
||||
tabindex="1"
|
||||
ng-focus="$ctrl.hasFocus = true"
|
||||
ng-blur="$ctrl.hasFocus = false"
|
||||
ng-mouseenter="$ctrl.hasMouseIn = true"
|
||||
ng-mouseleave="$ctrl.hasMouseIn = false"
|
||||
>
|
||||
<input type="text"
|
||||
class="mdl-textfield__input"
|
||||
name="{{::$ctrl.name}}"
|
||||
ng-model="$ctrl.modelView"
|
||||
ng-disabled="{{!$ctrl.enabled}}"
|
||||
rule="{{::$ctrl.rule}}"/>
|
||||
<button
|
||||
type="button"
|
||||
class="mdl-chip__action ng-hide"
|
||||
tabindex="-1"
|
||||
translate-attr="{title: 'Clear'}"
|
||||
ng-show="$ctrl.modelView"
|
||||
ng-click="$ctrl.onClear()"
|
||||
>
|
||||
<i class="material-icons">clear</i>
|
||||
</button>
|
||||
<label class="mdl-textfield__label">{{::$ctrl.label | translate}}</label>
|
||||
rule="{{::$ctrl.rule}}"/>
|
||||
|
||||
<div class="mdl-chip__action">
|
||||
<i class="material-icons" ng-if="$ctrl.isTimePicker" ng-click="$ctrl.vp.open()">query_builder</i>
|
||||
<i class="material-icons pointer" ng-show="$ctrl.modelView&&($ctrl.hasFocus||$ctrl.hasMouseIn)" ng-click="$ctrl.onClear()">clear</i>
|
||||
</div>
|
||||
<label class="mdl-textfield__label" translate>{{$ctrl.label}}</label>
|
||||
</div>
|
|
@ -27,7 +27,9 @@ class DatePicker extends Component {
|
|||
this.enabled = true;
|
||||
this._modelView = null;
|
||||
this._model = undefined;
|
||||
|
||||
this._optionsChecked = false;
|
||||
this.hasFocus = false;
|
||||
this.hasMouseIn = false;
|
||||
componentHandler.upgradeElement($element[0].firstChild);
|
||||
}
|
||||
|
||||
|
@ -37,7 +39,9 @@ class DatePicker extends Component {
|
|||
set model(value) {
|
||||
this._model = value;
|
||||
if (value && !this.modelView) {
|
||||
let format = this._formatFlat2Angular(this.iniOptions.dateFormat || 'Y-m-d');
|
||||
let options = this._getOptions();
|
||||
let initialDateFormat = (options && options.dateFormat) ? options.dateFormat : 'Y-m-d';
|
||||
let format = this._formatFlat2Angular(initialDateFormat);
|
||||
this.modelView = this.$filter('date')(value, format);
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +52,8 @@ class DatePicker extends Component {
|
|||
this._modelView = value;
|
||||
this.input.value = value;
|
||||
this._setModel(value);
|
||||
this.$timeout(
|
||||
() => {
|
||||
this.mdlUpdate();
|
||||
this.$timeout(() => {
|
||||
this.mdlUpdate();
|
||||
}, 500);
|
||||
}
|
||||
onClear() {
|
||||
|
@ -76,16 +79,15 @@ class DatePicker extends Component {
|
|||
return `${dates} ${hours}`.trim();
|
||||
} else if (string.indexOf(':') !== -1) { // only time format
|
||||
return parts.join(':');
|
||||
} else { // only date format
|
||||
return parts.join('-');
|
||||
}
|
||||
} // only date format
|
||||
return parts.join('-');
|
||||
}
|
||||
|
||||
_setModel(value) {
|
||||
let model;
|
||||
if (!value) {
|
||||
model = undefined;
|
||||
} else if (!this.iniOptions.dateFormat || (this.iniOptions.dateFormat && this.iniOptions.dateFormat.startsWith('Y-m-d'))) {
|
||||
} else if (!this.iniOptions || (this.iniOptions.dateFormat && this.iniOptions.dateFormat.startsWith('Y-m-d'))) {
|
||||
model = value;
|
||||
} else {
|
||||
let formats = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/);
|
||||
|
@ -136,9 +138,12 @@ class DatePicker extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (!this.iniOptions)
|
||||
_getOptions() {
|
||||
if (this.iniOptions && this._optionsChecked) {
|
||||
return this.iniOptions;
|
||||
} else if (!this.iniOptions) {
|
||||
this.iniOptions = {};
|
||||
}
|
||||
|
||||
if (!this.iniOptions.locale)
|
||||
this.iniOptions.locale = this.$translate.use();
|
||||
|
@ -158,9 +163,14 @@ class DatePicker extends Component {
|
|||
}
|
||||
);
|
||||
}
|
||||
this._optionsChecked = true;
|
||||
return this.iniOptions;
|
||||
}
|
||||
|
||||
if (this.input)
|
||||
this.vp = new Flatpickr(this.input, this.iniOptions);
|
||||
$onInit() {
|
||||
this.iniOptions = this._getOptions();
|
||||
this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar);
|
||||
this.vp = new Flatpickr(this.input, this.iniOptions);
|
||||
}
|
||||
$onDestroy() {
|
||||
if (this.vp)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import './datePicker.js';
|
||||
|
||||
describe('Component vnDatePicker', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $timeout;
|
||||
let $element;
|
||||
let $translate;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_, _$translate_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$timeout = _$timeout_;
|
||||
$element = angular.element(`<div><input></div>`);
|
||||
$translate = _$translate_;
|
||||
controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
|
||||
}));
|
||||
|
||||
describe('_formatFlat2Angular()', () => {
|
||||
it(`should format date from Y-m-d to yyyy-MM-dd`, () => {
|
||||
let formatedDate = controller._formatFlat2Angular(`Y-m-d`);
|
||||
|
||||
expect(formatedDate).toBe('yyyy-MM-dd');
|
||||
});
|
||||
|
||||
it(`should format date from d-m-Y to dd-MM-yyyy`, () => {
|
||||
let formatedDate = controller._formatFlat2Angular(`d-m-Y`);
|
||||
|
||||
expect(formatedDate).toBe('dd-MM-yyyy');
|
||||
});
|
||||
|
||||
it(`should split the given string into parts`, () => {
|
||||
controller.iniOptions = {dateFormat: 'd/m/Y'};
|
||||
controller.model = '2017-12-23';
|
||||
|
||||
expect(controller.modelView).toBe('23-12-2017');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,12 +1,18 @@
|
|||
vn-date-picker {
|
||||
div {
|
||||
outline: none; //remove chrome outline
|
||||
}
|
||||
.mdl-chip__action {
|
||||
position: absolute;
|
||||
position: absolute;
|
||||
width: auto;
|
||||
top: 0px;
|
||||
right: -6px;
|
||||
margin: 22px 0px;
|
||||
background-color: white;
|
||||
}
|
||||
.material-icons {
|
||||
font-size: 18px;
|
||||
font-size: 18px;
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
|
@ -13,21 +13,20 @@ export default class Dialog extends Component {
|
|||
super($element);
|
||||
$element.addClass('vn-dialog');
|
||||
this.dialog = $element[0].firstChild;
|
||||
this.element.addEventListener('mousedown',
|
||||
event => this.onBackgroundMouseDown(event));
|
||||
this.element.addEventListener('mousedown', event => this.onBackgroundMouseDown(event));
|
||||
}
|
||||
/**
|
||||
* Displays the dialog to the user.
|
||||
*/
|
||||
show() {
|
||||
let style = this.dialog.style;
|
||||
let screenMargin = 20;
|
||||
|
||||
let window = this.window;
|
||||
let innerWidth = window.innerWidth;
|
||||
let innerHeight = window.innerHeight;
|
||||
let width = this.dialog.offsetWidth;
|
||||
let height = this.dialog.offsetHeight;
|
||||
let screenMargin = 20;
|
||||
let dblMargin = screenMargin * 2;
|
||||
|
||||
if (width + screenMargin > innerWidth) {
|
||||
width = innerWidth - dblMargin;
|
||||
|
@ -38,10 +37,8 @@ export default class Dialog extends Component {
|
|||
style.height = height + 'px';
|
||||
}
|
||||
|
||||
this.keypressHandler =
|
||||
event => this.onKeypress(event);
|
||||
this.document.addEventListener('keypress',
|
||||
this.keypressHandler);
|
||||
this.keypressHandler = event => this.onKeypress(event);
|
||||
this.document.addEventListener('keypress', this.keypressHandler);
|
||||
this.element.style.display = 'block';
|
||||
|
||||
if (this.onOpen)
|
||||
|
@ -66,17 +63,17 @@ export default class Dialog extends Component {
|
|||
cancel = this.onResponse({response: response});
|
||||
return cancel;
|
||||
}
|
||||
|
||||
realHide() {
|
||||
this.element.style.display = 'none';
|
||||
this.document.removeEventListener('keypress',
|
||||
this.keypressHandler);
|
||||
this.document.removeEventListener('keypress', this.keypressHandler);
|
||||
this.lastEvent = null;
|
||||
}
|
||||
|
||||
onButtonClick(event) {
|
||||
let buttonBar = this.element.querySelector('.button-bar');
|
||||
let buttons = buttonBar.querySelector('tpl-buttons');
|
||||
let node = event.target;
|
||||
|
||||
while (node.parentNode != buttons) {
|
||||
if (node == buttonBar) return;
|
||||
node = node.parentNode;
|
||||
|
@ -86,13 +83,16 @@ export default class Dialog extends Component {
|
|||
let cancel = this.fireResponse(response);
|
||||
if (cancel !== false) this.realHide();
|
||||
}
|
||||
|
||||
onDialogMouseDown(event) {
|
||||
this.lastEvent = event;
|
||||
}
|
||||
|
||||
onBackgroundMouseDown(event) {
|
||||
if (event != this.lastEvent)
|
||||
this.hide();
|
||||
}
|
||||
|
||||
onKeypress(event) {
|
||||
if (event.keyCode == 27) // Esc
|
||||
this.hide();
|
||||
|
@ -107,8 +107,8 @@ module.component('vnDialog', {
|
|||
tplButtons: 'tplButtons'
|
||||
},
|
||||
bindings: {
|
||||
onOpen: '&',
|
||||
onResponse: '&'
|
||||
onOpen: '&?',
|
||||
onResponse: '&?'
|
||||
},
|
||||
controller: Dialog
|
||||
});
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
describe('Component vnDialog', () => {
|
||||
let $componentController;
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
$element = angular.element('<div></div>');
|
||||
controller = $componentController('vnDialog', {$element});
|
||||
}));
|
||||
|
||||
describe('show()', () => {
|
||||
it(`should define keypressHandler function, call addEventListener function and define element.style.display to block then call onOpen function`, () => {
|
||||
window.innerHeight = 600;
|
||||
window.innerWidth = 800;
|
||||
controller.onOpen = () => {};
|
||||
controller.dialog = {style: {}, offsetWidth: 780, offsetHeight: 581};
|
||||
spyOn(controller.document, 'addEventListener');
|
||||
spyOn(controller, 'onOpen');
|
||||
controller.show();
|
||||
|
||||
expect(controller.keypressHandler).toBeDefined();
|
||||
expect(controller.document.addEventListener).toHaveBeenCalledWith('keypress', controller.keypressHandler);
|
||||
expect(controller.element.style.display).toEqual('block');
|
||||
expect(controller.onOpen).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should define keypressHandler function, call addEventListener function and define element.style.display to block and never call onOpen function`, () => {
|
||||
window.innerHeight = 600;
|
||||
window.innerWidth = 800;
|
||||
controller.dialog = {style: {}, offsetWidth: 781, offsetHeight: 581};
|
||||
spyOn(controller.document, 'addEventListener');
|
||||
controller.show();
|
||||
|
||||
expect(controller.keypressHandler).toBeDefined();
|
||||
expect(controller.document.addEventListener).toHaveBeenCalledWith('keypress', controller.keypressHandler);
|
||||
expect(controller.element.style.display).toEqual('block');
|
||||
expect(controller.onOpen).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hide()', () => {
|
||||
it(`should call fireResponse() and realHide()`, () => {
|
||||
spyOn(controller, 'fireResponse');
|
||||
spyOn(controller, 'realHide');
|
||||
controller.hide();
|
||||
|
||||
expect(controller.fireResponse).toHaveBeenCalledWith();
|
||||
expect(controller.realHide).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fireResponse()', () => {
|
||||
it(`should return cancel as false`, () => {
|
||||
let result = controller.fireResponse('I am the answer!');
|
||||
|
||||
expect(controller.onResponse).not.toBeDefined();
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it(`should return onResponse()`, () => {
|
||||
let text = 'I am the answer!';
|
||||
controller.onResponse = () => {
|
||||
return {response: text};
|
||||
};
|
||||
let result = controller.fireResponse(text);
|
||||
|
||||
expect(result.response).toEqual(text);
|
||||
});
|
||||
});
|
||||
|
||||
describe('realHide()', () => {
|
||||
it(`should set element.style.display and lastEvent properties and call removeEvenListener()`, () => {
|
||||
spyOn(controller.document, 'removeEventListener');
|
||||
|
||||
expect(controller.element.style.display).not.toEqual('none');
|
||||
expect(controller.lastEvent).not.toBeDefined();
|
||||
controller.realHide();
|
||||
|
||||
expect(controller.element.style.display).toEqual('none');
|
||||
expect(controller.document.removeEventListener).toHaveBeenCalledWith('keypress', controller.keypressHandler);
|
||||
expect(controller.lastEvent).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onButtonClick()', () => {
|
||||
it(`should call realHide if cancel isn't false`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
controller.element.className = 'tpl-buttons';
|
||||
let childElement = document.createElement('div');
|
||||
childElement.className = 'button-bar';
|
||||
controller.element.appendChild(childElement);
|
||||
let event = {target: controller.element, attribute: true};
|
||||
spyOn(controller, 'realHide');
|
||||
spyOn(controller, 'fireResponse').and.returnValue(true);
|
||||
controller.onButtonClick(event);
|
||||
|
||||
expect(controller.realHide).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call fireResponse with the value of response`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
controller.element.className = 'tpl-buttons';
|
||||
let childElement = document.createElement('div');
|
||||
childElement.className = 'button-bar';
|
||||
controller.element.appendChild(childElement);
|
||||
let attribute = document.createAttribute('response');
|
||||
attribute.value = 'I am the response!';
|
||||
controller.element.setAttributeNode(attribute);
|
||||
spyOn(controller, 'fireResponse');
|
||||
let event = {target: controller.element};
|
||||
controller.onButtonClick(event);
|
||||
|
||||
expect(controller.fireResponse).toHaveBeenCalledWith('I am the response!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onDialogMouseDown()', () => {
|
||||
it(`should set controller's lastEvent property`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
controller.onDialogMouseDown(event);
|
||||
|
||||
expect(controller.lastEvent).toEqual(event);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onBackgroundMouseDown()', () => {
|
||||
it(`shouldn't call hide() function as event equals lastEvent`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
controller.lastEvent = event;
|
||||
spyOn(controller, 'hide');
|
||||
controller.onBackgroundMouseDown(event);
|
||||
|
||||
expect(controller.hide).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call hide() function as event doesn't equal lastEvent`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
controller.lastEvent = event;
|
||||
controller.lastEvent = 'the singularity event!';
|
||||
spyOn(controller, 'hide');
|
||||
controller.onBackgroundMouseDown(event);
|
||||
|
||||
expect(controller.hide).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onKeypress()', () => {
|
||||
it(`should call hide() if the key pressed equal the code 27`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
event.keyCode = 27;
|
||||
spyOn(controller, 'hide');
|
||||
controller.onKeypress(event);
|
||||
|
||||
expect(controller.hide).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should't call hide() as the key pressed equal the code 999`, () => {
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
event.keyCode = 999;
|
||||
spyOn(controller, 'hide');
|
||||
controller.onKeypress(event);
|
||||
|
||||
expect(controller.hide).not.toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -19,8 +19,8 @@ function vnAcl(aclService, $timeout) {
|
|||
$timeout(() => {
|
||||
input.setAttribute("disabled", "true");
|
||||
});
|
||||
$element[0].querySelectorAll('i, vn-drop-down').forEach(i => {
|
||||
i.parentNode.removeChild(i);
|
||||
$element[0].querySelectorAll('i, vn-drop-down').forEach(element => {
|
||||
element.parentNode.removeChild(element);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -11,7 +11,8 @@ export function directive() {
|
|||
restrict: 'A',
|
||||
link: function($scope, $element, $attrs) {
|
||||
$element.on('click', function(event) {
|
||||
let dialog = $scope[kebabToCamel($attrs.vnDialog)];
|
||||
let dialogKey = kebabToCamel($attrs.vnDialog);
|
||||
let dialog = $scope[dialogKey];
|
||||
if (dialog instanceof Dialog)
|
||||
dialog.show();
|
||||
event.preventDefault();
|
||||
|
|
|
@ -2,6 +2,8 @@ import {module} from '../module';
|
|||
|
||||
/**
|
||||
* Sets the focus and selects the text on the input.
|
||||
*
|
||||
* @return {Object} The directive
|
||||
*/
|
||||
export function directive() {
|
||||
return {
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
import {module} from '../module';
|
||||
|
||||
directive.$inject = ['$compile'];
|
||||
function directive($compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
priority: 9999,
|
||||
link: function(scope, element, attrs) {
|
||||
element.removeAttr('vn-repeat');
|
||||
element.attr('ng-repeat', attrs.vnRepeat);
|
||||
$compile(element)(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.directive('vnRepeat', directive);
|
|
@ -0,0 +1,54 @@
|
|||
describe('Directive acl', () => {
|
||||
let scope;
|
||||
let element;
|
||||
let compile;
|
||||
let $timeout;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
compile = (hasPermissions, _element) => {
|
||||
inject(($compile, $rootScope, aclService, _$timeout_) => {
|
||||
spyOn(aclService, 'aclPermission').and.returnValue(hasPermissions);
|
||||
scope = $rootScope.$new();
|
||||
$timeout = _$timeout_;
|
||||
element = angular.element(_element);
|
||||
$compile(element)(scope);
|
||||
scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
it('should not disable the input element as the user has permision', () => {
|
||||
let html = `<div vn-acl="administrative,client" vn-acl-action="disabled"><input/></div>`;
|
||||
compile(true, html);
|
||||
let input = element.find('input');
|
||||
|
||||
expect(input).toBeDefined();
|
||||
expect(input.attr('disabled')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should delete the element as the user does not have permission and there is no action', () => {
|
||||
let html = `<container><div vn-acl="administrative,client" vn-acl-action="anything but disabled"><input/></div></container>`;
|
||||
compile(false, html);
|
||||
|
||||
expect(element.children().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should disable the element as the action is to disable it but the user has no permission but present', () => {
|
||||
let html = `<div vn-acl="administrative,client" vn-acl-action="disabled"><input/></div>`;
|
||||
compile(false, html);
|
||||
let input = element.find('input');
|
||||
$timeout.flush();
|
||||
|
||||
expect(input).toBeDefined();
|
||||
expect(input.attr('disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should delete any element with the tag i and vn-drop-down', () => {
|
||||
let html = `<div vn-acl="administrative,client" vn-acl-action="disabled"><label><i/></label><input/></div>`;
|
||||
compile(false, html);
|
||||
|
||||
expect(element.find('i').length).toBe(0);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
describe('Directive dialog', () => {
|
||||
let $scope;
|
||||
let $element;
|
||||
let element;
|
||||
let compile;
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
compile = _element => {
|
||||
inject(($compile, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
$scope.myDialog = controller;
|
||||
element = angular.element(_element);
|
||||
$compile(element)($scope);
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
$element = angular.element('<div></div>');
|
||||
controller = $componentController('vnDialog', {$element});
|
||||
}));
|
||||
|
||||
it('should call show() function if dialog is a instance of vnDialog', () => {
|
||||
let html = `<div vn-dialog="myDialog"></div>`;
|
||||
spyOn(controller, 'show');
|
||||
compile(html);
|
||||
element[0].click();
|
||||
|
||||
expect(controller.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
describe('Directive focus', () => {
|
||||
let $scope;
|
||||
let $element;
|
||||
let compile;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
compile = (_element, _childElement) => {
|
||||
inject(($compile, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element(_element);
|
||||
if (_childElement) {
|
||||
let childElement = angular.element(_childElement);
|
||||
$element[0] < childElement;
|
||||
$element[0].firstChild.focus = jasmine.createSpy(focus);
|
||||
}
|
||||
$element[0].focus = jasmine.createSpy('focus');
|
||||
$element[0].select = jasmine.createSpy('select');
|
||||
$compile($element)($scope);
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
it('should call the querySelector function upon the input to redefine it with the expected selector then call focus', () => {
|
||||
let html = `<div vn-focus><input></input></div>`;
|
||||
let childHtml = '<input></input>';
|
||||
compile(html, childHtml);
|
||||
|
||||
expect($element[0].firstChild.focus).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should print a warning message on console', () => {
|
||||
let html = `<potato vn-focus></potato>`;
|
||||
console.warn = jasmine.createSpy('warn');
|
||||
compile(html);
|
||||
|
||||
expect(console.warn).toHaveBeenCalledWith(`vnFocus: Can't find a focusable element`);
|
||||
});
|
||||
|
||||
it('should call focus function on the element', () => {
|
||||
let html = `<input vn-focus></input>`;
|
||||
compile(html);
|
||||
|
||||
expect($element[0].focus).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should call select function on the element', () => {
|
||||
let html = `<input vn-focus></input>`;
|
||||
compile(html);
|
||||
|
||||
expect($element[0].select).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
describe('Directive vnId', () => {
|
||||
let $scope;
|
||||
let $element;
|
||||
let compile;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
compile = _element => {
|
||||
inject(($compile, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element(_element);
|
||||
$compile($element)($scope);
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
it(`should throw an error when there's no id defined`, () => {
|
||||
let html = `<form vn-id=""></form>`;
|
||||
|
||||
expect(() => {
|
||||
compile(html);
|
||||
}).toThrow(new Error(`vnId: Attribute can't be null`));
|
||||
});
|
||||
|
||||
it(`should throw an error when these's no controller defined in $element[0]`, () => {
|
||||
let html = `<div vn-id="1"></div>`;
|
||||
|
||||
expect(() => {
|
||||
compile(html);
|
||||
}).toThrow(new Error(`vnId: Can't find controller for element '1'`));
|
||||
});
|
||||
|
||||
it(`should set the controller into the $scope as there are no errors being thrown`, () => {
|
||||
let html = `<form vn-id="1"></form>`;
|
||||
|
||||
expect($scope['1']).not.toBeDefined();
|
||||
compile(html);
|
||||
|
||||
expect($scope['1']).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -16,7 +16,14 @@
|
|||
<input type="checkbox" ng-checked="item.checked" ng-if="$ctrl.multiple">
|
||||
<div ng-transclude="vnItem">{{item.name}}</div>
|
||||
</li>
|
||||
<li ng-if="$ctrl.showLoadMore" class="dropdown__loadMore" tabIndex="-1" ng-class="{'active': $ctrl.itemsFiltered.length === $ctrl.activeOption}" ng-click="$ctrl.loadMore();$ctrl.show = true;" translate="Load More"></li>
|
||||
<li
|
||||
ng-if="$ctrl.loadMore&&!$ctrl.removeLoadMore"
|
||||
class="dropdown__loadMore"
|
||||
tabIndex="-1"
|
||||
ng-class="{'active': $ctrl.itemsFiltered.length === $ctrl.activeOption, 'noMore' : !$ctrl.showLoadMore}"
|
||||
ng-click="$ctrl.loadItems()"
|
||||
translate="{{$ctrl.showLoadMore ? 'Show More' : 'No more results'}}"
|
||||
></li>
|
||||
</ul>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
|
@ -16,6 +16,7 @@ export default class DropDown {
|
|||
get show() {
|
||||
return this._show;
|
||||
}
|
||||
|
||||
set show(value) {
|
||||
let oldValue = this.show;
|
||||
this._show = value;
|
||||
|
@ -27,12 +28,14 @@ export default class DropDown {
|
|||
this._focusingFilter = false;
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get search() {
|
||||
return this._search;
|
||||
}
|
||||
|
||||
set search(value) {
|
||||
let val = (value === undefined && value === '') ? null : value;
|
||||
let val = (value === undefined || value === '') ? null : value;
|
||||
this._search = val;
|
||||
|
||||
if (this.filterAction)
|
||||
|
@ -40,9 +43,11 @@ export default class DropDown {
|
|||
else
|
||||
this.filterItems();
|
||||
}
|
||||
|
||||
get activeOption() {
|
||||
return this._activeOption;
|
||||
}
|
||||
|
||||
set activeOption(value) {
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
|
@ -51,6 +56,10 @@ export default class DropDown {
|
|||
}
|
||||
this.$timeout(() => {
|
||||
this._activeOption = value;
|
||||
// AutoLoad items with "scroll" (1st version):
|
||||
if (value && value >= this.items.length - 3 && !this.removeLoadMore) {
|
||||
this.loadItems();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -59,7 +68,9 @@ export default class DropDown {
|
|||
}
|
||||
|
||||
onFilterRest() {
|
||||
this.filterAction({search: this.search});
|
||||
if (this.filterAction) {
|
||||
this.filterAction({search: this.search});
|
||||
}
|
||||
}
|
||||
|
||||
$onChanges(changesObj) {
|
||||
|
@ -117,6 +128,7 @@ export default class DropDown {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
setScrollPosition() {
|
||||
let dropdown = this.$element[0].querySelector('ul.dropdown');
|
||||
let child = dropdown ? dropdown.childNodes[this.activeOption] : null;
|
||||
|
@ -135,6 +147,13 @@ export default class DropDown {
|
|||
}
|
||||
}
|
||||
|
||||
loadItems() {
|
||||
if (this.showLoadMore && this.loadMore) {
|
||||
this.loadMore();
|
||||
}
|
||||
this.show = true;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.parent)
|
||||
this.parent.addEventListener('keydown', e => this.onKeydown(e));
|
||||
|
@ -144,6 +163,7 @@ export default class DropDown {
|
|||
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
|
||||
}
|
||||
}
|
||||
|
||||
DropDown.$inject = ['$element', '$filter', '$timeout'];
|
||||
|
||||
module.component('vnDropDown', {
|
||||
|
@ -156,8 +176,9 @@ module.component('vnDropDown', {
|
|||
selected: '=',
|
||||
search: '=?',
|
||||
loadMore: '&?',
|
||||
removeLoadMore: '<?',
|
||||
filterAction: '&?',
|
||||
showLoadMore: '=?',
|
||||
showLoadMore: '<?',
|
||||
top: '<?',
|
||||
itemWidth: '<?',
|
||||
parent: '<?',
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
import './drop-down.js';
|
||||
|
||||
describe('Component vnDropDown', () => {
|
||||
let $componentController;
|
||||
let $timeout;
|
||||
let $element;
|
||||
let $filter;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$timeout_, _$filter_) => {
|
||||
$componentController = _$componentController_;
|
||||
$element = angular.element('<div><ul><li></li></ul></div>');
|
||||
$timeout = _$timeout_;
|
||||
$filter = _$filter_;
|
||||
controller = $componentController('vnDropDown', {$element, $timeout, $filter});
|
||||
}));
|
||||
|
||||
describe('show() setter', () => {
|
||||
it(`should define controllers _show using the value received as argument`, () => {
|
||||
controller._show = 'old value';
|
||||
controller.show = 'new value';
|
||||
|
||||
expect(controller._show).toEqual('new value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search()', () => {
|
||||
it(`should set controllers _search property with the value received`, () => {
|
||||
controller.search = 'some filter valiue';
|
||||
|
||||
expect(controller._search).toEqual('some filter valiue');
|
||||
});
|
||||
|
||||
it(`should set controllers _search property to null as the value received is an empty string`, () => {
|
||||
controller.search = '';
|
||||
|
||||
expect(controller._search).toEqual(null);
|
||||
});
|
||||
|
||||
it(`should call onFilterRest() if controllers filterAction is defined`, () => {
|
||||
controller.filterAction = true;
|
||||
spyOn(controller, 'onFilterRest');
|
||||
controller.search = 'some filter valiue';
|
||||
|
||||
expect(controller.onFilterRest).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call filterItems() if controllers filterAction is undefined`, () => {
|
||||
controller.filterAction = undefined;
|
||||
spyOn(controller, 'filterItems');
|
||||
controller.search = 'some filter valiue';
|
||||
|
||||
expect(controller.filterItems).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('activeOption() setter', () => {
|
||||
it(`should set _activeOption as items.length if showLoadMore is defined if activeOption is bigger than items.length then call loadItems()`, () => {
|
||||
spyOn(controller, 'loadItems');
|
||||
controller.showLoadMore = true;
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller.activeOption = 10;
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller._activeOption).toEqual(4);
|
||||
expect(controller.loadItems).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should set _activeOption as activeOption if showLoadMore is defined if activeOption is smaller than items.length then call loadItems()`, () => {
|
||||
spyOn(controller, 'loadItems');
|
||||
controller.showLoadMore = true;
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller.activeOption = 2;
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller._activeOption).toEqual(2);
|
||||
expect(controller.loadItems).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should set _activeOption as items.length -1 if showLoadMore is not defined then call loadItems()`, () => {
|
||||
spyOn(controller, 'loadItems');
|
||||
controller.showLoadMore = undefined;
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller.activeOption = 10;
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller._activeOption).toEqual(3);
|
||||
expect(controller.loadItems).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should define _activeOption as activeOption and never call loadItems()`, () => {
|
||||
spyOn(controller, 'loadItems');
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}, {id: 5, name: 'Doctor X'}];
|
||||
controller.activeOption = 1;
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller._activeOption).toEqual(1);
|
||||
expect(controller.loadItems).not.toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterItems() setter', () => {
|
||||
it(`should set _itemsFiltered using the value of items`, () => {
|
||||
controller.items = [{id: 1, name: 'Batman'}];
|
||||
controller.filterItems();
|
||||
|
||||
expect(controller.itemsFiltered).toEqual(controller.items);
|
||||
});
|
||||
|
||||
it(`should set _itemsFiltered with the filtered value of items`, () => {
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller.search = 'Batman';
|
||||
controller.filterItems();
|
||||
|
||||
expect(controller.itemsFiltered).toEqual([Object({id: 1, name: 'Batman'})]);
|
||||
});
|
||||
|
||||
it(`should set _itemsFiltered an empty array`, () => {
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller.search = 'the Joker';
|
||||
|
||||
expect(controller.itemsFiltered.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFilterRest()', () => {
|
||||
it(`should call the filterAction() with a constructed object as argument`, () => {
|
||||
controller.filterAction = () => {};
|
||||
controller.search = 'Batman';
|
||||
spyOn(controller, 'filterAction');
|
||||
controller.onFilterRest();
|
||||
|
||||
expect(controller.filterAction).toHaveBeenCalledWith({search: controller.search});
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should set the top css of the $element`, () => {
|
||||
let argumentObject = {show: true, top: {currentValue: 100}};
|
||||
spyOn(controller.$element, 'css');
|
||||
controller.$onChanges(argumentObject);
|
||||
|
||||
expect(controller.$element.css).toHaveBeenCalledWith('top', '100px');
|
||||
});
|
||||
|
||||
it(`should set the width css of the $element`, () => {
|
||||
let argumentObject = {show: true, itemWidth: {currentValue: 100}};
|
||||
spyOn(controller.$element, 'css');
|
||||
controller.$onChanges(argumentObject);
|
||||
|
||||
expect(controller.$element.css).toHaveBeenCalledWith('width', '100px');
|
||||
});
|
||||
|
||||
it(`should set the width css of the $element`, () => {
|
||||
let argumentObject = {items: {id: 1, name: 'Batman'}};
|
||||
spyOn(controller, 'filterItems');
|
||||
controller.$onChanges(argumentObject);
|
||||
|
||||
expect(controller.filterItems).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearSearch()', () => {
|
||||
it(`should set the controllers search property to null`, () => {
|
||||
controller.search = true;
|
||||
controller.clearSearch();
|
||||
|
||||
expect(controller.search).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectOption()', () => {
|
||||
it(`should set controllers selected and show properties then call clearSearch() as _activeOption is smaller than items.length`, () => {
|
||||
spyOn(controller, 'clearSearch');
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller._activeOption = 0;
|
||||
controller.selectOption();
|
||||
|
||||
expect(controller.selected).toEqual(controller.items[controller._activeOption]);
|
||||
expect(controller._show).toEqual(false);
|
||||
expect(controller.clearSearch).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should not set controllers selected, show and never call clearSearch() as _activeOption is bigger than items.length`, () => {
|
||||
spyOn(controller, 'clearSearch');
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller._activeOption = 100;
|
||||
controller.selectOption();
|
||||
|
||||
expect(controller.selected).not.toBeDefined();
|
||||
expect(controller._show).not.toBeDefined();
|
||||
expect(controller.clearSearch).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call loadMore() if the activeValue equals items.length`, () => {
|
||||
controller.loadMore = () => {};
|
||||
spyOn(controller, 'loadMore');
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
controller._activeOption = 4;
|
||||
controller.showLoadMore = 4;
|
||||
controller.selectOption();
|
||||
|
||||
expect(controller.loadMore).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('onKeydown()', () => {
|
||||
it(`should call selectOption() and preventDefault() if Enter key is pressed`, () => {
|
||||
spyOn(controller, 'selectOption');
|
||||
controller._show = true;
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element, preventDefault: () => {}};
|
||||
event.keyCode = 13;
|
||||
spyOn(event, 'preventDefault');
|
||||
controller.onKeydown(event);
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller.selectOption).toHaveBeenCalledWith();
|
||||
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call clearSearch() Esc key is pressed`, () => {
|
||||
spyOn(controller, 'clearSearch');
|
||||
controller._show = true;
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
event.keyCode = 27;
|
||||
controller.onKeydown(event);
|
||||
|
||||
expect(controller.clearSearch).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call clearSearch() Esc key is pressed and take off 1 from _activeOption`, () => {
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
spyOn(controller, 'setScrollPosition');
|
||||
controller._show = true;
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
event.keyCode = 38;
|
||||
controller._activeOption = 1;
|
||||
controller.onKeydown(event);
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller.setScrollPosition).toHaveBeenCalledWith();
|
||||
expect(controller._activeOption).toEqual(0);
|
||||
});
|
||||
|
||||
it(`should call clearSearch() Esc key is pressed and add up 1 to _activeOption`, () => {
|
||||
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
|
||||
spyOn(controller, 'setScrollPosition');
|
||||
controller._show = true;
|
||||
controller.element = document.createElement('div');
|
||||
let event = {target: controller.element};
|
||||
event.keyCode = 40;
|
||||
controller._activeOption = 1;
|
||||
controller.onKeydown(event);
|
||||
$timeout.flush();
|
||||
|
||||
expect(controller.setScrollPosition).toHaveBeenCalledWith();
|
||||
expect(controller._activeOption).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setScrollPosition()', () => {
|
||||
it(`should call child.scrollIntoView if defined `, () => {
|
||||
$element[0].firstChild.setAttribute('class', 'dropdown');
|
||||
let child = $element[0].firstChild.firstChild;
|
||||
child.scrollIntoView = () => {};
|
||||
spyOn(child, 'scrollIntoView');
|
||||
controller._activeOption = 0;
|
||||
controller.setScrollPosition();
|
||||
|
||||
expect(child.scrollIntoView).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectItem()', () => {
|
||||
it(`should pass item to selected and set controller._show to false`, () => {
|
||||
let item = {id: 1, name: 'Batman'};
|
||||
controller.selectItem(item);
|
||||
|
||||
expect(controller.selected).toEqual(item);
|
||||
expect(controller._show).toEqual(false);
|
||||
});
|
||||
|
||||
it(`should pass item to selected and set controller._show to true if the controller.multiple is defined`, () => {
|
||||
let item = {id: 1, name: 'Batman'};
|
||||
controller.multiple = true;
|
||||
controller.selectItem(item);
|
||||
|
||||
expect(controller.selected).toEqual(item);
|
||||
expect(controller._show).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadItems()', () => {
|
||||
it(`should set controller._show to true`, () => {
|
||||
controller.loadItems();
|
||||
|
||||
expect(controller._show).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should call loadMore() and then set controller._show to true`, () => {
|
||||
controller.showLoadMore = () => {};
|
||||
controller.loadMore = () => {};
|
||||
spyOn(controller, 'loadMore');
|
||||
controller.loadItems();
|
||||
|
||||
expect(controller._show).toEqual(true);
|
||||
expect(controller.loadMore).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it(`should add an event listener to the parent element`, () => {
|
||||
spyOn(controller.parent, 'addEventListener');
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.parent.addEventListener).toHaveBeenCalledWith('keydown', jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onDestroy()', () => {
|
||||
it(`should remove an event listener from the parent element`, () => {
|
||||
spyOn(controller.parent, 'removeEventListener');
|
||||
controller.$onDestroy();
|
||||
|
||||
expect(controller.parent.removeEventListener).toHaveBeenCalledWith('keydown', jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
});
|
|
@ -39,6 +39,11 @@ vn-drop-down {
|
|||
color: rgb(255,171,64);
|
||||
font-weight: 700;
|
||||
}
|
||||
&.dropdown__loadMore.noMore{
|
||||
color:#424242;
|
||||
font-weight: 700;
|
||||
opacity: 0.7;
|
||||
}
|
||||
input[type=checkbox]{
|
||||
float: left;
|
||||
margin: 5px 5px 0 0;
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import './grid-header.js';
|
||||
|
||||
describe('Component vnGridHeader', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnGridHeader', {});
|
||||
}));
|
||||
|
||||
describe('selectColum()', () => {
|
||||
it(`should set controller currentColumn to equal the argument received`, () => {
|
||||
let col = {columnStuff: 'some stuff'};
|
||||
controller.selectColum(col);
|
||||
|
||||
expect(controller.currentColumn).toEqual(col);
|
||||
});
|
||||
|
||||
it(`should set controller currentColumn.order to undefined then set currentColumn to equal the argument received`, () => {
|
||||
controller.currentColumn = {field: 'some field', order: 'ordered'};
|
||||
let col = {columnStuff: 'some stuff'};
|
||||
controller.selectColum(col);
|
||||
|
||||
expect(controller.currentColumn.order).not.toBeDefined();
|
||||
expect(controller.currentColumn).toEqual(col);
|
||||
});
|
||||
|
||||
it(`should set controller currentColumn.order to undefined then call onOrder passing currentColumn as argument`, () => {
|
||||
controller.onOrder = () => {};
|
||||
spyOn(controller, 'onOrder');
|
||||
let col = {columnStuff: 'some stuff'};
|
||||
controller.selectColum(col);
|
||||
|
||||
expect(controller.currentColumn).toEqual(col);
|
||||
expect(controller.onOrder).toHaveBeenCalledWith(col);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,5 +1,8 @@
|
|||
<div class="icon-menu">
|
||||
<vn-icon-button icon="{{::$ctrl.icon}}"></vn-icon-button>
|
||||
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored icon-square icon-menu__button">
|
||||
<vn-icon vn-none icon="{{::$ctrl.icon}}"></vn-icon>
|
||||
<vn-icon vn-none class="icon-menu__arrow_down" icon="keyboard_arrow_down" ng-click="$ctrl.showDropDown = true"></vn-icon>
|
||||
</button>
|
||||
<div ng-if="!$ctrl.findMore">
|
||||
<vn-drop-down
|
||||
items="$ctrl.items"
|
||||
|
|
|
@ -11,12 +11,15 @@ export default class IconMenu {
|
|||
this.findMore = false;
|
||||
this.element = $element[0];
|
||||
}
|
||||
|
||||
get showDropDown() {
|
||||
return this._showDropDown;
|
||||
}
|
||||
|
||||
set showDropDown(value) {
|
||||
this._showDropDown = value;
|
||||
}
|
||||
|
||||
findItems(search) {
|
||||
if (!this.url)
|
||||
return this.items ? this.items : [];
|
||||
|
@ -40,6 +43,7 @@ export default class IconMenu {
|
|||
this.getItems();
|
||||
}
|
||||
}
|
||||
|
||||
getItems() {
|
||||
let filter = {};
|
||||
|
||||
|
@ -66,6 +70,7 @@ export default class IconMenu {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (!this.items && this.url) {
|
||||
this.items = [];
|
||||
|
@ -104,6 +109,7 @@ export default class IconMenu {
|
|||
this.$element.unbind('focusout');
|
||||
}
|
||||
}
|
||||
|
||||
IconMenu.$inject = ['$element', '$http', '$timeout'];
|
||||
|
||||
module.component('vnIconMenu', {
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import './icon-menu.js';
|
||||
|
||||
describe('Component vnIconMenu', () => {
|
||||
let $componentController;
|
||||
let $element;
|
||||
let $httpBackend;
|
||||
let $timeout;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$timeout = _$timeout_;
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element('<div></div>');
|
||||
controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
||||
}));
|
||||
|
||||
describe('component vnIconMenu', () => {
|
||||
describe('findItem()', () => {
|
||||
it(`should return items empty array if the controller does not provide a url and have no items defined`, () => {
|
||||
controller.url = undefined;
|
||||
controller.items = undefined;
|
||||
let result = controller.findItems('some search value');
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it(`should return items array if the controller does not provide a url`, () => {
|
||||
controller.url = undefined;
|
||||
controller.items = ['Batman', 'Bruce Wayne'];
|
||||
controller.findItems('some search value');
|
||||
|
||||
expect(controller.items.length).toEqual(2);
|
||||
});
|
||||
|
||||
it(`should perform a search and store the result in controller items`, () => {
|
||||
let search = 'The Joker';
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
||||
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
|
||||
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
|
||||
controller.findItems(search);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
|
||||
});
|
||||
|
||||
it(`should call getItems function if there's no search value`, () => {
|
||||
spyOn(controller, 'getItems');
|
||||
controller.findItems();
|
||||
|
||||
expect(controller.getItems).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getItems()', () => {
|
||||
it(`should perform a query and then push elements found into controller.items`, () => {
|
||||
controller.items = [];
|
||||
$httpBackend.whenGET(`${controller.url}?filter={}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
|
||||
$httpBackend.expectGET(`${controller.url}?filter={}`);
|
||||
controller.getItems();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
|
||||
});
|
||||
|
||||
it(`should perform a query and then set controller.maxRow to false if there are no items in the controller`, () => {
|
||||
controller.items = [];
|
||||
controller.maxRow = true;
|
||||
$httpBackend.whenGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`).respond(controller.items);
|
||||
$httpBackend.expectGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`);
|
||||
controller.getItems();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.maxRow).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,3 +1,12 @@
|
|||
vn-icon-menu{
|
||||
position: relative;
|
||||
.icon-menu__button {
|
||||
padding: 0 10px;
|
||||
}
|
||||
vn-icon{
|
||||
float: left;
|
||||
}
|
||||
vn-icon.icon-menu__arrow_down{
|
||||
margin:2px 0 0 5px;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
import ngModule from './module';
|
||||
import {module} from '../module';
|
||||
|
||||
var acl = window.salix ? window.salix.acl : {};
|
||||
module.constant('aclConstant', acl);
|
||||
|
||||
aclService.$inject = ['aclConstant'];
|
||||
function aclService(aclConstant) {
|
||||
|
@ -29,4 +32,4 @@ function aclService(aclConstant) {
|
|||
};
|
||||
}
|
||||
|
||||
ngModule.service('aclService', aclService);
|
||||
module.service('aclService', aclService);
|
|
@ -1,6 +1,7 @@
|
|||
import {module} from '../module';
|
||||
|
||||
const isEqual = angular.equals;
|
||||
|
||||
export default isEqual;
|
||||
|
||||
export const NAME = 'equalsObject';
|
||||
|
|
|
@ -4,6 +4,7 @@ import './template';
|
|||
import './getTemplate';
|
||||
import './app';
|
||||
import './interceptor';
|
||||
import './aclService';
|
||||
|
||||
export * from './util';
|
||||
export {default as splitingRegister} from './splitingRegister';
|
||||
|
|
|
@ -5,7 +5,7 @@ export default function getModifiedData(object, objectOld) {
|
|||
var newObject = {};
|
||||
for (var k in object) {
|
||||
var val = object[k];
|
||||
var valOld = objectOld[k];
|
||||
var valOld = objectOld[k] === undefined ? null : objectOld[k];
|
||||
|
||||
if (!isEqual(val, valOld)) {
|
||||
if (val instanceof Object) {
|
||||
|
|
|
@ -6,5 +6,6 @@
|
|||
"Save": "Guardar",
|
||||
"Add": "Añadir",
|
||||
"Search": "Buscar",
|
||||
"Load More": "Cargar más"
|
||||
"Show More": "Ver más",
|
||||
"No more results" : "No hay más resultados"
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<vn-vertical class="multi-check" vn-none class="multi-check {{$ctrl.className}}" tabindex="-1" ng-blur="$ctrl.showDropDown = false">
|
||||
<vn-vertical class="multi-check" vn-none class="multi-check {{$ctrl.className}}" tabindex="1" ng-blur="$ctrl.onBlur()">
|
||||
<vn-one>
|
||||
<vn-horizontal>
|
||||
<vn-none class="primaryCheckbox" ng-if="$ctrl.checkAll===0">
|
||||
|
|
|
@ -2,58 +2,28 @@ import {module} from '../module';
|
|||
import './multi-check.scss';
|
||||
/**
|
||||
* Draw checkbox with a drop-down and multi options
|
||||
* @param {SmallInt} checkAll Primary input-check state: 0 -> uncheck, 1 -> checked, 2 -> indeterminate checked
|
||||
* @param {Array} options List of options shown in drop-down
|
||||
* @param {Array} models Elements to check / unCheck
|
||||
* @param {String} className Optional css class name
|
||||
*/
|
||||
export default class MultiCheck {
|
||||
constructor() {
|
||||
constructor($timeout) {
|
||||
this.$timeout = $timeout;
|
||||
this._checkAll = 0;
|
||||
this._models = [];
|
||||
this.type = {};
|
||||
this._type = {};
|
||||
this.showDropDown = false;
|
||||
}
|
||||
get models() {
|
||||
return this._models;
|
||||
|
||||
get type() {
|
||||
return this._type;
|
||||
}
|
||||
set models(value) {
|
||||
this._models = value;
|
||||
}
|
||||
get checkAll() {
|
||||
return this._checkAll;
|
||||
}
|
||||
set checkAll(value) {
|
||||
this._checkAll = value;
|
||||
this.switchChecks();
|
||||
}
|
||||
switchChecks() {
|
||||
if (this.models)
|
||||
this.models.forEach(
|
||||
el => {
|
||||
let checked;
|
||||
if (this.type.id && this.type.id !== 'all' && this.type.id !== 'any') {
|
||||
if (this.type.id.length > 3 && this.type.id.substr(0, 3) === 'no-') {
|
||||
checked = el[this.type.id.replace('no-', '')] == null;
|
||||
} else if (this.type.id.length > 6 && this.type.id.substr(0, 6) === 'equal-') {
|
||||
let label = this.type.id.replace('equal-', '');
|
||||
checked = (el[label] && el[label] === this.type.name);
|
||||
} else {
|
||||
checked = el[this.type.id] != null;
|
||||
}
|
||||
} else {
|
||||
checked = this.checkAll === 1;
|
||||
}
|
||||
el.checked = checked;
|
||||
}
|
||||
);
|
||||
}
|
||||
$onChanges() {
|
||||
this.type = {};
|
||||
this.checkAll = 0;
|
||||
}
|
||||
$doCheck() {
|
||||
if (this.type && this.type.id) {
|
||||
switch (this.type.id) {
|
||||
|
||||
set type(value) {
|
||||
if (value && value.id) {
|
||||
this._type = value;
|
||||
switch (value.id) {
|
||||
case 'all':
|
||||
this.checkAll = 1;
|
||||
break;
|
||||
|
@ -64,11 +34,64 @@ export default class MultiCheck {
|
|||
this.checkAll = 2;
|
||||
break;
|
||||
}
|
||||
this.type = {};
|
||||
}
|
||||
this._type = {};
|
||||
this.showDropDown = false;
|
||||
}
|
||||
|
||||
get models() {
|
||||
return this._models;
|
||||
}
|
||||
|
||||
set models(value) {
|
||||
this._models = value;
|
||||
}
|
||||
|
||||
get checkAll() {
|
||||
return this._checkAll;
|
||||
}
|
||||
|
||||
set checkAll(value) {
|
||||
this._checkAll = value;
|
||||
this.switchChecks();
|
||||
}
|
||||
|
||||
switchChecks() {
|
||||
if (this.models)
|
||||
this.models.forEach(
|
||||
el => {
|
||||
let checked;
|
||||
if (this.type.id && this.type.id !== 'all' && this.type.id !== 'any') {
|
||||
if (this.type.id.length > 3 && this.type.id.substr(0, 3) === 'no-') {
|
||||
let label = this.type.id.replace('no-', '');
|
||||
checked = Boolean(el[label]) === false;
|
||||
} else if (this.type.id.length > 6 && this.type.id.substr(0, 6) === 'equal-') {
|
||||
let label = this.type.id.replace('equal-', '');
|
||||
checked = (el[label] && el[label] === this.type.name);
|
||||
} else {
|
||||
checked = Boolean(el[this.type.id]) === true;
|
||||
}
|
||||
} else {
|
||||
checked = this.checkAll === 1;
|
||||
}
|
||||
el.checked = checked;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
this.type = {};
|
||||
this.checkAll = 0;
|
||||
}
|
||||
|
||||
onBlur() {
|
||||
this.$timeout(() => {
|
||||
this.showDropDown = false;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
MultiCheck.$inject = [];
|
||||
|
||||
MultiCheck.$inject = ['$timeout'];
|
||||
|
||||
module.component('vnMultiCheck', {
|
||||
template: require('./multi-check.html'),
|
||||
|
@ -76,7 +99,7 @@ module.component('vnMultiCheck', {
|
|||
bindings: {
|
||||
checkAll: '=',
|
||||
options: '<',
|
||||
models: '=',
|
||||
models: '<',
|
||||
className: '@?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
import './multi-check.js';
|
||||
|
||||
describe('Component vnMultiCheck', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnMultiCheck', {});
|
||||
}));
|
||||
|
||||
describe('models()', () => {
|
||||
it(`should set controller _models property with the argument received`, () => {
|
||||
let argument = 'I am the model';
|
||||
controller.models = argument;
|
||||
|
||||
expect(controller._models).toEqual(argument);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkAll()', () => {
|
||||
it(`should set controller _checkAll property with the argument received then call switchChecks()`, () => {
|
||||
let argument = 'I am the model';
|
||||
spyOn(controller, 'switchChecks');
|
||||
controller.checkAll = argument;
|
||||
|
||||
expect(controller._checkAll).toEqual(argument);
|
||||
expect(controller.switchChecks).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('switchChecks()', () => {
|
||||
it(`should set checked property inside each existing elemenet when id begings with no-`, () => {
|
||||
controller.type = {id: 'no-name'};
|
||||
controller.models = [
|
||||
{name: 'name'},
|
||||
{name: null}
|
||||
];
|
||||
|
||||
expect(controller._models[0].checked).not.toBeDefined();
|
||||
expect(controller._models[1].checked).not.toBeDefined();
|
||||
controller._checkAll = 1;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeTruthy();
|
||||
expect(controller._models[1].checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should set checked property inside each existing elemenet when id begings with equal-`, () => {
|
||||
controller.type = {id: 'equal-name', name: 'name'};
|
||||
controller.models = [
|
||||
{name: null},
|
||||
{name: 'name'}
|
||||
];
|
||||
|
||||
expect(controller._models[0].checked).not.toBeDefined();
|
||||
expect(controller._models[1].checked).not.toBeDefined();
|
||||
controller._checkAll = 1;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeTruthy();
|
||||
expect(controller._models[1].checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should set checked property inside each existing elemenet when begings with anything but any, all, no- or equal-`, () => {
|
||||
controller.type = {id: 'name'};
|
||||
controller.models = [
|
||||
{name: null},
|
||||
{name: 'name'}
|
||||
];
|
||||
|
||||
expect(controller._models[0].checked).not.toBeDefined();
|
||||
expect(controller._models[1].checked).not.toBeDefined();
|
||||
controller._checkAll = 1;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeTruthy();
|
||||
expect(controller._models[1].checked).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('when id is any', () => {
|
||||
it('should set element checked property based on controller._checkAll', () => {
|
||||
controller.type = {id: 'any'};
|
||||
controller.models = [
|
||||
{name: 'name'}
|
||||
];
|
||||
|
||||
expect(controller._models[0].checked).not.toBeDefined();
|
||||
controller._checkAll = 1;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeTruthy();
|
||||
controller._checkAll = 0;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeFalsy();
|
||||
controller._checkAll = 2;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when id is all', () => {
|
||||
it('should set element checked property based on controller._checkAll property', () => {
|
||||
controller.type = {id: 'all'};
|
||||
controller.models = [
|
||||
{name: 'name'}
|
||||
];
|
||||
|
||||
expect(controller._models[0].checked).not.toBeDefined();
|
||||
controller._checkAll = 1;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeTruthy();
|
||||
controller._checkAll = 0;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeFalsy();
|
||||
controller._checkAll = 2;
|
||||
controller.switchChecks();
|
||||
|
||||
expect(controller._models[0].checked).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it('should set controller.type to empty object and checkAll to zero', () => {
|
||||
controller.type = {id: 'all'};
|
||||
controller._checkAll = 1;
|
||||
controller.$onChanges();
|
||||
|
||||
expect(controller.type).toEqual({});
|
||||
expect(controller._checkAll).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('type setter', () => {
|
||||
it('should set controller.type to empty object and checkAll based on controller.type.id', () => {
|
||||
let value = {id: 'all'};
|
||||
controller._checkAll = 0;
|
||||
controller.type = value;
|
||||
|
||||
expect(controller.type).toEqual({});
|
||||
expect(controller._checkAll).toEqual(1);
|
||||
value = {id: 'any'};
|
||||
controller.type = value;
|
||||
|
||||
expect(controller.type).toEqual({});
|
||||
expect(controller._checkAll).toEqual(0);
|
||||
value = {id: 'any other id name'};
|
||||
controller.type = value;
|
||||
|
||||
expect(controller.type).toEqual({});
|
||||
expect(controller._checkAll).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
<paging
|
||||
page="$ctrl.currentPage"
|
||||
page-size="$ctrl.numPerPage"
|
||||
page-size="$ctrl.numPerPage"
|
||||
ng-if="$ctrl.numPages>1"
|
||||
total="$ctrl.numItems"
|
||||
show-prev-next="true"
|
||||
show-first-last="false"
|
||||
|
|
|
@ -5,6 +5,7 @@ export default class Paging {
|
|||
get numPages() {
|
||||
return Math.ceil(this.numItems / this.numPerPage);
|
||||
}
|
||||
|
||||
constructor($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
|
@ -13,6 +14,7 @@ export default class Paging {
|
|||
this.numItems = 0;
|
||||
$scope.$watch('$ctrl.index.model.length', () => this.onModelUpdated());
|
||||
}
|
||||
|
||||
$onChanges(changes) {
|
||||
if (!this.index) return;
|
||||
this.numPerPage = this.index.filter.size;
|
||||
|
@ -20,14 +22,15 @@ export default class Paging {
|
|||
if (changes.total)
|
||||
this.numItems = changes.total.currentValue;
|
||||
}
|
||||
|
||||
onModelUpdated() {
|
||||
let index = this.index;
|
||||
let filter = index.filter;
|
||||
|
||||
if (filter.page >= this.numPages
|
||||
&& index.model.length >= this.numPerPage)
|
||||
if (filter.page >= this.numPages && index.model.length >= this.numPerPage)
|
||||
this.numItems = filter.page * filter.size + 1;
|
||||
}
|
||||
|
||||
onPageChange(page) {
|
||||
this.index.filter.page = page;
|
||||
if (typeof this.pageChange === 'undefined') {
|
||||
|
@ -37,6 +40,7 @@ export default class Paging {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Paging.$inject = ['$http', '$scope'];
|
||||
|
||||
export const NAME = 'vnPaging';
|
||||
|
@ -49,4 +53,5 @@ export const COMPONENT = {
|
|||
},
|
||||
controller: Paging
|
||||
};
|
||||
|
||||
module.component(NAME, COMPONENT);
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
import './paging.js';
|
||||
|
||||
describe('Component vnPaging', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnPaging', {$scope, $httpBackend});
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should define numberPage and currentPage based on index.filter properties`, () => {
|
||||
controller.index = {filter: {size: 'something', page: 'something else'}};
|
||||
controller.$onChanges({index: 'simpleChange', currentValue: 'current value', previousValue: 'previous value'});
|
||||
|
||||
expect(controller.numPerPage).toBe(controller.index.filter.size);
|
||||
expect(controller.currentPage).toEqual(controller.index.filter.page);
|
||||
});
|
||||
|
||||
it(`should define numItems based on changes.total.currentValue`, () => {
|
||||
controller.index = {filter: {size: 'something', page: 'something else'}};
|
||||
controller.$onChanges({total: {currentValue: 'current value'}});
|
||||
|
||||
expect(controller.numItems).toEqual('current value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('onModelUpdated()', () => {
|
||||
it(`should define controllers numItems as the result of page times size plus one`, () => {
|
||||
controller.numPerPage = 2;
|
||||
controller.index = {
|
||||
filter: {size: 10, page: 10},
|
||||
model: ['one mother..', 'another model..', 'last model..']
|
||||
};
|
||||
controller.onModelUpdated();
|
||||
|
||||
expect(controller.numItems).toBe(101);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onPageChange()', () => {
|
||||
it(`should call accept() since pageChange property is undefined`, () => {
|
||||
controller.index = {accept: () => {}, filter: {page: 0}};
|
||||
spyOn(controller.index, 'accept');
|
||||
controller.onPageChange(100);
|
||||
|
||||
expect(controller.index.accept).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call pageChange() since pageChange property isn't undefined`, () => {
|
||||
controller.index = {accept: () => {}, filter: {page: 0}};
|
||||
controller.pageChange = true;
|
||||
spyOn(controller, 'pageChange');
|
||||
controller.onPageChange(100);
|
||||
|
||||
expect(controller.pageChange).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -13,6 +13,7 @@ export function directive(vnPopover) {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.directive('vnPopover', directive);
|
||||
|
||||
export class Popover {
|
||||
|
@ -69,6 +70,7 @@ export class Popover {
|
|||
width = innerWidth - dblMargin;
|
||||
style.width = width + 'px';
|
||||
}
|
||||
|
||||
if (height + dblMargin > innerHeight) {
|
||||
height = innerHeight - dblMargin;
|
||||
style.height = height + 'px';
|
||||
|
@ -82,11 +84,13 @@ export class Popover {
|
|||
|
||||
if (left + width > innerWidth)
|
||||
left -= (left + width) - innerWidth + margin;
|
||||
|
||||
if (top + height > innerHeight)
|
||||
top -= height + parentNode.offsetHeight + spacing * 2;
|
||||
|
||||
if (left < 0)
|
||||
left = screenMargin;
|
||||
|
||||
if (top < 0)
|
||||
top = screenMargin;
|
||||
|
||||
|
@ -102,6 +106,7 @@ export class Popover {
|
|||
}
|
||||
return popoverId;
|
||||
}
|
||||
|
||||
showComponent(childComponent, $scope, parent) {
|
||||
let childElement = this.document.createElement(childComponent);
|
||||
let id = 'popover-' + this.popOpens;
|
||||
|
@ -111,12 +116,14 @@ export class Popover {
|
|||
this.show(childElement, parent, id);
|
||||
return childElement;
|
||||
}
|
||||
|
||||
_checkOpens() {
|
||||
this.popOpens = this.document.querySelectorAll('*[id^="popover-"]').length;
|
||||
if (this.popOpens === 0) {
|
||||
this._destroy();
|
||||
}
|
||||
}
|
||||
|
||||
_removeElement(val) {
|
||||
if (!val) return;
|
||||
let element = angular.element(val);
|
||||
|
@ -136,6 +143,7 @@ export class Popover {
|
|||
}
|
||||
this._checkOpens();
|
||||
}
|
||||
|
||||
hideChilds(id) {
|
||||
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
||||
let idNumber = parseInt(id.split('-')[1], 10);
|
||||
|
@ -147,6 +155,7 @@ export class Popover {
|
|||
);
|
||||
this._checkOpens();
|
||||
}
|
||||
|
||||
hideAll() {
|
||||
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
||||
popovers.forEach(
|
||||
|
@ -156,6 +165,7 @@ export class Popover {
|
|||
);
|
||||
this._checkOpens();
|
||||
}
|
||||
|
||||
_findPopOver(node) {
|
||||
while (node != null) {
|
||||
if (node.id && node.id.startsWith('popover-')) {
|
||||
|
@ -165,6 +175,7 @@ export class Popover {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
onDocMouseDown(event) {
|
||||
let targetId = this._findPopOver(event.target);
|
||||
if (targetId) {
|
||||
|
@ -173,6 +184,7 @@ export class Popover {
|
|||
this.hideAll();
|
||||
}
|
||||
}
|
||||
|
||||
onDocKeyDown(event) {
|
||||
if (event.keyCode === 27) {
|
||||
let targetId = this._findPopOver(this.lastTarget);
|
||||
|
@ -184,9 +196,12 @@ export class Popover {
|
|||
this.lastTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
onPopoverMouseDown(event) {
|
||||
this.lastTarget = event.target;
|
||||
}
|
||||
}
|
||||
|
||||
Popover.$inject = ['$document', '$compile', '$transitions'];
|
||||
|
||||
module.service('vnPopover', Popover);
|
||||
|
|
|
@ -7,12 +7,12 @@ export const NAME = util.getName(_NAME);
|
|||
|
||||
directive.$inject = [resolveFactory.NAME];
|
||||
export function directive(resolve) {
|
||||
return{
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: function(_, attrs) {
|
||||
return resolve.getTemplate(_NAME, attrs);
|
||||
return resolve.getTemplate(_NAME, attrs);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_module.directive(NAME, directive);
|
||||
|
|
|
@ -15,7 +15,7 @@ export function factory() {
|
|||
enabled: 'true',
|
||||
className: DEFAULT_CLASS
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_module.factory(NAME, factory);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import './spinner.js';
|
||||
|
||||
describe('Component vnSpinner', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element('<div><div></div></div>');
|
||||
controller = $componentController('vnSpinner', {$scope, $element});
|
||||
}));
|
||||
|
||||
describe('enable()', () => {
|
||||
it(`should call start() based on a boolean value passed as argument`, () => {
|
||||
spyOn(controller, 'start');
|
||||
spyOn(controller, 'stop');
|
||||
controller.enable = true;
|
||||
|
||||
expect(controller.start).toHaveBeenCalledWith();
|
||||
expect(controller.stop).not.toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call stop() based on a boolean value passed as argument`, () => {
|
||||
spyOn(controller, 'start');
|
||||
spyOn(controller, 'stop');
|
||||
controller.enable = false;
|
||||
|
||||
expect(controller.start).not.toHaveBeenCalledWith();
|
||||
expect(controller.stop).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('start()', () => {
|
||||
it(`should call start() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
|
||||
controller.spinner = {MaterialSpinner: {start: () => {}}};
|
||||
spyOn(controller.spinner.MaterialSpinner, 'start');
|
||||
controller._enable = false;
|
||||
controller.start();
|
||||
|
||||
expect(controller.spinner.MaterialSpinner.start).toHaveBeenCalledWith();
|
||||
expect(controller._enable).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('stop()', () => {
|
||||
it(`should call stop() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
|
||||
controller.spinner = {MaterialSpinner: {stop: () => {}}};
|
||||
spyOn(controller.spinner.MaterialSpinner, 'stop');
|
||||
controller._enable = true;
|
||||
controller.stop();
|
||||
|
||||
expect(controller.spinner.MaterialSpinner.stop).toHaveBeenCalledWith();
|
||||
expect(controller._enable).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -16,8 +16,8 @@
|
|||
ng-readonly="$ctrl.readonly"
|
||||
/>
|
||||
<div class="mdl-chip__action">
|
||||
<i class="material-icons pointer" ng-show="$ctrl.hasValue&&($ctrl.hasFocus||$ctrl.hasMouseIn)" ng-click="$ctrl.clear()">clear</i>
|
||||
<i class="material-icons" ng-if="$ctrl.hasInfo" vn-tooltip="{{$ctrl.info}}" tooltip-position="up">info_outline</i>
|
||||
<i class="material-icons pointer" ng-show="$ctrl.hasValue&&($ctrl.hasFocus||$ctrl.hasMouseIn)" ng-click="$ctrl.clear()">clear</i>
|
||||
</div>
|
||||
<label class="mdl-textfield__label" translate>{{$ctrl.label}}</label>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class TextfieldController extends Component {
|
|||
this.hasValue = Boolean(this._value);
|
||||
this.mdlUpdate();
|
||||
}
|
||||
|
||||
|
||||
mdlUpdate() {
|
||||
let mdlField = this.$element[0].firstChild.MaterialTextfield;
|
||||
if (mdlField)
|
||||
|
@ -48,6 +48,7 @@ export default class TextfieldController extends Component {
|
|||
this.input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
TextfieldController.$inject = ['$element', '$scope', '$attrs', '$timeout', normalizerFactory.NAME];
|
||||
|
||||
module.component('vnTextfield', {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import './textfield.js';
|
||||
|
||||
describe('Component vnTextfield', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $attrs;
|
||||
let $timeout;
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$attrs = {};
|
||||
$timeout = _$timeout_;
|
||||
$element = angular.element('<div><input></div>');
|
||||
controller = $componentController('vnTextfield', {$scope, $element, $attrs, $timeout});
|
||||
}));
|
||||
|
||||
describe('value() setter', () => {
|
||||
it(`should set _value, input.value and hasValue properties to null, '' and false then call mdlUpdate()`, () => {
|
||||
spyOn(controller, 'mdlUpdate');
|
||||
let testValue = '';
|
||||
controller.value = testValue;
|
||||
|
||||
expect(controller._value).toEqual(null);
|
||||
expect(controller.input.value).toEqual(testValue);
|
||||
expect(controller.hasValue).toEqual(Boolean(testValue));
|
||||
expect(controller.mdlUpdate).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should set _value, input.value and hasValue propertiest to test, test and true then call mdlUpdate()`, () => {
|
||||
spyOn(controller, 'mdlUpdate');
|
||||
let testValue = 'test';
|
||||
controller.value = testValue;
|
||||
|
||||
expect(controller._value).toEqual(testValue);
|
||||
expect(controller.input.value).toEqual(testValue);
|
||||
expect(controller.hasValue).toEqual(Boolean(testValue));
|
||||
expect(controller.mdlUpdate).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import {module} from '../module';
|
||||
import Component from '../lib/component';
|
||||
import getModifiedData from '../lib/modified';
|
||||
// import copyObject from '../lib/copy';
|
||||
import copyObject from '../lib/copy';
|
||||
import isEqual from '../lib/equals';
|
||||
|
||||
/**
|
||||
|
@ -22,8 +22,9 @@ export default class Watcher extends Component {
|
|||
this.state = null;
|
||||
this.deregisterCallback = $transitions.onStart({},
|
||||
transition => this.callback(transition));
|
||||
this.copyData();
|
||||
this.updateOriginalData();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.get && this.url) {
|
||||
this.fetchData();
|
||||
|
@ -31,21 +32,24 @@ export default class Watcher extends Component {
|
|||
throw new Error('Error: Parameter url ommitted');
|
||||
}
|
||||
}
|
||||
|
||||
$onChanges(changes) {
|
||||
if (this.data) {
|
||||
this.copyData();
|
||||
this.updateOriginalData();
|
||||
}
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.deregisterCallback();
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
let id = this.data[this.idField];
|
||||
// return new Promise((resolve, reject) => {
|
||||
this.$http.get(`${this.url}/${id}`).then(
|
||||
json => {
|
||||
this.data = this.copyObject(json.data);
|
||||
this.copyData();
|
||||
this.data = copyObject(json.data);
|
||||
this.updateOriginalData();
|
||||
}
|
||||
// json => reject(json)
|
||||
);
|
||||
|
@ -55,7 +59,7 @@ export default class Watcher extends Component {
|
|||
* Submits the data and goes back in the history.
|
||||
*/
|
||||
submitBack() {
|
||||
this.submit().then(
|
||||
return this.submit().then(
|
||||
() => this.window.history.back()
|
||||
);
|
||||
}
|
||||
|
@ -65,7 +69,7 @@ export default class Watcher extends Component {
|
|||
* @param {String} state The state name
|
||||
*/
|
||||
submitGo(state) {
|
||||
this.submit().then(
|
||||
return this.submit().then(
|
||||
() => this.$state.go(state)
|
||||
);
|
||||
}
|
||||
|
@ -120,43 +124,49 @@ export default class Watcher extends Component {
|
|||
);
|
||||
});
|
||||
}
|
||||
writeData(json, resolve) {
|
||||
Object.keys(this.data).forEach(
|
||||
key => {
|
||||
this.data[key] = json.data[key];
|
||||
}
|
||||
);
|
||||
|
||||
this.copyData();
|
||||
writeData(json, resolve) {
|
||||
Object.assign(this.data, json.data);
|
||||
this.updateOriginalData();
|
||||
resolve(json);
|
||||
}
|
||||
|
||||
noChanges(resolve) {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('No changes to save')
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
|
||||
invalidForm(resolve) {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('Some fields are invalid')
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
copyData() {
|
||||
this.orgData = this.copyObject(this.data);
|
||||
|
||||
updateOriginalData() {
|
||||
this.orgData = this.copyInNewObject(this.data);
|
||||
}
|
||||
copyObject(data) {
|
||||
let copy = {};
|
||||
if (data) {
|
||||
|
||||
copyInNewObject(data) {
|
||||
let newCopy = {};
|
||||
if (data && typeof data === 'object') {
|
||||
Object.keys(data).forEach(
|
||||
val => {
|
||||
if (data[val] !== "" && data[val] !== undefined && data[val] !== null)
|
||||
copy[val] = data[val];
|
||||
if (data[val] !== "" && data[val] !== undefined && data[val] !== null) {
|
||||
if (typeof data[val] === 'object') {
|
||||
newCopy[val] = this.copyInNewObject(data[val]);
|
||||
} else {
|
||||
newCopy[val] = data[val];
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return copy;
|
||||
return newCopy;
|
||||
}
|
||||
|
||||
callback(transition) {
|
||||
let dataChanged = this.dataChanged();
|
||||
if (!this.state && dataChanged) {
|
||||
|
@ -167,19 +177,22 @@ export default class Watcher extends Component {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
dataChanged() {
|
||||
let newData = this.copyObject(this.data);
|
||||
let newData = this.copyInNewObject(this.data);
|
||||
return !isEqual(newData, this.orgData);
|
||||
}
|
||||
|
||||
onConfirmResponse(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.data = this.copyObject(this.orgData);
|
||||
Object.assign(this.data, this.orgData);
|
||||
this.$state.go(this.state);
|
||||
} else {
|
||||
this.state = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate'];
|
||||
|
||||
module.component('vnWatcher', {
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
import './watcher.js';
|
||||
import getModifiedData from '../lib/modified';
|
||||
|
||||
describe('Component vnWatcher', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $element;
|
||||
let $state;
|
||||
let $transitions;
|
||||
let $httpBackend;
|
||||
let vnApp;
|
||||
let $translate;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$transitions_, _$httpBackend_, _vnApp_, _$translate_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$element = angular.element('<div></div>');
|
||||
$state = _$state_;
|
||||
vnApp = _vnApp_;
|
||||
$transitions = _$transitions_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$translate = _$translate_;
|
||||
controller = $componentController('vnWatcher', {$scope, $element, $state, vnApp, $transitions, $httpBackend, $translate});
|
||||
}));
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it(`should call fetchData() if controllers get and url properties are defined`, () => {
|
||||
controller.get = () => {};
|
||||
controller.url = 'test.com';
|
||||
spyOn(controller, 'fetchData');
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller.fetchData).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should throw an error if $onInit is called without url defined`, () => {
|
||||
controller.get = () => {};
|
||||
|
||||
expect(function() {
|
||||
controller.$onInit();
|
||||
}).toThrow(new Error('Error: Parameter url ommitted'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it(`should call updateOriginalData() if controllers data is defined`, () => {
|
||||
controller.data = [];
|
||||
spyOn(controller, 'updateOriginalData');
|
||||
controller.$onChanges();
|
||||
|
||||
expect(controller.updateOriginalData).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onDestroy()', () => {
|
||||
it(`should call deregisterCallback()`, () => {
|
||||
spyOn(controller, 'deregisterCallback');
|
||||
controller.$onDestroy();
|
||||
|
||||
expect(controller.deregisterCallback).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchData()', () => {
|
||||
it(`should perform a query then store the received data into controller.data and call updateOriginalData()`, () => {
|
||||
spyOn(controller, 'updateOriginalData');
|
||||
let json = {data: 'some data'};
|
||||
controller.data = [1];
|
||||
controller.idField = 0;
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET('test.com/1').respond(json);
|
||||
$httpBackend.expectGET('test.com/1');
|
||||
controller.fetchData();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.data).toEqual({data: 'some data'});
|
||||
expect(controller.updateOriginalData).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('submitBack()', () => {
|
||||
it(`should call controller.window.history.back() function after calling controllers submit() function`, done => {
|
||||
spyOn(controller, 'submit').and.returnValue(Promise.resolve());
|
||||
spyOn(controller.window.history, 'back');
|
||||
controller.submitBack()
|
||||
.then(() => {
|
||||
expect(controller.submit).toHaveBeenCalledWith();
|
||||
expect(controller.window.history.back).toHaveBeenCalledWith();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('submitGo()', () => {
|
||||
it(`should call controller.$state.go() function after calling controllers submit() function`, done => {
|
||||
spyOn(controller, 'submit').and.returnValue(Promise.resolve());
|
||||
spyOn(controller.$state, 'go');
|
||||
let state = 'the state';
|
||||
controller.submitGo(state)
|
||||
.then(() => {
|
||||
expect(controller.submit).toHaveBeenCalledWith();
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(state);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('submit()', () => {
|
||||
describe('when controller.form', () => {
|
||||
it(`should call controller.form.setSubminted if controller.form is defined`, () => {
|
||||
controller.form = {$setSubmitted: () => {}};
|
||||
spyOn(controller.form, '$setSubmitted');
|
||||
controller.submit();
|
||||
|
||||
expect(controller.form.$setSubmitted).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it(`should call controller.invalidForm if controller.form.$valid is not defined`, () => {
|
||||
controller.form = {$setSubmitted: () => {}};
|
||||
spyOn(controller, 'invalidForm');
|
||||
controller.submit();
|
||||
|
||||
expect(controller.invalidForm).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when !controller.dataChanged()', () => {
|
||||
it(`should call controller.noChanges()`, () => {
|
||||
spyOn(controller, 'noChanges');
|
||||
controller.submit();
|
||||
|
||||
expect(controller.noChanges).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe('when controller.save()', () => {
|
||||
it(`should set controller.save.model property`, () => {
|
||||
controller.save = {};
|
||||
controller.data = {originalInfo: 'original data', info: 'new data'};
|
||||
controller.orgData = {originalInfo: 'original data'};
|
||||
controller.submit();
|
||||
|
||||
expect(controller.save.model).toEqual({info: 'new data'});
|
||||
});
|
||||
|
||||
it(`should call controller.save.accept() then controller.writeData`, done => {
|
||||
controller.save = {accept: () => {}};
|
||||
controller.data = {originalInfo: 'original data', info: 'new data'};
|
||||
controller.orgData = {originalInfo: 'original data'};
|
||||
spyOn(controller.save, 'accept').and.returnValue(Promise.resolve());
|
||||
spyOn(controller, 'writeData').and.callThrough();
|
||||
controller.submit()
|
||||
.then(() => {
|
||||
expect(controller.save.accept).toHaveBeenCalledWith();
|
||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when id is defined', () => {
|
||||
it(`should perform a query then call controller.writeData()`, () => {
|
||||
controller.dataChanged = () => {
|
||||
return true;
|
||||
};
|
||||
controller.data = {id: 2};
|
||||
controller.orgData = {id: 1};
|
||||
let changedData = getModifiedData(controller.data, controller.orgData);
|
||||
controller.idField = 'id';
|
||||
controller.url = 'test.com';
|
||||
let json = {data: 'some data'};
|
||||
spyOn(controller, 'writeData').and.callThrough();
|
||||
$httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
|
||||
$httpBackend.expectPATCH(`${controller.url}/1`);
|
||||
controller.submit()
|
||||
.then(() => {
|
||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||
done();
|
||||
});
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
it(`should perform a POST query then call controller.writeData()`, () => {
|
||||
controller.dataChanged = () => {
|
||||
return true;
|
||||
};
|
||||
controller.data = {id: 2};
|
||||
controller.orgData = {id: 1};
|
||||
controller.url = 'test.com';
|
||||
let json = {data: 'some data'};
|
||||
spyOn(controller, 'writeData').and.callThrough();
|
||||
$httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
|
||||
$httpBackend.expectPOST(`${controller.url}`, controller.data);
|
||||
controller.submit()
|
||||
.then(() => {
|
||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||
done();
|
||||
});
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
describe('writeData()', () => {
|
||||
it(`should call Object.asssign() function over controllers.data with json.data, then call updateOriginalData function and finally call resolve() function`, () => {
|
||||
spyOn(controller, 'updateOriginalData');
|
||||
controller.data = {};
|
||||
let json = {data: 'some data'};
|
||||
let resolve = jasmine.createSpy('resolve');
|
||||
controller.writeData(json, resolve);
|
||||
|
||||
expect(controller.updateOriginalData).toHaveBeenCalledWith();
|
||||
expect(resolve).toHaveBeenCalledWith(json);
|
||||
});
|
||||
});
|
||||
|
||||
describe('copyInNewObject()', () => {
|
||||
it(`should return newCopy object if data was an object`, () => {
|
||||
let data = {id: 1, Heroname: 'Batman', name: 'Bruce Wayne'};
|
||||
let result = controller.copyInNewObject(data);
|
||||
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('callback()', () => {
|
||||
describe(`when dataChanged() returns true and there's no state in the controller`, () => {
|
||||
it(`should define controller.state, call controller.$scope.confirm.show() and return false`, () => {
|
||||
$scope.confirm = {show: jasmine.createSpy('show')};
|
||||
controller.dataChanged = () => {
|
||||
return true;
|
||||
};
|
||||
controller.state = undefined;
|
||||
let transition = {to: () => {
|
||||
return {name: 'Batman'};
|
||||
}};
|
||||
let result = controller.callback(transition);
|
||||
|
||||
expect(controller.state).toEqual('Batman');
|
||||
expect(controller.$scope.confirm.show).toHaveBeenCalledWith();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe(`when dataChanged() returns false and/or there's a state in the controller`, () => {
|
||||
it(`should return true`, () => {
|
||||
$scope.confirm = {show: jasmine.createSpy('show')};
|
||||
controller.dataChanged = () => {
|
||||
return false;
|
||||
};
|
||||
controller.state = 'the state';
|
||||
let transition = {to: () => {
|
||||
return {name: 'Batman'};
|
||||
}};
|
||||
let result = controller.callback(transition);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(`onConfirmResponse()`, () => {
|
||||
describe(`when response is ACCEPT`, () => {
|
||||
it(`should call Object.assing on controlle.data with controller.orgData then call go() on state`, () => {
|
||||
let response = 'ACCEPT';
|
||||
controller.data = {};
|
||||
controller.orgData = {name: 'Batman'};
|
||||
controller.$state = {go: jasmine.createSpy('go')};
|
||||
controller.state = 'Batman';
|
||||
controller.onConfirmResponse(response);
|
||||
|
||||
expect(controller.data).toEqual(controller.orgData);
|
||||
expect(controller.$state.go).toHaveBeenCalledWith(controller.state);
|
||||
});
|
||||
});
|
||||
|
||||
describe(`when response is not ACCEPT`, () => {
|
||||
it(`should set controller.state to null`, () => {
|
||||
let response = 'anything but ACCEPT';
|
||||
controller.state = 'Batman';
|
||||
controller.onConfirmResponse(response);
|
||||
|
||||
expect(controller.state).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
// 309
|
|
@ -0,0 +1 @@
|
|||
export * from './src/locator';
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"module": "locator",
|
||||
"name": "Locator",
|
||||
"icon": "add_location",
|
||||
"validations" : false,
|
||||
"routes": [
|
||||
{
|
||||
"url": "/locator",
|
||||
"state": "locator",
|
||||
"component": "vn-locator-index",
|
||||
"acl": ["developer"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<vn-card margin-large>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-horizontal vn-one margin-large-bottom class="locator-header">
|
||||
<vn-title vn-one>Routes locator</vn-title>
|
||||
<form vn-two vn-horizontal class="filterPanel" ng-submit="$ctrl.searchRoutes()">
|
||||
<vn-textfield vn-one label="Filter" model="$ctrl.search"></vn-textfield>
|
||||
<vn-icon
|
||||
vn-none
|
||||
margin-medium-right
|
||||
pad-medium-top
|
||||
icon="keyboard_arrow_down"
|
||||
ng-click="$ctrl.moreFilters($event)">
|
||||
</vn-icon>
|
||||
<vn-button vn-none pad-small-top label="Filtrar" ng-click="$ctrl.searchRoutes()"></vn-button>
|
||||
</form>
|
||||
|
||||
<vn-one vn-horizontal>
|
||||
<vn-one></vn-one>
|
||||
<vn-autocomplete vn-two
|
||||
initial-value="$ctrl.filter.warehouseFk"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.filter.warehouseFk"
|
||||
url="/production/api/Warehouses/production"
|
||||
on-change = "$ctrl.onChangeWareHouse(item)"
|
||||
label="Store">
|
||||
</vn-autocomplete>
|
||||
<vn-icon-button vn-none pad-ten-top margin-medium-left icon="refresh" ng-click="$ctrl.refreshRoutes()"></vn-icon-button>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal vn-one margin-large-bottom>
|
||||
<vn-one>
|
||||
<vn-locator-actions routes="$ctrl.routes" states="$ctrl.states" hour-items="$ctrl.hourItems"></vn-locator-actions>
|
||||
</vn-one>
|
||||
<vn-two></vn-two>
|
||||
</vn-horizontal>
|
||||
<vn-locator-table check-all="$ctrl.checkAll" routes="$ctrl.routes" footer="$ctrl.footer"></vn-locator-table>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
|
@ -0,0 +1,33 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class LocatorIndex {
|
||||
constructor($state) {
|
||||
this.$state = $state;
|
||||
this.routes = [];
|
||||
|
||||
for (let i = 1; i < 100; i++) {
|
||||
let route = {
|
||||
id: i,
|
||||
zoneFk: Math.floor(Math.random() * 6) + 1,
|
||||
postalcode: 46006,
|
||||
order: Math.floor(Math.random() * 3) + 1,
|
||||
preparado: '25/08',
|
||||
entrada: '26/08',
|
||||
ticket: 1547890 + i,
|
||||
routeFk: Math.floor(Math.random() * 9999) + 1000,
|
||||
alias: `Flores X${Math.floor(Math.random() * 3) + 1}`,
|
||||
bultos: Math.floor(Math.random() * 20) + 10,
|
||||
m3: (Math.random()).toFixed(2),
|
||||
error: (Math.floor(Math.random() * 3) + 1) === 1
|
||||
};
|
||||
route.success = (!route.error && (Math.floor(Math.random() * 3) + 1) === 1);
|
||||
this.routes.push(route);
|
||||
}
|
||||
}
|
||||
}
|
||||
LocatorIndex.$inject = ['$state'];
|
||||
|
||||
ngModule.component('vnLocatorIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: LocatorIndex
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"Routes locator": "Localizador de rutas",
|
||||
"Filter": "Filtro",
|
||||
"Store": "Almacén",
|
||||
"Address": "Dirección"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<vn-horizontal class="actionPanel">
|
||||
<vn-none margin-medium-right>
|
||||
<vn-icon-button icon="local_shipping"></vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-none margin-medium-right>
|
||||
<vn-icon-menu icon="local_shipping" selected="$ctrl.actionRoute" items="[{id:1,name:'test_01'},{id:2,name:'test_02'}]"></vn-icon-menu>
|
||||
</vn-none>
|
||||
<vn-none margin-medium-right>
|
||||
|
||||
</vn-none>
|
||||
<vn-none margin-medium-right>
|
||||
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
|
@ -0,0 +1,13 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class LocatorActions {
|
||||
constructor($state) {
|
||||
this.$state = $state;
|
||||
}
|
||||
}
|
||||
LocatorActions.$inject = ['$state'];
|
||||
|
||||
ngModule.component('vnLocatorActions', {
|
||||
template: require('./locator-actions.html'),
|
||||
controller: LocatorActions
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
<vn-vertical>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h>
|
||||
<vn-multi-check
|
||||
check-all="$ctrl.checkAll"
|
||||
models="$ctrl.routes"
|
||||
options="[{id:'all',name:'Todos'},{id:'any',name:'Ninguno'}, {id:'error', name:'Con problema'}, {id:'no-error', name:'Sin problema'}]"
|
||||
></vn-multi-check>
|
||||
</vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="zoneFk" text="Zona"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="postalcode" text="Postal Code"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="order" text="Order" default-order="DESC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="preparado" text="Preparado"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="entrada" text="Entrada"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="ticket" text="Ticket"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="routeFk" text="ID de ruta"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="alias" text="Alias"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="bultos" text="Bultos"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="m3" text="m3"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-vertical
|
||||
class="list list-element text-center"
|
||||
ng-repeat="route in $ctrl.pageTable.model track by route.id"
|
||||
ng-class="{warning: route.error, success: route.success}"
|
||||
>
|
||||
<vn-horizontal>
|
||||
<vn-one pad-medium-h></vn-one>
|
||||
<vn-two pad-medium-h>{{::route.zoneFk}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.postalcode}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.order}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.preparado}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.entrada}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.ticket}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.routeFk}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.alias}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.bultos}}</vn-two>
|
||||
<vn-two pad-medium-h>{{::route.m3}}</vn-two>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-small-top>
|
||||
<vn-none pad-medium-h margin--small-top>
|
||||
<vn-check model="route.checked"></vn-check>
|
||||
</vn-none>
|
||||
<vn-none pad-medium-h></vn-none>
|
||||
<vn-one text-left pad-small border-solid>
|
||||
<strong translate>Address</strong>: {{::route.address}}
|
||||
</vn-one>
|
||||
<vn-none pad-medium-h>
|
||||
<vn-icon icon="more" vn-tooltip tooltip-template="/static/templates/tooltip.routes.tpl.html" tooltip-position="left"></vn-icon>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer">
|
||||
|
||||
</vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-paging page-change="$ctrl.paginate()" index="$ctrl.pageTable" total="$ctrl.totalFilter"></vn-paging>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,46 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class LocatorTable {
|
||||
constructor($filter) {
|
||||
this.$filter = $filter;
|
||||
this.itemsDisplayedInList = 7;
|
||||
this.pageTable = {
|
||||
filter: {
|
||||
page: 1,
|
||||
size: this.itemsDisplayedInList
|
||||
},
|
||||
model: []
|
||||
};
|
||||
this._routes = [];
|
||||
}
|
||||
|
||||
set routes(value) {
|
||||
this._routes = value;
|
||||
this.totalFilter = this._routes.length;
|
||||
this.pageTable.filter.page = 1;
|
||||
this.paginate();
|
||||
}
|
||||
get routes() {
|
||||
return this._routes;
|
||||
}
|
||||
|
||||
onOrder(field, order) {
|
||||
let reverse = order === 'DESC';
|
||||
this.routes = this.$filter('orderBy')(this.routes, field, reverse);
|
||||
this.paginate();
|
||||
}
|
||||
paginate() {
|
||||
let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;
|
||||
let fin = this.pageTable.filter.page * this.itemsDisplayedInList;
|
||||
this.pageTable.model = this.routes.slice(init, fin);
|
||||
}
|
||||
}
|
||||
LocatorTable.$inject = ['$filter'];
|
||||
|
||||
ngModule.component('vnLocatorTable', {
|
||||
template: require('./locator-table.html'),
|
||||
bindings: {
|
||||
routes: '<'
|
||||
},
|
||||
controller: LocatorTable
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
export * from './module';
|
||||
|
||||
import './index/index';
|
||||
import './locator-actions/locator-actions';
|
||||
import './locator-table/locator-table';
|
|
@ -0,0 +1,5 @@
|
|||
import {ng} from 'vendor';
|
||||
import 'core';
|
||||
|
||||
const ngModule = ng.module('locator', []);
|
||||
export default ngModule;
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"salix": [],
|
||||
"auth": [],
|
||||
"core": [],
|
||||
"client": [],
|
||||
"production": [],
|
||||
"route": [],
|
||||
"locator": []
|
||||
}
|
|
@ -7,7 +7,8 @@
|
|||
{
|
||||
"url": "/production",
|
||||
"state": "production",
|
||||
"component": "vn-production-index"
|
||||
"component": "vn-production-index",
|
||||
"acl": ["employee"]
|
||||
}
|
||||
]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue