merge
This commit is contained in:
commit
2c712b4f84
|
@ -1,5 +1,6 @@
|
|||
extends: [eslint:recommended, google, plugin:jasmine/recommended]
|
||||
installedESLint: true
|
||||
parserOptions:
|
||||
ecmaVersion: 2017
|
||||
plugins:
|
||||
- jasmine
|
||||
env:
|
||||
|
@ -18,3 +19,4 @@ rules:
|
|||
no-eq-null: 0
|
||||
no-console: 0
|
||||
no-warning-comments: 0
|
||||
no-empty: 0
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
build
|
||||
npm-debug.log
|
||||
debug.log
|
||||
datasources.development.json
|
||||
.idea
|
||||
docker-compose.yml
|
||||
|
|
|
@ -2,45 +2,10 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Iniciar",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/services/auth/server/server.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": null,
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"console": "internalConsole",
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
},
|
||||
{
|
||||
"name": "Asociar",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 5858,
|
||||
"address": "localhost",
|
||||
"restart": false,
|
||||
"sourceMaps": false,
|
||||
"outFiles": [],
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": null
|
||||
},
|
||||
{
|
||||
"name": "Asociar al proceso",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"processId": "${command:PickProcess}",
|
||||
"port": 5858,
|
||||
"sourceMaps": false,
|
||||
"outFiles": []
|
||||
"name": "Attach by Process ID",
|
||||
"processId": "${command:PickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
FROM node:6.9.1
|
||||
FROM node:8.9.4
|
||||
|
||||
COPY auth /app
|
||||
|
||||
COPY loopback /loopback
|
||||
COPY . /app
|
||||
COPY ../loopback /loopback
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install
|
||||
|
||||
RUN npm -g install pm2
|
||||
|
||||
CMD ["pm2-docker", "./server/server.js"]
|
|
@ -43,12 +43,18 @@ node
|
|||
|
||||
stage ("Stopping/Removing Docker")
|
||||
{
|
||||
sh "docker-compose down --rmi all"
|
||||
step{
|
||||
env.TAG = env.BUILD_NUMBER - 1;
|
||||
sh "docker-compose down --rmi 'all'"
|
||||
}
|
||||
}
|
||||
|
||||
stage ("Generar dockers")
|
||||
{
|
||||
sh "docker-compose up -d --build"
|
||||
step{
|
||||
env.TAG = env.BUILD_NUMBER + 1;
|
||||
sh "docker-compose up -d --build"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
Copyright (C) 2018 - Verdnatura Levante S.L.
|
||||
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in "/usr/share/common-licenses/GPL-3".
|
91
README.md
91
README.md
|
@ -1,53 +1,64 @@
|
|||
# Project Title
|
||||
# Salix
|
||||
|
||||
One Paragraph of project description goes here
|
||||
This project is an Enterprise resource planning (ERP) integrated management of core business processes, in real-time and mediated by software and technology developed with the stack listed below.
|
||||
|
||||
### Prerequisites
|
||||
Salix is also the scientific name of a beautifull tree! :)
|
||||
|
||||
For testing purposes you will need to install globally the following items:
|
||||
npm install -g karma
|
||||
npm install -g karma-cli
|
||||
## Prerequisites
|
||||
|
||||
## Getting Started // ### Installing
|
||||
Required applications.
|
||||
|
||||
Pull from repo.
|
||||
* Node.js = 8.9.4
|
||||
* NGINX
|
||||
* Docker
|
||||
|
||||
install nodejs v6 or above.
|
||||
You will need to install globally the following items.
|
||||
```
|
||||
$ npm install -g karma-cli gulp webpack nodemon
|
||||
```
|
||||
|
||||
install nginx globally.
|
||||
## Getting Started // Installing
|
||||
|
||||
Ask a senior dev for the datasources.development.json files required to run the project.
|
||||
Pull from repository.
|
||||
|
||||
on root run:
|
||||
npm install
|
||||
gulp install
|
||||
Run this commands on project root directory to install Node dependencies.
|
||||
```
|
||||
$ npm install
|
||||
$ gulp install
|
||||
```
|
||||
|
||||
lauching nginx:
|
||||
./dev.sh
|
||||
Launch application in developer environment.
|
||||
```
|
||||
$ gulp
|
||||
```
|
||||
|
||||
launching frontend:
|
||||
gulp client
|
||||
Also you can run backend and frontend as separately gulp tasks (including NGINX).
|
||||
```
|
||||
$ gulp client
|
||||
$ gulp services
|
||||
```
|
||||
|
||||
launching backend:
|
||||
gulp services
|
||||
Manually reset fixtures.
|
||||
```
|
||||
$ gulp docker
|
||||
```
|
||||
|
||||
## Running the tests
|
||||
## Running the unit tests
|
||||
|
||||
for client-side unit tests run from project's root:
|
||||
karma start
|
||||
For client-side unit tests run from project's root.
|
||||
```
|
||||
$ karma start
|
||||
```
|
||||
|
||||
for server-side unit tests run from project's root:
|
||||
npm run testWatch or test for single run
|
||||
For server-side unit tests run from project's root.
|
||||
```
|
||||
$ npm run test
|
||||
```
|
||||
|
||||
### Break down into end to end tests
|
||||
|
||||
on root run:
|
||||
|
||||
gulp docker
|
||||
|
||||
wait 10 secs for db to be ready
|
||||
|
||||
npm run e2e
|
||||
For end-to-end tests run from project's root.
|
||||
```
|
||||
$ gulp e2e
|
||||
```
|
||||
|
||||
## Built With
|
||||
|
||||
|
@ -57,12 +68,6 @@ npm run e2e
|
|||
* [loopback](https://loopback.io/)
|
||||
* [docker](https://www.docker.com/)
|
||||
* [gulp.js](https://gulpjs.com/)
|
||||
|
||||
## Versioning
|
||||
|
||||
We use [SourceTree](https://www.sourcetreeapp.com/) for versioning. For the versions available, see the [salix project](https://git.verdnatura.es).
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License
|
||||
|
||||
* [Karma](https://karma-runner.github.io/)
|
||||
* [Jasmine](https://jasmine.github.io/)
|
||||
* [Nightmare](http://www.nightmarejs.org/)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "@salix/auth",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.verdnatura.es/salix"
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"User": "User",
|
||||
"Password": "Password",
|
||||
"Do not close session": "Do not close session",
|
||||
"Enter": "Enter"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
User: User
|
||||
Password: Password
|
||||
Do not close session: Do not close session
|
||||
Enter: Enter
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"User": "Usuario",
|
||||
"Password": "Contraseña",
|
||||
"Do not close session": "No cerrar sesión",
|
||||
"Enter": "Entrar"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
User: Usuario
|
||||
Password: Contraseña
|
||||
Do not close session: No cerrar sesión
|
||||
Enter: Entrar
|
|
@ -48,7 +48,6 @@ export default class Controller {
|
|||
onLoginErr(json) {
|
||||
this.loading = false;
|
||||
this.password = '';
|
||||
this.focusUser();
|
||||
|
||||
let message;
|
||||
|
||||
|
@ -64,6 +63,7 @@ export default class Controller {
|
|||
}
|
||||
|
||||
this.showMessage(message);
|
||||
this.focusUser();
|
||||
}
|
||||
focusUser() {
|
||||
this.$.userField.select();
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "@salix/client",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.verdnatura.es/salix"
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@
|
|||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Datos básicos",
|
||||
"description": "Basic data",
|
||||
"icon": "person"
|
||||
}
|
||||
}, {
|
||||
|
@ -37,7 +37,7 @@
|
|||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Datos fiscales",
|
||||
"description": "Fiscal data",
|
||||
"icon": "account_balance"
|
||||
}
|
||||
}, {
|
||||
|
@ -64,7 +64,7 @@
|
|||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Consignatarios",
|
||||
"description": "Addresses",
|
||||
"icon": "local_shipping"
|
||||
}
|
||||
}, {
|
||||
|
@ -83,7 +83,7 @@
|
|||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Acceso web",
|
||||
"description": "Web access",
|
||||
"icon": "language"
|
||||
}
|
||||
}, {
|
||||
|
@ -99,13 +99,67 @@
|
|||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Notas",
|
||||
"description": "Notes",
|
||||
"icon": "insert_drive_file"
|
||||
}
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "clientCard.notes.create",
|
||||
"component": "vn-note-create"
|
||||
}, {
|
||||
"url": "/credit",
|
||||
"abstract": true,
|
||||
"state": "clientCard.credit",
|
||||
"component": "ui-view"
|
||||
}, {
|
||||
"url": "/list",
|
||||
"state": "clientCard.credit.list",
|
||||
"component": "vn-client-credit-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Credit",
|
||||
"icon": "credit_card"
|
||||
}
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "clientCard.credit.create",
|
||||
"component": "vn-client-credit-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
}, {
|
||||
"url": "/greuge",
|
||||
"abstract": true,
|
||||
"state": "clientCard.greuge",
|
||||
"component": "ui-view"
|
||||
}, {
|
||||
"url": "/list",
|
||||
"state": "clientCard.greuge.list",
|
||||
"component": "vn-client-greuge-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Greuge",
|
||||
"icon": "work"
|
||||
}
|
||||
}, {
|
||||
"url": "/create",
|
||||
"state": "clientCard.greuge.create",
|
||||
"component": "vn-client-greuge-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
}, {
|
||||
"url": "/mandate",
|
||||
"state": "clientCard.mandate",
|
||||
"component": "vn-client-mandate",
|
||||
"menu": {
|
||||
"description": "Mandate",
|
||||
"icon": "pan_tool"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<vn-check vn-one label="Default" field="$ctrl.address.isDefaultAddress"></vn-check>
|
||||
</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.nickname" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Street address" field="$ctrl.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
|
|
|
@ -4,7 +4,7 @@ export default class Controller {
|
|||
constructor($state) {
|
||||
this.address = {
|
||||
clientFk: parseInt($state.params.id),
|
||||
isEnabled: true
|
||||
isActive: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('Client', () => {
|
|||
|
||||
it('should define and set address property', () => {
|
||||
expect(controller.address.clientFk).toBe(1234);
|
||||
expect(controller.address.isEnabled).toBe(true);
|
||||
expect(controller.address.isActive).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"Street address": "Dirección postal",
|
||||
"Default": "Predeterminado",
|
||||
"Consignee": "Consignatario",
|
||||
"Postcode": "Código postal",
|
||||
"Town/City": "Ciudad",
|
||||
"Province": "Provincia",
|
||||
"Agency": "Agencia",
|
||||
"Phone": "Teléfono",
|
||||
"Mobile": "Móvil"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
Street address: Dirección postal
|
||||
Default: Predeterminado
|
||||
Consignee: Consignatario
|
||||
Postcode: Código postal
|
||||
Town/City: Ciudad
|
||||
Province: Provincia
|
||||
Agency: Agencia
|
||||
Phone: Teléfono
|
||||
Mobile: Móvil
|
|
@ -1,4 +1,4 @@
|
|||
<mg-ajax path="/client/api/Addresses/{{edit.params.addressId}}" actions="$ctrl.address=edit.model" options="mgEdit"></mg-ajax>
|
||||
<mg-ajax path="/client/api/Addresses/{{edit.params.addressId}}" actions="$ctrl.address=edit.model;$ctrl._setIconAdd();" options="mgEdit"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="/client/api/Addresses"
|
||||
|
@ -6,20 +6,20 @@
|
|||
data="$ctrl.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitBack()" pad-medium>
|
||||
<form name="form" ng-submit="$ctrl.submit()" pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Address</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-check label="enabled" field="$ctrl.address.isEnabled"></vn-check>
|
||||
<vn-check label="Enabled" field="$ctrl.address.isActive"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Is equalizated" field="$ctrl.address.isEqualizated"></vn-check>
|
||||
<vn-check label="Is equalizated" field="$ctrl.address.isEqualizated" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</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.nickname" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Street" field="$ctrl.address.street"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
|
@ -36,8 +36,8 @@
|
|||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.address.defaultAgency"
|
||||
field="$ctrl.address.defaultAgencyFk"
|
||||
initial-data="$ctrl.address.agency"
|
||||
field="$ctrl.address.agencyFk"
|
||||
url="/client/api/AgencyModes"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
|
@ -46,6 +46,46 @@
|
|||
<vn-textfield vn-one label="Phone" field="$ctrl.address.phone"></vn-textfield>
|
||||
<vn-textfield vn-one label="Mobile" field="$ctrl.address.mobile"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
||||
<vn-one margin-medium-top>
|
||||
<vn-title>Notes</vn-title>
|
||||
<mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax>
|
||||
<vn-horizontal ng-repeat="observation in $ctrl.observations track by $index">
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
initial-data = "observation.observationType"
|
||||
field = "observation.observationTypeFk"
|
||||
data = "observationsTypes.model"
|
||||
show-field = "description"
|
||||
label = "Observation type"
|
||||
order = "description ASC"
|
||||
filter-search="{where: {description: {regexp: 'search'}} }"
|
||||
>
|
||||
<tpl-item>{{$parent.$parent.item.description}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-three label="Description" model="observation.description"></vn-textfield>
|
||||
<vn-one pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removeObservation($index)"
|
||||
>
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
pointer
|
||||
margin-medium-left
|
||||
orange
|
||||
icon="add_circle"
|
||||
ng-if = "observation.showAddIcon"
|
||||
ng-click="$ctrl.addObservation()"
|
||||
></vn-icon>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
|
||||
</vn-one>
|
||||
|
||||
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
|
|
|
@ -1,13 +1,137 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($state) {
|
||||
constructor($state, $scope, $http, $q, $translate, vnApp) {
|
||||
this.$state = $state;
|
||||
this.$scope = $scope;
|
||||
this.$http = $http;
|
||||
this.$q = $q;
|
||||
this.$translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
|
||||
this.address = {
|
||||
id: parseInt($state.params.addressId)
|
||||
};
|
||||
this.observations = [];
|
||||
this.observationsDictionary = {};
|
||||
this.observationsRemoved = [];
|
||||
}
|
||||
|
||||
_setIconAdd() {
|
||||
if (this.observations.length) {
|
||||
this.observations.map(element => {
|
||||
element.showAddIcon = false;
|
||||
return true;
|
||||
});
|
||||
this.observations[this.observations.length - 1].showAddIcon = true;
|
||||
} else {
|
||||
this.addObservation();
|
||||
}
|
||||
}
|
||||
|
||||
_setDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
addObservation() {
|
||||
this.observations.push({observationTypeFk: null, addressFk: this.address.id, description: null, showAddIcon: true});
|
||||
this._setIconAdd();
|
||||
}
|
||||
|
||||
removeObservation(index) {
|
||||
let item = this.observations[index];
|
||||
if (item) {
|
||||
this.observations.splice(index, 1);
|
||||
this._setIconAdd();
|
||||
if (item.id) {
|
||||
this.observationsRemoved.push(item.id);
|
||||
this._setDirtyForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
_submitObservations(objectObservations) {
|
||||
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations);
|
||||
}
|
||||
|
||||
submit() {
|
||||
this._unsetDirtyForm();
|
||||
let submitWatcher = this.$scope.watcher.dataChanged();
|
||||
let submitObservations;
|
||||
let repeatedTypes = false;
|
||||
let observationsObj = {
|
||||
delete: this.observationsRemoved,
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
for (let i = 0; i < this.observations.length; i++) {
|
||||
let observation = this.observations[i];
|
||||
// only one observation is allowed for each of its types
|
||||
if (this.observationsDictionary[observation.observationTypeFk] !== undefined && // IF the dictionary contains the type
|
||||
(
|
||||
// AND (is a new Observation OR is old but with distinct Id) --> repeated
|
||||
!observation.id || (observation.id && this.observationsDictionary[observation.observationTypeFk].id !== observation.id)
|
||||
)
|
||||
) {
|
||||
repeatedTypes = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!observation.id && observation.observationTypeFk && observation.description) {
|
||||
observationsObj.create.push(observation);
|
||||
} else if (observation.id && this.observationsDictionary[observation.observationTypeFk].description !== observation.description) {
|
||||
observationsObj.update.push(observation);
|
||||
}
|
||||
|
||||
this.observationsDictionary[observation.observationTypeFk] = observation;
|
||||
}
|
||||
|
||||
submitObservations = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||
|
||||
if (repeatedTypes) {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('you can not repeat the types of observations')
|
||||
);
|
||||
} else if (submitWatcher && !submitObservations) {
|
||||
this.$scope.watcher.submit().then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (!submitWatcher && submitObservations) {
|
||||
this._submitObservations(observationsObj).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (submitWatcher && submitObservations) {
|
||||
this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('No changes to save')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
let filter = {
|
||||
where: {addressFk: this.address.id},
|
||||
include: {relation: 'observationType'}
|
||||
};
|
||||
this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => {
|
||||
this.observations = res.data;
|
||||
res.data.forEach(item => {
|
||||
this.observationsDictionary[item.observationTypeFk] = Object.assign({}, item);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$state'];
|
||||
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
||||
|
||||
ngModule.component('vnAddressEdit', {
|
||||
template: require('./address-edit.html'),
|
||||
|
|
|
@ -5,20 +5,33 @@ describe('Client', () => {
|
|||
let $componentController;
|
||||
let $state;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_) => {
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$state.params.addressId = '1234';
|
||||
$httpBackend = _$httpBackend_;
|
||||
$state.params.addressId = '1';
|
||||
controller = $componentController('vnAddressEdit', {$state: $state});
|
||||
}));
|
||||
|
||||
it('should define and set address property', () => {
|
||||
expect(controller.address.id).toBe(1234);
|
||||
expect(controller.address.id).toBe(1);
|
||||
});
|
||||
|
||||
describe('$onInit()', () => {
|
||||
it('should perform a GET query to receive the address observations', () => {
|
||||
let filter = {where: {addressFk: 1}, include: {relation: 'observationType'}};
|
||||
let res = ['some notes'];
|
||||
$httpBackend.when('GET', `/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).respond(res);
|
||||
$httpBackend.expectGET(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`);
|
||||
controller.$onInit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"Enabled": "Activo",
|
||||
"Is equalizated": "Recargo de equivalencia"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Enabled: Activo
|
||||
Is equalizated: Recargo de equivalencia
|
|
@ -1,33 +1,39 @@
|
|||
<mg-ajax path="/client/api/Clients/{{index.params.id}}/addressesList" options="mgIndex"></mg-ajax>
|
||||
<mg-ajax path="/client/api/Clients/{{index.params.id}}/listAddresses" options="mgIndex"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card>
|
||||
<vn-vertical pad-large>
|
||||
<vn-horizontal>
|
||||
<vn-title vn-one>Addresses</vn-title>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-repeat="i in index.model track by i.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-auto style="border-radius: .5em;" class="pad-small border-solid"
|
||||
ng-class="{'bg-dark-item': i.isDefaultAddress,'bg-opacity-item': !i.isEnabled && !i.isDefaultAddress}">
|
||||
<vn-horizontal ng-repeat="address in index.model.items track by address.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-one border-radius class="pad-small border-solid"
|
||||
ng-class="{'bg-dark-item': address.isDefaultAddress,'bg-opacity-item': !address.isActive && !address.isDefaultAddress}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h style="color:#FFA410;">
|
||||
<i class="material-icons" ng-if="i.isDefaultAddress">star</i>
|
||||
<i class="material-icons pointer" ng-if="!i.isDefaultAddress&&i.isEnabled" vn-tooltip="Set as default" tooltip-position="left" ng-click="$ctrl.setDefault(i.id)">star_border</i>
|
||||
<i class="material-icons" ng-if="address.isDefaultAddress">star</i>
|
||||
<i class="material-icons pointer" ng-if="!address.isDefaultAddress" vn-tooltip="Set as default" tooltip-position="left" ng-click="$ctrl.setDefault(address.id)">star_border</i>
|
||||
</vn-none>
|
||||
<vn-auto>
|
||||
<div><b>{{::i.consignee}}</b></div>
|
||||
<div>{{::i.street}}</div>
|
||||
<div>{{::i.city}}, {{::i.province}}</div>
|
||||
<div>{{::i.phone}}, {{::i.mobile}}</div>
|
||||
</vn-auto>
|
||||
<a vn-empty ui-sref="clientCard.addresses.edit({addressId: {{i.id}}})">
|
||||
<vn-one border-solid-right>
|
||||
<div><b>{{::address.nickname}}</b></div>
|
||||
<div>{{::address.street}}</div>
|
||||
<div>{{::address.city}}, {{::address.province}}</div>
|
||||
<div>{{::address.phone}}, {{::address.mobile}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one pad-medium-h>
|
||||
<vn-one ng-repeat="observation in address.observations track by $index" ng-class="{'pad-small-top': $index}">
|
||||
<b margin-medium-right>{{::observation.observationType.description}}:</b>
|
||||
<span>{{::observation.description}}</span>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="clientCard.addresses.edit({addressId: {{address.id}}})">
|
||||
<vn-icon-button icon="edit"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-auto>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-paging index="index"></vn-paging>
|
||||
<vn-paging index="index" total="index.model.total"></vn-paging>
|
||||
<vn-float-button
|
||||
fixed-bottom-right
|
||||
ui-sref="clientCard.addresses.create"
|
||||
|
|
|
@ -6,9 +6,10 @@ class ClientAddresses {
|
|||
this.$scope = $scope;
|
||||
}
|
||||
setDefault(id) {
|
||||
this.$http.patch(`/client/api/Addresses/${id}`, {id: id, isDefaultAddress: true}).then(() => {
|
||||
this.$scope.index.accept();
|
||||
});
|
||||
let params = {isDefaultAddress: true};
|
||||
this.$http.patch(`/client/api/Addresses/${id}`, params).then(
|
||||
() => this.$scope.index.accept()
|
||||
);
|
||||
}
|
||||
}
|
||||
ClientAddresses.$inject = ['$http', '$scope'];
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"Addresses": "Consignatarios",
|
||||
"Set as default": "Establecer como predeterminado"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Set as default: Establecer como predeterminado
|
|
@ -19,8 +19,7 @@
|
|||
<vn-textfield vn-one
|
||||
label="Email"
|
||||
field="$ctrl.client.email"
|
||||
info="You can save multiple emails by chaining them using comma without spaces, example: user@domain.com,user2@domain.com the first email will be considered as the main"
|
||||
>
|
||||
info="You can save multiple emails">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
|
@ -30,10 +29,9 @@
|
|||
url="/client/api/Clients/activeSalesPerson"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
select-fields="surname"
|
||||
select-fields="name"
|
||||
label="Salesperson"
|
||||
filter-search="{where: {or: [{name: {regexp: 'search'}}, {surname: {regexp: 'search'}}]}}"
|
||||
>
|
||||
filter-search="{where: {or: [{name: {regexp: 'search'}}, {name: {regexp: 'search'}}]}}">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.contactChannel"
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"Basic data": "Datos básicos",
|
||||
"Comercial Name": "Nombre comercial",
|
||||
"Tax number": "NIF/CIF",
|
||||
"Social name": "Razón social",
|
||||
"Phone": "Teléfono",
|
||||
"Mobile": "Móvil",
|
||||
"Fax": "Fax",
|
||||
"Email": "Correo electrónico",
|
||||
"Salesperson": "Comercial",
|
||||
"Channel": "Canal",
|
||||
"You can save multiple emails by chaining them using comma without spaces, example: user@domain.com,user2@domain.com the first email will be considered as the main": "Puede guardar varios correos electrónicos encadenándolos mediante comas sin espacios, ejemplo: user@dominio.com,user2@dominio.com siendo el primer correo electrónico el principal",
|
||||
"Contact": "Contacto"
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Comercial Name: Nombre comercial
|
||||
Tax number: NIF/CIF
|
||||
Social name: Razón social
|
||||
Phone: Teléfono
|
||||
Mobile: Móvil
|
||||
Fax: Fax
|
||||
Email: Correo electrónico
|
||||
Salesperson: Comercial
|
||||
Channel: Canal
|
||||
You can save multiple emails: >-
|
||||
Puede guardar varios correos electrónicos encadenándolos mediante comas
|
||||
sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer
|
||||
correo electrónico el principal
|
||||
Contact: Contacto
|
|
@ -19,28 +19,24 @@
|
|||
label="Pay method">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield vn-two label="IBAN" field="$ctrl.client.iban" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield vn-one label="Vencimiento" field="$ctrl.client.dueDay" vn-acl="administrative"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Crédito" field="$ctrl.client.credit" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield vn-one label="Crédito asegurado" field="$ctrl.client.creditInsurance" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield vn-one label="Due day" field="$ctrl.client.dueDay" vn-acl="administrative"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-medium-bottom>
|
||||
<vn-one>
|
||||
<vn-check label="Recibido core VNH" field="$ctrl.client.coreVnh" vn-acl="administrative"></vn-check>
|
||||
<vn-check label="Received core VNH" field="$ctrl.client.hasCoreVnh" 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-check label="Received core VNL" field="$ctrl.client.hasCoreVnl" 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-check label="Received B2B VNL" field="$ctrl.client.hasSepaVnl" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Guardar" vn-acl="administrative"></vn-submit>
|
||||
<vn-submit label="Save" vn-acl="administrative"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-dialog
|
||||
|
|
|
@ -17,9 +17,6 @@ export default class Controller {
|
|||
this.billData.payMethodFk = this.client.payMethodFk;
|
||||
this.billData.iban = this.client.iban;
|
||||
this.billData.dueDay = this.client.dueDay;
|
||||
this.billData.discount = this.client.discount;
|
||||
this.billData.credit = this.client.credit;
|
||||
this.billData.creditInsurance = this.client.creditInsurance;
|
||||
}
|
||||
}
|
||||
submit() {
|
||||
|
@ -43,10 +40,8 @@ export default class Controller {
|
|||
}
|
||||
returnDialog(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.post(`/mailer/manuscript/payment-update/${this.client.id}`).then(
|
||||
() => {
|
||||
this.vnApp.showMessage(this.translate.instant('Notification sent!'));
|
||||
}
|
||||
this.$http.post(`/mailer/notification/payment-update/${this.client.id}`).then(
|
||||
() => this.vnApp.showMessage(this.translate.instant('Notification sent!'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ describe('Client', () => {
|
|||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
$scope = $rootScope.$new();
|
||||
let submit = jasmine.createSpy('submit').and.returnValue(Promise.resolve());
|
||||
$scope.watcher = {submit};
|
||||
|
@ -25,9 +26,6 @@ describe('Client', () => {
|
|||
describe('copyData()', () => {
|
||||
it(`should define billData using client's data`, () => {
|
||||
controller.client = {
|
||||
credit: 1000000000000,
|
||||
creditInsurance: null,
|
||||
discount: 99,
|
||||
dueDay: 0,
|
||||
iban: null,
|
||||
payMethodFk: 1
|
||||
|
@ -72,8 +70,8 @@ describe('Client', () => {
|
|||
describe('returnDialog()', () => {
|
||||
it('should request to send notification email', () => {
|
||||
controller.client = {id: '123'};
|
||||
$httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done');
|
||||
$httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`);
|
||||
$httpBackend.when('POST', `/mailer/notification/payment-update/${controller.client.id}`).respond('done');
|
||||
$httpBackend.expectPOST(`/mailer/notification/payment-update/${controller.client.id}`);
|
||||
controller.returnDialog('ACCEPT');
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"Changed terms": "Has modificado las condiciones de pago",
|
||||
"Notify customer?" : "¿Deseas notificar al cliente de dichos cambios?",
|
||||
"No": "No",
|
||||
"Yes, notify": "Sí, notificar",
|
||||
"Notification sent!": "¡Notificación enviada!",
|
||||
"Notification error": "Error al enviar notificación",
|
||||
"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",
|
||||
"Invoice by address": "Facturar por consignatario",
|
||||
"Equalization tax": "Recargo de equivalencia"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
Changed terms: Has modificado las condiciones de pago
|
||||
Notify customer?: ¿Deseas notificar al cliente de dichos cambios?
|
||||
No: No
|
||||
Yes, notify: Sí, notificar
|
||||
Notification sent!: ¡Notificación enviada!
|
||||
Notification error: Error al enviar notificación
|
||||
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
|
||||
Invoice by address: Facturar por consignatario
|
||||
Equalization tax: Recargo de equivalencia
|
||||
Due day: Vencimiento
|
||||
Received core VNH: Recibido core VNH
|
||||
Received core VNL: Recibido core VNL
|
||||
Received B2B VNL: Recibido B2B VNL
|
||||
SAVE: GUARDAR
|
|
@ -1,18 +1,16 @@
|
|||
<vn-horizontal>
|
||||
<vn-main-block>
|
||||
<mg-ajax
|
||||
path="/client/api/Clients/{{edit.params.id}}/card"
|
||||
actions="$ctrl.client = edit.model"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-empty style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
|
||||
<vn-descriptor
|
||||
client="$ctrl.client"
|
||||
active="$ctrl.client.active"
|
||||
class="display-block" >
|
||||
</vn-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-empty>
|
||||
<vn-auto>
|
||||
<vn-vertical style="max-width: 70em; margin: 0 auto;" ui-view></vn-vertical>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-auto class="left-block">
|
||||
<vn-descriptor client="$ctrl.client"></vn-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-auto>
|
||||
<vn-one>
|
||||
<vn-vertical ui-view></vn-vertical>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-main-block>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import './style.css';
|
||||
|
||||
export default class Controller {
|
||||
constructor() {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
vn-descriptor {
|
||||
font-family: raleway-bold;
|
||||
}
|
|
@ -14,3 +14,8 @@ import './address-edit/address-edit';
|
|||
import './notes/notes';
|
||||
import './note-create/note-create';
|
||||
import './web-access/web-access';
|
||||
import './credit-list/credit-list';
|
||||
import './credit-create/credit-create';
|
||||
import './greuge-list/greuge-list';
|
||||
import './greuge-create/greuge-create';
|
||||
import './mandate/mandate';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<mg-ajax path="/client/api/Clients/createUserProfile" options="vnPost"></mg-ajax>
|
||||
<mg-ajax path="/client/api/Clients/createWithUser" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
|
@ -19,14 +19,21 @@
|
|||
<vn-textfield vn-one label="User name" field="$ctrl.client.userName"></vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Email" field="$ctrl.client.email" info="You can save multiple emails by chaining them using comma without spaces, example: user@domain.com,user2@domain.com the first email will be considered as the main"></vn-textfield>
|
||||
<vn-one></vn-one>
|
||||
<vn-textfield vn-one label="Email" field="$ctrl.client.email" info="You can save multiple emails"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
select-fields="name"
|
||||
label="Salesperson"
|
||||
filter-search="{where: {or: [{name: {regexp: 'search'}}, {name: {regexp: 'search'}}]}}">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Create and edit"></vn-submit>
|
||||
<vn-button label="Create" ng-click="watcher.submitBack()"></vn-button>
|
||||
<vn-submit label="Create"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"Name": "Nombre",
|
||||
"Tax number": "NIF/CIF",
|
||||
"Business name": "Razón social",
|
||||
"User name": "Nombre de usuario",
|
||||
"Email": "Correo electrónico",
|
||||
"Create and edit": "Crear y editar",
|
||||
"Create": "Crear",
|
||||
"You can save multiple emails by chaining them using comma without spaces, example: user@domain.com,user2@domain.com the first email will be considered as the main": "Puede guardar varios correos electrónicos encadenándolos mediante comas sin espacios, ejemplo: user@dominio.com,user2@dominio.com siendo el primer correo electrónico el principal"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
Name: Nombre
|
||||
Tax number: NIF/CIF
|
||||
Business name: Razón social
|
||||
User name: Nombre de usuario
|
||||
Email: Correo electrónico
|
||||
Create and edit: Crear y editar
|
||||
Create: Crear
|
||||
You can save multiple emails: >-
|
||||
Puede guardar varios correos electrónicos encadenándolos mediante comas
|
||||
sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer
|
||||
correo electrónico el principal
|
|
@ -0,0 +1,23 @@
|
|||
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.client"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitGo('clientCard.credit.list')" pad-medium>
|
||||
<vn-card >
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Add credit</vn-title>
|
||||
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Credit" field="$ctrl.client.credit" type="number" vn-focus></vn-textfield>
|
||||
<vn-one></vn-one>
|
||||
</vn-horizontal>
|
||||
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,8 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
ngModule.component('vnClientCreditCreate', {
|
||||
template: require('./credit-create.html'),
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
Add credit: Añadir crédito
|
|
@ -0,0 +1,27 @@
|
|||
<mg-ajax path="/client/api/ClientCredits/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-card pad-medium>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title vn-one margin-large-bottom>Credit</vn-title>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="amount" text="Credit"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="created" text="Since" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="worker.firstName" text="Employee" order-locked></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
vn-one class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="credit in index.model.instances track by credit.id">
|
||||
<vn-one pad-medium-h>{{::credit.amount | number:2}} €</vn-one>
|
||||
<vn-two pad-medium-h>{{::credit.created | date:'dd/MM/yyyy HH:mm' }}</vn-two>
|
||||
<vn-two pad-medium-h>{{::credit.worker.firstName}} {{::credit.worker.name}}</vn-two>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<a ui-sref="clientCard.credit.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -0,0 +1,9 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filterClientList';
|
||||
|
||||
class ClientCreditList extends FilterClientList {}
|
||||
|
||||
ngModule.component('vnClientCreditList', {
|
||||
template: require('./credit-list.html'),
|
||||
controller: ClientCreditList
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
Since : Desde
|
||||
Employee : Empleado
|
||||
No results: Sin resultados
|
|
@ -1,15 +1,18 @@
|
|||
<vn-card>
|
||||
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
|
||||
<vn-horizontal>
|
||||
<a vn-one ui-sref="clients">
|
||||
<i class="material-icons descriptor-icon">person</i>
|
||||
</a>
|
||||
<vn-vertical vn-two>
|
||||
<div class="margin-none">{{::$ctrl.client.id}}</div>
|
||||
<div class="margin-none">{{$ctrl.client.name}}</div>
|
||||
<div class="margin-none">{{$ctrl.client.phone}}</div>
|
||||
<vn-switch label="Activo" model="$ctrl.active"></vn-switch>
|
||||
<vn-card margin-medium-v>
|
||||
<vn-vertical>
|
||||
<vn-auto class="descriptor-header pointer" ui-sref="clients">
|
||||
<i class="material-icons">person</i>
|
||||
</vn-auto>
|
||||
<vn-auto pad-medium>
|
||||
<vn-vertical>
|
||||
<vn-horizontal ng-repeat="(field, title) in $ctrl.fieldsToShow">
|
||||
<strong vn-auto>{{::title}}:</strong>
|
||||
<vn-auto margin-small-left>
|
||||
<span ng-if="field.includes('credit')">{{$ctrl.client[field] || 0 | number:2}} €</span>
|
||||
<span ng-if="!field.includes('credit')">{{$ctrl.client[field]}}</span>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-horizontal>
|
||||
</vn-auto>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope, $http) {
|
||||
this.$http = $http;
|
||||
constructor($translate) {
|
||||
this.$translate = $translate;
|
||||
// CLient fields to display
|
||||
this.fields = ['id', 'name', 'phone', 'credit', 'creditInsurance'];
|
||||
this.fieldsToShow = {};
|
||||
}
|
||||
set active(value) {
|
||||
if (this._active !== value && this._active !== undefined)
|
||||
this.$http.put(`/client/api/Clients/${this.client.id}/activate`);
|
||||
|
||||
this._active = value;
|
||||
// concat 2 Arrays without duplicates
|
||||
_concatFields(a, b) {
|
||||
return a.concat(b.filter(item => a.indexOf(item) < 0));
|
||||
}
|
||||
get active() {
|
||||
return this._active;
|
||||
|
||||
$onInit() {
|
||||
let fields = (this.moreFields && this.moreFields instanceof Array) ? this._concatFields(this.fields, this.moreFields) : this.fields;
|
||||
fields.forEach(field => {
|
||||
this.fieldsToShow[field] = this.$translate.instant(field);
|
||||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$http'];
|
||||
Controller.$inject = ['$translate'];
|
||||
|
||||
ngModule.component('vnDescriptor', {
|
||||
template: require('./descriptor.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<',
|
||||
active: '<'
|
||||
moreFields: '<?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,30 +3,32 @@ import './descriptor.js';
|
|||
describe('Client', () => {
|
||||
describe('Component vnDescriptor', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $translate;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$translate_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnDescriptor', {$scope: $scope});
|
||||
$translate = _$translate_;
|
||||
controller = $componentController('vnDescriptor', {$translate: $translate});
|
||||
}));
|
||||
|
||||
describe('set active', () => {
|
||||
it('should check if active is defined and diferent from the new value', () => {
|
||||
controller.client = {id: 1};
|
||||
describe('onInit()', () => {
|
||||
it('should create Object with basic fields', () => {
|
||||
controller.client = {
|
||||
id: 1,
|
||||
name: "Peter Parker",
|
||||
phone: null,
|
||||
mobile: "666666",
|
||||
credit: 300,
|
||||
creditInsurance: null
|
||||
};
|
||||
controller.$onInit();
|
||||
|
||||
expect(controller._active).toBe(undefined);
|
||||
controller.active = false;
|
||||
|
||||
expect(controller._active).toBe(false);
|
||||
controller.active = true;
|
||||
|
||||
expect(controller._active).toBe(true);
|
||||
expect(controller.fieldsToShow.id).toBe('id');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Generic object to list models, related to the client, with mgCrud
|
||||
export default class FilterClientList {
|
||||
constructor($scope, $timeout, $state) {
|
||||
this.$ = $scope;
|
||||
this.$timeout = $timeout;
|
||||
this.$state = $state;
|
||||
|
||||
this.waitingMgCrud = 0;
|
||||
this.clientFk = $state.params.id;
|
||||
}
|
||||
onOrder(field, order) {
|
||||
this.filter(`${field} ${order}`);
|
||||
}
|
||||
filter(order) {
|
||||
if (this.$.index && this.clientFk) {
|
||||
this.waitingMgCrud = 0;
|
||||
this.$.index.filter = {
|
||||
page: 1,
|
||||
size: 10,
|
||||
clientFk: this.clientFk
|
||||
};
|
||||
|
||||
if (order) {
|
||||
this.$.index.filter.order = order;
|
||||
}
|
||||
|
||||
this.$.index.accept();
|
||||
} else if (!this.clientFk) {
|
||||
throw new Error('Error: ClientFk not found');
|
||||
} else if (this.waitingMgCrud > 3) {
|
||||
throw new Error('Error: Magic Crud is not loaded');
|
||||
} else {
|
||||
this.waitingMgCrud++;
|
||||
this.$timeout(() => {
|
||||
this.filter(order);
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
FilterClientList.$inject = ['$scope', '$timeout', '$state'];
|
|
@ -10,8 +10,9 @@
|
|||
<vn-vertical pad-large>
|
||||
<vn-title>Fiscal data</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield autofocus vn-two label="Social name" field="$ctrl.client.socialName" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield autofocus vn-two label="Social name" field="$ctrl.client.socialName" vn-acl="administrative"></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi" vn-acl="administrative"></vn-textfield>
|
||||
<vn-check vn-one label="Is equalizated" field="$ctrl.client.isEqualizated" vn-acl="administrative"></vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-two label="Street" field="$ctrl.client.street" vn-focus vn-acl="administrative"></vn-textfield>
|
||||
|
@ -26,57 +27,53 @@
|
|||
show-field="name"
|
||||
value-field="id"
|
||||
label="Province"
|
||||
vn-acl="administrative"
|
||||
>
|
||||
vn-acl="administrative">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.country"
|
||||
field="$ctrl.client.countryFk"
|
||||
url="/client/api/Countries"
|
||||
show-field="name"
|
||||
show-field="country"
|
||||
value-field="id"
|
||||
label="Country"
|
||||
vn-acl="administrative"
|
||||
>
|
||||
vn-acl="administrative">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-small-bottom>
|
||||
<vn-one>
|
||||
<vn-check label="Equalization tax" field="$ctrl.client.equalizationTax" vn-acl="administrative" vn-acl="administrative"></vn-check>
|
||||
<vn-check label="Active" field="$ctrl.client.isActive" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Invoice by address" field="$ctrl.client.hasToInvoiceByAddress" vn-acl="administrative" vn-acl="administrative"></vn-check>
|
||||
<vn-check label="Invoice by address" field="$ctrl.client.hasToInvoiceByAddress" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Verified data" field="$ctrl.client.isTaxDataChecked" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-check label="Has to invoice" field="$ctrl.client.hasToInvoice" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check vn-one label="Invoice by mail" field="$ctrl.client.isToBeMailed" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check vn-one label="Vies" field="$ctrl.client.isVies" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one></vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-check label="Has to invoice" field="$ctrl.client.hasToInvoice" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Invoice by mail" field="$ctrl.client.invoiceByEmail" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-check label="Vies" field="$ctrl.client.vies" vn-acl="administrative" vn-acl="administrative"></vn-check>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
|
||||
</vn-vertical>
|
||||
|
||||
</vn-card>
|
||||
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
<vn-submit label="Save" vn-acl="administrative"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
<vn-dialog
|
||||
vn-id="propagate-equalizationTax"
|
||||
on-response="$ctrl.returnDialogEt(response)"
|
||||
>
|
||||
vn-id="propagate-isEqualizated"
|
||||
on-response="$ctrl.returnDialogEt(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-one text-center translate>You changes the equivalen
|
||||
<vn-one text-center translate>Do you want to spread the change to their consig
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
|
|
|
@ -6,7 +6,7 @@ export default class ClientFiscalData {
|
|||
this.$http = $http;
|
||||
this.vnApp = vnApp;
|
||||
this.translate = $translate;
|
||||
this.equalizationTax = undefined;
|
||||
this.isEqualizated = undefined;
|
||||
this.copyData();
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ export default class ClientFiscalData {
|
|||
|
||||
copyData() {
|
||||
if (this.client) {
|
||||
this.equalizationTax = this.client.equalizationTax;
|
||||
this.isEqualizated = this.client.isEqualizated;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,16 +26,16 @@ export default class ClientFiscalData {
|
|||
}
|
||||
|
||||
checkEtChanges() {
|
||||
let equals = this.equalizationTax == this.client.equalizationTax;
|
||||
this.equalizationTax = this.client.equalizationTax;
|
||||
let equals = this.isEqualizated == this.client.isEqualizated;
|
||||
this.isEqualizated = this.client.isEqualizated;
|
||||
|
||||
if (!equals)
|
||||
this.$.propagateEqualizationTax.show();
|
||||
this.$.propagateIsEqualizated.show();
|
||||
}
|
||||
|
||||
returnDialogEt(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
this.$http.patch(`/client/api/Clients/${this.client.id}/addressesPropagateRe`, {isEqualizated: this.client.equalizationTax}).then(
|
||||
this.$http.patch(`/client/api/Clients/${this.client.id}/addressesPropagateRe`, {isEqualizated: this.client.isEqualizated}).then(
|
||||
res => {
|
||||
if (res.data)
|
||||
this.vnApp.showMessage(this.translate.instant('Equivalent tax spreaded'));
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import './fiscal-data.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientFiscalData', () => {
|
||||
let $componentController;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnClientFiscalData', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('returnDialogEt()', () => {
|
||||
it('should request to patch the propagation of tax status', () => {
|
||||
controller.client = {id: 123, isEqualizated: false};
|
||||
$httpBackend.when('PATCH', `/client/api/Clients/${controller.client.id}/addressesPropagateRe`, {isEqualizated: controller.client.isEqualizated}).respond('done');
|
||||
$httpBackend.expectPATCH(`/client/api/Clients/${controller.client.id}/addressesPropagateRe`, {isEqualizated: controller.client.isEqualizated});
|
||||
controller.returnDialogEt('ACCEPT');
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
<mg-ajax path="/client/api/greuges" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.greuge"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
|
||||
<form pad-medium name="form" ng-submit="$ctrl.onSubmit()">
|
||||
<vn-card>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-title vn-one margin-large-bottom>Add Greuge</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one margin-medium-right label="Amount" field="$ctrl.greuge.amount" type="number" step="1" vn-focus></vn-textfield>
|
||||
<vn-date-picker vn-one
|
||||
label="Date"
|
||||
model="$ctrl.greuge.shipped"
|
||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}"
|
||||
>
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one margin-medium-right label="Comment" field="$ctrl.greuge.description"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.greuge.greugeTypeFk"
|
||||
url="/client/api/greugeTypes"
|
||||
label="Type"
|
||||
>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,25 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ClientGreugeCreate {
|
||||
constructor($scope, $state, $filter) {
|
||||
this.$ = $scope;
|
||||
this.$state = $state;
|
||||
this.greuge = {
|
||||
shipped: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm')
|
||||
};
|
||||
}
|
||||
onSubmit() {
|
||||
this.greuge.clientFk = this.$state.params.id;
|
||||
this.$.watcher.submit().then(
|
||||
() => {
|
||||
this.$state.go('clientCard.greuge.list');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
ClientGreugeCreate.$inject = ['$scope', '$state', '$filter'];
|
||||
|
||||
ngModule.component('vnClientGreugeCreate', {
|
||||
template: require('./greuge-create.html'),
|
||||
controller: ClientGreugeCreate
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
import './greuge-create.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientGreugeCreate', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let $state;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$state = _$state_;
|
||||
$scope.watcher = {
|
||||
submit: () => {
|
||||
return {
|
||||
then: callback => {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientGreugeCreate', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should call the function go() on $state to go to the greuges list', () => {
|
||||
spyOn($state, 'go');
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('clientCard.greuge.list');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
<mg-ajax path="/client/api/greuges/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<mg-ajax path="/client/api/greuges/{{edit.params.id}}/sumAmount" options="mgEdit"></mg-ajax>
|
||||
<vn-card pad-medium>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-title vn-one margin-large-bottom>Greuge</vn-title>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="shipped" text="Date" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="description" text="Comment"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="amount" text="Amount"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="greugeTypeFk" text="Type"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="greuge in index.model.instances track by greuge.id">
|
||||
<vn-one pad-medium-h>{{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }}</vn-one>
|
||||
<vn-two pad-medium-h>{{::greuge.description}}</vn-two>
|
||||
<vn-one pad-medium-h>{{::greuge.amount | number:2}} €</vn-one>
|
||||
<vn-one pad-medium-h>{{::greuge.greugeType.name}}</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer text-center">
|
||||
<vn-one pad-medium-h></vn-one>
|
||||
<vn-two pad-medium-h></vn-two>
|
||||
<vn-one pad-medium-h ng-if="index.model.count > 0">{{edit.model.sumAmount | number:2}} €</vn-one>
|
||||
<vn-one pad-medium-h></vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-paging margin-large-top vn-one index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<a ui-sref="clientCard.greuge.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filterClientList';
|
||||
|
||||
class ClientGreugeList extends FilterClientList {}
|
||||
|
||||
ngModule.component('vnClientGreugeList', {
|
||||
template: require('./greuge-list.html'),
|
||||
controller: ClientGreugeList
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
Date: Fecha
|
||||
Comment: Comentario
|
||||
Amount: Importe
|
||||
Type: Tipo
|
||||
Add Greuge: Añadir Greuge
|
|
@ -3,12 +3,13 @@
|
|||
<div style="max-width: 40em; margin: 0 auto;">
|
||||
<vn-card>
|
||||
<vn-horizontal pad-medium>
|
||||
<vn-searchbar vn-auto
|
||||
<vn-searchbar vn-one
|
||||
index="index"
|
||||
on-search="$ctrl.search(index)"
|
||||
advanced="true"
|
||||
search="$ctrl.model.search"
|
||||
popover="vn-client-search-panel">
|
||||
popover="vn-client-search-panel"
|
||||
ignore-keys = "['page', 'size', 'search']"
|
||||
>
|
||||
</vn-searchbar>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
|
|
|
@ -7,7 +7,6 @@ export default class Controller {
|
|||
this.model = {};
|
||||
}
|
||||
search(index) {
|
||||
index.filter.search = this.model.search;
|
||||
index.accept();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,19 +18,19 @@ describe('Client', () => {
|
|||
expect(controller.model).toEqual({});
|
||||
});
|
||||
|
||||
describe('search()', () => {
|
||||
it(`should set model's search to the search input`, () => {
|
||||
controller.model.search = 'batman';
|
||||
let index = {
|
||||
filter: {},
|
||||
accept: () => {
|
||||
return 'accepted';
|
||||
}
|
||||
};
|
||||
controller.search(index);
|
||||
// describe('search()', () => {
|
||||
// it(`should set model's search to the search input`, () => {
|
||||
// controller.model.search = 'batman';
|
||||
// let index = {
|
||||
// filter: {},
|
||||
// accept: () => {
|
||||
// return 'accepted';
|
||||
// }
|
||||
// };
|
||||
// controller.search(index);
|
||||
|
||||
expect(index.filter.search).toBe('batman');
|
||||
});
|
||||
});
|
||||
// expect(index.filter.search).toBe('batman');
|
||||
// });
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<a ui-sref="clientCard.basicData({ id: {{$ctrl.client.id}} })" pad-medium border-solid-bottom>
|
||||
<div class="vn-item-client-name">{{$ctrl.client.name}}</div>
|
||||
<div><span translate>Client id</span>: <b>{{$ctrl.client.id}}</b></div>
|
||||
<div><span translate>Phone</span>: <b>{{$ctrl.client.phone | phone}}</b></div>
|
||||
<div><span translate>Town/City</span>: <b>{{$ctrl.client.city}}</b></div>
|
||||
<div><span translate>Email</span>: <b>{{$ctrl.client.email}}</b></div>
|
||||
<a ui-sref="clientCard.basicData({ id: {{::$ctrl.client.id}} })" pad-medium border-solid-bottom>
|
||||
<div class="vn-item-client-name">{{::$ctrl.client.name}}</div>
|
||||
<div><span translate>Client id</span>: <b>{{::$ctrl.client.id}}</b></div>
|
||||
<div><span translate>Phone</span>: <b>{{::$ctrl.client.phone | phone}}</b></div>
|
||||
<div><span translate>Town/City</span>: <b>{{::$ctrl.client.city}}</b></div>
|
||||
<div><span translate>Email</span>: <b>{{::$ctrl.client.email}}</b></div>
|
||||
</a>
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"Client id": "Id cliente",
|
||||
"Phone": "Teléfono",
|
||||
"Town/City": "Ciudad",
|
||||
"Email": "Correo electrónico",
|
||||
"Create client": "Crear cliente"
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Client id: Id cliente
|
||||
Phone: Teléfono
|
||||
Town/City: Ciudad
|
||||
Email: Correo electrónico
|
||||
Create client: Crear cliente
|
|
@ -12,5 +12,5 @@ vn-item-client a:hover {
|
|||
}
|
||||
|
||||
.vn-item-client-name {
|
||||
font-family: raleway-bold;
|
||||
font-family: vn-font-bold;
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"Client": "Client",
|
||||
"Clients": "Clients"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Client: Client
|
||||
Clients: Clients
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"Client": "Cliente",
|
||||
"Clients": "Clientes",
|
||||
"Fiscal data": "Datos Fiscales",
|
||||
"Has to invoice": "Factura",
|
||||
"Invoice by mail": "Factura impresa",
|
||||
"Country": "País",
|
||||
"Street": "Domicilio fiscal",
|
||||
"City": "Municipio",
|
||||
"Postcode": "Código postal",
|
||||
"Province": "Provincia",
|
||||
"Save": "Guardar",
|
||||
"Pay method" : "Forma de pago"
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
Active: Activo
|
||||
Client: Cliente
|
||||
Clients: Clientes
|
||||
Basic data: Datos básicos
|
||||
Fiscal data: Datos Fiscales
|
||||
Addresses: Consignatarios
|
||||
Web access: Acceso web
|
||||
Notes: Notas
|
||||
Has to invoice: Factura
|
||||
Invoice by mail: Factura impresa
|
||||
Country: País
|
||||
Street: Domicilio fiscal
|
||||
City: Municipio
|
||||
Postcode: Código postal
|
||||
Province: Provincia
|
||||
Save: Guardar
|
||||
Pay method : Forma de pago
|
||||
Address: Consignatario
|
||||
Credit : Crédito
|
||||
Secured credit: Crédito asegurado
|
||||
Verified data: Datos comprobados
|
||||
Mandate: Mandato
|
||||
Amount: Importe
|
|
@ -0,0 +1,3 @@
|
|||
Company: Empresa
|
||||
Register date: Fecha alta
|
||||
End date: Fecha baja
|
|
@ -0,0 +1,31 @@
|
|||
<mg-ajax path="/client/api/Mandates/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-card pad-medium>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-title vn-one margin-large-bottom>Mandate</vn-title>
|
||||
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="id" text="Id"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="companyFk" text="Company"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="mandateTypeFk" text="Type"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="created" text="Register date" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h field="finished" text="End date"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
vn-one class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="mandate in index.model.instances track by mandate.id"
|
||||
>
|
||||
<vn-one pad-medium-h>{{::mandate.id}}</vn-one>
|
||||
<vn-one pad-medium-h>{{::mandate.company.code}}</vn-one>
|
||||
<vn-one pad-medium-h>{{::mandate.mandateType.name}}</vn-one>
|
||||
<vn-one pad-medium-h>{{::mandate.created | date:'dd/MM/yyyy HH:mm' }}</vn-one>
|
||||
<vn-one pad-medium-h>{{::mandate.finished | date:'dd/MM/yyyy HH:mm' || '-'}}</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
|
||||
</vn-vertical>
|
||||
</vn-card>
|
|
@ -0,0 +1,7 @@
|
|||
import ngModule from '../module';
|
||||
import FilterClientList from '../filterClientList';
|
||||
|
||||
ngModule.component('vnClientMandate', {
|
||||
template: require('./mandate.html'),
|
||||
controller: FilterClientList
|
||||
});
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"New note": "Nueva nota",
|
||||
"Note": "Nota"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
New note: Nueva nota
|
||||
Note: Nota
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"Notes": "Notas"
|
||||
}
|
|
@ -1,13 +1,19 @@
|
|||
<vn-card ng-show="$ctrl.observations.length" pad-medium>
|
||||
<vn-vertical pad-large>
|
||||
<vn-title>Notes</vn-title>
|
||||
<vn-horizontal ng-repeat="n in $ctrl.observations" margin-small-bottom style="align-items: center;">
|
||||
<vn-auto style="border-radius: .3em;" class="pad-small border-solid">
|
||||
<div class="notes-date">{{::n.created | date:'dd/MM/yyyy HH:mm'}}</div>
|
||||
<div class="notes-date">{{::n.employee.name}}</div>
|
||||
<div>{{::n.text}}</div>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
<vn-one
|
||||
ng-repeat="n in $ctrl.observations"
|
||||
pad-small border-solid
|
||||
border-radius
|
||||
margin-small-bottom style="align-items: center;">
|
||||
<vn-horizontal>
|
||||
<vn-one >{{::n.worker.firstName}} {{::n.worker.name}}</vn-one>
|
||||
<vn-auto>{{::n.created | date:'dd/MM/yyyy HH:mm'}}</vn-auto>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<b>{{::n.text}}</b>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-float-button
|
||||
|
|
|
@ -15,7 +15,8 @@ describe('Client', () => {
|
|||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
controller = $componentController('vnClientNotes', {$state: $state});
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.notes-date {
|
||||
font-family: raleway-bold;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"Client id": "Id cliente",
|
||||
"Tax number": "NIF/CIF",
|
||||
"Name": "Nombre",
|
||||
"Social name": "Razon social",
|
||||
"Town/City": "Ciudad",
|
||||
"Postcode": "Código postal",
|
||||
"Email": "Correo electrónico",
|
||||
"Phone": "Teléfono"
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Client id: Id cliente
|
||||
Tax number: NIF/CIF
|
||||
Name: Nombre
|
||||
Social name: Razon social
|
||||
Town/City: Ciudad
|
||||
Postcode: Código postal
|
||||
Email: Correo electrónico
|
||||
Phone: Teléfono
|
|
@ -1,28 +1,16 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor(sessionStorage) {
|
||||
this.sessionStorage = sessionStorage;
|
||||
constructor() {
|
||||
// onSubmit() is defined by @vnSearchbar
|
||||
this.onSubmit = () => {};
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
this.setStorageValue();
|
||||
this.onSubmit(this.filter);
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
var value = this.sessionStorage.get('filter');
|
||||
if (value !== undefined)
|
||||
this.filter = value;
|
||||
}
|
||||
|
||||
setStorageValue() {
|
||||
this.sessionStorage.set('filter', this.filter);
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['sessionStorage'];
|
||||
Controller.$inject = [];
|
||||
|
||||
ngModule.component('vnClientSearchPanel', {
|
||||
template: require('./search-panel.html'),
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
import './search-panel.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientSearchPanel', () => {
|
||||
let $componentController;
|
||||
let sessionStorage;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _sessionStorage_) => {
|
||||
$componentController = _$componentController_;
|
||||
sessionStorage = _sessionStorage_;
|
||||
controller = $componentController('vnClientSearchPanel', {sessionStorage: sessionStorage});
|
||||
}));
|
||||
|
||||
describe('onSearch()', () => {
|
||||
it('should call setStorageValue() and onSubmit()', () => {
|
||||
spyOn(controller, 'setStorageValue');
|
||||
spyOn(controller, 'onSubmit');
|
||||
controller.setStorageValue();
|
||||
controller.onSubmit();
|
||||
|
||||
expect(controller.setStorageValue).toHaveBeenCalledWith();
|
||||
expect(controller.onSubmit).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it('should set filter properties using the search values', () => {
|
||||
expect(controller.filter).not.toBeDefined();
|
||||
spyOn(sessionStorage, 'get').and.returnValue({data: 'data'});
|
||||
controller.$onChanges();
|
||||
|
||||
expect(controller.filter).toBe(sessionStorage.get({data: 'data'}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"User": "Usuario",
|
||||
"Enable web access": "Habilitar acceso web",
|
||||
"Web access": "Acceso web",
|
||||
"New password": "Nueva contraseña",
|
||||
"Repeat password": "Repetir contraseña",
|
||||
"Change password": "Cambiar contraseña"
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
User: Usuario
|
||||
Enable web access: Habilitar acceso web
|
||||
New password: Nueva contraseña
|
||||
Repeat password: Repetir contraseña
|
||||
Change password: Cambiar contraseña
|
|
@ -16,7 +16,7 @@ export default class Controller {
|
|||
|
||||
isCustomer() {
|
||||
if (this.client && this.client.id) {
|
||||
this.$http.get(`/client/api/Clients/${this.client.id}/getRoleCustomer`).then(res => {
|
||||
this.$http.get(`/client/api/Clients/${this.client.id}/hasCustomerRole`).then(res => {
|
||||
this.canChangePassword = (res.data) ? res.data.isCustomer : false;
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -15,6 +15,7 @@ describe('Component VnClientWebAccess', () => {
|
|||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
vnApp = _vnApp_;
|
||||
spyOn(vnApp, 'showError');
|
||||
controller = $componentController('vnClientWebAccess', {$scope: $scope});
|
||||
|
@ -37,8 +38,8 @@ describe('Component VnClientWebAccess', () => {
|
|||
controller.client = {id: '1234'};
|
||||
controller.isCustomer();
|
||||
|
||||
$httpBackend.when('GET', `/client/api/Clients/${controller.client.id}/getRoleCustomer`).respond('ok');
|
||||
$httpBackend.expectGET(`/client/api/Clients/${controller.client.id}/getRoleCustomer`);
|
||||
$httpBackend.when('GET', `/client/api/Clients/${controller.client.id}/hasCustomerRole`).respond('ok');
|
||||
$httpBackend.expectGET(`/client/api/Clients/${controller.client.id}/hasCustomerRole`);
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"name": "@salix/core",
|
||||
"version": "0.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.verdnatura.es/salix"
|
||||
}
|
||||
}
|
|
@ -1,6 +1,12 @@
|
|||
<vn-vertical ng-click="$ctrl.showDropDown = true">
|
||||
<vn-textfield vn-one label="{{$ctrl.label}}" model="$ctrl.displayValue" readonly="$ctrl.readonly"></vn-textfield>
|
||||
<vn-drop-down vn-one
|
||||
<vn-vertical ng-click="$ctrl.showDropDown = true" tabindex="0">
|
||||
<vn-textfield vn-auto
|
||||
label="{{$ctrl.label}}"
|
||||
model="$ctrl.displayValue"
|
||||
readonly="$ctrl.readonly"
|
||||
tab-index="-1"
|
||||
>
|
||||
</vn-textfield>
|
||||
<vn-drop-down vn-auto
|
||||
items="$ctrl.items"
|
||||
show="$ctrl.showDropDown"
|
||||
selected="$ctrl.field"
|
||||
|
@ -11,5 +17,6 @@
|
|||
filter-action="$ctrl.findItems(search)"
|
||||
item-width="$ctrl.width"
|
||||
multiple="$ctrl.multiple"
|
||||
><vn-item ng-transclude="tplItem">{{$parent.item.name}}</vn-item></vn-drop-down>
|
||||
parent = "$ctrl.element"
|
||||
><vn-item ng-transclude="tplItem">{{$parent.item[$ctrl.showField]}}</vn-item></vn-drop-down>
|
||||
</vn-vertical>
|
|
@ -19,14 +19,15 @@ class Autocomplete extends Component {
|
|||
this._field = null;
|
||||
this._preLoad = false;
|
||||
this.maxRow = 10;
|
||||
this.showField = this.showField || 'name';
|
||||
this.valueField = this.valueField || 'id';
|
||||
this.order = this.order || 'name ASC';
|
||||
this.showField = 'name';
|
||||
this.valueField = 'id';
|
||||
this.items = copyObject(this.data) || [];
|
||||
this.displayValueMultiCheck = [];
|
||||
this._multiField = [];
|
||||
this.readonly = true;
|
||||
this.removeLoadMore = false;
|
||||
this.form = null;
|
||||
this.findForm = false;
|
||||
}
|
||||
|
||||
get showDropDown() {
|
||||
|
@ -87,6 +88,7 @@ class Autocomplete extends Component {
|
|||
if (this.multiple) {
|
||||
this.setMultiField(value[this.valueField]);
|
||||
}
|
||||
this.setDirtyForm();
|
||||
} else {
|
||||
this.setValue(value);
|
||||
}
|
||||
|
@ -191,6 +193,10 @@ class Autocomplete extends Component {
|
|||
return fields;
|
||||
}
|
||||
|
||||
getOrder() {
|
||||
return this.order ? this.order : `${this.showField} ASC`;
|
||||
}
|
||||
|
||||
findItems(search) {
|
||||
if (this.url && search && !this.finding) {
|
||||
this.maxRow = false;
|
||||
|
@ -204,7 +210,7 @@ class Autocomplete extends Component {
|
|||
Object.assign(filter.where, this.filter.where);
|
||||
}
|
||||
}
|
||||
filter.order = this.order;
|
||||
filter.order = this.getOrder();
|
||||
let json = JSON.stringify(filter);
|
||||
this.finding = true;
|
||||
this.$http.get(`${this.url}?filter=${json}`).then(
|
||||
|
@ -248,7 +254,7 @@ class Autocomplete extends Component {
|
|||
filter.skip = this.items.length;
|
||||
}
|
||||
filter.limit = this.maxRow;
|
||||
filter.order = this.order;
|
||||
filter.order = this.getOrder();
|
||||
}
|
||||
if (this.filter) {
|
||||
Object.assign(filter, this.filter);
|
||||
|
@ -284,6 +290,22 @@ class Autocomplete extends Component {
|
|||
}
|
||||
}
|
||||
}
|
||||
_parentForm() {
|
||||
this.findForm = true;
|
||||
let formScope = this.$scope;
|
||||
while (formScope && !formScope.form && formScope.$id > 1) {
|
||||
formScope = formScope.$parent;
|
||||
}
|
||||
this.form = formScope ? formScope.form || null : null;
|
||||
}
|
||||
setDirtyForm() {
|
||||
if (!this.form && !this.findForm) {
|
||||
this._parentForm();
|
||||
}
|
||||
if (this.form) {
|
||||
this.form.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.findMore = this.url && this.maxRow;
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('Component vnAutocomplete', () => {
|
|||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||
$timeout = _$timeout_;
|
||||
$element = angular.element('<div></div>');
|
||||
controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
|
@ -120,7 +121,6 @@ describe('Component vnAutocomplete', () => {
|
|||
|
||||
it(`should perform a query if the item id isn't present in the controller.items property`, () => {
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`).respond();
|
||||
$httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`);
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.field = 3;
|
||||
|
@ -136,7 +136,6 @@ describe('Component vnAutocomplete', () => {
|
|||
|
||||
it(`should set field performing a query as the item id isn't present in the controller.items property`, () => {
|
||||
controller.url = 'test.com';
|
||||
$httpBackend.whenGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`).respond();
|
||||
$httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`);
|
||||
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
|
||||
controller.field = 3;
|
||||
|
@ -150,7 +149,7 @@ describe('Component vnAutocomplete', () => {
|
|||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.url = 'test.com';
|
||||
let search = 'The Joker';
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.order});
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
|
||||
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
|
||||
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
|
||||
controller.findItems(search);
|
||||
|
@ -163,8 +162,8 @@ describe('Component vnAutocomplete', () => {
|
|||
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
|
||||
controller.url = 'test.com';
|
||||
let search = 'The Joker';
|
||||
controller.filterSearch = "{where: {surname: {regexp: 'search'}}}";
|
||||
let json = JSON.stringify({where: {surname: {regexp: search}}, order: controller.order});
|
||||
controller.filterSearch = "{where: {name: {regexp: 'search'}}}";
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
|
||||
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
|
||||
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
|
||||
controller.findItems(search);
|
||||
|
@ -177,7 +176,7 @@ describe('Component vnAutocomplete', () => {
|
|||
controller.url = 'test.com';
|
||||
let search = 'Joker';
|
||||
controller.multiple = true;
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.order});
|
||||
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
|
||||
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}, {id: 4, name: 'Joker'}]);
|
||||
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
|
||||
controller.findItems(search);
|
||||
|
|
|
@ -18,18 +18,23 @@ ul.vn-autocomplete {
|
|||
}
|
||||
&.load-more {
|
||||
color: #ffa410;
|
||||
font-weight: bold;
|
||||
font-family: vn-font-bold;
|
||||
padding: .4em .8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
vn-autocomplete {
|
||||
position: relative;
|
||||
vn-vertical {
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.mdl-chip__action {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: -6px;
|
||||
margin: 22px 0px;
|
||||
background-color: white;
|
||||
background: transparent;
|
||||
}
|
||||
.material-icons {
|
||||
font-size: 18px;
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
<div class="{{$ctrl.className}}" ng-mouseover="$ctrl.mouseIsOver = true" ng-mouseleave="$ctrl.mouseIsOver = false">
|
||||
<vn-horizontal ng-if="$ctrl.text" class="orderly" ng-click="$ctrl.onClick()">
|
||||
<vn-none class="title" translate>
|
||||
{{::$ctrl.text}}
|
||||
<vn-horizontal ng-if="$ctrl.text" class="orderly">
|
||||
<vn-none
|
||||
class="title"
|
||||
ng-class="{'noDrop': $ctrl.orderLocked, 'pointer' : !$ctrl.orderLocked}"
|
||||
ng-click="$ctrl.onClick($event)" translate>
|
||||
{{::$ctrl.text}}
|
||||
</vn-none>
|
||||
<vn-none>
|
||||
<vn-icon icon="arrow_drop_down" ng-if="$ctrl.showArrow('DESC')"></vn-icon>
|
||||
<vn-icon icon="arrow_drop_up" ng-if="$ctrl.showArrow('ASC')"></vn-icon>
|
||||
<vn-none ng-if="!$ctrl.orderLocked">
|
||||
<vn-icon
|
||||
icon="arrow_drop_down"
|
||||
ng-class="{'active': $ctrl.showArrow('DESC')}"
|
||||
ng-click="$ctrl.onClick($event, 'DESC')"
|
||||
></vn-icon>
|
||||
<vn-icon
|
||||
icon="arrow_drop_up"
|
||||
ng-class="{'active': $ctrl.showArrow('ASC')}"
|
||||
ng-click="$ctrl.onClick($event, 'ASC')"
|
||||
></vn-icon>
|
||||
</vn-none>
|
||||
</vn-horizontal>
|
||||
<ng-transclude ng-if="!$ctrl.text"></ng-transclude>
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
import {module} from '../module';
|
||||
|
||||
export default class ColumnHeader {
|
||||
constructor() {
|
||||
constructor($attrs) {
|
||||
this.order = undefined;
|
||||
this.mouseIsOver = false;
|
||||
this.orderLocked = ($attrs.orderLocked !== undefined);
|
||||
}
|
||||
onClick() {
|
||||
if (this.order === 'ASC') {
|
||||
this.order = 'DESC';
|
||||
} else {
|
||||
this.order = 'ASC';
|
||||
onClick(event, order) {
|
||||
if (!this.orderLocked) {
|
||||
if (order) {
|
||||
this.order = order;
|
||||
} else if (this.order === 'ASC') {
|
||||
this.order = 'DESC';
|
||||
} else {
|
||||
this.order = 'ASC';
|
||||
}
|
||||
this.gridHeader.selectColum(this);
|
||||
}
|
||||
this.gridHeader.selectColum(this);
|
||||
if (event)
|
||||
event.preventDefault();
|
||||
}
|
||||
showArrow(type) {
|
||||
if (this.orderLocked)
|
||||
return false;
|
||||
|
||||
let showArrow = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order === type);
|
||||
let showOther = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order !== type);
|
||||
if (type === 'DESC' && this.mouseIsOver && !showOther) {
|
||||
|
@ -22,13 +32,13 @@ export default class ColumnHeader {
|
|||
return showArrow;
|
||||
}
|
||||
$onInit() {
|
||||
if (this.defaultOrder) {
|
||||
if (this.defaultOrder && !this.orderLocked) {
|
||||
this.order = this.defaultOrder;
|
||||
this.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnHeader.$inject = [];
|
||||
ColumnHeader.$inject = ['$attrs'];
|
||||
|
||||
module.component('vnColumnHeader', {
|
||||
template: require('./column-header.html'),
|
||||
|
|
|
@ -3,6 +3,8 @@ import './column-header.js';
|
|||
describe('Component vnColumnHeader', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
let $event;
|
||||
let $attrs;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
|
@ -10,14 +12,18 @@ describe('Component vnColumnHeader', () => {
|
|||
|
||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||
$componentController = _$componentController_;
|
||||
controller = $componentController('vnColumnHeader', {});
|
||||
$event = {
|
||||
preventDefault: () => {}
|
||||
};
|
||||
$attrs = {};
|
||||
controller = $componentController('vnColumnHeader', {$attrs});
|
||||
}));
|
||||
|
||||
describe('onClick()', () => {
|
||||
it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
|
||||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.order = 'ASC';
|
||||
controller.onClick();
|
||||
controller.onClick($event);
|
||||
|
||||
expect(controller.order).toEqual('DESC');
|
||||
});
|
||||
|
@ -25,7 +31,7 @@ describe('Component vnColumnHeader', () => {
|
|||
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();
|
||||
controller.onClick($event);
|
||||
|
||||
expect(controller.order).toEqual('ASC');
|
||||
});
|
||||
|
@ -34,7 +40,7 @@ describe('Component vnColumnHeader', () => {
|
|||
controller.gridHeader = {selectColum: () => {}};
|
||||
controller.order = 'Change me!';
|
||||
spyOn(controller.gridHeader, 'selectColum');
|
||||
controller.onClick();
|
||||
controller.onClick($event);
|
||||
|
||||
expect(controller.gridHeader.selectColum).toHaveBeenCalledWith(controller);
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue