Merge branch 'dev' into test
gitea/salix/test This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-10-04 14:28:31 +02:00
commit fc8d5da606
78 changed files with 1591 additions and 1187 deletions

View File

@ -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,

View File

@ -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',

View File

@ -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();

View File

@ -1,4 +1,4 @@
<div class="check">
<div class="btn">
<div class="focus-mark"></div>
<div class="mark"></div>
</div>

View File

@ -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: '@?'

View File

@ -1,26 +1,9 @@
@import "variables";
vn-check {
position: relative;
display: inline-block;
outline: none;
cursor: pointer;
&.disabled {
cursor: inherit;
}
& > .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;

View File

@ -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;
}

View File

@ -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>

View File

@ -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: '<?'
}
});

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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';
}

View File

@ -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;
}
}

View File

@ -26,21 +26,22 @@ 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';
import './treeview/child';

View File

@ -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;
}
/**

View File

@ -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>

View File

@ -3,7 +3,8 @@ vn-pagination {
display: block;
text-align: center;
& > div > vn-icon-button {
& > div > vn-icon-button {
font-size: 2em;
padding: 0;
}
}

View File

@ -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>

View File

@ -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
});

View File

@ -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();
});
});
});

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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: '@?'
}
});

View File

@ -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');
});
});
});

View File

@ -1,31 +1,14 @@
@import "variables";
vn-radio {
position: relative;
cursor: pointer;
display: inline-block;
outline: none;
&.disabled {
cursor: inherit;
}
& > .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);
}
}

View File

@ -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>

View File

@ -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();
}

View File

@ -1,4 +1,4 @@
<div class="radio">
<div class="btn">
<div class="focus-mark"></div>
<div class="mark"></div>
</div>

View File

@ -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: '<?'
}
});

View File

@ -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);
}
}

View File

@ -28,7 +28,7 @@ vn-treeview {
& > vn-check:not(.indeterminate) {
color: $color-main;
& > .check {
& > .btn {
border-color: $color-main;
}
}

View File

@ -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

View File

@ -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'
];

View File

@ -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

View File

@ -1,7 +1,7 @@
@import "./effects";
.vn-list {
max-width: 36em;
max-width: $width-sm;
margin: 0 auto;
a.vn-list-item {

View File

@ -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%;

View File

@ -2,11 +2,12 @@
$menu-width: 16em;
$topbar-height: 4em;
$mobile-width: 800px;
$input-font-size: 16px;
// Width
$width-xs: 25em;
$width-sm: 32em;
$width-sm: 34em;
$width-md: 50em;
$width-lg: 80em;
$width-xl: 100em;
@ -49,6 +50,7 @@ $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, .05);
$color-hover-cd: rgba(0, 0, 0, .1);
@ -86,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);

View File

@ -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>

View File

@ -1,6 +1,10 @@
<div class="main-with-right-menu">
<div class="vn-list vn-w-sm">
<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,14 +56,9 @@
</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

View File

@ -1,26 +1,25 @@
<div class="main-with-right-menu">
<vn-card ng-if="data.length" class="vn-w-xs">
<vn-table>
<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(row.id)">
</vn-icon-button>
</vn-td>
</vn-tr>
<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(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-table>
</vn-card>
</vn-data-viewer>
</div>
<vn-side-menu side="right">
<vn-zone-calendar

View File

@ -4,21 +4,24 @@
filter="::$ctrl.filter"
limit="20"
data="zones"
auto-load="false">
auto-load="true">
</vn-crud-model>
<div>
<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>
<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"

View File

@ -1,4 +1,8 @@
<vn-card ng-if="data.length" class="vn-w-xs">
<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'">
@ -13,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'}"

View File

@ -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 + ')'}"

View File

@ -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
}
}

View File

@ -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!

View File

@ -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">

View File

@ -6,69 +6,70 @@
data="$ctrl.addresses"
auto-load="true">
</vn-crud-model>
<div compact>
<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>
<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
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>
</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>

View File

@ -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,7 +12,7 @@
filter="$ctrl.filter"
data="$ctrl.clientRisks">
</vn-crud-model>
<div>
<div class="vn-w-lg">
<vn-card class="pad-medium margin-medium-bottom">
<vn-horizontal
style="align-items: center;">
@ -40,11 +41,12 @@
</vn-one>
</vn-horizontal>
</vn-card>
<vn-card>
<vn-data-viewer model="model">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th default-order>Date</vn-th>
<vn-th>Date</vn-th>
<vn-th>Creation date</vn-th>
<vn-th>Employee</vn-th>
<vn-th>Reference</vn-th>
@ -97,8 +99,8 @@
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-data-viewer>
</div>
<vn-float-button
vn-acl="administrative"

View File

@ -1,58 +1,55 @@
<div class="vn-w-md">
<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-horizontal ng-if="model.data.length == 0">
<vn-one ad-small translate>
No results
</vn-one>
</vn-horizontal>
<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>
</div>
</vn-data-viewer>
<vn-float-button
ng-if="$ctrl.canCreateNew()"
vn-tooltip="New contract"

View File

@ -4,29 +4,32 @@
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>
<div class="vn-w-md">
<vn-data-viewer
model="model"
class="vn-w-md">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="created" default-order="DESC">Since</vn-th>
<vn-th>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-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-pagination model="model"></vn-pagination>
</div>
</vn-data-viewer>
<vn-float-button
icon="add"
ui-sref="client.card.credit.create"

View File

@ -1,3 +1,2 @@
Since : Desde
Employee : Empleado
No results: Sin resultados
Employee : Empleado

View File

@ -4,99 +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>
<div class="vn-w-lg">
<vn-data-viewer
model="model"
class="vn-w-lg">
<vn-card>
<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-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="delete"
ng-click="$ctrl.showDeleteConfirm($index)"
title="{{'Remove file' | translate}}"
tabindex="-1">
icon="cloud_download"
title="{{'Download file' | translate}}">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</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>
</div>
<vn-pagination model="model"></vn-pagination>
</vn-data-viewer>
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>

View File

@ -11,7 +11,9 @@
path="/client/api/greuges/{{$ctrl.$stateParams.id}}/sumAmount"
options="mgEdit">
</mg-ajax>
<div class="vn-w-md">
<vn-data-viewer
model="model"
class="vn-w-md">
<vn-card
ng-if="model.data.length > 0"
style="text-align: right;"
@ -43,8 +45,7 @@
</vn-table>
</vn-vertical>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</div>
</vn-data-viewer>
<vn-float-button
icon="add"
ui-sref="client.card.greuge.create"

View File

@ -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>

View File

@ -5,30 +5,32 @@
link="{clientFk: $ctrl.$stateParams.id}"
limit="20"
data="mandates"
auto-load="false">
order="created DESC"
auto-load="true">
</vn-crud-model>
<div class="vn-w-md">
<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" 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 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-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-pagination model="model"></vn-pagination>
</vn-vertical>
</vn-data-viewer>

View File

@ -6,7 +6,9 @@
data="notes"
auto-load="true">
</vn-crud-model>
<div class="vn-w-md">
<vn-data-viewer
model="model"
class="vn-w-md">
<vn-card pad-medium>
<div class="note"
ng-repeat="note in notes"
@ -22,12 +24,8 @@
{{::note.text}}
</vn-horizontal>
</div>
<div ng-if="model.data.length == 0" ad-small translate>
No results
</div>
</vn-card>
</div>
</vn-data-viewer>
<a vn-tooltip="New note"
ui-sref="client.card.note.create({id: $ctrl.$stateParams.id})"
vn-bind="+"

View File

@ -4,42 +4,44 @@
link="{clientFk: $ctrl.$stateParams.id}"
limit="20"
data="recoveries"
auto-load="false">
order="started DESC"
auto-load="true">
</vn-crud-model>
<div class="vn-w-md">
<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" default-order="DESC">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-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-pagination model="model"></vn-pagination>
</div>
</vn-data-viewer>
<vn-float-button
icon="add"
fixed-bottom-right

View File

@ -1,5 +1,4 @@
Since: Desde
Employee: Empleado
No results: Sin resultados
To: Hasta
Finish that recovery period: Terminar el recobro

View File

@ -5,14 +5,17 @@
link="{clientFk: $ctrl.$stateParams.id}"
limit="20"
data="samples"
auto-load="false">
order="created DESC"
auto-load="true">
</vn-crud-model>
<div class="vn-w-md">
<vn-data-viewer
model="model"
class="vn-w-md">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="created" default-order="DESC">Sent</vn-th>
<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>
@ -36,14 +39,16 @@
</vn-tbody>
</vn-table>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</div>
</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>

View File

@ -3,50 +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>
<div class="vn-w-md">
<vn-data-viewer
model="model"
class="vn-w-md">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th>State</vn-th>
<vn-th field="id"number>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 number>{{::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-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-pagination model="model"></vn-pagination>
</div>
</vn-data-viewer>

View File

@ -1,6 +1,5 @@
Web Payment: Pago Web
Confirmed: Confirmado
Payed: Pagado
Confirm transaction: Confirmar transacción
Confirm: Confirmar
State: Estado

View File

@ -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>

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -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';
}
}

View File

@ -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>

View File

@ -3,8 +3,6 @@ Catalog: Catálogo
from: desde
results: resultados
More than: Más de
No results: Sin resultados
Enter a new search: Introduce una nueva búsqueda
Plant: Planta
Flower: Flor
Handmade: Confección

View File

@ -3,32 +3,36 @@
url="/api/Routes/filter"
limit="20"
data="routes"
order="created DESC">
order="created DESC"
auto-load="true">
</vn-crud-model>
<div class="content-block">
<div class="vn-list">
<vn-card pad-medium-h>
<vn-searchbar
filter="$ctrl.filter"
panel="vn-route-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search routes by id"
vn-focus>
</vn-searchbar>
</vn-card>
</div>
<vn-card margin-medium-v margin-huge-bottom class="index">
<vn-table model="model" auto-load="false">
<vn-card pad-medium-h class="vn-w-sm">
<vn-searchbar
filter="$ctrl.filter"
panel="vn-route-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search routes by id"
vn-focus>
</vn-searchbar>
</vn-card>
<vn-data-viewer
model="model"
class="vn-w-lg"
margin-medium-v
margin-huge-bottom>
<vn-card class="index">
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="id" number>id</vn-th>
<vn-th field="id" number>Id</vn-th>
<vn-th th-id="worker">Worker</vn-th>
<vn-th th-id="agency">Agency</vn-th>
<vn-th th-id="vehicle">Vehicle</vn-th>
<vn-th th-id="created">Date</vn-th>
<vn-th th-id="m3" number></vn-th>
<vn-th th-id="description">Description</vn-th>
<vn-th></vn-th>
<vn-th shrink></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
@ -58,21 +62,26 @@
</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-route-summary route="$ctrl.routeSelected"></vn-route-summary>
<vn-route-summary
route="$ctrl.routeSelected">
</vn-route-summary>
</tpl-body>
</vn-dialog>
<vn-worker-descriptor-popover
vn-id="workerDescriptor"
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover>
<a ui-sref="route.create" vn-tooltip="New route" vn-bind="+" fixed-bottom-right>
<a ui-sref="route.create"
vn-tooltip="New route"
vn-bind="+"
fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>
<vn-scroll-up></vn-scroll-up>

View File

@ -4,34 +4,35 @@
limit="20"
params="::$ctrl.params"
data="tickets"
order="shipped DESC, zoneHour ASC, zoneMinute ASC, clientFk"
auto-load="false">
order="shipped DESC, zoneHour ASC, zoneMinute ASC, clientFk">
</vn-crud-model>
<div class="content-block">
<div class="vn-list">
<vn-card pad-medium-h>
<vn-horizontal>
<vn-searchbar
vn-id="ticketSearchbar"
panel="vn-ticket-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search ticket by id or alias"
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">
<vn-card pad-medium-h class="vn-w-sm">
<vn-horizontal>
<vn-searchbar
vn-id="ticketSearchbar"
panel="vn-ticket-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search ticket by id or alias"
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">
<vn-thead>
<vn-tr>
<vn-th shrink>
@ -42,7 +43,7 @@
<vn-th></vn-th>
<vn-th field="id" number>Id</vn-th>
<vn-th field="salesPerson">Salesperson</vn-th>
<vn-th field="shipped" default-order="DESC">Date</vn-th>
<vn-th field="shipped">Date</vn-th>
<vn-th>Hour</vn-th>
<vn-th field="nickname">Alias</vn-th>
<vn-th field="province">Province</vn-th>
@ -142,8 +143,8 @@
</a>
</vn-tbody>
</vn-table>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-data-viewer>
</div>
<a ui-sref="ticket.create" vn-tooltip="New ticket" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>

View File

@ -10,7 +10,6 @@ vn-ticket-index {
color: initial;
}
}
vn-searchbar {
width: 100%
}

View File

@ -1,5 +1,9 @@
<vn-card class="summary">
<h5 >Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} ({{$ctrl.summary.client.id}}) - {{$ctrl.summary.nickname}}
<h5>
<span>
Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}}
({{$ctrl.summary.client.id}}) - {{$ctrl.summary.nickname}}
</span>
<vn-button
disabled="!$ctrl.isEditable"
label="SET OK"

View File

@ -3,9 +3,24 @@
vn-ticket-summary .summary {
max-width: $width-lg;
h5 {
display: flex;
justify-content: space-between;
align-items: center;
align-content: center;
span {
flex: 1;
}
vn-button {
flex: none
}
}
vn-button {
max-height: 27px;
float: right;
button {
box-shadow: none;
height: inherit;

View File

@ -3,23 +3,24 @@
url="/travel/api/Travels"
filter="::$ctrl.filter"
limit="20"
data="travels"
auto-load="false">
data="travels">
</vn-crud-model>
<div class="content-block">
<div class="vn-list">
<vn-card pad-medium-h>
<vn-searchbar
panel="vn-travel-search-panel"
model="model"
expr-builder="$ctrl.exprBuilder(param, value)"
info="Search travels 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-travel-search-panel"
model="model"
expr-builder="$ctrl.exprBuilder(param, value)"
info="Search travels by id"
vn-focus>
</vn-searchbar>
</vn-card>
<vn-data-viewer
model="model"
class="vn-w-lg"
margin-medium-v>
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="id" number>Id</vn-th>
@ -50,6 +51,6 @@
</vn-tbody>
</vn-table>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</vn-data-viewer>
</div>
<vn-scroll-up></vn-scroll-up>

View File

@ -5,72 +5,70 @@
order="id"
data="workers">
</vn-crud-model>
<div class="content-block">
<div class="vn-list">
<vn-card pad-medium-h>
<div class="content-block vn-w-sm">
<vn-card pad-medium-h>
<vn-horizontal>
<vn-searchbar
style="width: 100%"
panel="vn-worker-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search workers by id, firstName, lastName or user name"
vn-focus>
</vn-searchbar>
<vn-icon-menu
vn-id="more-button"
icon="more_vert"
show-filter="false"
value-field="callback"
translate-fields="['name']"
data="$ctrl.moreOptions"
on-change="$ctrl.onMoreChange(value)">
</vn-icon-menu>
</vn-horizontal>
</vn-card>
<vn-data-viewer
model="model"
margin-medium-v>
<vn-card>
<div class="vn-list">
<a
ng-repeat="worker in workers track by worker.id"
ui-sref="worker.card.summary({id: worker.id})"
translate-attr="{title: 'View worker'}"
class="vn-list-item searchResult">
<vn-horizontal>
<vn-searchbar
style="width: 100%"
panel="vn-worker-search-panel"
on-search="$ctrl.onSearch($params)"
info="Search workers by id, firstName, lastName or user name"
vn-focus>
</vn-searchbar>
<vn-icon-menu
vn-id="more-button"
icon="more_vert"
show-filter="false"
value-field="callback"
translate-fields="['name']"
data="$ctrl.moreOptions"
on-change="$ctrl.onMoreChange(value)">
</vn-icon-menu>
</vn-horizontal>
</vn-card>
<vn-card margin-medium-v>
<a
ng-repeat="worker in workers track by worker.id"
ui-sref="worker.card.summary({id: worker.id})"
translate-attr="{title: 'View worker'}"
class="vn-list-item searchResult">
<vn-horizontal>
<vn-one>
<h6>{{::worker.nickname}}</h6>
<vn-label-value label="Id"
value="{{::worker.id}}">
</vn-label-value>
<vn-label-value label="User"
value="{{::worker.userName}}">
</vn-label-value>
<vn-label-value label="Email"
value="{{::worker.email}}">
</vn-label-value>
<vn-label-value label="Department"
value="{{::worker.department}}">
</vn-label-value>
</vn-one>
<vn-horizontal class="buttons">
<vn-icon-button
ng-click="$ctrl.preview($event, worker)"
vn-tooltip="Preview"
icon="desktop_windows">
</vn-icon-button>
</vn-horizontal>
<vn-one>
<h6>{{::worker.nickname}}</h6>
<vn-label-value label="Id"
value="{{::worker.id}}">
</vn-label-value>
<vn-label-value label="User"
value="{{::worker.userName}}">
</vn-label-value>
<vn-label-value label="Email"
value="{{::worker.email}}">
</vn-label-value>
<vn-label-value label="Department"
value="{{::worker.department}}">
</vn-label-value>
</vn-one>
<vn-horizontal class="buttons">
<vn-icon-button
ng-click="$ctrl.preview($event, worker)"
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-card>
<vn-pagination model="model"></vn-pagination>
</div>
</vn-horizontal>
</a>
</vn-card>
</vn-data-viewer>
</div>
<vn-dialog vn-id="preview" class="dialog-summary">
<tpl-body>
<vn-worker-summary worker="$ctrl.selectedWorker"></vn-worker-summary>
<vn-worker-summary
worker="$ctrl.selectedWorker">
</vn-worker-summary>
</tpl-body>
</vn-dialog>
<vn-scroll-up></vn-scroll-up>

View File

@ -7,7 +7,9 @@
limit="20"
auto-load="true">
</vn-crud-model>
<div>
<vn-data-viewer
model="model"
class="vn-w-lg">
<vn-card>
<vn-table model="model">
<vn-thead>
@ -95,7 +97,7 @@
</vn-table>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</div>
</vn-data-viewer>
<vn-worker-descriptor-popover
vn-id="workerDescriptor"
worker-fk="$ctrl.selectedWorker">

View File

@ -218,9 +218,9 @@ class Controller {
const timed = new Date(weekday.dated);
const now = new Date();
now.setHours(now.getHours(), now.getMinutes(), 0, 0);
now.setMonth(timed.getMonth());
now.setDate(timed.getDate());
now.setHours(0, 0, 0, 0);
this.newTime = now;
this.selectedWeekday = weekday;

127
package-lock.json generated
View File

@ -2166,7 +2166,7 @@
},
"util": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
"resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
"dev": true,
"requires": {
@ -2960,7 +2960,7 @@
"base": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
"integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
"integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
"dev": true,
"requires": {
"cache-base": "^1.0.1",
@ -3293,7 +3293,7 @@
},
"browserify-rsa": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
"dev": true,
"requires": {
@ -3352,7 +3352,7 @@
},
"buffer": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
"requires": {
"base64-js": "^1.0.2",
@ -3490,7 +3490,7 @@
"cache-base": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
"integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
"integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
"dev": true,
"requires": {
"collection-visit": "^1.0.0",
@ -3528,7 +3528,7 @@
},
"camelcase-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"dev": true,
"requires": {
@ -3667,7 +3667,7 @@
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
"integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
"integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
"dev": true,
"requires": {
"arr-union": "^3.1.0",
@ -4769,7 +4769,7 @@
"dot-prop": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
"integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=",
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
"requires": {
"is-obj": "^1.0.0"
}
@ -4801,7 +4801,7 @@
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dev": true,
"requires": {
@ -4924,7 +4924,7 @@
"dependencies": {
"fs-extra": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=",
"dev": true,
"requires": {
@ -4937,7 +4937,7 @@
},
"jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
"dev": true,
"requires": {
@ -5840,7 +5840,7 @@
},
"file-loader": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
"resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
"dev": true,
"requires": {
@ -6204,7 +6204,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -6225,12 +6226,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -6245,17 +6248,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -6372,7 +6378,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -6384,6 +6391,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -6398,6 +6406,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -6405,12 +6414,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -6429,6 +6440,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -6509,7 +6521,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -6521,6 +6534,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -6606,7 +6620,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -6642,6 +6657,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -6661,6 +6677,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -6704,12 +6721,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@ -6992,7 +7011,7 @@
"global-modules": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
"integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=",
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
"dev": true,
"requires": {
"global-prefix": "^1.0.1",
@ -7029,7 +7048,7 @@
},
"globby": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"resolved": "http://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
"integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
"dev": true,
"requires": {
@ -7133,7 +7152,7 @@
},
"got": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
"resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz",
"integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
"dev": true,
"requires": {
@ -7466,7 +7485,7 @@
},
"kind-of": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
"resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
"integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
"dev": true
},
@ -7686,7 +7705,7 @@
"dependencies": {
"es6-promise": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
"resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
"dev": true
},
@ -8720,7 +8739,7 @@
},
"is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-path-cwd": {
@ -8750,7 +8769,7 @@
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dev": true,
"requires": {
"isobject": "^3.0.1"
@ -9101,7 +9120,7 @@
},
"jasmine-core": {
"version": "2.99.1",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
"resolved": "http://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
"dev": true
},
@ -10224,7 +10243,7 @@
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
@ -11013,7 +11032,7 @@
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"mem": {
@ -11038,7 +11057,7 @@
},
"meow": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
"dev": true,
"requires": {
@ -11161,7 +11180,7 @@
},
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
},
"minstache": {
@ -11273,7 +11292,7 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
@ -11281,7 +11300,7 @@
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
@ -11482,7 +11501,7 @@
},
"multipipe": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
"resolved": "http://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
"integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=",
"dev": true,
"requires": {
@ -11688,7 +11707,7 @@
},
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
"dev": true
},
@ -12330,7 +12349,7 @@
"dependencies": {
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
"dev": true
},
@ -12392,7 +12411,7 @@
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
},
@ -12408,7 +12427,7 @@
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
@ -12931,7 +12950,7 @@
},
"pretty-bytes": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
"resolved": "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
"integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=",
"dev": true,
"requires": {
@ -13022,7 +13041,7 @@
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dev": true,
"requires": {
@ -13040,7 +13059,7 @@
},
"through2": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
"resolved": "http://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
"integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
"dev": true,
"requires": {
@ -13859,7 +13878,7 @@
},
"safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
"requires": {
@ -13984,7 +14003,7 @@
"dependencies": {
"source-map": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
"dev": true,
"requires": {
@ -14404,7 +14423,7 @@
"snapdragon-node": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
"integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
"integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
"dev": true,
"requires": {
"define-property": "^1.0.0",
@ -14455,7 +14474,7 @@
"snapdragon-util": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
"integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
"integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
"dev": true,
"requires": {
"kind-of": "^3.2.0"
@ -14736,7 +14755,7 @@
"split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
"integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
"integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
"dev": true,
"requires": {
"extend-shallow": "^3.0.0"
@ -14745,7 +14764,7 @@
"split2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
"integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=",
"integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==",
"dev": true,
"requires": {
"through2": "^2.0.2"
@ -15671,7 +15690,7 @@
},
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
},
"through2": {
@ -15866,7 +15885,7 @@
"touch": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
"integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=",
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
"dev": true,
"requires": {
"nopt": "~1.0.10"
@ -15964,7 +15983,7 @@
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
"resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
"integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
"dev": true
},