Merge branch 'dev' of https://git.verdnatura.es/salix
This commit is contained in:
commit
9d67a622fc
|
@ -16,3 +16,5 @@ rules:
|
||||||
camelcase: 0
|
camelcase: 0
|
||||||
default-case: 0
|
default-case: 0
|
||||||
no-eq-null: 0
|
no-eq-null: 0
|
||||||
|
no-console: 0
|
||||||
|
no-warning-comments: 0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
spliting.js
|
|
||||||
build
|
build
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
debug.log
|
debug.log
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"name": "Iniciar",
|
"name": "Iniciar",
|
||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/services/client/server/server.js",
|
"program": "${workspaceRoot}/services/auth/server/server.js",
|
||||||
"stopOnEntry": false,
|
"stopOnEntry": false,
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceRoot}",
|
"cwd": "${workspaceRoot}",
|
||||||
|
|
|
@ -1,28 +1,25 @@
|
||||||
#!/usr/bin/env groovy
|
#!/usr/bin/env groovy
|
||||||
|
|
||||||
import groovy.json.*;
|
|
||||||
|
|
||||||
def image;
|
|
||||||
def branchName = "${env.BRANCH_NAME}";
|
def branchName = "${env.BRANCH_NAME}";
|
||||||
def branchNameTest = "preprod";
|
def branchProduction = "master"
|
||||||
def branchNameProd = "master";
|
def branchTest = "test";
|
||||||
def prefixDocker = "test";
|
def dockerHost = "${env.DOCKER_HOST}";
|
||||||
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 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 == branchProduction)
|
||||||
|
dockerHost = "tcp://172.16.255.29:2375";
|
||||||
if (branchName == branchNameProd)
|
|
||||||
prefixDocker = "prod";
|
|
||||||
|
|
||||||
|
node
|
||||||
|
{
|
||||||
|
stage ('Print environment variables'){
|
||||||
|
echo "Branch ${branchName}, Build ${env.TAG}, NODE_ENV ${env.NODE_ENV} en docker Host ${dockerHost}"
|
||||||
|
}
|
||||||
stage ('Checkout') {
|
stage ('Checkout') {
|
||||||
checkout scm
|
checkout scm
|
||||||
}
|
}
|
||||||
|
@ -31,51 +28,25 @@ node {
|
||||||
sh "npm install"
|
sh "npm install"
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('build Project Salix'){
|
stage ('build Project'){
|
||||||
sh "gulp build"
|
sh "gulp build"
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < dockers.size(); i++)
|
stage ("docker")
|
||||||
{
|
{
|
||||||
def element = dockers[i][0]
|
stage ("install modules loopback service")
|
||||||
def ports = dockers[i][1]
|
{
|
||||||
|
sh "cd ./services/loopback && npm install"
|
||||||
|
}
|
||||||
|
|
||||||
stage ("docker ${element}")
|
stage ("Stopping/Removing Docker")
|
||||||
{
|
{
|
||||||
stage ("Stopping ${prefixDocker}-${element} actual")
|
sh "docker-compose down --rmi all"
|
||||||
|
}
|
||||||
|
|
||||||
|
stage ("Generar dockers")
|
||||||
{
|
{
|
||||||
try
|
sh "docker-compose up -d --build"
|
||||||
{
|
|
||||||
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')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,6 +43,10 @@ npm run testWatch or test for single run
|
||||||
|
|
||||||
on root run:
|
on root run:
|
||||||
|
|
||||||
|
gulp docker
|
||||||
|
|
||||||
|
wait 10 secs for db to be ready
|
||||||
|
|
||||||
npm run e2e
|
npm run e2e
|
||||||
|
|
||||||
## Built With
|
## Built With
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
{
|
{
|
||||||
"url": "/clients",
|
"url": "/clients",
|
||||||
"state": "clients",
|
"state": "clients",
|
||||||
"component": "vn-client-index"
|
"component": "vn-client-index",
|
||||||
|
"acl": ["employee"]
|
||||||
}, {
|
}, {
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "create",
|
"state": "create",
|
||||||
|
@ -22,7 +23,7 @@
|
||||||
"state": "clientCard.basicData",
|
"state": "clientCard.basicData",
|
||||||
"component": "vn-client-basic-data",
|
"component": "vn-client-basic-data",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Datos básicos",
|
"description": "Datos básicos",
|
||||||
|
@ -33,7 +34,7 @@
|
||||||
"state": "clientCard.fiscalData",
|
"state": "clientCard.fiscalData",
|
||||||
"component": "vn-client-fiscal-data",
|
"component": "vn-client-fiscal-data",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Datos fiscales",
|
"description": "Datos fiscales",
|
||||||
|
@ -44,7 +45,7 @@
|
||||||
"state": "clientCard.billingData",
|
"state": "clientCard.billingData",
|
||||||
"component": "vn-client-billing-data",
|
"component": "vn-client-billing-data",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Datos facturación",
|
"description": "Datos facturación",
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
"state": "clientCard.addresses.list",
|
"state": "clientCard.addresses.list",
|
||||||
"component": "vn-client-addresses",
|
"component": "vn-client-addresses",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Consignatarios",
|
"description": "Consignatarios",
|
||||||
|
@ -79,7 +80,7 @@
|
||||||
"state": "clientCard.webAccess",
|
"state": "clientCard.webAccess",
|
||||||
"component": "vn-client-web-access",
|
"component": "vn-client-web-access",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Acceso web",
|
"description": "Acceso web",
|
||||||
|
@ -95,7 +96,7 @@
|
||||||
"state": "clientCard.notes.list",
|
"state": "clientCard.notes.list",
|
||||||
"component": "vn-client-notes",
|
"component": "vn-client-notes",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "card.client"
|
"client": "$ctrl.client"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"description": "Notas",
|
"description": "Notas",
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
field="$ctrl.address.agencyFk"
|
field="$ctrl.address.agencyFk"
|
||||||
url="/client/api/AgencyServices"
|
url="/client/api/AgencyModes"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
label="Agency">
|
label="Agency">
|
||||||
|
|
|
@ -2,6 +2,7 @@ import './address-create.js';
|
||||||
|
|
||||||
describe('Client', () => {
|
describe('Client', () => {
|
||||||
describe('Component vnAddressCreate', () => {
|
describe('Component vnAddressCreate', () => {
|
||||||
|
let controller;
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $state;
|
let $state;
|
||||||
|
|
||||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$state.params.id = '1234';
|
$state.params.id = '1234';
|
||||||
|
controller = $componentController('vnAddressCreate', {$state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define and set address property', () => {
|
it('should define and set address property', () => {
|
||||||
let controller = $componentController('vnAddressCreate', {$state});
|
|
||||||
|
|
||||||
expect(controller.address.clientFk).toBe(1234);
|
expect(controller.address.clientFk).toBe(1234);
|
||||||
expect(controller.address.isEnabled).toBe(true);
|
expect(controller.address.isEnabled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,8 +11,12 @@
|
||||||
<vn-vertical pad-large>
|
<vn-vertical pad-large>
|
||||||
<vn-title>Address</vn-title>
|
<vn-title>Address</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check vn-one label="enabled" field="$ctrl.address.isEnabled"></vn-check>
|
<vn-one>
|
||||||
<vn-check vn-one label="Is equalizated" field="$ctrl.address.isEqualizated"></vn-check>
|
<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-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Consignee" field="$ctrl.address.consignee" vn-focus></vn-textfield>
|
<vn-textfield vn-one label="Consignee" field="$ctrl.address.consignee" vn-focus></vn-textfield>
|
||||||
|
@ -33,7 +37,7 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
field="$ctrl.address.defaultAgencyFk"
|
field="$ctrl.address.defaultAgencyFk"
|
||||||
url="/client/api/AgencyServices"
|
url="/client/api/AgencyModes"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
label="Agency">
|
label="Agency">
|
||||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
||||||
describe('Component vnAddressEdit', () => {
|
describe('Component vnAddressEdit', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $state;
|
let $state;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$state.params.addressId = '1234';
|
$state.params.addressId = '1234';
|
||||||
|
controller = $componentController('vnAddressEdit', {$state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define and set address property', () => {
|
it('should define and set address property', () => {
|
||||||
let controller = $componentController('vnAddressEdit', {$state: $state});
|
|
||||||
|
|
||||||
expect(controller.address.id).toBe(1234);
|
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-textfield vn-one label="Crédito asegurado" field="$ctrl.client.creditInsurance" vn-acl="administrative"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check vn-one label="Recargo de equivalencia" field="$ctrl.client.equalizationTax" vn-acl="administrative"></vn-check>
|
<vn-one>
|
||||||
<vn-check vn-one label="Vies" field="$ctrl.client.vies" vn-acl="administrative"></vn-check>
|
<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-horizontal>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
@ -36,9 +40,15 @@
|
||||||
<vn-vertical pad-large>
|
<vn-vertical pad-large>
|
||||||
<vn-title>Documentación</vn-title>
|
<vn-title>Documentación</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check vn-one label="Recibido core VNH" field="$ctrl.client.coreVnh" vn-acl="administrative"></vn-check>
|
<vn-one>
|
||||||
<vn-check vn-one label="Recibido core VNL" field="$ctrl.client.coreVnl" vn-acl="administrative"></vn-check>
|
<vn-check label="Recibido core VNH" field="$ctrl.client.coreVnh" 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-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-horizontal>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
@ -60,3 +70,17 @@
|
||||||
<button response="ACCEPT" translate>Yes, notify</button>
|
<button response="ACCEPT" translate>Yes, notify</button>
|
||||||
</tpl-buttons>
|
</tpl-buttons>
|
||||||
</vn-dialog>
|
</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.discount = this.client.discount;
|
||||||
this.billData.credit = this.client.credit;
|
this.billData.credit = this.client.credit;
|
||||||
this.billData.creditInsurance = this.client.creditInsurance;
|
this.billData.creditInsurance = this.client.creditInsurance;
|
||||||
|
this.equalizationTax = this.client.equalizationTax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
submit() {
|
submit() {
|
||||||
|
@ -36,13 +37,41 @@ export default class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
if (!equals)
|
|
||||||
|
if (equals) {
|
||||||
|
this.checkREChanges();
|
||||||
|
} else {
|
||||||
this.$.sendMail.show();
|
this.$.sendMail.show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
returnDialog(response) {
|
returnDialog(response) {
|
||||||
if (response === 'ACCEPT') {
|
if (response === 'ACCEPT') {
|
||||||
this.$http.post(`/mailer/manuscript/payment-update/${this.client.id}`).then(
|
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 $componentController;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
let $scope;
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -18,11 +19,11 @@ describe('Client', () => {
|
||||||
$scope.watcher = {submit};
|
$scope.watcher = {submit};
|
||||||
let show = jasmine.createSpy('show');
|
let show = jasmine.createSpy('show');
|
||||||
$scope.sendMail = {show};
|
$scope.sendMail = {show};
|
||||||
|
controller = $componentController('vnClientBillingData', {$scope: $scope});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('copyData()', () => {
|
describe('copyData()', () => {
|
||||||
it(`should define billData using client's data`, () => {
|
it(`should define billData using client's data`, () => {
|
||||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
|
||||||
controller.client = {
|
controller.client = {
|
||||||
credit: 1000000000000,
|
credit: 1000000000000,
|
||||||
creditInsurance: null,
|
creditInsurance: null,
|
||||||
|
@ -40,7 +41,6 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('submit()', () => {
|
describe('submit()', () => {
|
||||||
it(`should call submit() on the watcher then receive a callback`, done => {
|
it(`should call submit() on the watcher then receive a callback`, done => {
|
||||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
|
||||||
spyOn(controller, 'checkPaymentChanges');
|
spyOn(controller, 'checkPaymentChanges');
|
||||||
controller.submit()
|
controller.submit()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -53,7 +53,6 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('checkPaymentChanges()', () => {
|
describe('checkPaymentChanges()', () => {
|
||||||
it(`should not call sendMail.show() if there are no changes on billing data`, () => {
|
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.billData = {marvelHero: 'Silver Surfer'};
|
||||||
controller.client = {marvelHero: 'Silver Surfer'};
|
controller.client = {marvelHero: 'Silver Surfer'};
|
||||||
controller.checkPaymentChanges();
|
controller.checkPaymentChanges();
|
||||||
|
@ -62,7 +61,6 @@ describe('Client', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should call sendMail.show() if there are changes on billing data object`, () => {
|
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.billData = {marvelHero: 'Silver Surfer'};
|
||||||
controller.client = {marvelHero: 'Spider-Man'};
|
controller.client = {marvelHero: 'Spider-Man'};
|
||||||
controller.checkPaymentChanges();
|
controller.checkPaymentChanges();
|
||||||
|
@ -73,7 +71,6 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('returnDialog()', () => {
|
describe('returnDialog()', () => {
|
||||||
it('should request to send notification email', () => {
|
it('should request to send notification email', () => {
|
||||||
let controller = $componentController('vnClientBillingData', {$scope: $scope});
|
|
||||||
controller.client = {id: '123'};
|
controller.client = {id: '123'};
|
||||||
$httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done');
|
$httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done');
|
||||||
$httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`);
|
$httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`);
|
||||||
|
|
|
@ -4,5 +4,9 @@
|
||||||
"No": "No",
|
"No": "No",
|
||||||
"Yes, notify": "Sí, notificar",
|
"Yes, notify": "Sí, notificar",
|
||||||
"Notification sent!": "¡Notificación enviada!",
|
"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>
|
<vn-horizontal>
|
||||||
<mg-ajax
|
<mg-ajax
|
||||||
path="/client/api/Clients/{{edit.params.id}}/card"
|
path="/client/api/Clients/{{edit.params.id}}/card"
|
||||||
actions="card.client = edit.model"
|
actions="$ctrl.client = edit.model"
|
||||||
options="mgEdit">
|
options="mgEdit">
|
||||||
</mg-ajax>
|
</mg-ajax>
|
||||||
<vn-empty style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
|
<vn-empty style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
|
||||||
<vn-descriptor
|
<vn-descriptor
|
||||||
client="card.client"
|
client="$ctrl.client"
|
||||||
active="card.client.active"
|
active="$ctrl.client.active"
|
||||||
class="display-block" >
|
class="display-block" >
|
||||||
</vn-descriptor>
|
</vn-descriptor>
|
||||||
<vn-left-menu></vn-left-menu>
|
<vn-left-menu></vn-left-menu>
|
||||||
|
|
|
@ -9,6 +9,5 @@ export default class Controller {
|
||||||
|
|
||||||
ngModule.component('vnClientCard', {
|
ngModule.component('vnClientCard', {
|
||||||
template: require('./card.html'),
|
template: require('./card.html'),
|
||||||
controller: Controller,
|
controller: Controller
|
||||||
controllerAs: 'card'
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
||||||
describe('Component vnClientCard', () => {
|
describe('Component vnClientCard', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $scope;
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -12,11 +13,10 @@ describe('Client', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$scope = $rootScope;
|
$scope = $rootScope;
|
||||||
|
controller = $componentController('vnClientCard', {$scope: $scope});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define and set client property to null in the module instance', () => {
|
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).toBeDefined();
|
||||||
expect(controller.client).toBe(null);
|
expect(controller.client).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ describe('Client', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $scope;
|
let $scope;
|
||||||
let $state;
|
let $state;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
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', () => {
|
it('should define and set scope, state and client properties', () => {
|
||||||
let controller = $componentController('vnClientCreate', {$scope: $scope});
|
|
||||||
|
|
||||||
expect(controller.$).toBe($scope);
|
expect(controller.$).toBe($scope);
|
||||||
expect(controller.$state).toBe($state);
|
expect(controller.$state).toBe($state);
|
||||||
expect(controller.client.active).toBe(true);
|
expect(controller.client.active).toBe(true);
|
||||||
|
@ -35,7 +35,6 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
describe('onSubmit()', () => {
|
||||||
it(`should call submit() on the watcher then expect a callback`, () => {
|
it(`should call submit() on the watcher then expect a callback`, () => {
|
||||||
let controller = $componentController('vnClientCreate', {$scope: $scope});
|
|
||||||
spyOn($state, 'go');
|
spyOn($state, 'go');
|
||||||
controller.onSubmit();
|
controller.onSubmit();
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
|
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-one>
|
<a vn-one ui-sref="clients">
|
||||||
<i class="material-icons descriptor-icon">person</i>
|
<i class="material-icons descriptor-icon">person</i>
|
||||||
</vn-one>
|
</a>
|
||||||
<vn-vertical vn-two>
|
<vn-vertical vn-two>
|
||||||
<div class="margin-none">{{::$ctrl.client.id}}</div>
|
<div class="margin-none">{{::$ctrl.client.id}}</div>
|
||||||
<div class="margin-none">{{$ctrl.client.name}}</div>
|
<div class="margin-none">{{$ctrl.client.name}}</div>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import './style.css';
|
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($scope, $http) {
|
constructor($scope, $http) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
||||||
describe('Component vnDescriptor', () => {
|
describe('Component vnDescriptor', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $scope;
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -12,11 +13,11 @@ describe('Client', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
|
controller = $componentController('vnDescriptor', {$scope: $scope});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('set active', () => {
|
describe('set active', () => {
|
||||||
it('should check if active is defined and diferent from the new value', () => {
|
it('should check if active is defined and diferent from the new value', () => {
|
||||||
let controller = $componentController('vnDescriptor', {$scope: $scope});
|
|
||||||
controller.client = {id: 1};
|
controller.client = {id: 1};
|
||||||
|
|
||||||
expect(controller._active).toBe(undefined);
|
expect(controller._active).toBe(undefined);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
.descriptor-icon{
|
|
||||||
font-size:60px;
|
|
||||||
}
|
|
|
@ -10,8 +10,12 @@
|
||||||
<vn-vertical pad-large>
|
<vn-vertical pad-large>
|
||||||
<vn-title>Fiscal data</vn-title>
|
<vn-title>Fiscal data</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check vn-one label="Facturar" field="$ctrl.client.hasToInvoice"></vn-check>
|
<vn-one>
|
||||||
<vn-check vn-one label="Factura impresa" field="$ctrl.client.invoiceByEmail"></vn-check>
|
<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-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-two label="Domicilio fiscal" field="$ctrl.client.street" vn-focus></vn-textfield>
|
<vn-textfield vn-two label="Domicilio fiscal" field="$ctrl.client.street" vn-focus></vn-textfield>
|
||||||
|
@ -33,7 +37,7 @@
|
||||||
url="/client/api/Countries"
|
url="/client/api/Countries"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
label="País">
|
label="CountryFk">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
|
|
|
@ -3,6 +3,7 @@ import './index.js';
|
||||||
describe('Client', () => {
|
describe('Client', () => {
|
||||||
describe('Component vnClientIndex', () => {
|
describe('Component vnClientIndex', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -10,17 +11,15 @@ describe('Client', () => {
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
|
controller = $componentController('vnClientIndex');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define and set model property as an empty object', () => {
|
it('should define and set model property as an empty object', () => {
|
||||||
let controller = $componentController('vnClientIndex');
|
|
||||||
|
|
||||||
expect(controller.model).toEqual({});
|
expect(controller.model).toEqual({});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('search()', () => {
|
describe('search()', () => {
|
||||||
it(`should set model's search to the search input`, () => {
|
it(`should set model's search to the search input`, () => {
|
||||||
let controller = $componentController('vnClientIndex');
|
|
||||||
controller.model.search = 'batman';
|
controller.model.search = 'batman';
|
||||||
let index = {
|
let index = {
|
||||||
filter: {},
|
filter: {},
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
{
|
{
|
||||||
"Client": "Cliente",
|
"Client": "Cliente",
|
||||||
"Clients": "Clientes",
|
"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', () => {
|
describe('Component vnNoteCreate', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $state;
|
let $state;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -13,11 +14,10 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$state.params.id = '1234';
|
$state.params.id = '1234';
|
||||||
|
controller = $componentController('vnNoteCreate', {$state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define clientFk using $state.params.id', () => {
|
it('should define clientFk using $state.params.id', () => {
|
||||||
let controller = $componentController('vnNoteCreate', {$state: $state});
|
|
||||||
|
|
||||||
expect(controller.note.clientFk).toBe(1234);
|
expect(controller.note.clientFk).toBe(1234);
|
||||||
expect(controller.note.client).toBe(undefined);
|
expect(controller.note.client).toBe(undefined);
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ describe('Client', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $state;
|
let $state;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -14,11 +15,11 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
describe('$onChanges()', () => {
|
||||||
it(`should call getObservation() with the client id`, () => {
|
it(`should call getObservation() with the client id`, () => {
|
||||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
|
||||||
controller.client = {
|
controller.client = {
|
||||||
id: 1234
|
id: 1234
|
||||||
};
|
};
|
||||||
|
@ -31,19 +32,20 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('$getObservation()', () => {
|
describe('$getObservation()', () => {
|
||||||
it(`should request to GET the client notes`, () => {
|
it(`should request to GET the client notes`, () => {
|
||||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
let json = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
|
let jsonString = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
|
||||||
$httpBackend.when('GET', `/client/api/clientObservations?filter=${json}`).respond('ok');
|
let json = {data: 'some data'};
|
||||||
$httpBackend.expectGET(`/client/api/clientObservations?filter=${json}`, {Accept: 'application/json, text/plain, */*'});
|
$httpBackend.when('GET', `/client/api/clientObservations?filter=${jsonString}`).respond(json);
|
||||||
|
$httpBackend.expectGET(`/client/api/clientObservations?filter=${jsonString}`, {Accept: 'application/json, text/plain, */*'});
|
||||||
controller.getObservation();
|
controller.getObservation();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.observations).toEqual(json);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$newObservation()', () => {
|
describe('$newObservation()', () => {
|
||||||
it(`should redirect the user to the newObservation view`, () => {
|
it(`should redirect the user to the newObservation view`, () => {
|
||||||
let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
spyOn(controller.$state, 'go');
|
spyOn(controller.$state, 'go');
|
||||||
controller.newObservation();
|
controller.newObservation();
|
||||||
|
|
|
@ -4,6 +4,7 @@ describe('Client', () => {
|
||||||
describe('Component vnClientSearchPanel', () => {
|
describe('Component vnClientSearchPanel', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $window;
|
let $window;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -12,11 +13,11 @@ describe('Client', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$window_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$window_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$window = _$window_;
|
$window = _$window_;
|
||||||
|
controller = $componentController('vnClientSearchPanel', {$window: $window});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('onSearch()', () => {
|
describe('onSearch()', () => {
|
||||||
it(`should call setStorageValue() and onSubmit()`, () => {
|
it(`should call setStorageValue() and onSubmit()`, () => {
|
||||||
let controller = $componentController('vnClientSearchPanel', {$window: $window});
|
|
||||||
spyOn(controller, 'setStorageValue');
|
spyOn(controller, 'setStorageValue');
|
||||||
spyOn(controller, 'onSubmit');
|
spyOn(controller, 'onSubmit');
|
||||||
controller.setStorageValue();
|
controller.setStorageValue();
|
||||||
|
@ -29,8 +30,6 @@ describe('Client', () => {
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
describe('$onChanges()', () => {
|
||||||
it(`should set filter properties using the search values`, () => {
|
it(`should set filter properties using the search values`, () => {
|
||||||
let controller = $componentController('vnClientSearchPanel', {$window: $window});
|
|
||||||
|
|
||||||
expect(controller.filter).not.toBeDefined();
|
expect(controller.filter).not.toBeDefined();
|
||||||
spyOn(JSON, 'parse').and.returnValue({data: 'data'});
|
spyOn(JSON, 'parse').and.returnValue({data: 'data'});
|
||||||
controller.$onChanges();
|
controller.$onChanges();
|
||||||
|
|
|
@ -8,9 +8,15 @@
|
||||||
<form name="form" ng-submit="watcher.submit()" pad-medium>
|
<form name="form" ng-submit="watcher.submit()" pad-medium>
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<vn-vertical pad-large>
|
<vn-vertical pad-large>
|
||||||
|
<vn-one>
|
||||||
<vn-title>Web access</vn-title>
|
<vn-title>Web access</vn-title>
|
||||||
|
</vn-one>
|
||||||
|
<vn-one>
|
||||||
<vn-check label="Enable web access" field="$ctrl.account.active"></vn-check>
|
<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-textfield label="User" class="margin-medium-top" field="$ctrl.account.name" vn-focus></vn-textfield>
|
||||||
|
</vn-one>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
|
|
|
@ -5,6 +5,7 @@ describe('Component VnClientWebAccess', () => {
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
let $scope;
|
let $scope;
|
||||||
let vnApp;
|
let vnApp;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -16,11 +17,11 @@ describe('Component VnClientWebAccess', () => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
vnApp = _vnApp_;
|
vnApp = _vnApp_;
|
||||||
spyOn(vnApp, 'showError');
|
spyOn(vnApp, 'showError');
|
||||||
|
controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
describe('$onChanges()', () => {
|
||||||
it(`should pass client's account data to account then call isCustomer function`, () => {
|
it(`should pass client's account data to account then call isCustomer function`, () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
spyOn(controller, 'isCustomer');
|
spyOn(controller, 'isCustomer');
|
||||||
controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
|
controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
|
||||||
controller.account = {};
|
controller.account = {};
|
||||||
|
@ -33,7 +34,6 @@ describe('Component VnClientWebAccess', () => {
|
||||||
|
|
||||||
describe('isCustomer()', () => {
|
describe('isCustomer()', () => {
|
||||||
it(`should perform a query if client is defined with an ID`, () => {
|
it(`should perform a query if client is defined with an ID`, () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
controller.isCustomer();
|
controller.isCustomer();
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ describe('Component VnClientWebAccess', () => {
|
||||||
|
|
||||||
describe('onPassOpen()', () => {
|
describe('onPassOpen()', () => {
|
||||||
it('should set passwords to empty values', () => {
|
it('should set passwords to empty values', () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
controller.newPassword = 'm24x8';
|
controller.newPassword = 'm24x8';
|
||||||
controller.repeatPassword = 'm24x8';
|
controller.repeatPassword = 'm24x8';
|
||||||
controller.onPassOpen();
|
controller.onPassOpen();
|
||||||
|
@ -57,7 +56,6 @@ describe('Component VnClientWebAccess', () => {
|
||||||
|
|
||||||
describe('onPassChange()', () => {
|
describe('onPassChange()', () => {
|
||||||
it('should request to update the password', () => {
|
it('should request to update the password', () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
controller.newPassword = 'm24x8';
|
controller.newPassword = 'm24x8';
|
||||||
controller.repeatPassword = 'm24x8';
|
controller.repeatPassword = 'm24x8';
|
||||||
|
@ -70,7 +68,6 @@ describe('Component VnClientWebAccess', () => {
|
||||||
|
|
||||||
describe(`when password is empty`, () => {
|
describe(`when password is empty`, () => {
|
||||||
it(`should throw Passwords can't be empty error`, () => {
|
it(`should throw Passwords can't be empty error`, () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
controller.newPassword = '';
|
controller.newPassword = '';
|
||||||
controller.canChangePassword = true;
|
controller.canChangePassword = true;
|
||||||
|
@ -82,7 +79,6 @@ describe('Component VnClientWebAccess', () => {
|
||||||
|
|
||||||
describe(`when passwords don't match`, () => {
|
describe(`when passwords don't match`, () => {
|
||||||
it(`should throw Passwords don't match error`, () => {
|
it(`should throw Passwords don't match error`, () => {
|
||||||
let controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
|
||||||
controller.client = {id: '1234'};
|
controller.client = {id: '1234'};
|
||||||
controller.newPassword = 'm24x8';
|
controller.newPassword = 'm24x8';
|
||||||
controller.canChangePassword = true;
|
controller.canChangePassword = true;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
filter="true"
|
filter="true"
|
||||||
load-more="$ctrl.getItems()"
|
load-more="$ctrl.getItems()"
|
||||||
show-load-more="$ctrl.maxRow"
|
show-load-more="$ctrl.maxRow"
|
||||||
|
remove-load-more="$ctrl.removeLoadMore"
|
||||||
filter-action="$ctrl.findItems(search)"
|
filter-action="$ctrl.findItems(search)"
|
||||||
item-width="$ctrl.width"
|
item-width="$ctrl.width"
|
||||||
multiple="$ctrl.multiple"
|
multiple="$ctrl.multiple"
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import {module} from '../module';
|
import {module} from '../module';
|
||||||
import Component from '../lib/component';
|
import Component from '../lib/component';
|
||||||
|
import copyObject from '../lib/copy';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Autocomplete extends Component {
|
class Autocomplete extends Component {
|
||||||
constructor($element, $scope, $http, $timeout) {
|
constructor($element, $scope, $http, $timeout, $filter) {
|
||||||
super($element);
|
super($element);
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
|
this.$filter = $filter;
|
||||||
|
|
||||||
this._showDropDown = false;
|
this._showDropDown = false;
|
||||||
this.finding = false;
|
this.finding = false;
|
||||||
|
@ -19,10 +21,12 @@ class Autocomplete extends Component {
|
||||||
this.maxRow = 10;
|
this.maxRow = 10;
|
||||||
this.showField = this.showField || 'name';
|
this.showField = this.showField || 'name';
|
||||||
this.valueField = this.valueField || 'id';
|
this.valueField = this.valueField || 'id';
|
||||||
this.items = this.data || [];
|
this.order = this.order || 'name ASC';
|
||||||
|
this.items = copyObject(this.data) || [];
|
||||||
this.displayValueMultiCheck = [];
|
this.displayValueMultiCheck = [];
|
||||||
this._multiField = [];
|
this._multiField = [];
|
||||||
this.readonly = true;
|
this.readonly = true;
|
||||||
|
this.removeLoadMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get showDropDown() {
|
get showDropDown() {
|
||||||
|
@ -33,6 +37,10 @@ class Autocomplete extends Component {
|
||||||
this._preLoad = true;
|
this._preLoad = true;
|
||||||
this.getItems();
|
this.getItems();
|
||||||
}
|
}
|
||||||
|
if (value && !this.width) {
|
||||||
|
let rectangle = this.$element[0].getBoundingClientRect();
|
||||||
|
this.width = Math.round(rectangle.width) - 10;
|
||||||
|
}
|
||||||
this._showDropDown = value;
|
this._showDropDown = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +78,7 @@ class Autocomplete extends Component {
|
||||||
return this.multiple ? this._multiField : this._field;
|
return this.multiple ? this._multiField : this._field;
|
||||||
}
|
}
|
||||||
set field(value) {
|
set field(value) {
|
||||||
|
if (!angular.equals(value, this.field)) {
|
||||||
this.finding = true;
|
this.finding = true;
|
||||||
if (value && value.hasOwnProperty(this.valueField)) {
|
if (value && value.hasOwnProperty(this.valueField)) {
|
||||||
this._field = value[this.valueField];
|
this._field = value[this.valueField];
|
||||||
|
@ -88,10 +97,17 @@ class Autocomplete extends Component {
|
||||||
if (this.onChange)
|
if (this.onChange)
|
||||||
this.onChange({item: this._field});
|
this.onChange({item: this._field});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
set initialData(value) {
|
set initialData(value) {
|
||||||
if (value) {
|
if (value && value.hasOwnProperty(this.valueField)) {
|
||||||
this.field = value;
|
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) {
|
findItems(search) {
|
||||||
if (!this.url)
|
if (this.url && search && !this.finding) {
|
||||||
return this.items ? this.items : [];
|
|
||||||
|
|
||||||
if (search && !this.finding) {
|
|
||||||
this.maxRow = false;
|
this.maxRow = false;
|
||||||
let filter = {where: {name: {regexp: search}}};
|
let filter = {where: {name: {regexp: search}}};
|
||||||
|
if (this.filter && this.filter.where) {
|
||||||
|
Object.assign(filter.where, this.filter.where);
|
||||||
|
}
|
||||||
let json = JSON.stringify(filter);
|
let json = JSON.stringify(filter);
|
||||||
this.finding = true;
|
this.finding = true;
|
||||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||||
|
@ -198,29 +214,42 @@ class Autocomplete extends Component {
|
||||||
this.finding = false;
|
this.finding = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else if (search && !this.url && this.data) {
|
||||||
|
this.items = this.$filter('filter')(this.data, search);
|
||||||
} else if (!search && !this.finding) {
|
} else if (!search && !this.finding) {
|
||||||
this.maxRow = 10;
|
this.maxRow = 10;
|
||||||
this.items = [];
|
this.items = [];
|
||||||
this.getItems();
|
this.getItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getItems() {
|
getItems() {
|
||||||
|
if (this.url === undefined) {
|
||||||
|
this.items = copyObject(this.data);
|
||||||
|
this.maxRow = false;
|
||||||
|
this.removeLoadMore = true;
|
||||||
|
} else {
|
||||||
let filter = {};
|
let filter = {};
|
||||||
|
if (!this.finding) {
|
||||||
|
this.finding = true;
|
||||||
|
|
||||||
if (this.maxRow) {
|
if (this.maxRow) {
|
||||||
if (this.items) {
|
if (this.items) {
|
||||||
filter.skip = this.items.length;
|
filter.skip = this.items.length;
|
||||||
}
|
}
|
||||||
filter.limit = this.maxRow;
|
filter.limit = this.maxRow;
|
||||||
filter.order = 'name ASC';
|
filter.order = this.order;
|
||||||
|
}
|
||||||
|
if (this.filter) {
|
||||||
|
Object.assign(filter, this.filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
let json = JSON.stringify(filter);
|
let json = JSON.stringify(filter);
|
||||||
|
|
||||||
|
this.removeLoadMore = false;
|
||||||
|
|
||||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||||
json => {
|
json => {
|
||||||
if (json.data.length)
|
if (json.data.length) {
|
||||||
json.data.forEach(
|
json.data.forEach(
|
||||||
el => {
|
el => {
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
|
@ -229,12 +258,21 @@ class Autocomplete extends Component {
|
||||||
this.items.push(el);
|
this.items.push(el);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
else
|
if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) {
|
||||||
|
this.removeLoadMore = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.maxRow = false;
|
this.maxRow = false;
|
||||||
}
|
}
|
||||||
|
this.finding = false;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.finding = false;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
$onInit() {
|
$onInit() {
|
||||||
this.findMore = this.url && this.maxRow;
|
this.findMore = this.url && this.maxRow;
|
||||||
this.mouseFocus = false;
|
this.mouseFocus = false;
|
||||||
|
@ -265,9 +303,6 @@ class Autocomplete extends Component {
|
||||||
this.showDropDown = this.mouseFocus;
|
this.showDropDown = this.mouseFocus;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let rectangle = this.$element[0].getBoundingClientRect();
|
|
||||||
this.width = Math.round(rectangle.width) - 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
|
@ -277,9 +312,17 @@ class Autocomplete extends Component {
|
||||||
this.$element.unbind('focusout');
|
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', {
|
module.component('vnAutocomplete', {
|
||||||
template: require('./autocomplete.html'),
|
template: require('./autocomplete.html'),
|
||||||
|
@ -292,11 +335,11 @@ module.component('vnAutocomplete', {
|
||||||
initialData: '<?',
|
initialData: '<?',
|
||||||
onChange: '&?',
|
onChange: '&?',
|
||||||
data: '<?',
|
data: '<?',
|
||||||
itemAs: '@?',
|
|
||||||
field: '=',
|
field: '=',
|
||||||
label: '@',
|
label: '@',
|
||||||
itemTemplate: '@?',
|
multiple: '@?',
|
||||||
multiple: '@?'
|
order: '@?',
|
||||||
|
filter: '<?'
|
||||||
},
|
},
|
||||||
transclude: {
|
transclude: {
|
||||||
tplItem: '?tplItem'
|
tplItem: '?tplItem'
|
||||||
|
|
|
@ -6,6 +6,7 @@ describe('Component vnAutocomplete', () => {
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
let $timeout;
|
let $timeout;
|
||||||
let $element;
|
let $element;
|
||||||
|
let controller;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
|
@ -17,11 +18,11 @@ describe('Component vnAutocomplete', () => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$timeout = _$timeout_;
|
$timeout = _$timeout_;
|
||||||
$element = angular.element('<div></div>');
|
$element = angular.element('<div></div>');
|
||||||
|
controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('showDropDown() setter', () => {
|
describe('showDropDown() setter', () => {
|
||||||
it(`should set _showDropDown value`, () => {
|
it(`should set _showDropDown value`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
controller._showDropDown = '';
|
controller._showDropDown = '';
|
||||||
controller.showDropDown = 'some value';
|
controller.showDropDown = 'some value';
|
||||||
|
|
||||||
|
@ -29,7 +30,6 @@ describe('Component vnAutocomplete', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should set _showDropDown value`, () => {
|
it(`should set _showDropDown value`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
controller._showDropDown = '';
|
controller._showDropDown = '';
|
||||||
controller.showDropDown = 'some value';
|
controller.showDropDown = 'some value';
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ describe('Component vnAutocomplete', () => {
|
||||||
|
|
||||||
describe('displayValue() setter', () => {
|
describe('displayValue() setter', () => {
|
||||||
it(`should display value in a formated way`, () => {
|
it(`should display value in a formated way`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
let value = 'some value';
|
let value = 'some value';
|
||||||
controller.displayValue = value;
|
controller.displayValue = value;
|
||||||
|
|
||||||
|
@ -48,7 +47,6 @@ describe('Component vnAutocomplete', () => {
|
||||||
|
|
||||||
describe('when the autocomeplete is multiple', () => {
|
describe('when the autocomeplete is multiple', () => {
|
||||||
it(`should display values separated with commas`, () => {
|
it(`should display values separated with commas`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
controller.multiple = true;
|
controller.multiple = true;
|
||||||
controller.displayValue = 'some value';
|
controller.displayValue = 'some value';
|
||||||
controller.displayValue = 'another value';
|
controller.displayValue = 'another value';
|
||||||
|
@ -61,14 +59,12 @@ describe('Component vnAutocomplete', () => {
|
||||||
describe('field() setter', () => {
|
describe('field() setter', () => {
|
||||||
describe('when value is an object', () => {
|
describe('when value is an object', () => {
|
||||||
it(`should set _field controllers property`, () => {
|
it(`should set _field controllers property`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
controller.field = {id: 1, name: 'Bruce Wayne'};
|
||||||
|
|
||||||
expect(controller._field).toEqual(1);
|
expect(controller._field).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should set _multifield controllers property `, () => {
|
it(`should set _multifield controllers property `, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
|
||||||
controller.multiple = true;
|
controller.multiple = true;
|
||||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
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`, () => {
|
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.multiple = true;
|
||||||
controller.field = {id: 1, name: 'Bruce Wayne'};
|
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`, () => {
|
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.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||||
controller.field = {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', () => {
|
describe('when value is a number', () => {
|
||||||
it(`should set _field controller property finding an existing item in the controller.items property`, () => {
|
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.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
|
||||||
controller.field = 2;
|
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`, () => {
|
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.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
|
||||||
controller.multiple = true;
|
controller.multiple = true;
|
||||||
controller.field = 2;
|
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`, () => {
|
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.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}}');
|
$httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
|
||||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
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`, () => {
|
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.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||||
controller.field = 2;
|
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`, () => {
|
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.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}}');
|
$httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
|
||||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||||
|
@ -154,25 +145,10 @@ describe('Component vnAutocomplete', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findItem()', () => {
|
describe('findItems()', () => {
|
||||||
it(`should return items array if the controller does not provide a url and nither it has items`, () => {
|
it(`should perform a search and store the result in controller items`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||||
controller.items = ['Batman', 'Bruce Wayne'];
|
controller.url = 'test.com';
|
||||||
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'});
|
|
||||||
let search = 'The Joker';
|
let search = 'The Joker';
|
||||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
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'}]);
|
||||||
|
@ -183,18 +159,37 @@ describe('Component vnAutocomplete', () => {
|
||||||
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
|
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`, () => {
|
it(`should perform a search with multiple true and store the result in controller items with the checked property defined`, () => {
|
||||||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
|
controller.url = 'test.com';
|
||||||
let search = 'The Joker';
|
let search = 'Joker';
|
||||||
|
controller.multiple = true;
|
||||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
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}`);
|
$httpBackend.expectGET(`test.com?filter=${json}`);
|
||||||
controller.findItems(search);
|
controller.findItems(search);
|
||||||
$httpBackend.flush();
|
$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 resolveFactory from '../lib/resolveDefaultComponents';
|
||||||
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
|
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
|
||||||
import * as util from '../lib/util';
|
import * as util from '../lib/util';
|
||||||
|
import './style.css';
|
||||||
|
|
||||||
const _NAME = 'check';
|
const _NAME = 'check';
|
||||||
export const NAME = util.getName(_NAME);
|
export const NAME = util.getName(_NAME);
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
vn-check {
|
||||||
|
float: left;
|
||||||
|
}
|
|
@ -21,6 +21,12 @@ export default class ColumnHeader {
|
||||||
}
|
}
|
||||||
return showArrow;
|
return showArrow;
|
||||||
}
|
}
|
||||||
|
$onInit() {
|
||||||
|
if (this.defaultOrder) {
|
||||||
|
this.order = this.defaultOrder;
|
||||||
|
this.onClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ColumnHeader.$inject = [];
|
ColumnHeader.$inject = [];
|
||||||
|
|
||||||
|
@ -29,7 +35,8 @@ module.component('vnColumnHeader', {
|
||||||
bindings: {
|
bindings: {
|
||||||
field: '@?',
|
field: '@?',
|
||||||
text: '@?',
|
text: '@?',
|
||||||
className: '@?'
|
className: '@?',
|
||||||
|
defaultOrder: '@?'
|
||||||
},
|
},
|
||||||
require: {
|
require: {
|
||||||
gridHeader: '^^vnGridHeader'
|
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 SUBMIT_MDL, factory as submitMdl} from './submit/submit.mdl';
|
||||||
export {NAME as COMBO, directive as ComboDirective} from './combo/combo';
|
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 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, directive as CardDirective} from './card/card';
|
||||||
export {NAME as CARD_MDL, factory as cardMdl} from './card/card.mdl';
|
export {NAME as CARD_MDL, factory as cardMdl} from './card/card.mdl';
|
||||||
export {NAME as SWITCH, directive as SwitchDirective} from './switch/switch';
|
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"
|
<input type="text"
|
||||||
class="mdl-textfield__input"
|
class="mdl-textfield__input"
|
||||||
name="{{::$ctrl.name}}"
|
name="{{::$ctrl.name}}"
|
||||||
ng-model="$ctrl.modelView"
|
ng-model="$ctrl.modelView"
|
||||||
ng-disabled="{{!$ctrl.enabled}}"
|
ng-disabled="{{!$ctrl.enabled}}"
|
||||||
rule="{{::$ctrl.rule}}"/>
|
rule="{{::$ctrl.rule}}"/>
|
||||||
<button
|
|
||||||
type="button"
|
<div class="mdl-chip__action">
|
||||||
class="mdl-chip__action ng-hide"
|
<i class="material-icons" ng-if="$ctrl.isTimePicker" ng-click="$ctrl.vp.open()">query_builder</i>
|
||||||
tabindex="-1"
|
<i class="material-icons pointer" ng-show="$ctrl.modelView&&($ctrl.hasFocus||$ctrl.hasMouseIn)" ng-click="$ctrl.onClear()">clear</i>
|
||||||
translate-attr="{title: 'Clear'}"
|
</div>
|
||||||
ng-show="$ctrl.modelView"
|
<label class="mdl-textfield__label" translate>{{$ctrl.label}}</label>
|
||||||
ng-click="$ctrl.onClear()"
|
|
||||||
>
|
|
||||||
<i class="material-icons">clear</i>
|
|
||||||
</button>
|
|
||||||
<label class="mdl-textfield__label">{{::$ctrl.label | translate}}</label>
|
|
||||||
</div>
|
</div>
|
|
@ -27,7 +27,9 @@ class DatePicker extends Component {
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
this._modelView = null;
|
this._modelView = null;
|
||||||
this._model = undefined;
|
this._model = undefined;
|
||||||
|
this._optionsChecked = false;
|
||||||
|
this.hasFocus = false;
|
||||||
|
this.hasMouseIn = false;
|
||||||
componentHandler.upgradeElement($element[0].firstChild);
|
componentHandler.upgradeElement($element[0].firstChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +39,9 @@ class DatePicker extends Component {
|
||||||
set model(value) {
|
set model(value) {
|
||||||
this._model = value;
|
this._model = value;
|
||||||
if (value && !this.modelView) {
|
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);
|
this.modelView = this.$filter('date')(value, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,8 +52,7 @@ class DatePicker extends Component {
|
||||||
this._modelView = value;
|
this._modelView = value;
|
||||||
this.input.value = value;
|
this.input.value = value;
|
||||||
this._setModel(value);
|
this._setModel(value);
|
||||||
this.$timeout(
|
this.$timeout(() => {
|
||||||
() => {
|
|
||||||
this.mdlUpdate();
|
this.mdlUpdate();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
@ -76,16 +79,15 @@ class DatePicker extends Component {
|
||||||
return `${dates} ${hours}`.trim();
|
return `${dates} ${hours}`.trim();
|
||||||
} else if (string.indexOf(':') !== -1) { // only time format
|
} else if (string.indexOf(':') !== -1) { // only time format
|
||||||
return parts.join(':');
|
return parts.join(':');
|
||||||
} else { // only date format
|
} // only date format
|
||||||
return parts.join('-');
|
return parts.join('-');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_setModel(value) {
|
_setModel(value) {
|
||||||
let model;
|
let model;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
model = undefined;
|
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;
|
model = value;
|
||||||
} else {
|
} else {
|
||||||
let formats = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/);
|
let formats = this.iniOptions.dateFormat.split(/[ZT.,/ :-]/);
|
||||||
|
@ -136,9 +138,12 @@ class DatePicker extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
_getOptions() {
|
||||||
if (!this.iniOptions)
|
if (this.iniOptions && this._optionsChecked) {
|
||||||
|
return this.iniOptions;
|
||||||
|
} else if (!this.iniOptions) {
|
||||||
this.iniOptions = {};
|
this.iniOptions = {};
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.iniOptions.locale)
|
if (!this.iniOptions.locale)
|
||||||
this.iniOptions.locale = this.$translate.use();
|
this.iniOptions.locale = this.$translate.use();
|
||||||
|
@ -158,8 +163,13 @@ class DatePicker extends Component {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this._optionsChecked = true;
|
||||||
|
return this.iniOptions;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.input)
|
$onInit() {
|
||||||
|
this.iniOptions = this._getOptions();
|
||||||
|
this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar);
|
||||||
this.vp = new Flatpickr(this.input, this.iniOptions);
|
this.vp = new Flatpickr(this.input, this.iniOptions);
|
||||||
}
|
}
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
|
|
|
@ -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,6 +1,10 @@
|
||||||
vn-date-picker {
|
vn-date-picker {
|
||||||
|
div {
|
||||||
|
outline: none; //remove chrome outline
|
||||||
|
}
|
||||||
.mdl-chip__action {
|
.mdl-chip__action {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
width: auto;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
right: -6px;
|
right: -6px;
|
||||||
margin: 22px 0px;
|
margin: 22px 0px;
|
||||||
|
@ -8,5 +12,7 @@ vn-date-picker {
|
||||||
}
|
}
|
||||||
.material-icons {
|
.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);
|
super($element);
|
||||||
$element.addClass('vn-dialog');
|
$element.addClass('vn-dialog');
|
||||||
this.dialog = $element[0].firstChild;
|
this.dialog = $element[0].firstChild;
|
||||||
this.element.addEventListener('mousedown',
|
this.element.addEventListener('mousedown', event => this.onBackgroundMouseDown(event));
|
||||||
event => this.onBackgroundMouseDown(event));
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Displays the dialog to the user.
|
* Displays the dialog to the user.
|
||||||
*/
|
*/
|
||||||
show() {
|
show() {
|
||||||
let style = this.dialog.style;
|
let style = this.dialog.style;
|
||||||
let screenMargin = 20;
|
|
||||||
|
|
||||||
let window = this.window;
|
let window = this.window;
|
||||||
let innerWidth = window.innerWidth;
|
let innerWidth = window.innerWidth;
|
||||||
let innerHeight = window.innerHeight;
|
let innerHeight = window.innerHeight;
|
||||||
let width = this.dialog.offsetWidth;
|
let width = this.dialog.offsetWidth;
|
||||||
let height = this.dialog.offsetHeight;
|
let height = this.dialog.offsetHeight;
|
||||||
|
let screenMargin = 20;
|
||||||
|
let dblMargin = screenMargin * 2;
|
||||||
|
|
||||||
if (width + screenMargin > innerWidth) {
|
if (width + screenMargin > innerWidth) {
|
||||||
width = innerWidth - dblMargin;
|
width = innerWidth - dblMargin;
|
||||||
|
@ -38,10 +37,8 @@ export default class Dialog extends Component {
|
||||||
style.height = height + 'px';
|
style.height = height + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.keypressHandler =
|
this.keypressHandler = event => this.onKeypress(event);
|
||||||
event => this.onKeypress(event);
|
this.document.addEventListener('keypress', this.keypressHandler);
|
||||||
this.document.addEventListener('keypress',
|
|
||||||
this.keypressHandler);
|
|
||||||
this.element.style.display = 'block';
|
this.element.style.display = 'block';
|
||||||
|
|
||||||
if (this.onOpen)
|
if (this.onOpen)
|
||||||
|
@ -66,17 +63,17 @@ export default class Dialog extends Component {
|
||||||
cancel = this.onResponse({response: response});
|
cancel = this.onResponse({response: response});
|
||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
realHide() {
|
realHide() {
|
||||||
this.element.style.display = 'none';
|
this.element.style.display = 'none';
|
||||||
this.document.removeEventListener('keypress',
|
this.document.removeEventListener('keypress', this.keypressHandler);
|
||||||
this.keypressHandler);
|
|
||||||
this.lastEvent = null;
|
this.lastEvent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onButtonClick(event) {
|
onButtonClick(event) {
|
||||||
let buttonBar = this.element.querySelector('.button-bar');
|
let buttonBar = this.element.querySelector('.button-bar');
|
||||||
let buttons = buttonBar.querySelector('tpl-buttons');
|
let buttons = buttonBar.querySelector('tpl-buttons');
|
||||||
let node = event.target;
|
let node = event.target;
|
||||||
|
|
||||||
while (node.parentNode != buttons) {
|
while (node.parentNode != buttons) {
|
||||||
if (node == buttonBar) return;
|
if (node == buttonBar) return;
|
||||||
node = node.parentNode;
|
node = node.parentNode;
|
||||||
|
@ -86,13 +83,16 @@ export default class Dialog extends Component {
|
||||||
let cancel = this.fireResponse(response);
|
let cancel = this.fireResponse(response);
|
||||||
if (cancel !== false) this.realHide();
|
if (cancel !== false) this.realHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDialogMouseDown(event) {
|
onDialogMouseDown(event) {
|
||||||
this.lastEvent = event;
|
this.lastEvent = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackgroundMouseDown(event) {
|
onBackgroundMouseDown(event) {
|
||||||
if (event != this.lastEvent)
|
if (event != this.lastEvent)
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeypress(event) {
|
onKeypress(event) {
|
||||||
if (event.keyCode == 27) // Esc
|
if (event.keyCode == 27) // Esc
|
||||||
this.hide();
|
this.hide();
|
||||||
|
@ -107,8 +107,8 @@ module.component('vnDialog', {
|
||||||
tplButtons: 'tplButtons'
|
tplButtons: 'tplButtons'
|
||||||
},
|
},
|
||||||
bindings: {
|
bindings: {
|
||||||
onOpen: '&',
|
onOpen: '&?',
|
||||||
onResponse: '&'
|
onResponse: '&?'
|
||||||
},
|
},
|
||||||
controller: Dialog
|
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(() => {
|
$timeout(() => {
|
||||||
input.setAttribute("disabled", "true");
|
input.setAttribute("disabled", "true");
|
||||||
});
|
});
|
||||||
$element[0].querySelectorAll('i, vn-drop-down').forEach(i => {
|
$element[0].querySelectorAll('i, vn-drop-down').forEach(element => {
|
||||||
i.parentNode.removeChild(i);
|
element.parentNode.removeChild(element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,7 +11,8 @@ export function directive() {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
link: function($scope, $element, $attrs) {
|
link: function($scope, $element, $attrs) {
|
||||||
$element.on('click', function(event) {
|
$element.on('click', function(event) {
|
||||||
let dialog = $scope[kebabToCamel($attrs.vnDialog)];
|
let dialogKey = kebabToCamel($attrs.vnDialog);
|
||||||
|
let dialog = $scope[dialogKey];
|
||||||
if (dialog instanceof Dialog)
|
if (dialog instanceof Dialog)
|
||||||
dialog.show();
|
dialog.show();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -2,6 +2,8 @@ import {module} from '../module';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the focus and selects the text on the input.
|
* Sets the focus and selects the text on the input.
|
||||||
|
*
|
||||||
|
* @return {Object} The directive
|
||||||
*/
|
*/
|
||||||
export function directive() {
|
export function directive() {
|
||||||
return {
|
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">
|
<input type="checkbox" ng-checked="item.checked" ng-if="$ctrl.multiple">
|
||||||
<div ng-transclude="vnItem">{{item.name}}</div>
|
<div ng-transclude="vnItem">{{item.name}}</div>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
|
@ -16,6 +16,7 @@ export default class DropDown {
|
||||||
get show() {
|
get show() {
|
||||||
return this._show;
|
return this._show;
|
||||||
}
|
}
|
||||||
|
|
||||||
set show(value) {
|
set show(value) {
|
||||||
let oldValue = this.show;
|
let oldValue = this.show;
|
||||||
this._show = value;
|
this._show = value;
|
||||||
|
@ -28,11 +29,13 @@ export default class DropDown {
|
||||||
}, 250);
|
}, 250);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get search() {
|
get search() {
|
||||||
return this._search;
|
return this._search;
|
||||||
}
|
}
|
||||||
|
|
||||||
set search(value) {
|
set search(value) {
|
||||||
let val = (value === undefined && value === '') ? null : value;
|
let val = (value === undefined || value === '') ? null : value;
|
||||||
this._search = val;
|
this._search = val;
|
||||||
|
|
||||||
if (this.filterAction)
|
if (this.filterAction)
|
||||||
|
@ -40,9 +43,11 @@ export default class DropDown {
|
||||||
else
|
else
|
||||||
this.filterItems();
|
this.filterItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
get activeOption() {
|
get activeOption() {
|
||||||
return this._activeOption;
|
return this._activeOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
set activeOption(value) {
|
set activeOption(value) {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
value = 0;
|
value = 0;
|
||||||
|
@ -51,6 +56,10 @@ export default class DropDown {
|
||||||
}
|
}
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
this._activeOption = value;
|
this._activeOption = value;
|
||||||
|
// AutoLoad items with "scroll" (1st version):
|
||||||
|
if (value && value >= this.items.length - 3 && !this.removeLoadMore) {
|
||||||
|
this.loadItems();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +68,10 @@ export default class DropDown {
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterRest() {
|
onFilterRest() {
|
||||||
|
if (this.filterAction) {
|
||||||
this.filterAction({search: this.search});
|
this.filterAction({search: this.search});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$onChanges(changesObj) {
|
$onChanges(changesObj) {
|
||||||
if (changesObj.show && changesObj.top && changesObj.top.currentValue) {
|
if (changesObj.show && changesObj.top && changesObj.top.currentValue) {
|
||||||
|
@ -117,6 +128,7 @@ export default class DropDown {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setScrollPosition() {
|
setScrollPosition() {
|
||||||
let dropdown = this.$element[0].querySelector('ul.dropdown');
|
let dropdown = this.$element[0].querySelector('ul.dropdown');
|
||||||
let child = dropdown ? dropdown.childNodes[this.activeOption] : null;
|
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() {
|
$onInit() {
|
||||||
if (this.parent)
|
if (this.parent)
|
||||||
this.parent.addEventListener('keydown', e => this.onKeydown(e));
|
this.parent.addEventListener('keydown', e => this.onKeydown(e));
|
||||||
|
@ -144,6 +163,7 @@ export default class DropDown {
|
||||||
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
|
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDown.$inject = ['$element', '$filter', '$timeout'];
|
DropDown.$inject = ['$element', '$filter', '$timeout'];
|
||||||
|
|
||||||
module.component('vnDropDown', {
|
module.component('vnDropDown', {
|
||||||
|
@ -156,8 +176,9 @@ module.component('vnDropDown', {
|
||||||
selected: '=',
|
selected: '=',
|
||||||
search: '=?',
|
search: '=?',
|
||||||
loadMore: '&?',
|
loadMore: '&?',
|
||||||
|
removeLoadMore: '<?',
|
||||||
filterAction: '&?',
|
filterAction: '&?',
|
||||||
showLoadMore: '=?',
|
showLoadMore: '<?',
|
||||||
top: '<?',
|
top: '<?',
|
||||||
itemWidth: '<?',
|
itemWidth: '<?',
|
||||||
parent: '<?',
|
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);
|
color: rgb(255,171,64);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
&.dropdown__loadMore.noMore{
|
||||||
|
color:#424242;
|
||||||
|
font-weight: 700;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
input[type=checkbox]{
|
input[type=checkbox]{
|
||||||
float: left;
|
float: left;
|
||||||
margin: 5px 5px 0 0;
|
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">
|
<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">
|
<div ng-if="!$ctrl.findMore">
|
||||||
<vn-drop-down
|
<vn-drop-down
|
||||||
items="$ctrl.items"
|
items="$ctrl.items"
|
||||||
|
|
|
@ -11,12 +11,15 @@ export default class IconMenu {
|
||||||
this.findMore = false;
|
this.findMore = false;
|
||||||
this.element = $element[0];
|
this.element = $element[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
get showDropDown() {
|
get showDropDown() {
|
||||||
return this._showDropDown;
|
return this._showDropDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
set showDropDown(value) {
|
set showDropDown(value) {
|
||||||
this._showDropDown = value;
|
this._showDropDown = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
findItems(search) {
|
findItems(search) {
|
||||||
if (!this.url)
|
if (!this.url)
|
||||||
return this.items ? this.items : [];
|
return this.items ? this.items : [];
|
||||||
|
@ -40,6 +43,7 @@ export default class IconMenu {
|
||||||
this.getItems();
|
this.getItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getItems() {
|
getItems() {
|
||||||
let filter = {};
|
let filter = {};
|
||||||
|
|
||||||
|
@ -66,6 +70,7 @@ export default class IconMenu {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
if (!this.items && this.url) {
|
if (!this.items && this.url) {
|
||||||
this.items = [];
|
this.items = [];
|
||||||
|
@ -104,6 +109,7 @@ export default class IconMenu {
|
||||||
this.$element.unbind('focusout');
|
this.$element.unbind('focusout');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IconMenu.$inject = ['$element', '$http', '$timeout'];
|
IconMenu.$inject = ['$element', '$http', '$timeout'];
|
||||||
|
|
||||||
module.component('vnIconMenu', {
|
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{
|
vn-icon-menu{
|
||||||
position: relative;
|
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'];
|
aclService.$inject = ['aclConstant'];
|
||||||
function aclService(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';
|
import {module} from '../module';
|
||||||
|
|
||||||
const isEqual = angular.equals;
|
const isEqual = angular.equals;
|
||||||
|
|
||||||
export default isEqual;
|
export default isEqual;
|
||||||
|
|
||||||
export const NAME = 'equalsObject';
|
export const NAME = 'equalsObject';
|
||||||
|
|
|
@ -4,6 +4,7 @@ import './template';
|
||||||
import './getTemplate';
|
import './getTemplate';
|
||||||
import './app';
|
import './app';
|
||||||
import './interceptor';
|
import './interceptor';
|
||||||
|
import './aclService';
|
||||||
|
|
||||||
export * from './util';
|
export * from './util';
|
||||||
export {default as splitingRegister} from './splitingRegister';
|
export {default as splitingRegister} from './splitingRegister';
|
||||||
|
|
|
@ -5,7 +5,7 @@ export default function getModifiedData(object, objectOld) {
|
||||||
var newObject = {};
|
var newObject = {};
|
||||||
for (var k in object) {
|
for (var k in object) {
|
||||||
var val = object[k];
|
var val = object[k];
|
||||||
var valOld = objectOld[k];
|
var valOld = objectOld[k] === undefined ? null : objectOld[k];
|
||||||
|
|
||||||
if (!isEqual(val, valOld)) {
|
if (!isEqual(val, valOld)) {
|
||||||
if (val instanceof Object) {
|
if (val instanceof Object) {
|
||||||
|
|
|
@ -6,5 +6,6 @@
|
||||||
"Save": "Guardar",
|
"Save": "Guardar",
|
||||||
"Add": "Añadir",
|
"Add": "Añadir",
|
||||||
"Search": "Buscar",
|
"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-one>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-none class="primaryCheckbox" ng-if="$ctrl.checkAll===0">
|
<vn-none class="primaryCheckbox" ng-if="$ctrl.checkAll===0">
|
||||||
|
|
|
@ -2,58 +2,28 @@ import {module} from '../module';
|
||||||
import './multi-check.scss';
|
import './multi-check.scss';
|
||||||
/**
|
/**
|
||||||
* Draw checkbox with a drop-down and multi options
|
* 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} options List of options shown in drop-down
|
||||||
* @param {Array} models Elements to check / unCheck
|
* @param {Array} models Elements to check / unCheck
|
||||||
* @param {String} className Optional css class name
|
* @param {String} className Optional css class name
|
||||||
*/
|
*/
|
||||||
export default class MultiCheck {
|
export default class MultiCheck {
|
||||||
constructor() {
|
constructor($timeout) {
|
||||||
|
this.$timeout = $timeout;
|
||||||
this._checkAll = 0;
|
this._checkAll = 0;
|
||||||
this._models = [];
|
this._models = [];
|
||||||
this.type = {};
|
this._type = {};
|
||||||
this.showDropDown = false;
|
this.showDropDown = false;
|
||||||
}
|
}
|
||||||
get models() {
|
|
||||||
return this._models;
|
get type() {
|
||||||
|
return this._type;
|
||||||
}
|
}
|
||||||
set models(value) {
|
|
||||||
this._models = value;
|
set type(value) {
|
||||||
}
|
if (value && value.id) {
|
||||||
get checkAll() {
|
this._type = value;
|
||||||
return this._checkAll;
|
switch (value.id) {
|
||||||
}
|
|
||||||
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) {
|
|
||||||
case 'all':
|
case 'all':
|
||||||
this.checkAll = 1;
|
this.checkAll = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -64,11 +34,64 @@ export default class MultiCheck {
|
||||||
this.checkAll = 2;
|
this.checkAll = 2;
|
||||||
break;
|
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', {
|
module.component('vnMultiCheck', {
|
||||||
template: require('./multi-check.html'),
|
template: require('./multi-check.html'),
|
||||||
|
@ -76,7 +99,7 @@ module.component('vnMultiCheck', {
|
||||||
bindings: {
|
bindings: {
|
||||||
checkAll: '=',
|
checkAll: '=',
|
||||||
options: '<',
|
options: '<',
|
||||||
models: '=',
|
models: '<',
|
||||||
className: '@?'
|
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
|
<paging
|
||||||
page="$ctrl.currentPage"
|
page="$ctrl.currentPage"
|
||||||
page-size="$ctrl.numPerPage"
|
page-size="$ctrl.numPerPage"
|
||||||
|
ng-if="$ctrl.numPages>1"
|
||||||
total="$ctrl.numItems"
|
total="$ctrl.numItems"
|
||||||
show-prev-next="true"
|
show-prev-next="true"
|
||||||
show-first-last="false"
|
show-first-last="false"
|
||||||
|
|
|
@ -5,6 +5,7 @@ export default class Paging {
|
||||||
get numPages() {
|
get numPages() {
|
||||||
return Math.ceil(this.numItems / this.numPerPage);
|
return Math.ceil(this.numItems / this.numPerPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor($http, $scope) {
|
constructor($http, $scope) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
|
@ -13,6 +14,7 @@ export default class Paging {
|
||||||
this.numItems = 0;
|
this.numItems = 0;
|
||||||
$scope.$watch('$ctrl.index.model.length', () => this.onModelUpdated());
|
$scope.$watch('$ctrl.index.model.length', () => this.onModelUpdated());
|
||||||
}
|
}
|
||||||
|
|
||||||
$onChanges(changes) {
|
$onChanges(changes) {
|
||||||
if (!this.index) return;
|
if (!this.index) return;
|
||||||
this.numPerPage = this.index.filter.size;
|
this.numPerPage = this.index.filter.size;
|
||||||
|
@ -20,14 +22,15 @@ export default class Paging {
|
||||||
if (changes.total)
|
if (changes.total)
|
||||||
this.numItems = changes.total.currentValue;
|
this.numItems = changes.total.currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
onModelUpdated() {
|
onModelUpdated() {
|
||||||
let index = this.index;
|
let index = this.index;
|
||||||
let filter = index.filter;
|
let filter = index.filter;
|
||||||
|
|
||||||
if (filter.page >= this.numPages
|
if (filter.page >= this.numPages && index.model.length >= this.numPerPage)
|
||||||
&& index.model.length >= this.numPerPage)
|
|
||||||
this.numItems = filter.page * filter.size + 1;
|
this.numItems = filter.page * filter.size + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageChange(page) {
|
onPageChange(page) {
|
||||||
this.index.filter.page = page;
|
this.index.filter.page = page;
|
||||||
if (typeof this.pageChange === 'undefined') {
|
if (typeof this.pageChange === 'undefined') {
|
||||||
|
@ -37,6 +40,7 @@ export default class Paging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Paging.$inject = ['$http', '$scope'];
|
Paging.$inject = ['$http', '$scope'];
|
||||||
|
|
||||||
export const NAME = 'vnPaging';
|
export const NAME = 'vnPaging';
|
||||||
|
@ -49,4 +53,5 @@ export const COMPONENT = {
|
||||||
},
|
},
|
||||||
controller: Paging
|
controller: Paging
|
||||||
};
|
};
|
||||||
|
|
||||||
module.component(NAME, COMPONENT);
|
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);
|
module.directive('vnPopover', directive);
|
||||||
|
|
||||||
export class Popover {
|
export class Popover {
|
||||||
|
@ -69,6 +70,7 @@ export class Popover {
|
||||||
width = innerWidth - dblMargin;
|
width = innerWidth - dblMargin;
|
||||||
style.width = width + 'px';
|
style.width = width + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height + dblMargin > innerHeight) {
|
if (height + dblMargin > innerHeight) {
|
||||||
height = innerHeight - dblMargin;
|
height = innerHeight - dblMargin;
|
||||||
style.height = height + 'px';
|
style.height = height + 'px';
|
||||||
|
@ -82,11 +84,13 @@ export class Popover {
|
||||||
|
|
||||||
if (left + width > innerWidth)
|
if (left + width > innerWidth)
|
||||||
left -= (left + width) - innerWidth + margin;
|
left -= (left + width) - innerWidth + margin;
|
||||||
|
|
||||||
if (top + height > innerHeight)
|
if (top + height > innerHeight)
|
||||||
top -= height + parentNode.offsetHeight + spacing * 2;
|
top -= height + parentNode.offsetHeight + spacing * 2;
|
||||||
|
|
||||||
if (left < 0)
|
if (left < 0)
|
||||||
left = screenMargin;
|
left = screenMargin;
|
||||||
|
|
||||||
if (top < 0)
|
if (top < 0)
|
||||||
top = screenMargin;
|
top = screenMargin;
|
||||||
|
|
||||||
|
@ -102,6 +106,7 @@ export class Popover {
|
||||||
}
|
}
|
||||||
return popoverId;
|
return popoverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
showComponent(childComponent, $scope, parent) {
|
showComponent(childComponent, $scope, parent) {
|
||||||
let childElement = this.document.createElement(childComponent);
|
let childElement = this.document.createElement(childComponent);
|
||||||
let id = 'popover-' + this.popOpens;
|
let id = 'popover-' + this.popOpens;
|
||||||
|
@ -111,12 +116,14 @@ export class Popover {
|
||||||
this.show(childElement, parent, id);
|
this.show(childElement, parent, id);
|
||||||
return childElement;
|
return childElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkOpens() {
|
_checkOpens() {
|
||||||
this.popOpens = this.document.querySelectorAll('*[id^="popover-"]').length;
|
this.popOpens = this.document.querySelectorAll('*[id^="popover-"]').length;
|
||||||
if (this.popOpens === 0) {
|
if (this.popOpens === 0) {
|
||||||
this._destroy();
|
this._destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_removeElement(val) {
|
_removeElement(val) {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
let element = angular.element(val);
|
let element = angular.element(val);
|
||||||
|
@ -136,6 +143,7 @@ export class Popover {
|
||||||
}
|
}
|
||||||
this._checkOpens();
|
this._checkOpens();
|
||||||
}
|
}
|
||||||
|
|
||||||
hideChilds(id) {
|
hideChilds(id) {
|
||||||
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
||||||
let idNumber = parseInt(id.split('-')[1], 10);
|
let idNumber = parseInt(id.split('-')[1], 10);
|
||||||
|
@ -147,6 +155,7 @@ export class Popover {
|
||||||
);
|
);
|
||||||
this._checkOpens();
|
this._checkOpens();
|
||||||
}
|
}
|
||||||
|
|
||||||
hideAll() {
|
hideAll() {
|
||||||
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
let popovers = this.document.querySelectorAll('*[id^="popover-"]');
|
||||||
popovers.forEach(
|
popovers.forEach(
|
||||||
|
@ -156,6 +165,7 @@ export class Popover {
|
||||||
);
|
);
|
||||||
this._checkOpens();
|
this._checkOpens();
|
||||||
}
|
}
|
||||||
|
|
||||||
_findPopOver(node) {
|
_findPopOver(node) {
|
||||||
while (node != null) {
|
while (node != null) {
|
||||||
if (node.id && node.id.startsWith('popover-')) {
|
if (node.id && node.id.startsWith('popover-')) {
|
||||||
|
@ -165,6 +175,7 @@ export class Popover {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocMouseDown(event) {
|
onDocMouseDown(event) {
|
||||||
let targetId = this._findPopOver(event.target);
|
let targetId = this._findPopOver(event.target);
|
||||||
if (targetId) {
|
if (targetId) {
|
||||||
|
@ -173,6 +184,7 @@ export class Popover {
|
||||||
this.hideAll();
|
this.hideAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocKeyDown(event) {
|
onDocKeyDown(event) {
|
||||||
if (event.keyCode === 27) {
|
if (event.keyCode === 27) {
|
||||||
let targetId = this._findPopOver(this.lastTarget);
|
let targetId = this._findPopOver(this.lastTarget);
|
||||||
|
@ -184,9 +196,12 @@ export class Popover {
|
||||||
this.lastTarget = null;
|
this.lastTarget = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPopoverMouseDown(event) {
|
onPopoverMouseDown(event) {
|
||||||
this.lastTarget = event.target;
|
this.lastTarget = event.target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popover.$inject = ['$document', '$compile', '$transitions'];
|
Popover.$inject = ['$document', '$compile', '$transitions'];
|
||||||
|
|
||||||
module.service('vnPopover', Popover);
|
module.service('vnPopover', Popover);
|
||||||
|
|
|
@ -7,12 +7,12 @@ export const NAME = util.getName(_NAME);
|
||||||
|
|
||||||
directive.$inject = [resolveFactory.NAME];
|
directive.$inject = [resolveFactory.NAME];
|
||||||
export function directive(resolve) {
|
export function directive(resolve) {
|
||||||
return{
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
template: function(_, attrs) {
|
template: function(_, attrs) {
|
||||||
return resolve.getTemplate(_NAME, attrs);
|
return resolve.getTemplate(_NAME, attrs);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_module.directive(NAME, directive);
|
_module.directive(NAME, directive);
|
||||||
|
|
|
@ -15,7 +15,7 @@ export function factory() {
|
||||||
enabled: 'true',
|
enabled: 'true',
|
||||||
className: DEFAULT_CLASS
|
className: DEFAULT_CLASS
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_module.factory(NAME, factory);
|
_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"
|
ng-readonly="$ctrl.readonly"
|
||||||
/>
|
/>
|
||||||
<div class="mdl-chip__action">
|
<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" 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>
|
</div>
|
||||||
<label class="mdl-textfield__label" translate>{{$ctrl.label}}</label>
|
<label class="mdl-textfield__label" translate>{{$ctrl.label}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,6 +48,7 @@ export default class TextfieldController extends Component {
|
||||||
this.input.focus();
|
this.input.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextfieldController.$inject = ['$element', '$scope', '$attrs', '$timeout', normalizerFactory.NAME];
|
TextfieldController.$inject = ['$element', '$scope', '$attrs', '$timeout', normalizerFactory.NAME];
|
||||||
|
|
||||||
module.component('vnTextfield', {
|
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 {module} from '../module';
|
||||||
import Component from '../lib/component';
|
import Component from '../lib/component';
|
||||||
import getModifiedData from '../lib/modified';
|
import getModifiedData from '../lib/modified';
|
||||||
// import copyObject from '../lib/copy';
|
import copyObject from '../lib/copy';
|
||||||
import isEqual from '../lib/equals';
|
import isEqual from '../lib/equals';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,8 +22,9 @@ export default class Watcher extends Component {
|
||||||
this.state = null;
|
this.state = null;
|
||||||
this.deregisterCallback = $transitions.onStart({},
|
this.deregisterCallback = $transitions.onStart({},
|
||||||
transition => this.callback(transition));
|
transition => this.callback(transition));
|
||||||
this.copyData();
|
this.updateOriginalData();
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
if (this.get && this.url) {
|
if (this.get && this.url) {
|
||||||
this.fetchData();
|
this.fetchData();
|
||||||
|
@ -31,21 +32,24 @@ export default class Watcher extends Component {
|
||||||
throw new Error('Error: Parameter url ommitted');
|
throw new Error('Error: Parameter url ommitted');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$onChanges(changes) {
|
$onChanges(changes) {
|
||||||
if (this.data) {
|
if (this.data) {
|
||||||
this.copyData();
|
this.updateOriginalData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
this.deregisterCallback();
|
this.deregisterCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
let id = this.data[this.idField];
|
let id = this.data[this.idField];
|
||||||
// return new Promise((resolve, reject) => {
|
// return new Promise((resolve, reject) => {
|
||||||
this.$http.get(`${this.url}/${id}`).then(
|
this.$http.get(`${this.url}/${id}`).then(
|
||||||
json => {
|
json => {
|
||||||
this.data = this.copyObject(json.data);
|
this.data = copyObject(json.data);
|
||||||
this.copyData();
|
this.updateOriginalData();
|
||||||
}
|
}
|
||||||
// json => reject(json)
|
// json => reject(json)
|
||||||
);
|
);
|
||||||
|
@ -55,7 +59,7 @@ export default class Watcher extends Component {
|
||||||
* Submits the data and goes back in the history.
|
* Submits the data and goes back in the history.
|
||||||
*/
|
*/
|
||||||
submitBack() {
|
submitBack() {
|
||||||
this.submit().then(
|
return this.submit().then(
|
||||||
() => this.window.history.back()
|
() => this.window.history.back()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +69,7 @@ export default class Watcher extends Component {
|
||||||
* @param {String} state The state name
|
* @param {String} state The state name
|
||||||
*/
|
*/
|
||||||
submitGo(state) {
|
submitGo(state) {
|
||||||
this.submit().then(
|
return this.submit().then(
|
||||||
() => this.$state.go(state)
|
() => 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);
|
resolve(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
noChanges(resolve) {
|
noChanges(resolve) {
|
||||||
this.vnApp.showMessage(
|
this.vnApp.showMessage(
|
||||||
this.$translate.instant('No changes to save')
|
this.$translate.instant('No changes to save')
|
||||||
);
|
);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidForm(resolve) {
|
invalidForm(resolve) {
|
||||||
this.vnApp.showMessage(
|
this.vnApp.showMessage(
|
||||||
this.$translate.instant('Some fields are invalid')
|
this.$translate.instant('Some fields are invalid')
|
||||||
);
|
);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
copyData() {
|
|
||||||
this.orgData = this.copyObject(this.data);
|
updateOriginalData() {
|
||||||
|
this.orgData = this.copyInNewObject(this.data);
|
||||||
}
|
}
|
||||||
copyObject(data) {
|
|
||||||
let copy = {};
|
copyInNewObject(data) {
|
||||||
if (data) {
|
let newCopy = {};
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
Object.keys(data).forEach(
|
Object.keys(data).forEach(
|
||||||
val => {
|
val => {
|
||||||
if (data[val] !== "" && data[val] !== undefined && data[val] !== null)
|
if (data[val] !== "" && data[val] !== undefined && data[val] !== null) {
|
||||||
copy[val] = data[val];
|
if (typeof data[val] === 'object') {
|
||||||
|
newCopy[val] = this.copyInNewObject(data[val]);
|
||||||
|
} else {
|
||||||
|
newCopy[val] = data[val];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return copy;
|
return newCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(transition) {
|
callback(transition) {
|
||||||
let dataChanged = this.dataChanged();
|
let dataChanged = this.dataChanged();
|
||||||
if (!this.state && dataChanged) {
|
if (!this.state && dataChanged) {
|
||||||
|
@ -167,19 +177,22 @@ export default class Watcher extends Component {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dataChanged() {
|
dataChanged() {
|
||||||
let newData = this.copyObject(this.data);
|
let newData = this.copyInNewObject(this.data);
|
||||||
return !isEqual(newData, this.orgData);
|
return !isEqual(newData, this.orgData);
|
||||||
}
|
}
|
||||||
|
|
||||||
onConfirmResponse(response) {
|
onConfirmResponse(response) {
|
||||||
if (response === 'ACCEPT') {
|
if (response === 'ACCEPT') {
|
||||||
this.data = this.copyObject(this.orgData);
|
Object.assign(this.data, this.orgData);
|
||||||
this.$state.go(this.state);
|
this.$state.go(this.state);
|
||||||
} else {
|
} else {
|
||||||
this.state = null;
|
this.state = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate'];
|
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate'];
|
||||||
|
|
||||||
module.component('vnWatcher', {
|
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",
|
"url": "/production",
|
||||||
"state": "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