merge pull changes
gitea/salix/1625-worker_department_treeview This commit looks good
Details
gitea/salix/1625-worker_department_treeview This commit looks good
Details
This commit is contained in:
parent
b32cf4a386
commit
eb655215f4
|
@ -1,5 +1,6 @@
|
|||
USE `vn`;
|
||||
|
||||
CREATE TABLE vn.`zoneWarehouse` (
|
||||
CREATE TABLE `vn`.`zoneWarehouse` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`zoneFk` int(11) NOT NULL,
|
||||
`warehouseFk` smallint(6) unsigned NOT NULL,
|
||||
|
@ -10,7 +11,7 @@ CREATE TABLE vn.`zoneWarehouse` (
|
|||
CONSTRAINT `zoneWarehouse_ibfk_2` FOREIGN KEY (`warehouseFk`) REFERENCES `vn2008`.`warehouse` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE vn.`zoneEvent` (
|
||||
CREATE TABLE `vn`.`zoneEvent` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`zoneFk` int(11) NOT NULL,
|
||||
`from` date DEFAULT NULL,
|
||||
|
@ -25,7 +26,7 @@ CREATE TABLE vn.`zoneEvent` (
|
|||
CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE vn.`zoneExclusion` (
|
||||
CREATE TABLE `vn`.`zoneExclusion` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`zoneFk` int(11) NOT NULL,
|
||||
`day` date NOT NULL,
|
||||
|
|
|
@ -175,8 +175,8 @@ export default {
|
|||
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
|
||||
},
|
||||
dms: {
|
||||
deleteFileButton: 'vn-client-dms-index vn-table vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||
firstDocWorker: 'vn-client-dms-index vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(8) > span',
|
||||
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
|
||||
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
|
||||
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
|
||||
acceptDeleteButton: 'vn-client-dms-index > vn-confirm button[response="ACCEPT"]'
|
||||
},
|
||||
|
@ -190,8 +190,8 @@ export default {
|
|||
searchItemInput: 'vn-searchbar vn-textfield input',
|
||||
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
||||
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close',
|
||||
fieldsToShowButton: 'vn-item-index vn-table > div.ng-scope > div > vn-icon-button[icon="menu"]',
|
||||
fieldsToShowForm: 'vn-item-index > div > vn-card > div > vn-table > div.ng-scope > div > vn-dialog > div > form',
|
||||
fieldsToShowButton: 'vn-item-index vn-table > div > div > vn-icon-button[icon="menu"]',
|
||||
fieldsToShowForm: 'vn-item-index vn-table > div > div > vn-dialog > div > form',
|
||||
firstItemImage: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(1)',
|
||||
firstItemId: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(2)',
|
||||
idCheckbox: 'vn-item-index vn-dialog form vn-horizontal:nth-child(2) > vn-check',
|
||||
|
@ -494,9 +494,9 @@ export default {
|
|||
},
|
||||
ticketLog: {
|
||||
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
|
||||
changedBy: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
|
||||
actionTaken: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > div > div:nth-child(3) > span.value.ng-scope.ng-binding',
|
||||
id: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr > vn-td.before > vn-one:nth-child(1) > div > span.value.ng-scope.ng-binding'
|
||||
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
|
||||
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
|
||||
id: 'vn-ticket-log > vn-log vn-td.before > vn-one:nth-child(1) > div > span.value'
|
||||
},
|
||||
ticketService: {
|
||||
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
|
||||
|
|
|
@ -65,6 +65,18 @@ describe('Client create path', () => {
|
|||
expect(result).toEqual('Some fields are invalid');
|
||||
});
|
||||
|
||||
it(`should attempt to create a new user with all it's data but wrong postal code`, async() => {
|
||||
const result = await nightmare
|
||||
.clearInput(selectors.createClientView.email)
|
||||
.write(selectors.createClientView.email, 'CarolDanvers@verdnatura.es')
|
||||
.clearInput(selectors.createClientView.postcode)
|
||||
.write(selectors.createClientView.postcode, '479999')
|
||||
.waitToClick(selectors.createClientView.createButton)
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result).toEqual(`The postcode doesn't exists. Ensure you put the correct format`);
|
||||
});
|
||||
|
||||
it(`should check for autocompleted city, province and country`, async() => {
|
||||
const clientCity = await nightmare
|
||||
.waitToGetProperty(`${selectors.createClientView.city}`, 'value');
|
||||
|
@ -82,8 +94,8 @@ describe('Client create path', () => {
|
|||
|
||||
it(`should create a new user with all correct data`, async() => {
|
||||
const result = await nightmare
|
||||
.clearInput(selectors.createClientView.email)
|
||||
.write(selectors.createClientView.email, 'caroldanvers@verdnatura.es')
|
||||
.clearInput(selectors.createClientView.postcode)
|
||||
.write(selectors.createClientView.postcode, '46000')
|
||||
.waitToClick(selectors.createClientView.createButton)
|
||||
.waitForLastSnackbar();
|
||||
|
||||
|
|
|
@ -262,10 +262,12 @@ export default class Calendar extends Component {
|
|||
*/
|
||||
select(index) {
|
||||
if (this.disabled) return;
|
||||
let day = this.days[index];
|
||||
day.index = index;
|
||||
let day = this.days[index].dated;
|
||||
|
||||
this.emit('selection', {values: [day]});
|
||||
this.emit('selection', {
|
||||
$days: [day],
|
||||
$type: 'day'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,15 +278,17 @@ export default class Calendar extends Component {
|
|||
selectAll(weekday) {
|
||||
if (this.disabled) return;
|
||||
|
||||
let selected = [];
|
||||
let days = [];
|
||||
for (let i in this.days) {
|
||||
const day = this.days[i];
|
||||
const date = day.dated;
|
||||
day.index = i;
|
||||
if (date.getDay() === weekday && date.getMonth() == this.defaultDate.getMonth())
|
||||
selected.push(day);
|
||||
const day = this.days[i].dated;
|
||||
if (day.getDay() === weekday && day.getMonth() == this.defaultDate.getMonth())
|
||||
days.push(day);
|
||||
}
|
||||
this.emit('selection', {values: selected});
|
||||
this.emit('selection', {
|
||||
$days: days,
|
||||
$type: 'weekday',
|
||||
$weekday: weekday
|
||||
});
|
||||
}
|
||||
|
||||
renderStyle(style) {
|
||||
|
|
|
@ -60,12 +60,17 @@ describe('Component vnCalendar', () => {
|
|||
describe('select()', () => {
|
||||
it(`should return the selected element, then emit a 'selection' event`, () => {
|
||||
spyOn(controller, 'emit');
|
||||
const days = [{dated: new Date()}];
|
||||
const dated = new Date();
|
||||
const days = [{dated}];
|
||||
controller.days = days;
|
||||
|
||||
controller.select(0);
|
||||
|
||||
expect(controller.emit).toHaveBeenCalledWith('selection', {values: days});
|
||||
let res = {
|
||||
$days: [dated],
|
||||
$type: 'day'
|
||||
};
|
||||
|
||||
expect(controller.emit).toHaveBeenCalledWith('selection', res);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="check">
|
||||
<div class="btn">
|
||||
<div class="focus-mark"></div>
|
||||
<div class="mark"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,29 +1,16 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import Toggle from '../toggle';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Basic element for user input. You can use this to supply a way for the user
|
||||
* to toggle an option.
|
||||
*
|
||||
* @property {String} label Label to display along the component
|
||||
* @property {any} field The value with which the element is linked
|
||||
* @property {Boolean} checked Whether the checkbox is checked
|
||||
* @property {Boolean} disabled Put component in disabled mode
|
||||
* @property {Boolean} tripleState Switch between three states when clicked
|
||||
* @property {Boolean} indeterminate Sets the element into indeterminate state
|
||||
* @property {String} info Shows a text information tooltip to the user
|
||||
*/
|
||||
export default class Controller extends Component {
|
||||
constructor($element, $, $attrs) {
|
||||
super($element, $);
|
||||
|
||||
let element = this.element;
|
||||
element.addEventListener('click', e => this.onClick(e));
|
||||
element.addEventListener('keydown', e => this.onKeydown(e));
|
||||
element.tabIndex = 0;
|
||||
}
|
||||
|
||||
export default class Check extends Toggle {
|
||||
set field(value) {
|
||||
this._field = value;
|
||||
this.element.classList.toggle('checked', Boolean(value));
|
||||
|
@ -34,14 +21,12 @@ export default class Controller extends Component {
|
|||
return this._field;
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
this.element.tabIndex = !value ? 0 : -1;
|
||||
this.element.classList.toggle('disabled', Boolean(value));
|
||||
this._disabled = value;
|
||||
set checked(value) {
|
||||
this.field = Boolean(value);
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this._disabled;
|
||||
get checked() {
|
||||
return Boolean(this.field);
|
||||
}
|
||||
|
||||
set indeterminate(value) {
|
||||
|
@ -63,9 +48,7 @@ export default class Controller extends Component {
|
|||
}
|
||||
|
||||
onClick(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.disabled) return;
|
||||
if (super.onClick(event)) return;
|
||||
|
||||
if (this.tripleState) {
|
||||
if (this.field == null)
|
||||
|
@ -77,28 +60,18 @@ export default class Controller extends Component {
|
|||
} else
|
||||
this.field = !this.field;
|
||||
|
||||
this.$.$applyAsync();
|
||||
this.element.dispatchEvent(new Event('change'));
|
||||
this.emit('change', {value: this.field});
|
||||
}
|
||||
|
||||
onKeydown(event) {
|
||||
if (event.code == 'Space')
|
||||
this.onClick(event);
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$attrs'];
|
||||
|
||||
ngModule.component('vnCheck', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
|
||||
controller: Check,
|
||||
bindings: {
|
||||
label: '@?',
|
||||
field: '=?',
|
||||
checked: '<?',
|
||||
disabled: '<?',
|
||||
checked: '<?',
|
||||
tripleState: '<?',
|
||||
indeterminate: '<?',
|
||||
info: '@?'
|
||||
|
|
|
@ -1,26 +1,9 @@
|
|||
@import "variables";
|
||||
|
||||
vn-check {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
& > .check {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
& > .btn {
|
||||
border-radius: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transition: background 250ms;
|
||||
border: 2px solid #666;
|
||||
margin: 6px 0;
|
||||
margin-right: .4em;
|
||||
|
||||
& > .mark {
|
||||
box-sizing: border-box;
|
||||
|
@ -29,13 +12,10 @@ vn-check {
|
|||
border-width: 0;
|
||||
}
|
||||
}
|
||||
&.checked > .check {
|
||||
background-color: $color-main;
|
||||
&.checked > .btn {
|
||||
border-color: $color-main;
|
||||
background-color: $color-main;
|
||||
|
||||
& > .focus-mark {
|
||||
background-color: rgba($color-main, .15);
|
||||
}
|
||||
& > .mark {
|
||||
top: 0;
|
||||
left: 4px;
|
||||
|
@ -47,7 +27,7 @@ vn-check {
|
|||
border-left: 0;
|
||||
}
|
||||
}
|
||||
&.indeterminate > .check > .mark {
|
||||
&.indeterminate > .btn > .mark {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
@ -55,23 +35,6 @@ vn-check {
|
|||
height: 2px;
|
||||
border-bottom: 2px solid #666;
|
||||
}
|
||||
& > .check > .focus-mark {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
margin-top: -19px;
|
||||
margin-left: -19px;
|
||||
border-radius: 50%;
|
||||
transform: scale3d(0, 0, 0);
|
||||
transition: background 250ms;
|
||||
transition: transform 250ms;
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
&:focus:not(.disabled) > .check > .focus-mark {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
& > vn-icon {
|
||||
margin-left: 5px;
|
||||
color: $color-font-secondary;
|
||||
|
|
|
@ -207,8 +207,8 @@ export default class CrudModel extends ModelProxy {
|
|||
sendRequest(filter, append) {
|
||||
this.cancelRequest();
|
||||
this.canceler = this.$q.defer();
|
||||
this.isRefreshing = !append;
|
||||
this.isPaging = append;
|
||||
if (!append) this.status = 'loading';
|
||||
|
||||
let params = Object.assign(
|
||||
{filter},
|
||||
|
@ -221,9 +221,8 @@ export default class CrudModel extends ModelProxy {
|
|||
|
||||
return this.$http.get(this._url, options).then(
|
||||
json => this.onRemoteDone(json, filter, append),
|
||||
json => this.onRemoteError(json)
|
||||
json => this.onRemoteError(json, append)
|
||||
).finally(() => {
|
||||
this.isRefreshing = false;
|
||||
this.isPaging = false;
|
||||
});
|
||||
}
|
||||
|
@ -243,7 +242,12 @@ export default class CrudModel extends ModelProxy {
|
|||
this.onRequestEnd();
|
||||
}
|
||||
|
||||
onRemoteError(err) {
|
||||
onRemoteError(err, append) {
|
||||
if (!append) {
|
||||
this.clear();
|
||||
this.status = 'error';
|
||||
}
|
||||
|
||||
this.onRequestEnd();
|
||||
throw err;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<div ng-if="$ctrl.isReady">
|
||||
<div ng-transclude></div>
|
||||
<vn-pagination
|
||||
model="$ctrl.model"
|
||||
pad-medium-top>
|
||||
</vn-pagination>
|
||||
</div>
|
||||
<div
|
||||
class="empty-rows"
|
||||
ng-if="!$ctrl.isReady"
|
||||
ng-switch="$ctrl.status">
|
||||
<vn-spinner
|
||||
ng-switch-when="loading"
|
||||
enable="::true">
|
||||
</vn-spinner>
|
||||
<span
|
||||
ng-switch-when="clear"
|
||||
translate>
|
||||
Enter a new search
|
||||
</span>
|
||||
<span
|
||||
ng-switch-when="error"
|
||||
translate>
|
||||
Ups! It seems there was an error
|
||||
</span>
|
||||
<span
|
||||
ng-switch-when="empty"
|
||||
translate>
|
||||
No results
|
||||
</span>
|
||||
</div>
|
|
@ -0,0 +1,33 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
export default class DataViewer {
|
||||
get isReady() {
|
||||
return this.status == 'ready';
|
||||
}
|
||||
|
||||
get status() {
|
||||
if (this.model)
|
||||
return this.model.status;
|
||||
|
||||
if (this.isLoading)
|
||||
return 'loading';
|
||||
if (!this.data)
|
||||
return 'clear';
|
||||
if (this.data.length)
|
||||
return 'ready';
|
||||
else
|
||||
return 'empty';
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnDataViewer', {
|
||||
template: require('./index.html'),
|
||||
transclude: true,
|
||||
controller: DataViewer,
|
||||
bindings: {
|
||||
model: '<?',
|
||||
data: '<?',
|
||||
isLoading: '<?'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
@import "variables";
|
||||
|
||||
vn-data-viewer {
|
||||
display: block;
|
||||
|
||||
& > .empty-rows {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 1.5em;
|
||||
box-sizing: border-box;
|
||||
color: $color-font-secondary;
|
||||
font-size: 1.4em;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<div class="container">
|
||||
<div
|
||||
ng-transclude="prepend"
|
||||
class="prepend">
|
||||
</div>
|
||||
<div class="infix">
|
||||
<div class="fix prefix"></div>
|
||||
<div class="control">
|
||||
<input type="text" ng-model="$ctrl.field"/>
|
||||
</div>
|
||||
<div class="fix suffix"></div>
|
||||
<label>
|
||||
<span translate>{{::$ctrl.label}}</span>
|
||||
<span class="required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="icons">
|
||||
<vn-icon
|
||||
icon="clear"
|
||||
translate-attr="{title: 'Clear'}"
|
||||
ng-click="$ctrl.onClear()">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
ng-if="::$ctrl.info"
|
||||
icon="info_outline"
|
||||
vn-tooltip="{{::$ctrl.info}}">
|
||||
</vn-icon>
|
||||
</div>
|
||||
<div
|
||||
ng-transclude="append"
|
||||
class="append">
|
||||
</div>
|
||||
<div class="underline blur"></div>
|
||||
<div class="underline focus"></div>
|
||||
</div>
|
||||
<div class="hint"></div>
|
|
@ -0,0 +1,178 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import './style.scss';
|
||||
|
||||
export default class Field extends Component {
|
||||
constructor($element, $scope) {
|
||||
super($element, $scope);
|
||||
this._value = undefined;
|
||||
this.prefix = null;
|
||||
this.suffix = null;
|
||||
|
||||
this.input = this.element.querySelector('input');
|
||||
this.classList = this.element.classList;
|
||||
this.classList.add('vn-field');
|
||||
|
||||
this.element.addEventListener('focusin',
|
||||
() => this.onFocus(true));
|
||||
this.element.addEventListener('focusout',
|
||||
() => this.onFocus(false));
|
||||
this.element.addEventListener('click',
|
||||
() => this.onClick());
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.info) this.classList.add('has-icons');
|
||||
}
|
||||
|
||||
set field(value) {
|
||||
this._field = value;
|
||||
this.classList.toggle('not-empty', value != null && value !== '');
|
||||
}
|
||||
|
||||
get field() {
|
||||
return this._field;
|
||||
}
|
||||
|
||||
set type(value) {
|
||||
this.input.type = value;
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this.input.type;
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
this._disabled = boolTag(value);
|
||||
this.input.disabled = this._disabled;
|
||||
this.classList.toggle('disabled', this._disabled);
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this._disabled;
|
||||
}
|
||||
|
||||
set readonly(value) {
|
||||
this._readonly = boolTag(value);
|
||||
this.input.readOnly = this._readonly;
|
||||
this.classList.toggle('readonly', this._readonly);
|
||||
}
|
||||
|
||||
get readonly() {
|
||||
return this._readonly;
|
||||
}
|
||||
|
||||
set required(value) {
|
||||
this._required = boolTag(value);
|
||||
let required = this.element.querySelector('.required');
|
||||
display(required, this._required);
|
||||
}
|
||||
|
||||
get required() {
|
||||
return this._required;
|
||||
}
|
||||
|
||||
set prefix(value) {
|
||||
this._prefix = value;
|
||||
this.refreshFix('.prefix', value);
|
||||
}
|
||||
|
||||
get prefix() {
|
||||
return this._prefix;
|
||||
}
|
||||
|
||||
set suffix(value) {
|
||||
this._suffix = value;
|
||||
this.refreshFix('.suffix', value);
|
||||
}
|
||||
|
||||
get suffix() {
|
||||
return this._suffix;
|
||||
}
|
||||
|
||||
set hint(value) {
|
||||
this._hint = value;
|
||||
this.refreshHint();
|
||||
}
|
||||
|
||||
get hint() {
|
||||
return this._hint;
|
||||
}
|
||||
|
||||
set error(value) {
|
||||
this._error = value;
|
||||
this.refreshHint();
|
||||
this.classList.toggle('invalid', Boolean(value));
|
||||
}
|
||||
|
||||
get error() {
|
||||
return this._error;
|
||||
}
|
||||
|
||||
refreshHint() {
|
||||
let hint = this.error || this.hint || '';
|
||||
let hintEl = this.element.querySelector('.hint');
|
||||
hintEl.innerText = hint;
|
||||
hintEl.classList.toggle('filled', Boolean(hint));
|
||||
}
|
||||
|
||||
refreshFix(selector, text) {
|
||||
let fix = this.element.querySelector(selector);
|
||||
display(fix, text);
|
||||
fix.innerText = text || '';
|
||||
}
|
||||
|
||||
onClick() {
|
||||
if (this.input !== document.activeElement)
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
onFocus(hasFocus) {
|
||||
this.classList.toggle('focused', hasFocus);
|
||||
}
|
||||
|
||||
onClear() {
|
||||
this.input.value = '';
|
||||
this.input.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
select() {
|
||||
this.input.select();
|
||||
}
|
||||
}
|
||||
Field.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.component('vnField', {
|
||||
template: require('./index.html'),
|
||||
transclude: {
|
||||
prepend: '?prepend',
|
||||
append: '?append'
|
||||
},
|
||||
controller: Field,
|
||||
bindings: {
|
||||
field: '=?',
|
||||
label: '@?',
|
||||
name: '@?',
|
||||
type: '@?',
|
||||
info: '@?',
|
||||
disabled: '@?',
|
||||
readonly: '@?',
|
||||
required: '@?',
|
||||
prefix: '@?',
|
||||
suffix: '@?',
|
||||
hint: '@?',
|
||||
error: '<?'
|
||||
}
|
||||
});
|
||||
|
||||
function boolTag(value) {
|
||||
return Boolean(value || value === '');
|
||||
}
|
||||
|
||||
function display(element, display) {
|
||||
element.style.display = display ? 'initial' : 'none';
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
@import "variables";
|
||||
|
||||
.vn-field {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
|
||||
& > .container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
height: 56px;
|
||||
|
||||
& > .infix {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: auto;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
|
||||
& > label {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 18px;
|
||||
line-height: 20px;
|
||||
pointer-events: none;
|
||||
color: $color-font-secondary;
|
||||
transition-property: top, color, font-size;
|
||||
transition-duration: 400ms;
|
||||
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
|
||||
|
||||
& > .required {
|
||||
display: none;
|
||||
color: $color-alert
|
||||
}
|
||||
}
|
||||
& > .fix {
|
||||
padding-top: 24px;
|
||||
line-height: 24px;
|
||||
font-size: $input-font-size;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms ease-in-out;
|
||||
|
||||
&.prefix {
|
||||
padding-right: 5px;
|
||||
}
|
||||
&.suffix {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
& > .control {
|
||||
height: 100%;
|
||||
flex: auto;
|
||||
}
|
||||
& > .control > input {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 8px;
|
||||
height: inherit;
|
||||
outline: none;
|
||||
border: none;
|
||||
font-family: Arial, sans-serif;
|
||||
display: block;
|
||||
font-size: $input-font-size;
|
||||
width: 100%;
|
||||
background: 0;
|
||||
color: inherit;
|
||||
box-sizing: border-box;
|
||||
|
||||
&[type=time],
|
||||
&[type=date] {
|
||||
clip-path: inset(0 20px 0 0);
|
||||
}
|
||||
&[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
|
||||
&::-webkit-outer-spin-button,
|
||||
&::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
&:invalid {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
& > .prepend,
|
||||
& > .append,
|
||||
& > .icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $color-font-secondary;
|
||||
}
|
||||
& > .prepend > prepend,
|
||||
& > .append > append,
|
||||
& > .icons {
|
||||
display: flex;
|
||||
|
||||
& > vn-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
& > .prepend > prepend {
|
||||
padding-right: 12px;
|
||||
}
|
||||
& > .append > append {
|
||||
padding-left: 12px;
|
||||
}
|
||||
& > .icons > vn-icon[icon=clear] {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
& > .underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: ' ';
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
|
||||
&.blur {
|
||||
border-bottom: 1px solid $color-input-underline;
|
||||
transition: border-color 200ms ease-in-out;
|
||||
}
|
||||
&.focus {
|
||||
height: 2px;
|
||||
background-color: $color-main;
|
||||
left: 50%;
|
||||
width: 0;
|
||||
transition-property: width, left, background-color;
|
||||
transition-duration: 300ms;
|
||||
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.not-empty > .container,
|
||||
&.focused > .container {
|
||||
& > .infix {
|
||||
& > .fix {
|
||||
opacity: 1;
|
||||
}
|
||||
& > label {
|
||||
top: 5px;
|
||||
color: $color-main;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.has-icons,
|
||||
&.not-empty:hover,
|
||||
&.not-empty.focused {
|
||||
& > .container > .append > append {
|
||||
padding-left: 0;
|
||||
}
|
||||
& > .container > .icons {
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
&:not(.disabled):not(.readonly) {
|
||||
&.focused > .container > .underline.focus {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
& > .container:hover > .underline.blur {
|
||||
border-color: $color-input-underline-hover;
|
||||
}
|
||||
&.not-empty:hover,
|
||||
&.not-empty.focused {
|
||||
& > .container > .icons > vn-icon[icon=clear] {
|
||||
display: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(.not-empty):not(.focused) > .container > .infix > .control > input {
|
||||
&[type=time],
|
||||
&[type=date] {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
&.readonly > .container {
|
||||
& > .infix > .control > input {
|
||||
caret-color: transparent;
|
||||
}
|
||||
& > .underline.blur {
|
||||
border-bottom-style: dashed;
|
||||
}
|
||||
}
|
||||
& > .hint {
|
||||
z-index: -1;
|
||||
padding-top: 8px;
|
||||
height: 20px;
|
||||
color: rgba(0, 0, 0, .4);
|
||||
font-size: 12px;
|
||||
transform: translateY(-28px);
|
||||
transition-property: opacity, transform, color;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
opacity: 0;
|
||||
|
||||
&.filled {
|
||||
z-index: 0;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
&.invalid {
|
||||
& > .container {
|
||||
& > .infix > label {
|
||||
color: $color-alert;
|
||||
}
|
||||
& > .underline.focus {
|
||||
background-color: $color-alert;
|
||||
}
|
||||
& > .underline.blur {
|
||||
border-bottom-color: $color-alert;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
& > .hint {
|
||||
color: $color-alert;
|
||||
}
|
||||
}
|
||||
}
|
||||
vn-table {
|
||||
.vn-field {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
|
@ -26,20 +26,21 @@ import './card/card';
|
|||
import './float-button/float-button';
|
||||
import './step-control/step-control';
|
||||
import './label-value/label-value';
|
||||
import './paging/paging';
|
||||
import './pagination/pagination';
|
||||
import './searchbar/searchbar';
|
||||
import './scroll-up/scroll-up';
|
||||
import './table';
|
||||
import './td-editable';
|
||||
import './input-range';
|
||||
import './calendar';
|
||||
import './check';
|
||||
import './chip';
|
||||
import './color-legend';
|
||||
import './data-viewer';
|
||||
import './field';
|
||||
import './input-number';
|
||||
import './input-time';
|
||||
import './input-file';
|
||||
import './radio';
|
||||
import './table';
|
||||
import './td-editable';
|
||||
import './th';
|
||||
import './treeview';
|
||||
|
|
|
@ -57,6 +57,7 @@ export default class ModelProxy extends DataModel {
|
|||
constructor($element, $scope) {
|
||||
super($element, $scope);
|
||||
this.resetChanges();
|
||||
this.status = 'clear';
|
||||
}
|
||||
|
||||
get orgData() {
|
||||
|
@ -90,6 +91,14 @@ export default class ModelProxy extends DataModel {
|
|||
|
||||
set data(value) {
|
||||
this._data = value;
|
||||
|
||||
if (value == null)
|
||||
this.status = 'clear';
|
||||
else if (value.length)
|
||||
this.status = 'ready';
|
||||
else
|
||||
this.status = 'empty';
|
||||
|
||||
this.emit('dataChange');
|
||||
this.emit('dataUpdate');
|
||||
}
|
||||
|
@ -109,8 +118,12 @@ export default class ModelProxy extends DataModel {
|
|||
this.removed.push(item);
|
||||
|
||||
this.isChanged = true;
|
||||
if (!this.data.length)
|
||||
this.status = 'empty';
|
||||
|
||||
this.emit('rowRemove', index);
|
||||
this.emit('dataUpdate');
|
||||
|
||||
if (this.autoSave)
|
||||
this.save();
|
||||
}
|
||||
|
@ -131,8 +144,11 @@ export default class ModelProxy extends DataModel {
|
|||
this.data.push(newRow);
|
||||
|
||||
this.isChanged = true;
|
||||
this.status = 'ready';
|
||||
|
||||
this.emit('rowInsert', index);
|
||||
this.emit('dataUpdate');
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -322,10 +338,10 @@ export class Paginable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @type {Boolean} Whether the model is refreshing.
|
||||
* @type {ready|loading|clear|empty|error} The current model status.
|
||||
*/
|
||||
get isRefreshing() {
|
||||
return false;
|
||||
get status() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<div
|
||||
ng-if="$ctrl.model.moreRows">
|
||||
<div ng-if="$ctrl.model.moreRows">
|
||||
<vn-icon-button
|
||||
ng-if="!$ctrl.model.isLoading"
|
||||
ng-if="!$ctrl.model.isPaging"
|
||||
icon="more_horiz"
|
||||
vn-tooltip="Load more"
|
||||
ng-click="$ctrl.onLoadClick()">
|
||||
</vn-icon-button>
|
||||
<vn-spinner
|
||||
ng-if="$ctrl.model.isLoading"
|
||||
enable="$ctrl.model.isLoading">
|
||||
ng-if="$ctrl.model.isPaging"
|
||||
enable="::true">
|
||||
</vn-spinner>
|
||||
</div>
|
|
@ -3,7 +3,8 @@ vn-pagination {
|
|||
display: block;
|
||||
text-align: center;
|
||||
|
||||
& > div > vn-icon-button {
|
||||
& > div > vn-icon-button {
|
||||
font-size: 2em;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<paging
|
||||
page="$ctrl.currentPage"
|
||||
page-size="$ctrl.numPerPage"
|
||||
ng-if="$ctrl.numPages>1"
|
||||
total="$ctrl.numItems"
|
||||
show-prev-next="true"
|
||||
show-first-last="false"
|
||||
active-class="active"
|
||||
ng-click="$ctrl.figureOutToDisplay()"
|
||||
paging-action="$ctrl.onPageChange(page)">
|
||||
</paging>
|
|
@ -1,58 +0,0 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
export default class Paging {
|
||||
get numPages() {
|
||||
return Math.ceil(this.numItems / this.numPerPage);
|
||||
}
|
||||
|
||||
constructor($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
this.where = this.filter;
|
||||
this.numPerPage = null;
|
||||
this.numItems = 0;
|
||||
$scope.$watch('$ctrl.index.model.length', () => this.onModelUpdated());
|
||||
}
|
||||
|
||||
$onChanges(changes) {
|
||||
if (!this.index) return;
|
||||
this.numPerPage = this.index.filter.size;
|
||||
this.currentPage = this.index.filter.page;
|
||||
if (changes.total)
|
||||
this.numItems = changes.total.currentValue;
|
||||
}
|
||||
|
||||
onModelUpdated() {
|
||||
let index = this.index;
|
||||
let filter = index.filter;
|
||||
|
||||
if (filter.page >= this.numPages && index.model.length >= this.numPerPage)
|
||||
this.numItems = filter.page * filter.size + 1;
|
||||
}
|
||||
|
||||
onPageChange(page) {
|
||||
this.index.filter.page = page;
|
||||
if (typeof this.pageChange === 'undefined') {
|
||||
this.index.accept();
|
||||
} else {
|
||||
this.pageChange();
|
||||
}
|
||||
}
|
||||
$doCheck() {
|
||||
if (this.index && this.index.filter && this.index.filter.page && this.index.filter.page != this.currentPage) {
|
||||
this.currentPage = this.index.filter.page;
|
||||
}
|
||||
}
|
||||
}
|
||||
Paging.$inject = ['$http', '$scope'];
|
||||
|
||||
ngModule.component('vnPaging', {
|
||||
template: require('./paging.html'),
|
||||
bindings: {
|
||||
index: '<',
|
||||
pageChange: '&?',
|
||||
total: '<'
|
||||
},
|
||||
controller: Paging
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
import './paging.js';
|
||||
|
||||
describe('Component vnPaging', () => {
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(angular.mock.module('vnCore', $translateProvider => {
|
||||
$translateProvider.translations('en', {});
|
||||
}));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, $rootScope) => {
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnPaging', {$scope});
|
||||
}));
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
@import "variables";
|
||||
|
||||
vn-paging {
|
||||
display: block;
|
||||
text-align: center;
|
||||
|
||||
ul {
|
||||
box-shadow: 0 0 .4em $color-shadow;
|
||||
background-color: #fff;
|
||||
display: inline-block;
|
||||
margin: 20px 0;
|
||||
border-radius: .1em;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline;
|
||||
|
||||
&:first-child > a,
|
||||
&:first-child > span {
|
||||
margin-left: 0;
|
||||
}
|
||||
&.active > a {
|
||||
background: $color-active;
|
||||
color: #fff;
|
||||
}
|
||||
& > a,
|
||||
& > span {
|
||||
position: relative;
|
||||
float: left;
|
||||
padding: 6px 12px;
|
||||
margin-left: -1px;
|
||||
line-height: 1.42857143;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
&:not(.active) > a:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -180,11 +180,8 @@ export default class Popover extends Component {
|
|||
|
||||
onDocKeyDown(event) {
|
||||
if (event.defaultPrevented) return;
|
||||
|
||||
if (event.keyCode == 27) { // Esc
|
||||
event.preventDefault();
|
||||
if (event.code == 'Escape')
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
onMouseDown(event) {
|
||||
|
|
|
@ -1,29 +1,14 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import Toggle from '../toggle';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Basic element for user input. You can use this to supply a way for the user
|
||||
* to pick an option from multiple choices.
|
||||
*
|
||||
* @property {String} label Label to display along the component
|
||||
* @property {any} field The value with which the element is linked
|
||||
* @property {Boolean} checked Whether the radio is checked
|
||||
* @property {String} val The actual value of the option
|
||||
* @property {Boolean} disabled Put component in disabled mode
|
||||
*/
|
||||
export default class Controller extends Component {
|
||||
constructor($element, $, $attrs) {
|
||||
super($element, $);
|
||||
this.hasInfo = Boolean($attrs.info);
|
||||
this.info = $attrs.info || null;
|
||||
|
||||
let element = this.element;
|
||||
element.addEventListener('click', e => this.onClick(e));
|
||||
element.addEventListener('keydown', e => this.onKeydown(e));
|
||||
element.tabIndex = 0;
|
||||
}
|
||||
|
||||
export default class Radio extends Toggle {
|
||||
set field(value) {
|
||||
this._field = value;
|
||||
this.element.classList.toggle('checked',
|
||||
|
@ -34,6 +19,14 @@ export default class Controller extends Component {
|
|||
return this._field;
|
||||
}
|
||||
|
||||
set checked(value) {
|
||||
this.field = value ? this.val : null;
|
||||
}
|
||||
|
||||
get checked() {
|
||||
return this.field == this.val;
|
||||
}
|
||||
|
||||
set val(value) {
|
||||
this._val = value;
|
||||
this.field = this.field;
|
||||
|
@ -43,51 +36,21 @@ export default class Controller extends Component {
|
|||
return this._val;
|
||||
}
|
||||
|
||||
set checked(value) {
|
||||
this.field = value ? this.val : null;
|
||||
this.$.$applyAsync();
|
||||
}
|
||||
|
||||
get checked() {
|
||||
return this.field == this.val;
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
this.element.tabIndex = !value ? 0 : -1;
|
||||
this.element.classList.toggle('disabled', Boolean(value));
|
||||
this._disabled = value;
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this._disabled;
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
if (this.disabled) return;
|
||||
event.preventDefault();
|
||||
|
||||
if (super.onClick(event)) return;
|
||||
this.field = this.val;
|
||||
this.$.$applyAsync();
|
||||
this.element.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
onKeydown(event) {
|
||||
if (event.code == 'Space')
|
||||
this.onClick(event);
|
||||
this.changed();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', '$attrs'];
|
||||
|
||||
ngModule.component('vnRadio', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
|
||||
template: require('../toggle/index.html'),
|
||||
controller: Radio,
|
||||
bindings: {
|
||||
label: '@?',
|
||||
field: '=?',
|
||||
disabled: '<?',
|
||||
checked: '<?',
|
||||
val: '@?',
|
||||
disabled: '<?'
|
||||
val: '@?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
describe('Component vnCheck', () => {
|
||||
describe('Component vnRadio', () => {
|
||||
let $element;
|
||||
let $ctrl;
|
||||
let element;
|
||||
|
@ -8,8 +8,8 @@ describe('Component vnCheck', () => {
|
|||
}));
|
||||
|
||||
beforeEach(inject(($compile, $rootScope) => {
|
||||
$element = $compile(`<vn-check></vn-check`)($rootScope);
|
||||
$ctrl = $element.controller('vnCheck');
|
||||
$element = $compile(`<vn-radio val="myVal"></vn-radio`)($rootScope);
|
||||
$ctrl = $element.controller('vnRadio');
|
||||
element = $element[0];
|
||||
}));
|
||||
|
||||
|
@ -18,47 +18,10 @@ describe('Component vnCheck', () => {
|
|||
});
|
||||
|
||||
describe('field() setter', () => {
|
||||
it(`should set model value`, () => {
|
||||
$ctrl.field = true;
|
||||
|
||||
expect($ctrl.field).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should uncheck value and change to true when clicked`, () => {
|
||||
$ctrl.field = false;
|
||||
it(`should change field value when clicked`, () => {
|
||||
element.click();
|
||||
|
||||
expect($ctrl.field).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should check value and change to false when clicked`, () => {
|
||||
$ctrl.field = true;
|
||||
element.click();
|
||||
|
||||
expect($ctrl.field).toEqual(false);
|
||||
});
|
||||
|
||||
it(`should uncheck value and change to null when clicked`, () => {
|
||||
$ctrl.field = false;
|
||||
$ctrl.tripleState = true;
|
||||
element.click();
|
||||
|
||||
expect($ctrl.field).toEqual(null);
|
||||
});
|
||||
|
||||
it(`should set value to null and change to true when clicked`, () => {
|
||||
$ctrl.field = null;
|
||||
$ctrl.tripleState = true;
|
||||
element.click();
|
||||
|
||||
expect($ctrl.field).toEqual(true);
|
||||
});
|
||||
|
||||
it(`should cast value to boolean when clicked`, () => {
|
||||
$ctrl.field = 0;
|
||||
element.click();
|
||||
|
||||
expect($ctrl.field).toEqual(true);
|
||||
expect($ctrl.field).toEqual('myVal');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,31 +1,14 @@
|
|||
@import "variables";
|
||||
|
||||
vn-radio {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
& > .radio {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
& > .btn {
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #666;
|
||||
margin: 6px 0;
|
||||
margin-right: .4em;
|
||||
|
||||
& > .mark {
|
||||
transition: background 250ms;
|
||||
}
|
||||
}
|
||||
&.checked > .radio {
|
||||
&.checked > .btn {
|
||||
border-color: $color-main;
|
||||
|
||||
& > .mark {
|
||||
|
@ -38,25 +21,5 @@ vn-radio {
|
|||
height: 10px;
|
||||
background-color: $color-main;
|
||||
}
|
||||
& > .focus-mark {
|
||||
background-color: rgba($color-main, .15);
|
||||
}
|
||||
}
|
||||
& > .radio > .focus-mark {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
margin-top: -19px;
|
||||
margin-left: -19px;
|
||||
border-radius: 50%;
|
||||
transform: scale3d(0, 0, 0);
|
||||
transition: background 250ms;
|
||||
transition: transform 250ms;
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
&:focus:not(.disabled) > .radio > .focus-mark {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,2 @@
|
|||
<div class="table">
|
||||
<vn-empty-rows ng-if="$ctrl.isRefreshing">
|
||||
<vn-spinner enable="$ctrl.isRefreshing"></vn-spinner>
|
||||
</vn-empty-rows>
|
||||
<vn-empty-rows ng-if="$ctrl.model && !$ctrl.isRefreshing && !$ctrl.model.data">
|
||||
<span translate>Enter a new search</span>
|
||||
</vn-empty-rows>
|
||||
<vn-empty-rows ng-if="$ctrl.model && !$ctrl.isRefreshing && $ctrl.model.data.length == 0">
|
||||
<span translate>No results</span>
|
||||
</vn-empty-rows>
|
||||
<div class="table" ng-transclude>
|
||||
</div>
|
|
@ -8,18 +8,6 @@ export default class Table {
|
|||
this.field = null;
|
||||
this.order = null;
|
||||
this.autoLoad = true;
|
||||
|
||||
$transclude($scope.$parent, clone => {
|
||||
angular.element($element[0].querySelector('.table')).append(clone);
|
||||
});
|
||||
}
|
||||
|
||||
get isRefreshing() {
|
||||
return (this.model && this.model.isRefreshing);
|
||||
}
|
||||
|
||||
get isPaging() {
|
||||
return (this.model && this.model.isPaging);
|
||||
}
|
||||
|
||||
setOrder(field, order) {
|
||||
|
@ -37,7 +25,9 @@ export default class Table {
|
|||
}
|
||||
|
||||
$onChanges() {
|
||||
if (this.model && this.autoLoad)
|
||||
// FIXME: The autoload property should be removed from vnTable
|
||||
// because it's already implemented at vnModel
|
||||
if (this.autoLoad && this.model && !this.model.data)
|
||||
this.applyOrder();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,14 +51,15 @@ vn-table {
|
|||
}
|
||||
& > * > vn-tr,
|
||||
& > * > a.vn-tr {
|
||||
display: table-row
|
||||
display: table-row;
|
||||
height: 3em;
|
||||
}
|
||||
vn-thead, vn-tbody, vn-tfoot {
|
||||
& > * {
|
||||
display: table-row;
|
||||
|
||||
& > vn-th {
|
||||
font-weight: bold;
|
||||
color: $color-font-light;
|
||||
padding-top: 1em;
|
||||
padding-bottom: .8em;
|
||||
}
|
||||
|
@ -97,10 +98,10 @@ vn-table {
|
|||
}
|
||||
}
|
||||
& > :last-child {
|
||||
padding-right: 1em;
|
||||
padding-right: 1.4em;
|
||||
}
|
||||
& > :first-child {
|
||||
padding-left: 1em;
|
||||
padding-left: 1.4em;
|
||||
}
|
||||
}
|
||||
& > a.vn-tr {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="radio">
|
||||
<div class="btn">
|
||||
<div class="focus-mark"></div>
|
||||
<div class="mark"></div>
|
||||
</div>
|
|
@ -0,0 +1,62 @@
|
|||
import ngModule from '../../module';
|
||||
import Component from '../../lib/component';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Base component with common logic and styles for checkbox and radio button.
|
||||
*
|
||||
* @property {String} label Label to display along the component
|
||||
* @property {any} field The value with which the element is linked
|
||||
* @property {Boolean} checked Whether the checkbox is checked
|
||||
* @property {Boolean} disabled Put component in disabled mode
|
||||
*/
|
||||
export default class Toggle extends Component {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
let element = this.element;
|
||||
element.tabIndex = 0;
|
||||
element.addEventListener('click', e => this.onClick(e));
|
||||
element.addEventListener('keydown', e => this.onKeydown(e));
|
||||
element.classList.add('vn-toggle');
|
||||
}
|
||||
|
||||
set disabled(value) {
|
||||
this.element.tabIndex = !value ? 0 : -1;
|
||||
this.element.classList.toggle('disabled', Boolean(value));
|
||||
this._disabled = value;
|
||||
}
|
||||
|
||||
get disabled() {
|
||||
return this._disabled;
|
||||
}
|
||||
|
||||
onKeydown(event) {
|
||||
if (event.code == 'Space')
|
||||
this.onClick(event);
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
if (this.disabled || event.defaultPrevented)
|
||||
return true;
|
||||
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
changed() {
|
||||
this.$.$applyAsync();
|
||||
this.element.dispatchEvent(new Event('change'));
|
||||
this.emit('change', {value: this.field});
|
||||
}
|
||||
}
|
||||
Toggle.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.component('vnToggle', {
|
||||
controller: Toggle,
|
||||
bindings: {
|
||||
label: '@?',
|
||||
field: '=?',
|
||||
disabled: '<?',
|
||||
checked: '<?'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
@import "variables";
|
||||
|
||||
.vn-toggle {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
|
||||
&.disabled {
|
||||
cursor: inherit;
|
||||
}
|
||||
& > span {
|
||||
font-size: $input-font-size;
|
||||
}
|
||||
& > .btn {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 6px 0;
|
||||
margin-right: .4em;
|
||||
border: 2px solid #666;
|
||||
}
|
||||
&.checked > .btn {
|
||||
border-color: $color-main;
|
||||
|
||||
& > .focus-mark {
|
||||
background-color: rgba($color-main, .15);
|
||||
}
|
||||
}
|
||||
& > .btn > .focus-mark {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
margin-top: -19px;
|
||||
margin-left: -19px;
|
||||
border-radius: 50%;
|
||||
transform: scale3d(0, 0, 0);
|
||||
transition: background 250ms;
|
||||
transition: transform 250ms;
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
&:focus:not(.disabled) > .btn > .focus-mark {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,5 @@
|
|||
@import "effects";
|
||||
|
||||
vn-treeview {
|
||||
& > .add-item {
|
||||
@extend %clickable;
|
||||
}
|
||||
}
|
||||
|
||||
vn-treeview-childs {
|
||||
display: block;
|
||||
|
||||
|
@ -13,9 +7,26 @@ vn-treeview-childs {
|
|||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
& > li {
|
||||
li {
|
||||
list-style: none;
|
||||
|
||||
& > .node {
|
||||
@extend %clickable;
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
& > div > .arrow {
|
||||
min-width: 24px;
|
||||
margin-right: 10px;
|
||||
transition: transform 200ms;
|
||||
}
|
||||
|
||||
& > div.expanded > .arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 2.2em;
|
||||
}
|
||||
|
@ -35,33 +46,8 @@ vn-treeview-childs {
|
|||
.node:hover > .buttons {
|
||||
display: block
|
||||
}
|
||||
|
||||
& > ul > li > .node {
|
||||
@extend %clickable;
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
align-items: center;
|
||||
|
||||
& > .arrow {
|
||||
min-width: 24px;
|
||||
margin-right: 10px;
|
||||
transition: transform 200ms;
|
||||
}
|
||||
&.expanded > .arrow {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
& > vn-check:not(.indeterminate) {
|
||||
color: $color-main;
|
||||
|
||||
& > .check {
|
||||
border-color: $color-main;
|
||||
}
|
||||
}
|
||||
& > vn-check.checked {
|
||||
color: $color-main;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vn-treeview-content {
|
||||
flex-grow: 1;
|
||||
flex-grow: 1
|
||||
}
|
|
@ -2,7 +2,6 @@ import './module-loader';
|
|||
import './crud';
|
||||
import './acl-service';
|
||||
import './template';
|
||||
import './interpolate';
|
||||
import './copy';
|
||||
import './equals';
|
||||
import './modified';
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import {ng} from '../vendor';
|
||||
|
||||
function stringify(value) {
|
||||
if (value === null) { // null || undefined
|
||||
return '';
|
||||
}
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
break;
|
||||
case 'number':
|
||||
value = String(value);
|
||||
break;
|
||||
default:
|
||||
value = angular.toJson(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
var $interpolateMinErr = ng.$interpolateMinErr = ng.$$minErr('$interpolate');
|
||||
|
||||
$interpolateMinErr.throwNoconcat = function(text) {
|
||||
throw $interpolateMinErr('noconcat',
|
||||
'Error while interpolating: {0}\nStrict Contextual Escaping disallows ' +
|
||||
'interpolations that concatenate multiple expressions when a trusted value is ' +
|
||||
'required. See http://docs.angularjs.org/api/ng.$sce', text);
|
||||
};
|
||||
|
||||
$interpolateMinErr.interr = function(text, err) {
|
||||
return $interpolateMinErr('interr', 'Can\'t interpolate: {0}\n{1}', text, err.toString());
|
||||
};
|
||||
|
||||
function $get($parse, $exceptionHandler, $sce) {
|
||||
let startSymbolLength = this._startSymbol.length;
|
||||
let endSymbolLength = this._endSymbol.length;
|
||||
let escapedStartRegexp = new RegExp(this._startSymbol.replace(/./g, escape), 'g');
|
||||
let escapedEndRegexp = new RegExp(this._endSymbol.replace(/./g, escape), 'g');
|
||||
let self = this;
|
||||
|
||||
function escape(ch) {
|
||||
return '\\\\\\' + ch;
|
||||
}
|
||||
|
||||
function unescapeText(text) {
|
||||
return text.replace(escapedStartRegexp, self._startSymbol)
|
||||
.replace(escapedEndRegexp, self._endSymbol);
|
||||
}
|
||||
|
||||
// TODO: this is the same as the constantWatchDelegate in parse.js
|
||||
function constantWatchDelegate(scope, listener, objectEquality, constantInterp) {
|
||||
var unwatch = scope.$watch(function constantInterpolateWatch(scope) {
|
||||
unwatch();
|
||||
return constantInterp(scope);
|
||||
}, listener, objectEquality);
|
||||
return unwatch;
|
||||
}
|
||||
|
||||
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
|
||||
// Provide a quick exit and simplified result function for text with no interpolation
|
||||
if (!text.length || text.indexOf(self._startSymbol) === -1) {
|
||||
var constantInterp;
|
||||
if (!mustHaveExpression) {
|
||||
var unescapedText = unescapeText(text);
|
||||
constantInterp = valueFn(unescapedText);
|
||||
constantInterp.exp = text;
|
||||
constantInterp.expressions = [];
|
||||
constantInterp.$$watchDelegate = constantWatchDelegate;
|
||||
}
|
||||
return constantInterp;
|
||||
}
|
||||
|
||||
allOrNothing = Boolean(allOrNothing);
|
||||
let startIndex;
|
||||
let endIndex;
|
||||
let index = 0;
|
||||
let expressions = [];
|
||||
let parseFns = [];
|
||||
let textLength = text.length;
|
||||
let exp;
|
||||
let concat = [];
|
||||
let expressionPositions = [];
|
||||
|
||||
while (index < textLength) {
|
||||
if (((startIndex = text.indexOf(self._startSymbol, index)) !== -1) &&
|
||||
((endIndex = text.indexOf(self._endSymbol, startIndex + startSymbolLength)) !== -1)) {
|
||||
if (index !== startIndex)
|
||||
concat.push(unescapeText(text.substring(index, startIndex)));
|
||||
exp = text.substring(startIndex + startSymbolLength, endIndex);
|
||||
expressions.push(exp);
|
||||
parseFns.push($parse(exp, parseStringifyInterceptor));
|
||||
index = endIndex + endSymbolLength;
|
||||
expressionPositions.push(concat.length);
|
||||
concat.push('');
|
||||
} else {
|
||||
// we did not find an interpolation, so we have to add the remainder to the separators array
|
||||
if (index !== textLength)
|
||||
concat.push(unescapeText(text.substring(index)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trustedContext && concat.length > 1) {
|
||||
$interpolateMinErr.throwNoconcat(text);
|
||||
}
|
||||
|
||||
var getValue = function(value) {
|
||||
return trustedContext ?
|
||||
$sce.getTrusted(trustedContext, value) :
|
||||
$sce.valueOf(value);
|
||||
};
|
||||
|
||||
if (!mustHaveExpression || expressions.length) {
|
||||
var compute = function(values) {
|
||||
for (var i = 0, ii = expressions.length; i < ii; i++) {
|
||||
if (allOrNothing && isUndefined(values[i])) return;
|
||||
concat[expressionPositions[i]] = values[i];
|
||||
}
|
||||
return concat.join('');
|
||||
};
|
||||
|
||||
return angular.extend(function interpolationFn(context) {
|
||||
var i = 0;
|
||||
var ii = expressions.length;
|
||||
var values = new Array(ii);
|
||||
|
||||
try {
|
||||
for (; i < ii; i++) {
|
||||
values[i] = parseFns[i](context);
|
||||
}
|
||||
|
||||
return compute(values);
|
||||
} catch (err) {
|
||||
$exceptionHandler($interpolateMinErr.interr(text, err));
|
||||
}
|
||||
}, {
|
||||
// all of these properties are undocumented for now
|
||||
exp: text, // just for compatibility with regular watchers created via $watch
|
||||
expressions: expressions
|
||||
});
|
||||
}
|
||||
|
||||
function parseStringifyInterceptor(value) {
|
||||
try {
|
||||
value = getValue(value);
|
||||
return allOrNothing && !isDefined(value) ? value : stringify(value);
|
||||
} catch (err) {
|
||||
$exceptionHandler($interpolateMinErr.interr(text, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$interpolate.startSymbol = function() {
|
||||
return startSymbol;
|
||||
};
|
||||
|
||||
$interpolate.endSymbol = function() {
|
||||
return endSymbol;
|
||||
};
|
||||
|
||||
return $interpolate;
|
||||
}
|
||||
|
||||
$get.$inject = ['$parse', '$exceptionHandler', '$sce'];
|
||||
|
||||
export class Interpolate {
|
||||
constructor() {
|
||||
this._startSymbol = '*[';
|
||||
this._endSymbol = ']*';
|
||||
}
|
||||
set startSymbol(value) {
|
||||
if (value) {
|
||||
this._startSymbol = value;
|
||||
return this;
|
||||
}
|
||||
return this._startSymbol;
|
||||
}
|
||||
set endSymbol(value) {
|
||||
if (value) {
|
||||
this._endSymbol = value;
|
||||
return this;
|
||||
}
|
||||
return this._endSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
Interpolate.prototype.$get = $get;
|
||||
var interpolate = new Interpolate();
|
||||
ngModule.provider('vnInterpolate', () => interpolate);
|
|
@ -0,0 +1,34 @@
|
|||
import Component from './component';
|
||||
|
||||
/**
|
||||
* Class with commonly injected services assigned as properties. It also has
|
||||
* abbreviations for commonly used methods like tranlation.
|
||||
*
|
||||
* @property {Object} $translate Angular tranlation service
|
||||
* @property {Object} $http Angular HTTP service
|
||||
* @property {Object} $state Router state service
|
||||
* @property {Object} $stateParams Router state parameters
|
||||
*/
|
||||
export default class Section extends Component {
|
||||
constructor($element, $scope, $translate, $http, $state) {
|
||||
super($element, $scope);
|
||||
Object.assign(this, {
|
||||
$translate,
|
||||
$http,
|
||||
$state,
|
||||
$stateParams: $state.params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates an string.
|
||||
*
|
||||
* @param {String} string String to translate
|
||||
* @param {Array} params Translate parameters
|
||||
* @return {String} The translated string
|
||||
*/
|
||||
_(string, params) {
|
||||
return this.$translate.instant(string, params, );
|
||||
}
|
||||
}
|
||||
Section.$inject = ['$element', '$scope', '$translate', '$http', '$state'];
|
|
@ -1,13 +1,6 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
export default class Template {
|
||||
constructor(vnInterpolate) {
|
||||
this.vnInterpolate = vnInterpolate;
|
||||
}
|
||||
get(template, $attrs, defaults) {
|
||||
let scope = Object.assign({}, defaults, $attrs);
|
||||
return template && this.vnInterpolate(template)(scope);
|
||||
}
|
||||
getNormalized(template, $attrs, defaults) {
|
||||
this.normalizeInputAttrs($attrs);
|
||||
return this.get(template, $attrs, defaults);
|
||||
|
@ -43,6 +36,5 @@ export default class Template {
|
|||
$attrs.focus = 'vn-focus';
|
||||
}
|
||||
}
|
||||
Template.$inject = ['vnInterpolate'];
|
||||
|
||||
ngModule.service('vnTemplate', Template);
|
||||
|
|
|
@ -24,6 +24,9 @@ Value should be %s characters long: El valor debe ser de %s carácteres de longi
|
|||
Value should have a length between %s and %s: El valor debe tener una longitud de entre %s y %s
|
||||
Value should have at least %s characters: El valor debe tener al menos %s carácteres
|
||||
Value should have at most %s characters: El valor debe tener un máximo de %s carácteres
|
||||
Enter a new search: Introduce una nueva búsqueda
|
||||
No results: Sin resultados
|
||||
Ups! It seems there was an error: ¡Vaya! Parece que ha habido un error
|
||||
General search: Busqueda general
|
||||
January: Enero
|
||||
February: Febrero
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import './md-override.scss';
|
||||
import './mdl-override.scss';
|
||||
import './mdi-override.css';
|
||||
import './zoom-image.scss';
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
|
||||
html {
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
// Disable ng-repeat effects
|
||||
|
||||
.ng-enter,
|
||||
.ng-leave {
|
||||
transition: none !important;
|
||||
}
|
|
@ -7,10 +7,6 @@ import 'angular-translate-loader-partial';
|
|||
import '@uirouter/angularjs';
|
||||
import 'mg-crud';
|
||||
import 'oclazyload';
|
||||
/*
|
||||
import 'angular-material';
|
||||
import 'angular-material/modules/scss/angular-material.scss';
|
||||
*/
|
||||
import 'angular-moment';
|
||||
|
||||
export const ngDeps = [
|
||||
|
@ -18,7 +14,6 @@ export const ngDeps = [
|
|||
'ui.router',
|
||||
'mgCrud',
|
||||
'oc.lazyLoad',
|
||||
// 'ngMaterial',
|
||||
'angularMoment'
|
||||
];
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@ import ngModule from '../../module';
|
|||
import './style.scss';
|
||||
|
||||
export default class LeftMenu {
|
||||
constructor($state, $transitions, aclService) {
|
||||
constructor($state, $transitions, aclService, $timeout, $element) {
|
||||
this.$element = $element;
|
||||
this.$timeout = $timeout;
|
||||
this.$state = $state;
|
||||
this.deregisterCallback = $transitions.onSuccess({},
|
||||
() => this.activateItem());
|
||||
|
@ -89,13 +91,19 @@ export default class LeftMenu {
|
|||
setActive(item) {
|
||||
if (item.state) return;
|
||||
item.active = !item.active;
|
||||
|
||||
this.$timeout(() => {
|
||||
let element = this.$element[0].querySelector('a[class="expanded"]');
|
||||
if (element)
|
||||
element.scrollIntoView();
|
||||
});
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.deregisterCallback();
|
||||
}
|
||||
}
|
||||
LeftMenu.$inject = ['$state', '$transitions', 'aclService'];
|
||||
LeftMenu.$inject = ['$state', '$transitions', 'aclService', '$timeout', '$element'];
|
||||
|
||||
ngModule.component('vnLeftMenu', {
|
||||
template: require('./left-menu.html'),
|
||||
|
|
|
@ -2,16 +2,18 @@ import './left-menu.js';
|
|||
|
||||
describe('Component vnLeftMenu', () => {
|
||||
let controller;
|
||||
let $element;
|
||||
|
||||
beforeEach(angular.mock.module('salix', $translateProvider => {
|
||||
$translateProvider.translations('en', {});
|
||||
}));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, $state, $window) => {
|
||||
$element = angular.element('<div></div>');
|
||||
$state.current.name = 'client.card.summary';
|
||||
$state.current.data = {moduleIndex: 0};
|
||||
$window.routes = [{menu: []}];
|
||||
controller = $componentController('vnLeftMenu', {$state, $window});
|
||||
controller = $componentController('vnLeftMenu', {$state, $window, $element});
|
||||
controller.items = [
|
||||
{description: 'Client', state: 'client', icon: null, childs: []},
|
||||
{description: 'Client', state: 'client.card', icon: null, childs: []},
|
||||
|
|
|
@ -14,8 +14,6 @@ Push on applications menu: Para abrir un módulo pulsa en el menú de aplicacion
|
|||
Return to module index: Volver a la página principal del módulo
|
||||
What is new: Novedades de la versión
|
||||
Settings: Ajustes
|
||||
Enter a new search: Introduce una nueva búsqueda
|
||||
No results: Sin resultados
|
||||
|
||||
# Actions
|
||||
|
||||
|
|
|
@ -15,3 +15,4 @@ import './descriptor.scss';
|
|||
import './list.scss';
|
||||
import './modal-form.scss';
|
||||
import './photo-list.scss';
|
||||
import './width.scss';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "./effects";
|
||||
|
||||
.vn-list {
|
||||
max-width: 36em;
|
||||
max-width: $width-sm;
|
||||
margin: 0 auto;
|
||||
|
||||
a.vn-list-item {
|
||||
|
|
|
@ -47,7 +47,6 @@ vn-bg-title {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 18px;
|
||||
margin-bottom: 10px;
|
||||
max-width: 12em;
|
||||
}
|
||||
.form {
|
||||
|
@ -99,11 +98,6 @@ html [pointer], .pointer{
|
|||
html [noDrop], .noDrop{
|
||||
cursor: no-drop;
|
||||
}
|
||||
html [compact], .compact{
|
||||
max-width: $width-compact;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
button {
|
||||
@extend %clickable;
|
||||
}
|
||||
|
@ -147,6 +141,12 @@ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
|
|||
font-size: 0.7em
|
||||
}
|
||||
}
|
||||
[compact], .compact {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: $width-md;
|
||||
}
|
||||
|
||||
.vn-grid {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),
|
||||
0 3px 1px -2px rgba(0,0,0,.2),
|
||||
0 1px 5px 0 rgba(0,0,0,.12);
|
||||
background: no-repeat center center fixed;
|
||||
background-size: cover !important;
|
||||
overflow: hidden;
|
||||
cursor: zoom-in;
|
||||
height: 100%;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@import "variables";
|
||||
|
||||
/* Desktop - Laptop 1360x768 */
|
||||
@media (max-resolution: 119dpi) and (min-device-width: 1340px) and (max-device-width: 1899px)
|
||||
|
@ -46,3 +47,9 @@
|
|||
{
|
||||
body { font-size: 11pt; }
|
||||
}
|
||||
|
||||
.vn-hide-narrow {
|
||||
@media (max-width: $mobile-width) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,15 @@
|
|||
$menu-width: 16em;
|
||||
$topbar-height: 4em;
|
||||
$mobile-width: 800px;
|
||||
$input-font-size: 16px;
|
||||
|
||||
// Width
|
||||
|
||||
$width-small: 36em;
|
||||
$width-compact: 60em;
|
||||
$width-large: 80em;
|
||||
$width-xs: 25em;
|
||||
$width-sm: 34em;
|
||||
$width-md: 50em;
|
||||
$width-lg: 80em;
|
||||
$width-xl: 100em;
|
||||
|
||||
// Padding
|
||||
|
||||
|
@ -29,7 +32,8 @@ $margin-huge: 100px;
|
|||
$color-header: #3d3d3d;
|
||||
$color-bg: #e5e5e5;
|
||||
$color-bg-dark: #3d3d3d;
|
||||
$color-font: #222222;
|
||||
$color-font: #222;
|
||||
$color-font-light: #555;
|
||||
$color-font-secondary: #9b9b9b;
|
||||
$color-font-dark: white;
|
||||
$color-font-bg: rgba(0, 0, 0, .7);
|
||||
|
@ -46,8 +50,9 @@ $color-alert: #f42121;
|
|||
$color-spacer: rgba(0, 0, 0, .3);
|
||||
$color-spacer-light: rgba(0, 0, 0, .12);
|
||||
$color-input-underline: rgba(0, 0, 0, .12);
|
||||
$color-input-underline-hover: rgba(0, 0, 0, .6);
|
||||
$color-shadow: rgba(0, 0, 0, .2);
|
||||
$color-hightlight: rgba(0, 0, 0, .15);
|
||||
$color-hightlight: rgba(0, 0, 0, .05);
|
||||
$color-hover-cd: rgba(0, 0, 0, .1);
|
||||
$color-hover-dc: .7;
|
||||
$color-disabled: .6;
|
||||
|
@ -70,6 +75,7 @@ $color-header: #3d3d3d;
|
|||
$color-bg: #222;
|
||||
$color-bg-dark: #222;
|
||||
$color-font: white;
|
||||
$color-font-light: #aaa;
|
||||
$color-font-secondary: #777;
|
||||
$color-font-dark: white;
|
||||
$color-font-bg: rgba(0, 0, 0, .8);
|
||||
|
@ -82,6 +88,7 @@ $color-secondary: #ccc;
|
|||
$color-success: #a3d131;
|
||||
$color-notice: #32b1ce;
|
||||
$color-alert: #f42121;
|
||||
|
||||
$color-spacer: rgba(255, 255, 255, .3);
|
||||
$color-spacer-light: rgba(255, 255, 255, .12);
|
||||
$color-input-underline: rgba(255, 255, 255, .12);
|
||||
|
@ -104,5 +111,5 @@ $color-alert-light: darken($color-alert, 35%);
|
|||
|
||||
// Border
|
||||
|
||||
$border-thin: .1em solid $color-spacer;
|
||||
$border-thin-light: .1em solid $color-spacer-light;
|
||||
$border-thin: .05em solid $color-spacer;
|
||||
$border-thin-light: .05em solid $color-spacer-light;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
@import "./variables";
|
||||
|
||||
%margin-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.vn-w-xs {
|
||||
@extend %margin-auto;
|
||||
max-width: $width-xs;
|
||||
}
|
||||
.vn-w-sm {
|
||||
@extend %margin-auto;
|
||||
max-width: $width-sm;
|
||||
}
|
||||
.vn-w-md {
|
||||
@extend %margin-auto;
|
||||
max-width: $width-md;
|
||||
}
|
||||
.vn-w-lg {
|
||||
@extend %margin-auto;
|
||||
max-width: $width-lg;
|
||||
}
|
||||
.vn-w-xl {
|
||||
@extend %margin-auto;
|
||||
max-width: $width-xl;
|
||||
}
|
|
@ -5,7 +5,10 @@
|
|||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
|
||||
<form
|
||||
name="form"
|
||||
ng-submit="$ctrl.onSubmit()"
|
||||
class="vn-w-md">
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
|
@ -73,7 +76,14 @@
|
|||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save" vn-acl="deliveryBoss"></vn-submit>
|
||||
<vn-button label="Undo changes" ng-if="watcher.dataChanged()" ng-click="watcher.loadOriginalData()"></vn-button>
|
||||
<vn-submit
|
||||
label="Save"
|
||||
vn-acl="deliveryBoss">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
label="Undo changes"
|
||||
ng-if="watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
skip="2"
|
||||
has-events="$ctrl.hasEvents($day)"
|
||||
get-class="$ctrl.getClass($day)"
|
||||
on-selection="$ctrl.onSelection($days, $type, $weekday)"
|
||||
on-move-next="ndMonth.moveNext(2)"
|
||||
on-move-previous="ndMonth.movePrevious(2)"
|
||||
vn-acl="deliveryBoss"
|
||||
|
@ -13,6 +14,7 @@
|
|||
skip="2"
|
||||
has-events="$ctrl.hasEvents($day)"
|
||||
get-class="$ctrl.getClass($day)"
|
||||
on-selection="$ctrl.onSelection($days, $type, $weekday)"
|
||||
default-date="$ctrl.ndMonthDate"
|
||||
vn-acl="deliveryBoss"
|
||||
display-controls="false"
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'core/lib/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($, $stateParams) {
|
||||
Object.assign(this, {
|
||||
$,
|
||||
$stateParams
|
||||
});
|
||||
class Controller extends Section {
|
||||
constructor($el, $, $t, $http, $state) {
|
||||
super($el, $, $t, $http, $state);
|
||||
|
||||
this.excls = {};
|
||||
this.resetEvents();
|
||||
|
@ -14,6 +12,10 @@ class Controller {
|
|||
this.ndMonthDate.setMonth(this.ndMonthDate.getMonth() + 1);
|
||||
}
|
||||
|
||||
onSelection($days, $type, $weekday) {
|
||||
this.emit('selection', {$days, $type, $weekday});
|
||||
}
|
||||
|
||||
resetEvents() {
|
||||
this.wdays = [];
|
||||
this.days = {};
|
||||
|
@ -96,8 +98,6 @@ class Controller {
|
|||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$stateParams'];
|
||||
|
||||
ngModule.component('vnZoneCalendar', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-side-menu>
|
||||
<div class="content-block" ui-view></div>
|
||||
<div ui-view></div>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<div class="main-with-right-menu">
|
||||
<div class="vn-list" style="max-width: 30em;">
|
||||
<vn-card ng-if="data.length">
|
||||
<vn-data-viewer
|
||||
data="data"
|
||||
is-loading="!data"
|
||||
class="vn-w-sm">
|
||||
<vn-card>
|
||||
<div class="vn-list">
|
||||
<a
|
||||
ng-repeat="row in data"
|
||||
translate-attr="{title: 'Edit'}"
|
||||
|
@ -52,35 +56,23 @@
|
|||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
</div>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-bg-title ng-if="!data">
|
||||
<vn-spinner enable="true"></vn-spinner>
|
||||
</vn-bg-title>
|
||||
<vn-bg-title ng-if="data.length == 0" translate>
|
||||
No records found
|
||||
</vn-bg-title>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-side-menu side="right">
|
||||
<vn-zone-calendar
|
||||
events="data"
|
||||
exclusions="exclusions">
|
||||
exclusions="exclusions"
|
||||
on-selection="$ctrl.onCreate($days, $type, $weekday)">
|
||||
</vn-zone-calendar>
|
||||
</vn-side-menu>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
translate-attr="{title: 'Add'}"
|
||||
vn-bind="+"
|
||||
ng-click="$ctrl.onCreate()"
|
||||
fixed-bottom-right
|
||||
style="z-index: 10;">
|
||||
</vn-float-button>
|
||||
<vn-dialog
|
||||
vn-id="dialog"
|
||||
on-response="$ctrl.onSave(response)">
|
||||
<tpl-body>
|
||||
<vn-vertical>
|
||||
<vn-vertical>
|
||||
<vn-vertical pad-medium-bottom>
|
||||
<vn-radio
|
||||
field="$ctrl.eventType"
|
||||
label="One day"
|
||||
|
@ -88,13 +80,13 @@
|
|||
</vn-radio>
|
||||
<vn-radio
|
||||
field="$ctrl.eventType"
|
||||
label="Range of dates"
|
||||
val="range">
|
||||
label="Indefinitely"
|
||||
val="indefinitely">
|
||||
</vn-radio>
|
||||
<vn-radio
|
||||
field="$ctrl.eventType"
|
||||
label="Indefinitely"
|
||||
val="indefinitely">
|
||||
label="Range of dates"
|
||||
val="range">
|
||||
</vn-radio>
|
||||
</vn-vertical>
|
||||
<div
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'core/lib/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($, _, $http, $stateParams) {
|
||||
Object.assign(this, {
|
||||
$,
|
||||
_,
|
||||
$http
|
||||
});
|
||||
class Controller extends Section {
|
||||
constructor($el, $, $t, $http, $state) {
|
||||
super($el, $, $t, $http, $state);
|
||||
|
||||
this.wdays = [
|
||||
{
|
||||
|
@ -36,15 +33,15 @@ class Controller {
|
|||
|
||||
this.abrWdays = {};
|
||||
for (let wday of this.wdays) {
|
||||
let locale = _.instant(wday.name);
|
||||
let locale = this._(wday.name);
|
||||
this.abrWdays[wday.code] = locale.substr(0, 3);
|
||||
wday.abr = locale.substr(0, 1);
|
||||
}
|
||||
|
||||
this.$http.get(`/api/Zones/${$stateParams.id}/exclusions`)
|
||||
this.$http.get(`/api/Zones/${this.$stateParams.id}/exclusions`)
|
||||
.then(res => this.$.exclusions = res.data);
|
||||
|
||||
this.path = `/api/Zones/${$stateParams.id}/events`;
|
||||
this.path = `/api/Zones/${this.$stateParams.id}/events`;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
|
@ -62,7 +59,7 @@ class Controller {
|
|||
|
||||
return abrWdays.length < 7
|
||||
? abrWdays.join(', ')
|
||||
: this._.instant('Everyday');
|
||||
: this._('Everyday');
|
||||
}
|
||||
|
||||
onEdit(row, event) {
|
||||
|
@ -89,10 +86,19 @@ class Controller {
|
|||
this.$.dialog.show();
|
||||
}
|
||||
|
||||
onCreate() {
|
||||
onCreate($day, $type, $weekday) {
|
||||
this.isNew = true;
|
||||
this.eventType = 'day';
|
||||
this.selected = {};
|
||||
this.eventType = $type == 'day' ? 'day' : 'indefinitely';
|
||||
|
||||
if ($type == 'weekday') {
|
||||
let wdays = [];
|
||||
let index = $weekday - 1;
|
||||
if (index < 0) index = 7 - index;
|
||||
wdays[this.wdays[index].code] = true;
|
||||
this.selected = {wdays};
|
||||
} else
|
||||
this.selected = {from: $day[0]};
|
||||
|
||||
this.$.dialog.show();
|
||||
}
|
||||
|
||||
|
@ -153,7 +159,6 @@ class Controller {
|
|||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$translate', '$http', '$stateParams'];
|
||||
|
||||
ngModule.component('vnZoneEvents', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -1,50 +1,33 @@
|
|||
<vn-card
|
||||
ng-if="data.length"
|
||||
style="max-width: 25em; margin: 0 auto;">
|
||||
<vn-table>
|
||||
<vn-tbody>
|
||||
<div class="main-with-right-menu">
|
||||
<vn-data-viewer
|
||||
data="data"
|
||||
is-loading="!data"
|
||||
class="vn-w-xs">
|
||||
<vn-card>
|
||||
<vn-table>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="row in data | orderBy:'day'">
|
||||
<vn-td>{{::row.day | dateTime:'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td style="width: 1px; text-align: center">
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
translate-attr="{title: 'Delete'}"
|
||||
ng-click="$ctrl.onDelete($index)">
|
||||
ng-click="$ctrl.onDelete(row.id)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-bg-title ng-if="!data">
|
||||
<vn-spinner enable="true"></vn-spinner>
|
||||
</vn-bg-title>
|
||||
<vn-bg-title ng-if="data.length == 0" translate>
|
||||
No records found
|
||||
</vn-bg-title>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
translate-attr="{title: 'Add'}"
|
||||
vn-bind="+"
|
||||
ng-click="$ctrl.onCreate()"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
<vn-dialog
|
||||
vn-id="dialog"
|
||||
on-response="$ctrl.onSave(response)">
|
||||
<tpl-body>
|
||||
<vn-vertical>
|
||||
<vn-date-picker
|
||||
label="Day"
|
||||
model="$ctrl.selected.day">
|
||||
</vn-date-picker>
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="ACCEPT" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-side-menu side="right">
|
||||
<vn-zone-calendar
|
||||
events="events"
|
||||
exclusions="data"
|
||||
on-selection="$ctrl.onCreate($days)">
|
||||
</vn-zone-calendar>
|
||||
</vn-side-menu>
|
||||
<vn-confirm
|
||||
vn-id="confirm"
|
||||
message="This item will be deleted"
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'core/lib/section';
|
||||
|
||||
class Controller {
|
||||
constructor($, $http, $stateParams) {
|
||||
Object.assign(this, {
|
||||
$,
|
||||
$http
|
||||
});
|
||||
class Controller extends Section {
|
||||
constructor($el, $, $t, $http, $state) {
|
||||
super($el, $, $t, $http, $state);
|
||||
|
||||
this.path = `/api/Zones/${$stateParams.id}/exclusions`;
|
||||
this.$http.get(`/api/Zones/${this.$stateParams.id}/events`)
|
||||
.then(res => this.$.events = res.data);
|
||||
|
||||
this.path = `/api/Zones/${this.$stateParams.id}/exclusions`;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
|
@ -16,43 +17,26 @@ class Controller {
|
|||
.then(res => this.$.data = res.data);
|
||||
}
|
||||
|
||||
onCreate() {
|
||||
this.isNew = true;
|
||||
this.selected = {};
|
||||
this.$.dialog.show();
|
||||
onCreate($days) {
|
||||
this.$http.post(this.path, {day: $days[0]})
|
||||
.then(() => this.refresh());
|
||||
}
|
||||
|
||||
onSave(response) {
|
||||
if (response != 'ACCEPT') return;
|
||||
|
||||
this.$http.post(this.path, this.selected)
|
||||
.then(() => {
|
||||
this.selected = null;
|
||||
this.isNew = null;
|
||||
this.$.dialog.hide();
|
||||
this.refresh();
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
onDelete(index) {
|
||||
onDelete(id) {
|
||||
this.$.confirm.show();
|
||||
this.deleteIndex = index;
|
||||
this.deleteId = id;
|
||||
}
|
||||
|
||||
delete(response) {
|
||||
if (response != 'ACCEPT') return;
|
||||
let id = this.$.data[this.deleteIndex].id;
|
||||
if (!id) return;
|
||||
this.$http.delete(`${this.path}/${id}`)
|
||||
if (!this.deleteId) return;
|
||||
this.$http.delete(`${this.path}/${this.deleteId}`)
|
||||
.then(() => {
|
||||
this.$.data.splice(this.deleteIndex, 1);
|
||||
this.deleteIndex = null;
|
||||
this.refresh();
|
||||
this.deleteId = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$http', '$stateParams'];
|
||||
|
||||
ngModule.component('vnZoneExclusions', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -4,21 +4,24 @@
|
|||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
data="zones"
|
||||
auto-load="false">
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-zone-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search zone by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v margin-huge-bottom compact>
|
||||
<div>
|
||||
<vn-card class="vn-w-sm pad-medium-h">
|
||||
<vn-searchbar
|
||||
panel="vn-zone-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search zone by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md"
|
||||
margin-medium-top
|
||||
margin-huge-bottom>
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
|
@ -59,8 +62,8 @@
|
|||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-dialog
|
||||
vn-id="summary"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
url="/api/Zones/{{$ctrl.$stateParams.id}}/getLeaves"
|
||||
filter="::$ctrl.filter">
|
||||
</vn-crud-model>
|
||||
<div compact>
|
||||
<div class="vn-w-md">
|
||||
<vn-card pad-large-h>
|
||||
<vn-searchbar auto-load="false"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'core/lib/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($, $http, $stateParams) {
|
||||
this.$ = $;
|
||||
this.$http = $http;
|
||||
this.$stateParams = $stateParams;
|
||||
}
|
||||
|
||||
class Controller extends Section {
|
||||
onSearch(params) {
|
||||
this.$.model.applyFilter({}, params).then(() => {
|
||||
const data = this.$.model.data;
|
||||
|
@ -49,8 +45,6 @@ class Controller {
|
|||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$http', '$stateParams'];
|
||||
|
||||
ngModule.component('vnZoneLocation', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
@import "variables";
|
||||
|
||||
vn-treeview-content {
|
||||
& > vn-check:not(.indeterminate) {
|
||||
color: $color-main;
|
||||
|
||||
& > .btn {
|
||||
border-color: $color-main;
|
||||
}
|
||||
}
|
||||
& > vn-check.checked {
|
||||
color: $color-main;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<vn-card
|
||||
ng-if="data.length"
|
||||
style="max-width: 25em; margin: 0 auto;">
|
||||
<vn-data-viewer
|
||||
data="data"
|
||||
is-loading="!data"
|
||||
class="vn-w-xs">
|
||||
<vn-card>
|
||||
<vn-table>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="row in data | orderBy:'warehouse.name'">
|
||||
|
@ -15,13 +17,8 @@
|
|||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-bg-title ng-if="!data">
|
||||
<vn-spinner enable="true"></vn-spinner>
|
||||
</vn-bg-title>
|
||||
<vn-bg-title ng-if="data.length == 0" translate>
|
||||
No records found
|
||||
</vn-bg-title>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
translate-attr="{title: 'Add'}"
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'core/lib/section';
|
||||
|
||||
class Controller {
|
||||
constructor($, _, $http, $stateParams) {
|
||||
Object.assign(this, {
|
||||
$,
|
||||
$http
|
||||
});
|
||||
class Controller extends Section {
|
||||
constructor($el, $, $t, $http, $state) {
|
||||
super($el, $, $t, $http, $state);
|
||||
|
||||
this.path = `/api/Zones/${$stateParams.id}/warehouses`;
|
||||
this.path = `/api/Zones/${this.$stateParams.id}/warehouses`;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
|
@ -52,7 +50,6 @@ class Controller {
|
|||
});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$translate', '$http', '$stateParams'];
|
||||
|
||||
ngModule.component('vnZoneWarehouses', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -4,7 +4,13 @@
|
|||
limit="20"
|
||||
data="$ctrl.photos">
|
||||
</vn-crud-model>
|
||||
<vn-horizontal class="photo-list" vn-droppable="true" on-drop="$ctrl.onDrop(event)">
|
||||
|
||||
<section class="drop-zone" vn-droppable="true" on-drop="$ctrl.onDrop(event)">
|
||||
<section><vn-icon icon="add_circle"></vn-icon></section>
|
||||
<section translate>Drag & Drop files here...</section>
|
||||
</section>
|
||||
|
||||
<vn-horizontal class="photo-list">
|
||||
<section class="photo" ng-repeat="photo in $ctrl.photos">
|
||||
<section class="image mdl-shadow--2dp" on-error-src
|
||||
ng-style="{'background': 'url(/api/dms/' + photo.dmsFk + '/downloadFile?access_token=' + $ctrl.accessToken + ')'}"
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
@import "./variables";
|
||||
|
||||
vn-claim-dms-index {
|
||||
.photo-list {
|
||||
.drop-zone {
|
||||
border: 2px dashed $color-font-secondary;
|
||||
color: $color-font-secondary;
|
||||
box-sizing: border-box;
|
||||
padding: 2em $pad-medium;
|
||||
border-radius: 0.5em;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
|
||||
vn-icon {
|
||||
font-size: 3em
|
||||
}
|
||||
}
|
||||
|
||||
.photo-list {
|
||||
|
||||
padding: $pad-medium;
|
||||
min-height: 100%;
|
||||
|
||||
|
@ -13,9 +25,4 @@ vn-claim-dms-index {
|
|||
height: 18em;
|
||||
}
|
||||
}
|
||||
|
||||
vn-empty-rows {
|
||||
color: $color-font-secondary;
|
||||
font-size: 2em
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
Are you sure you want to continue?: ¿Seguro que quieres continuar?
|
||||
Drag & Drop files here...: Arrasta y suelta archivos aquí...
|
||||
Drag & Drop files here...: Arrastra y suelta archivos aquí...
|
||||
Photo deleted: Foto eliminada
|
||||
Photo uploaded!: Foto subida!
|
|
@ -3,20 +3,23 @@
|
|||
url="/claim/api/Claims/filter"
|
||||
limit="20"
|
||||
data="claims"
|
||||
order="claimStateFk ASC, created DESC">
|
||||
order="claimStateFk ASC, created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-claim-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search claim by id or client name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v compact>
|
||||
<vn-card pad-medium-h class="vn-w-sm">
|
||||
<vn-searchbar
|
||||
panel="vn-claim-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search claim by id or client name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md"
|
||||
margin-medium-v>
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
|
@ -62,10 +65,12 @@
|
|||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-client-descriptor-popover vn-id="clientDescriptor"></vn-client-descriptor-popover>
|
||||
<vn-client-descriptor-popover
|
||||
vn-id="clientDescriptor">
|
||||
</vn-client-descriptor-popover>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor"
|
||||
worker-fk="$ctrl.selectedWorker">
|
||||
|
|
|
@ -168,7 +168,7 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
function isAlpha(value) {
|
||||
const regexp = new RegExp(/^[ñça-zA-Z0-9\s]*$/);
|
||||
const regexp = new RegExp(/^[ñça-zA-Z0-9\s]*$/i);
|
||||
|
||||
return regexp.test(value);
|
||||
}
|
||||
|
|
|
@ -6,75 +6,70 @@
|
|||
data="$ctrl.addresses"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<div compact>
|
||||
<vn-card pad-large>
|
||||
<div
|
||||
ng-repeat="address in $ctrl.addresses"
|
||||
class="address">
|
||||
<a
|
||||
ui-sref="client.card.address.edit({addressId: {{::address.id}}})"
|
||||
class="pad-small border-solid"
|
||||
ng-class="{
|
||||
'item-hightlight': $ctrl.isDefaultAddress(address),
|
||||
'item-disabled': !address.isActive && !$ctrl.isDefaultAddress(address)
|
||||
}"
|
||||
translate-attr="{title: 'Edit address'}"
|
||||
border-radius>
|
||||
<vn-none
|
||||
pad-small-right
|
||||
ng-click="$ctrl.onStarClick($event)">
|
||||
<vn-icon-button
|
||||
icon="star"
|
||||
ng-if="$ctrl.isDefaultAddress(address)">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-if="!address.isActive && !$ctrl.isDefaultAddress(address)"
|
||||
icon="star_border"
|
||||
vn-tooltip="Active first to set as default">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-if="address.isActive && !$ctrl.isDefaultAddress(address)"
|
||||
icon="star_border"
|
||||
vn-tooltip="Set as default"
|
||||
ng-click="$ctrl.setDefault(address)">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one
|
||||
style="overflow: hidden; min-width: 14em;">
|
||||
<div class="ellipsize"><b>{{::address.nickname}}</b></div>
|
||||
<div class="ellipsize" name="street">{{::address.street}}</div>
|
||||
<div class="ellipsize">{{::address.city}}, {{::address.province.name}}</div>
|
||||
<div class="ellipsize">
|
||||
{{::address.phone}}<span ng-if="::address.mobile">, </span>
|
||||
{{::address.mobile}}
|
||||
</div>
|
||||
<vn-check
|
||||
vn-one label="Is equalizated"
|
||||
field="address.isEqualizated"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card pad-medium>
|
||||
<div
|
||||
ng-repeat="address in $ctrl.addresses"
|
||||
class="address">
|
||||
<a
|
||||
ui-sref="client.card.address.edit({addressId: {{::address.id}}})"
|
||||
class="pad-small border-solid"
|
||||
ng-class="{'item-disabled': !address.isActive}"
|
||||
translate-attr="{title: 'Edit address'}"
|
||||
border-radius>
|
||||
<vn-none
|
||||
pad-small-right
|
||||
ng-click="$ctrl.onStarClick($event)">
|
||||
<vn-icon-button
|
||||
ng-if="$ctrl.isDefaultAddress(address)"
|
||||
icon="star"
|
||||
translate-attr="{title: 'Default address'}">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-if="!$ctrl.isDefaultAddress(address)"
|
||||
icon="star_border"
|
||||
ng-click="$ctrl.setDefault(address)"
|
||||
translate-attr="{title: 'Set as default'}">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one
|
||||
style="overflow: hidden; min-width: 14em;">
|
||||
<div class="ellipsize"><b>{{::address.nickname}}</b></div>
|
||||
<div class="ellipsize" name="street">{{::address.street}}</div>
|
||||
<div class="ellipsize">{{::address.city}}, {{::address.province.name}}</div>
|
||||
<div class="ellipsize">
|
||||
{{::address.phone}}<span ng-if="::address.mobile">, </span>
|
||||
{{::address.mobile}}
|
||||
</div>
|
||||
<vn-check
|
||||
vn-one label="Is equalizated"
|
||||
field="address.isEqualizated"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-one>
|
||||
<vn-vertical
|
||||
vn-one
|
||||
ng-if="address.observations.length"
|
||||
border-solid-left
|
||||
pad-medium-h
|
||||
class="vn-hide-narrow"
|
||||
style="height: 6em; overflow: auto;">
|
||||
<vn-one ng-repeat="observation in address.observations track by $index" ng-class="{'pad-small-top': $index}">
|
||||
<b>{{::observation.observationType.description}}:</b>
|
||||
<span>{{::observation.description}}</span>
|
||||
</vn-one>
|
||||
<vn-vertical
|
||||
vn-one
|
||||
ng-if="address.observations.length"
|
||||
border-solid-left
|
||||
pad-medium-h
|
||||
style="height: 6em; overflow: auto;">
|
||||
<vn-one ng-repeat="observation in address.observations track by $index" ng-class="{'pad-small-top': $index}">
|
||||
<b>{{::observation.observationType.description}}:</b>
|
||||
<span>{{::observation.description}}</span>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
</a>
|
||||
</div>
|
||||
</vn-card>
|
||||
<vn-float-button
|
||||
vn-bind="+"
|
||||
fixed-bottom-right
|
||||
vn-tooltip="New address"
|
||||
ui-sref="client.card.address.create"
|
||||
icon="add"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</div>
|
||||
</vn-vertical>
|
||||
</a>
|
||||
</div>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
vn-bind="+"
|
||||
fixed-bottom-right
|
||||
vn-tooltip="New address"
|
||||
ui-sref="client.card.address.create"
|
||||
icon="add"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
|
|
|
@ -56,8 +56,7 @@ class Controller {
|
|||
}
|
||||
|
||||
isDefaultAddress(address) {
|
||||
if (this.client)
|
||||
return this.client.defaultAddressFk === address.id;
|
||||
return this.client && this.client.defaultAddressFk === address.id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
url="/client/api/receipts/filter"
|
||||
params="$ctrl.params"
|
||||
limit="20"
|
||||
data="$ctrl.balances">
|
||||
data="$ctrl.balances"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
vn-id="riskModel"
|
||||
|
@ -11,9 +12,10 @@
|
|||
filter="$ctrl.filter"
|
||||
data="$ctrl.clientRisks">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal>
|
||||
<div class="vn-w-lg">
|
||||
<vn-card class="pad-medium margin-medium-bottom">
|
||||
<vn-horizontal
|
||||
style="align-items: center;">
|
||||
<vn-one></vn-one>
|
||||
<vn-one>
|
||||
<vn-autocomplete
|
||||
|
@ -23,7 +25,7 @@
|
|||
url="/client/api/Companies"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
label="Select company">
|
||||
label="Company">
|
||||
</vn-autocomplete>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
|
@ -38,68 +40,68 @@
|
|||
</div>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th default-order>Date</vn-th>
|
||||
<vn-th>Creation date</vn-th>
|
||||
<vn-th>Employee</vn-th>
|
||||
<vn-th>Reference</vn-th>
|
||||
<vn-th number>Bank</vn-th>
|
||||
<vn-th number>Debit</vn-th>
|
||||
<vn-th number>Havings</vn-th>
|
||||
<vn-th number>Balance</vn-th>
|
||||
<vn-th center>Conciliated</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="balance in $ctrl.balances">
|
||||
<vn-td>{{::balance.payed | dateTime:'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td>{{::balance.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, balance.workerFk)">
|
||||
{{::balance.userNickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
ng-class="{'link': balance.isInvoice}"
|
||||
ng-click="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
ng-show="balance.ref">{{balance.isInvoice ? 'BILL' : balance.ref | translate: {ref: balance.ref} }}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{::balance.bankFk}}</vn-td>
|
||||
<vn-td number>{{::balance.debit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::balance.credit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{balance.balance | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td center>
|
||||
<vn-check
|
||||
field="balance.isConciliate"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td center>
|
||||
<a ng-show="balance.hasPdf"
|
||||
target="_blank"
|
||||
href="api/InvoiceOuts/{{::balance.id}}/download?access_token={{::$ctrl.accessToken}}">
|
||||
<vn-icon-button
|
||||
icon="cloud_download"
|
||||
title="{{'Download PDF' | translate}}">
|
||||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
|
||||
<vn-data-viewer model="model">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th>Date</vn-th>
|
||||
<vn-th>Creation date</vn-th>
|
||||
<vn-th>Employee</vn-th>
|
||||
<vn-th>Reference</vn-th>
|
||||
<vn-th number>Bank</vn-th>
|
||||
<vn-th number>Debit</vn-th>
|
||||
<vn-th number>Havings</vn-th>
|
||||
<vn-th number>Balance</vn-th>
|
||||
<vn-th center>Conciliated</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="balance in $ctrl.balances">
|
||||
<vn-td>{{::balance.payed | dateTime:'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td>{{::balance.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, balance.workerFk)">
|
||||
{{::balance.userNickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
ng-class="{'link': balance.isInvoice}"
|
||||
ng-click="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
ng-show="balance.ref">{{balance.isInvoice ? 'BILL' : balance.ref | translate: {ref: balance.ref} }}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{::balance.bankFk}}</vn-td>
|
||||
<vn-td number>{{::balance.debit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::balance.credit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{balance.balance | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td center>
|
||||
<vn-check
|
||||
field="balance.isConciliate"
|
||||
disabled="true">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td center>
|
||||
<a ng-show="balance.hasPdf"
|
||||
target="_blank"
|
||||
href="api/InvoiceOuts/{{::balance.id}}/download?access_token={{::$ctrl.accessToken}}">
|
||||
<vn-icon-button
|
||||
icon="cloud_download"
|
||||
title="{{'Download PDF' | translate}}">
|
||||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-float-button
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
|
@ -109,15 +111,13 @@
|
|||
fixed-bottom-right
|
||||
ng-click="$ctrl.openCreateDialog()">
|
||||
</vn-float-button>
|
||||
|
||||
<vn-client-balance-create vn-id="balanceCreateDialog">
|
||||
<vn-client-balance-create
|
||||
vn-id="balanceCreateDialog">
|
||||
</vn-client-balance-create>
|
||||
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor"
|
||||
worker-fk="$ctrl.selectedWorker">
|
||||
</vn-worker-descriptor-popover>
|
||||
|
||||
<vn-invoice-out-descriptor-popover
|
||||
vn-id="invoiceOutDescriptor"
|
||||
invoice-out-id="$ctrl.selectedInvoiceOut">
|
||||
|
|
|
@ -1,67 +1,64 @@
|
|||
<div compact>
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal
|
||||
ng-repeat="classification in $ctrl.classifications track by classification.id"
|
||||
class="pad-medium-top"
|
||||
style="align-items: center;">
|
||||
<vn-one
|
||||
border-radius
|
||||
class="pad-small border-solid"
|
||||
ng-class="{'item-hightlight': !classification.finished,'item-disabled': classification.finished}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h>
|
||||
<vn-icon-button
|
||||
ng-if="!classification.finished"
|
||||
icon="lock"
|
||||
vn-tooltip="Close contract"
|
||||
ng-click="$ctrl.closeContract(classification)">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one border-solid-right>
|
||||
<div><vn-label translate>Since</vn-label> {{::classification.started | dateTime:'dd/MM/yyyy'}}</div>
|
||||
<div><vn-label translate>To</vn-label> {{classification.finished | dateTime:'dd/MM/yyyy'}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one pad-medium-h>
|
||||
<vn-horizontal ng-repeat="insurance in classification.insurances track by insurance.id">
|
||||
<vn-one>
|
||||
<vn-label-value label="Credit"
|
||||
value="{{::insurance.credit}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Grade"
|
||||
value="{{::insurance.grade}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Date"
|
||||
value="{{::insurance.created | dateTime:'dd/MM/yyyy' }}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="client.card.creditInsurance.insurance.index({classificationId: {{classification.id}}})">
|
||||
<vn-icon-button icon="desktop_windows" vn-tooltip="View credits"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-if="model.data.length == 0">
|
||||
<vn-one ad-small translate>
|
||||
No results
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
<vn-data-viewer
|
||||
data="$ctrl.classifications"
|
||||
class="vn-w-md">
|
||||
<vn-card pad-medium>
|
||||
<vn-horizontal
|
||||
ng-repeat="classification in $ctrl.classifications track by classification.id"
|
||||
class="pad-medium-bottom insurance"
|
||||
style="align-items: center;">
|
||||
<vn-one
|
||||
border-radius
|
||||
class="pad-small border-solid"
|
||||
ng-class="{'item-hightlight': !classification.finished,'item-disabled': classification.finished}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h>
|
||||
<vn-icon-button
|
||||
ng-if="!classification.finished"
|
||||
icon="lock"
|
||||
vn-tooltip="Close contract"
|
||||
ng-click="$ctrl.closeContract(classification)">
|
||||
</vn-icon-button>
|
||||
</vn-none>
|
||||
<vn-one border-solid-right>
|
||||
<div><vn-label translate>Since</vn-label> {{::classification.started | dateTime:'dd/MM/yyyy'}}</div>
|
||||
<div><vn-label translate>To</vn-label> {{classification.finished | dateTime:'dd/MM/yyyy'}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one pad-medium-h>
|
||||
<vn-horizontal ng-repeat="insurance in classification.insurances track by insurance.id">
|
||||
<vn-one>
|
||||
<vn-label-value label="Credit"
|
||||
value="{{::insurance.credit}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Grade"
|
||||
value="{{::insurance.grade}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Date"
|
||||
value="{{::insurance.created | dateTime:'dd/MM/yyyy' }}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="client.card.creditInsurance.insurance.index({classificationId: {{classification.id}}})">
|
||||
<vn-icon-button icon="desktop_windows" vn-tooltip="View credits"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-float-button
|
||||
ng-if="$ctrl.canCreateNew()"
|
||||
vn-tooltip="New contract"
|
||||
fixed-bottom-right
|
||||
ui-sref="client.card.creditInsurance.create"
|
||||
icon="add"
|
||||
vn-bind="+"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
</div>
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
ng-if="$ctrl.canCreateNew()"
|
||||
vn-tooltip="New contract"
|
||||
fixed-bottom-right
|
||||
ui-sref="client.card.creditInsurance.create"
|
||||
icon="add"
|
||||
vn-bind="+"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
<vn-confirm
|
||||
vn-id="close-contract"
|
||||
on-response="$ctrl.returnDialog(response)"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
|
||||
constructor($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
vn-client-credit-insurance-index{
|
||||
.insurance:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
|
@ -4,36 +4,38 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="credits" auto-load="false">
|
||||
data="credits"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="amount">Credit</vn-th>
|
||||
<vn-th field="created" default-order="DESC">Since</vn-th>
|
||||
<vn-th>Employee</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="credit in credits track by credit.id">
|
||||
<vn-td>{{::credit.amount | number:2}} €</vn-td>
|
||||
<vn-td>{{::credit.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td>{{::credit.worker.user.nickname}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="created">Since</vn-th>
|
||||
<vn-th field="workerFk">Employee</vn-th>
|
||||
<vn-th field="amount" number>Credit</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="credit in credits track by credit.id">
|
||||
<vn-td>{{::credit.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td>{{::credit.worker.user.nickname}}</vn-td>
|
||||
<vn-td number>{{::credit.amount | currency:'EUR':2}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
|
||||
<vn-float-button icon="add" fixed-bottom-right
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
ui-sref="client.card.credit.create"
|
||||
vn-acl="teamBoss"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="New credit"
|
||||
vn-bind="+">
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
Since : Desde
|
||||
Employee : Empleado
|
||||
No results: Sin resultados
|
||||
Employee : Empleado
|
|
@ -4,101 +4,102 @@
|
|||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
data="$ctrl.clientDms">
|
||||
data="$ctrl.clientDms"
|
||||
order="dmsFk DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="dmsFk" default-order="DESC" shrink>Id</vn-th>
|
||||
<vn-th field="dmsTypeFk" shrink>Type</vn-th>
|
||||
<vn-th field="hardCopyNumber" shrink number>Order</vn-th>
|
||||
<vn-th field="reference" shrink>Reference</vn-th>
|
||||
<vn-th expand>Description</vn-th>
|
||||
<vn-th field="hasFile" shrink>Original</vn-th>
|
||||
<vn-th shrink>File</vn-th>
|
||||
<vn-th shrink>Employee</vn-th>
|
||||
<vn-th field="created">Created</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="document in $ctrl.clientDms">
|
||||
<vn-td number shrink>{{::document.dmsFk}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.dmsType.name}}">
|
||||
{{::document.dms.dmsType.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink number>
|
||||
<span class="chip" title="{{::document.dms.hardCopyNumber}}"
|
||||
ng-class="{'message': document.dms.hardCopyNumber}">
|
||||
{{::document.dms.hardCopyNumber}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.reference}}">
|
||||
{{::document.dms.reference}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
<span title="{{::document.dms.description}}">
|
||||
{{::document.dms.description}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-check disabled="true"
|
||||
field="document.dms.hasFile">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<a target="_blank"
|
||||
title="{{'Download file' | translate}}"
|
||||
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">{{::document.dms.file}}
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, document.dms.workerFk)">
|
||||
{{::document.dms.worker.user.nickname | dashIfEmpty}}
|
||||
</span></vn-td>
|
||||
<vn-td>
|
||||
{{::document.dms.created | dateTime:'dd/MM/yyyy HH:mm'}}
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<a target="_blank"
|
||||
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
|
||||
<vn-icon-button
|
||||
icon="cloud_download"
|
||||
title="{{'Download file' | translate}}">
|
||||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button ui-sref="client.card.dms.edit({dmsId: {{::document.dmsFk}}})"
|
||||
icon="edit"
|
||||
title="{{'Edit file' | translate}}">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
ng-click="$ctrl.showDeleteConfirm($index)"
|
||||
title="{{'Remove file' | translate}}"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-lg">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="dmsFk" shrink>Id</vn-th>
|
||||
<vn-th field="dmsTypeFk" shrink>Type</vn-th>
|
||||
<vn-th field="hardCopyNumber" shrink number>Order</vn-th>
|
||||
<vn-th field="reference" shrink>Reference</vn-th>
|
||||
<vn-th expand>Description</vn-th>
|
||||
<vn-th field="hasFile" shrink>Original</vn-th>
|
||||
<vn-th shrink>File</vn-th>
|
||||
<vn-th shrink>Employee</vn-th>
|
||||
<vn-th field="created">Created</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="document in $ctrl.clientDms">
|
||||
<vn-td number shrink>{{::document.dmsFk}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.dmsType.name}}">
|
||||
{{::document.dms.dmsType.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink number>
|
||||
<span class="chip" title="{{::document.dms.hardCopyNumber}}"
|
||||
ng-class="{'message': document.dms.hardCopyNumber}">
|
||||
{{::document.dms.hardCopyNumber}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span title="{{::document.dms.reference}}">
|
||||
{{::document.dms.reference}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
<span title="{{::document.dms.description}}">
|
||||
{{::document.dms.description}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-check disabled="true"
|
||||
field="document.dms.hasFile">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<a target="_blank"
|
||||
title="{{'Download file' | translate}}"
|
||||
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">{{::document.dms.file}}
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, document.dms.workerFk)">
|
||||
{{::document.dms.worker.user.nickname | dashIfEmpty}}
|
||||
</span></vn-td>
|
||||
<vn-td>
|
||||
{{::document.dms.created | dateTime:'dd/MM/yyyy HH:mm'}}
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<a target="_blank"
|
||||
href="api/dms/{{::document.dmsFk}}/downloadFile?access_token={{::$ctrl.accessToken}}">
|
||||
<vn-icon-button
|
||||
icon="cloud_download"
|
||||
title="{{'Download file' | translate}}">
|
||||
</vn-icon-button>
|
||||
</a>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button ui-sref="client.card.dms.edit({dmsId: {{::document.dmsFk}}})"
|
||||
icon="edit"
|
||||
title="{{'Edit file' | translate}}">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
icon="delete"
|
||||
ng-click="$ctrl.showDeleteConfirm($index)"
|
||||
title="{{'Remove file' | translate}}"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
|
|
|
@ -4,49 +4,54 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="greuges" auto-load="true">
|
||||
data="greuges"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<mg-ajax
|
||||
path="/client/api/greuges/{{$ctrl.$stateParams.id}}/sumAmount"
|
||||
options="mgEdit">
|
||||
</mg-ajax>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal>
|
||||
<div class="totalBox" ng-if="model.data.length > 0">
|
||||
<vn-label-value label="Total"
|
||||
value="{{edit.model.sumAmount | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</vn-horizontal>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card
|
||||
ng-if="model.data.length > 0"
|
||||
style="text-align: right;"
|
||||
class="margin-medium-bottom pad-large">
|
||||
<vn-label-value
|
||||
label="Total"
|
||||
value="{{edit.model.sumAmount | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</vn-card>
|
||||
<vn-card>
|
||||
<vn-vertical>
|
||||
<vn-table model="model" auto-load="false">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="shipped" default-order="DESC">Date</vn-th>
|
||||
<vn-th field="description">Comment</vn-th>
|
||||
<vn-th field="amount" >Amount</vn-th>
|
||||
<vn-th field="greugeTypeFk">Type</vn-th>
|
||||
<vn-th field="amount" number>Amount</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="greuge in greuges">
|
||||
<vn-td>{{::greuge.shipped | dateTime:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||
<vn-td>{{::greuge.description}}</vn-td>
|
||||
<vn-td>{{::greuge.amount | currency: 'EUR': 2}}</vn-td>
|
||||
<vn-td>{{::greuge.greugeType.name}}</vn-td>
|
||||
<vn-td number>{{::greuge.amount | currency: 'EUR': 2}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
|
||||
<vn-float-button icon="add" fixed-bottom-right
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
ui-sref="client.card.greuge.create"
|
||||
vn-tooltip="New greuge"
|
||||
vn-acl="salesAssistant"
|
||||
vn-acl-action="remove"
|
||||
vn-bind="+">
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
</vn-float-button>
|
||||
|
|
|
@ -3,73 +3,74 @@
|
|||
url="/item/api/Clients"
|
||||
order="id DESC"
|
||||
limit="8"
|
||||
data="clients"
|
||||
auto-load="false">
|
||||
data="clients">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-client-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search client by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-card margin-medium-v>
|
||||
<a
|
||||
ng-repeat="client in clients track by client.id"
|
||||
ui-sref="client.card.summary({ id: {{::client.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item searchResult">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::client.name}}</h6>
|
||||
<vn-label-value label="Id"
|
||||
value="{{::client.id}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Phone"
|
||||
value="{{::client.phone | phone}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Town/City"
|
||||
value="{{::client.city}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Email"
|
||||
value="{{::client.email}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.filterTickets(client, $event)"
|
||||
vn-tooltip="Client tickets"
|
||||
icon="icon-ticket">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.openSummary(client, $event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<div class="content-block vn-w-sm">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-client-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
info="Search client by id or name"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
margin-medium-v>
|
||||
<vn-card>
|
||||
<div class="vn-list">
|
||||
<a
|
||||
ng-repeat="client in clients track by client.id"
|
||||
ui-sref="client.card.summary({ id: {{::client.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item searchResult">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::client.name}}</h6>
|
||||
<vn-label-value label="Id"
|
||||
value="{{::client.id}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Phone"
|
||||
value="{{::client.phone | phone}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Town/City"
|
||||
value="{{::client.city}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Email"
|
||||
value="{{::client.email}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.filterTickets(client, $event)"
|
||||
vn-tooltip="Client tickets"
|
||||
icon="icon-ticket">
|
||||
</vn-icon-button>
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.openSummary(client, $event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
<vn-empty-rows translate ng-if="model.data.length === 0">
|
||||
No results
|
||||
</vn-empty-rows>
|
||||
<vn-empty-rows translate ng-if="model.data === null">
|
||||
Enter a new search
|
||||
</vn-empty-rows>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
</div>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</div>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<a ui-sref="client.create" vn-tooltip="New client" vn-bind="+" fixed-bottom-right>
|
||||
<a ui-sref="client.create"
|
||||
vn-tooltip="New client"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
<vn-float-button icon="person_add"></vn-float-button>
|
||||
</a>
|
||||
<vn-dialog class="dialog-summary"
|
||||
vn-id="dialog-summary-client">
|
||||
<tpl-body>
|
||||
<vn-client-summary client="$ctrl.clientSelected"></vn-client-summary>
|
||||
<vn-client-summary
|
||||
client="$ctrl.clientSelected">
|
||||
</vn-client-summary>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
<vn-scroll-up></vn-scroll-up>
|
|
@ -4,32 +4,33 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="mandates" auto-load="false">
|
||||
data="mandates"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id">Id</vn-th>
|
||||
<vn-th field="companyFk">Company</vn-th>
|
||||
<vn-th field="mandateTypeFk">Type</vn-th>
|
||||
<vn-th field="created" default-order="DESC">Register date</vn-th>
|
||||
<vn-th field="finished">End date</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="mandate in mandates">
|
||||
<vn-td>{{::mandate.id}}</vn-td>
|
||||
<vn-td>{{::mandate.company.code}}</vn-td>
|
||||
<vn-td>{{::mandate.mandateType.name}}</vn-td>
|
||||
<vn-td>{{::mandate.created | dateTime:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||
<vn-td>{{::mandate.finished | dateTime:'dd/MM/yyyy HH:mm' || '-'}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
<vn-th field="companyFk">Company</vn-th>
|
||||
<vn-th field="mandateTypeFk">Type</vn-th>
|
||||
<vn-th field="created">Register date</vn-th>
|
||||
<vn-th field="finished">End date</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="mandate in mandates">
|
||||
<vn-td number>{{::mandate.id}}</vn-td>
|
||||
<vn-td>{{::mandate.company.code}}</vn-td>
|
||||
<vn-td>{{::mandate.mandateType.name}}</vn-td>
|
||||
<vn-td>{{::mandate.created | dateTime:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||
<vn-td>{{::mandate.finished | dateTime:'dd/MM/yyyy HH:mm' || '-'}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
</vn-data-viewer>
|
|
@ -6,15 +6,14 @@ class Controller {
|
|||
this.filter = {
|
||||
include: [
|
||||
{
|
||||
relation: "mandateType",
|
||||
relation: 'mandateType',
|
||||
scope: {
|
||||
fields: ["id", "name"]
|
||||
fields: ['id', 'name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: "company",
|
||||
}, {
|
||||
relation: 'company',
|
||||
scope: {
|
||||
fields: ["id", "code"]
|
||||
fields: ['id', 'code']
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
data="notes"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card pad-medium>
|
||||
<div class="note"
|
||||
ng-repeat="note in notes"
|
||||
pad-small
|
||||
border-solid
|
||||
|
@ -21,15 +23,9 @@
|
|||
<vn-horizontal class="text">
|
||||
{{::note.text}}
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
<vn-horizontal ng-if="model.data.length == 0">
|
||||
<vn-one ad-small translate>
|
||||
No results
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</div>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
|
||||
</vn-data-viewer>
|
||||
<a vn-tooltip="New note"
|
||||
ui-sref="client.card.note.create({id: $ctrl.$stateParams.id})"
|
||||
vn-bind="+"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
constructor($stateParams) {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
vn-client-note {
|
||||
.note:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
|
@ -1,51 +1,53 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/client/api/Recoveries"
|
||||
filter="{}"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="recoveries" auto-load="false">
|
||||
data="recoveries"
|
||||
order="started DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th></vn-th>
|
||||
<vn-th field="started" default-order="DESC">Since</vn-th>
|
||||
<vn-th field="finished">To</vn-th>
|
||||
<vn-th field="amount">Amount</vn-th>
|
||||
<vn-th field="period">Period</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="recovery in recoveries">
|
||||
<vn-td>
|
||||
<vn-icon-button icon="lock"
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="Finish that recovery period"
|
||||
ng-if="!recovery.finished"
|
||||
ng-click="$ctrl.setFinished(recovery)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td>{{::recovery.started | dateTime:'dd/MM/yyyy' }}</vn-td>
|
||||
<vn-td>{{recovery.finished | dateTime:'dd/MM/yyyy' }}</vn-td>
|
||||
<vn-td>{{::recovery.amount | currency: 'EUR': 0}}</vn-td>
|
||||
<vn-td>{{::recovery.period}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th></vn-th>
|
||||
<vn-th field="started">Since</vn-th>
|
||||
<vn-th field="finished">To</vn-th>
|
||||
<vn-th field="amount" number>Amount</vn-th>
|
||||
<vn-th field="period" number>Period</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="recovery in recoveries">
|
||||
<vn-td>
|
||||
<vn-icon-button
|
||||
icon="lock"
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="Finish that recovery period"
|
||||
ng-if="!recovery.finished"
|
||||
ng-click="$ctrl.setFinished(recovery)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td>{{::recovery.started | dateTime:'dd/MM/yyyy' }}</vn-td>
|
||||
<vn-td>{{recovery.finished | dateTime:'dd/MM/yyyy' }}</vn-td>
|
||||
<vn-td number>{{::recovery.amount | currency: 'EUR': 0}}</vn-td>
|
||||
<vn-td number>{{::recovery.period}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
|
||||
<vn-float-button icon="add" fixed-bottom-right
|
||||
</vn-data-viewer>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
fixed-bottom-right
|
||||
vn-tooltip="New recovery"
|
||||
vn-bind="+"
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
ui-sref="client.card.recovery.create">
|
||||
</vn-float-button>
|
||||
</vn-float-button>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
Since: Desde
|
||||
Employee: Empleado
|
||||
No results: Sin resultados
|
||||
To: Hasta
|
||||
Finish that recovery period: Terminar el recobro
|
|
@ -4,49 +4,51 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="samples" auto-load="false">
|
||||
data="samples"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-horizontal>
|
||||
</vn-horizontal>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="created" default-order="DESC">Sent</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th field="workerFk">Worker</vn-th>
|
||||
<vn-th field="companyFk">Company</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="sample in samples">
|
||||
<vn-td>{{::sample.created | dateTime:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||
<vn-td
|
||||
title="{{::sample.type.description}}">
|
||||
{{::sample.type.description}}
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, sample.worker.id)">
|
||||
{{::sample.worker.user.nickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::sample.company.code}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="created">Sent</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th field="workerFk">Worker</vn-th>
|
||||
<vn-th field="companyFk">Company</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="sample in samples">
|
||||
<vn-td>{{::sample.created | dateTime:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||
<vn-td
|
||||
title="{{::sample.type.description}}">
|
||||
{{::sample.type.description}}
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span class="link"
|
||||
ng-click="$ctrl.showWorkerDescriptor($event, sample.worker.id)">
|
||||
{{::sample.worker.user.nickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{::sample.company.code}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="workerDescriptor"
|
||||
worker-fk="$ctrl.selectedWorker">
|
||||
</vn-worker-descriptor-popover>
|
||||
<a ui-sref="client.card.sample.create" vn-tooltip="Send sample"
|
||||
vn-bind="+" fixed-bottom-right>
|
||||
<a
|
||||
ui-sref="client.card.sample.create"
|
||||
vn-tooltip="Send sample"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
Default address: Consignatario pred.
|
||||
Default address: Consignatario predeterminado
|
||||
Total greuge: Greuge total
|
||||
Financial information: Datos financieros
|
||||
Mana: Maná
|
||||
|
|
|
@ -3,52 +3,53 @@
|
|||
url="/client/api/clients/getTransactions"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="transactions" auto-load="false">
|
||||
data="transactions"
|
||||
order="created DESC"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-vertical compact>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th>State</vn-th>
|
||||
<vn-th field="id">Id</vn-th>
|
||||
<vn-th field="amount" number>Amount</vn-th>
|
||||
<vn-th field="created" default-order="DESC">Payed</vn-th>
|
||||
<vn-th>Confirm</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="transaction in transactions">
|
||||
<vn-td style="width: 3em; text-align: center">
|
||||
<vn-icon
|
||||
vn-tooltip="{{$ctrl.getFormattedMessage(transaction)}}"
|
||||
ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)"
|
||||
icon="clear">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Confirmed"
|
||||
ng-show="::(transaction.isConfirmed)"
|
||||
icon="check">
|
||||
</vn-icon>
|
||||
</vn-td>
|
||||
<vn-td>{{::transaction.id}}</vn-td>
|
||||
<vn-td number>{{::transaction.amount | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td>{{::transaction.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td style="width: 3em; text-align: center">
|
||||
<vn-icon-button
|
||||
icon="done_all"
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
vn-tooltip="Confirm transaction"
|
||||
ng-show="::!transaction.isConfirmed"
|
||||
ng-click="$ctrl.confirm(transaction)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md">
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th shrink>State</vn-th>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
<vn-th field="created">Date</vn-th>
|
||||
<vn-th field="amount" number>Amount</vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="transaction in transactions">
|
||||
<vn-td shrink>
|
||||
<vn-icon
|
||||
vn-tooltip="{{$ctrl.getFormattedMessage(transaction)}}"
|
||||
ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)"
|
||||
icon="clear">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Confirmed"
|
||||
ng-show="::(transaction.isConfirmed)"
|
||||
icon="check">
|
||||
</vn-icon>
|
||||
</vn-td>
|
||||
<vn-td number>{{::transaction.id}}</vn-td>
|
||||
<vn-td>{{::transaction.created | dateTime:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||
<vn-td number>{{::transaction.amount | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
icon="done_all"
|
||||
vn-acl="administrative"
|
||||
vn-acl-action="remove"
|
||||
translate-attr="{title: 'Confirm transaction'}"
|
||||
ng-show="::!transaction.isConfirmed"
|
||||
ng-click="$ctrl.confirm(transaction)">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
</vn-data-viewer>
|
|
@ -1,6 +1,5 @@
|
|||
Web Payment: Pago Web
|
||||
Confirmed: Confirmado
|
||||
Payed: Pagado
|
||||
Confirm transaction: Confirmar transacción
|
||||
Confirm: Confirmar
|
||||
State: Estado
|
|
@ -7,7 +7,7 @@
|
|||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-card pad-medium-h class="vn-w-sm">
|
||||
<vn-searchbar
|
||||
panel="vn-invoice-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
|
@ -16,8 +16,12 @@
|
|||
</vn-searchbar>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v compact>
|
||||
<vn-table model="model" auto-load="false">
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-w-md"
|
||||
margin-medium-v>
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="ref">Reference</vn-th>
|
||||
|
@ -67,15 +71,19 @@
|
|||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<vn-dialog
|
||||
vn-id="summary"
|
||||
class="dialog-summary">
|
||||
<tpl-body>
|
||||
<vn-invoice-out-summary invoice-out="$ctrl.selectedInvoiceOut"></vn-invoice-out-summary>
|
||||
<vn-invoice-out-summary
|
||||
invoice-out="$ctrl.selectedInvoiceOut">
|
||||
</vn-invoice-out-summary>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
<vn-client-descriptor-popover vn-id="clientDescriptor"></vn-client-descriptor-popover>
|
||||
<vn-client-descriptor-popover
|
||||
vn-id="clientDescriptor">
|
||||
</vn-client-descriptor-popover>
|
||||
<vn-scroll-up></vn-scroll-up>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
|
||||
vn-invoice-out-summary .summary {
|
||||
max-width: $width-large;
|
||||
max-width: $width-lg;
|
||||
|
||||
vn-icon[icon=insert_drive_file]{
|
||||
color: $color-font-secondary;
|
||||
|
|
|
@ -62,13 +62,26 @@ module.exports = Self => {
|
|||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
let codeWhere;
|
||||
|
||||
if (ctx.args.search) {
|
||||
let items = await Self.app.models.ItemBarcode.find({
|
||||
where: {code: ctx.args.search},
|
||||
fields: ['itemFk']
|
||||
});
|
||||
let itemIds = [];
|
||||
for (const item of items)
|
||||
itemIds.push(item.itemFk);
|
||||
|
||||
codeWhere = {'i.id': {inq: itemIds}};
|
||||
}
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {or: [{'i.id': value}, {'ib.code': value}]}
|
||||
: {or: [{'i.name': {like: `%${value}%`}}, {'ib.code': value}]};
|
||||
? {or: [{'i.id': value}, codeWhere]}
|
||||
: {or: [{'i.name': {like: `%${value}%`}}, codeWhere]};
|
||||
case 'id':
|
||||
return {'i.id': value};
|
||||
case 'description':
|
||||
|
@ -83,8 +96,8 @@ module.exports = Self => {
|
|||
return {'i.isActive': value};
|
||||
}
|
||||
});
|
||||
|
||||
filter = mergeFilters(filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
|
@ -123,8 +136,7 @@ module.exports = Self => {
|
|||
LEFT JOIN origin ori ON ori.id = i.originFk
|
||||
LEFT JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = t.warehouseFk
|
||||
LEFT JOIN vn.buy b ON b.id = lb.buy_id
|
||||
LEFT JOIN itemPlacement itn ON itn.itemFk = i.id AND itn.warehouseFk = t.warehouseFk
|
||||
LEFT JOIN itemBarcode ib ON ib.itemFk = i.id`
|
||||
LEFT JOIN itemPlacement itn ON itn.itemFk = i.id AND itn.warehouseFk = t.warehouseFk`
|
||||
);
|
||||
|
||||
if (ctx.args.tags) {
|
||||
|
@ -150,7 +162,6 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
stmt.merge(conn.makeWhere(filter.where));
|
||||
stmt.merge(`GROUP BY i.id`);
|
||||
stmt.merge(conn.makePagination(filter));
|
||||
|
||||
let itemsIndex = stmts.push(stmt) - 1;
|
||||
|
|
|
@ -3,35 +3,39 @@
|
|||
url="/item/api/Items/filter"
|
||||
limit="12"
|
||||
order="isActive DESC, name, id"
|
||||
data="items"
|
||||
auto-load="false">
|
||||
data="items">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-horizontal>
|
||||
<vn-searchbar
|
||||
vn-three
|
||||
panel="vn-item-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search items by id, name or barcode"
|
||||
suggested-filter="{isActive: true}"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
<vn-icon-menu
|
||||
vn-id="more-button"
|
||||
icon="more_vert"
|
||||
show-filter="false"
|
||||
value-field="callback"
|
||||
translate-fields="['name']"
|
||||
on-change="$ctrl.onMoreChange(value)"
|
||||
on-open="$ctrl.onMoreOpen()">
|
||||
</vn-icon-menu>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v margin-huge-bottom>
|
||||
<vn-table model="model" auto-load="false" show-fields="$ctrl.showFields" vn-uvc="itemIndex">
|
||||
<vn-card pad-medium-h class="vn-w-sm">
|
||||
<vn-horizontal>
|
||||
<vn-searchbar
|
||||
vn-three
|
||||
panel="vn-item-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search items by id, name or barcode"
|
||||
suggested-filter="{isActive: true}"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
<vn-icon-menu
|
||||
vn-id="more-button"
|
||||
icon="more_vert"
|
||||
show-filter="false"
|
||||
value-field="callback"
|
||||
translate-fields="['name']"
|
||||
on-change="$ctrl.onMoreChange(value)"
|
||||
on-open="$ctrl.onMoreOpen()">
|
||||
</vn-icon-menu>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
margin-medium-v
|
||||
margin-huge-bottom>
|
||||
<vn-card>
|
||||
<vn-table
|
||||
model="model"
|
||||
show-fields="$ctrl.showFields"
|
||||
vn-uvc="itemIndex">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th th-id="picture" shrink></vn-th>
|
||||
|
@ -124,8 +128,8 @@
|
|||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
|
|
|
@ -33,8 +33,6 @@ Remove niche: Quitar nicho
|
|||
Add barcode: Añadir código de barras
|
||||
Remove barcode: Quitar código de barras
|
||||
Buyer: Comprador
|
||||
No results: Sin resultados
|
||||
Enter a new search: Introduce una nueva búsqueda
|
||||
Tag: Etiqueta
|
||||
Worker: Trabajador
|
||||
Available: Disponible
|
||||
|
|
|
@ -131,7 +131,7 @@ class Controller {
|
|||
}
|
||||
|
||||
get isRefreshing() {
|
||||
return this.$scope.model && this.$scope.model.isRefreshing;
|
||||
return this.$scope.model && this.$scope.model.status == 'loading';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,24 +3,23 @@
|
|||
url="/api/Orders/filter"
|
||||
limit="20"
|
||||
data="orders"
|
||||
order="landed DESC, clientFk"
|
||||
auto-load="false">
|
||||
order="landed DESC, clientFk">
|
||||
</vn-crud-model>
|
||||
<div class="content-block">
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
panel="vn-order-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search orders by id"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v>
|
||||
<vn-table
|
||||
model="model"
|
||||
auto-load="false">
|
||||
<vn-card pad-medium-h class="vn-w-sm">
|
||||
<vn-searchbar
|
||||
panel="vn-order-search-panel"
|
||||
on-search="$ctrl.onSearch($params)"
|
||||
info="Search orders by id"
|
||||
vn-focus>
|
||||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
margin-medium-v
|
||||
margin-huge-bottom>
|
||||
<vn-card>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
|
@ -71,8 +70,8 @@
|
|||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
</div>
|
||||
<a ui-sref="order.create" vn-bind="+" vn-tooltip="New order" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue