diff --git a/e2e/helpers/components_selectors.js b/e2e/helpers/components_selectors.js index 4cd8241ab..3e2715ba2 100644 --- a/e2e/helpers/components_selectors.js +++ b/e2e/helpers/components_selectors.js @@ -1,6 +1,6 @@ export default { - vnTextfield: 'vn-textfield > div > div > div > input', - vnInputNumber: 'vn-input-number > div > div > div > input', + vnTextfield: 'vn-textfield input', + vnInputNumber: 'vn-input-number input', vnSubmit: 'vn-submit > input', vnFloatButton: 'vn-float-button > button' }; diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index 081332337..c000a471a 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -18,8 +18,18 @@ let actions = { clearInput: function(selector, done) { this.wait(selector) - .evaluate(inputSelector => { - return document.querySelector(inputSelector).closest('*[model], *[field], *[value]').$ctrl.value = ''; + .evaluate(selector => { + let field = document.querySelector(selector) + .closest('*[model], *[field], *[value]'); + let $ctrl = field.$ctrl; + + if (field.classList.contains('vn-field')) { + $ctrl.field = null; + $ctrl.$.$apply(); + } else + $ctrl.value = null; + + $ctrl.input.dispatchEvent(new Event('change')); }, selector) .then(done) .catch(done); @@ -167,8 +177,8 @@ let actions = { focusElement: function(selector, done) { this.wait(selector) - .evaluate_now(elemenetSelector => { - let element = document.querySelector(elemenetSelector); + .evaluate_now(selector => { + let element = document.querySelector(selector); element.focus(); }, done, selector) .then(done) @@ -401,8 +411,7 @@ let actions = { }, autocompleteSearch: function(autocompleteSelector, searchValue, done) { - this.wait(`${autocompleteSelector} input`) - .waitToClick(`${autocompleteSelector} input`) + this.waitToClick(`${autocompleteSelector} input`) .write(`.vn-popover.shown .vn-drop-down input`, searchValue) .waitToClick(`.vn-popover.shown .vn-drop-down li.active`) .wait((autocompleteSelector, searchValue) => { @@ -412,7 +421,7 @@ let actions = { }, autocompleteSelector, searchValue) .then(done) .catch(() => { - done(new Error(`.autocompleteSearch() for ${autocompleteSelector}, timed out`)); + done(new Error(`.autocompleteSearch() for value ${searchValue} in ${autocompleteSelector} timed out`)); }); }, @@ -427,25 +436,22 @@ let actions = { .catch(done); }, - datePicker: function(datePickerSelector, changeMonth, day, done) { - this.wait(datePickerSelector) - .mousedown(datePickerSelector) - .wait('div.flatpickr-calendar.open'); + datePicker: function(selector, changeMonth, day, done) { + this.wait(selector) + .mousedown(`${selector} input`) + .wait('.flatpickr-calendar.open'); + if (changeMonth > 0) - this.mousedown('body > div.flatpickr-calendar.open > div.flatpickr-months > span.flatpickr-next-month > svg'); - - + this.mousedown(`.flatpickr-calendar.open .flatpickr-next-month`); if (changeMonth < 0) - this.mousedown('body > div.flatpickr-calendar.open > div.flatpickr-months > span.flatpickr-prev-month > svg'); + this.mousedown(`.flatpickr-calendar.open .flatpickr-prev-month`); let daySelector; if (!day) - daySelector = 'div.flatpickr-calendar.open span.flatpickr-day:nth-child(16)'; - + daySelector = `.flatpickr-calendar.open .flatpickr-day:nth-child(16)`; if (day) - daySelector = `span.flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`; - + daySelector = `.flatpickr-calendar.open .flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`; this.wait(selector => { return document.querySelector(selector); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 351053a02..b032caf0d 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -16,9 +16,9 @@ export default { userLocalCompany: '.user-configuration vn-autocomplete[field="$ctrl.localCompanyFk"]', userWarehouse: '.user-configuration vn-autocomplete[field="$ctrl.warehouseFk"]', userCompany: '.user-configuration vn-autocomplete[field="$ctrl.companyFk"]', - userConfigFirstAutocompleteClear: '#localWarehouse > div > div > div > vn-icon.clear', - userConfigSecondAutocompleteClear: '#localBank > div > div > div > vn-icon.clear', - userConfigThirdAutocompleteClear: '#localCompany > div > div > div > vn-icon.clear', + userConfigFirstAutocompleteClear: '#localWarehouse .icons > vn-icon[icon=clear]', + userConfigSecondAutocompleteClear: '#localBank .icons > vn-icon[icon=clear]', + userConfigThirdAutocompleteClear: '#localCompany .icons > vn-icon[icon=clear]', acceptButton: 'vn-confirm button[response=ACCEPT]' }, clientsIndex: { @@ -79,14 +79,14 @@ export default { saveButton: `${components.vnSubmit}` }, clientBillingData: { - payMethodAutocomplete: 'vn-autocomplete[field="$ctrl.client.payMethodFk"]', - IBANInput: `${components.vnTextfield}[name="iban"]`, - dueDayInput: `${components.vnInputNumber}[name="dueDay"]`, - receivedCoreLCRCheckbox: 'vn-check[label="Received LCR"]', - receivedCoreVNLCheckbox: 'vn-check[label="Received core VNL"]', - receivedB2BVNLCheckbox: 'vn-check[label="Received B2B VNL"]', + payMethodAutocomplete: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.payMethodFk"]', + IBANInput: `vn-client-billing-data ${components.vnTextfield}[name="iban"]`, + dueDayInput: `vn-client-billing-data ${components.vnInputNumber}[name="dueDay"]`, + receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]', + receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]', + receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]', swiftBicAutocomplete: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"]', - clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"] > div > div > div > vn-icon > i', + clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"] .icons > vn-icon[icon=clear]', newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button', newBankEntityName: 'vn-client-billing-data > vn-dialog vn-textfield[label="Name"] input', newBankEntityBIC: 'vn-client-billing-data > vn-dialog vn-textfield[label="Swift / BIC"] input', @@ -345,7 +345,7 @@ export default { createTicketView: { clientAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.clientFk"]', addressAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.addressFk"]', - deliveryDateInput: 'vn-ticket-create > div > div > vn-card > div > vn-ticket-create-card > vn-date-picker > div > input', + deliveryDateInput: 'vn-ticket-create vn-date-picker[field="$ctrl.landed"]', warehouseAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.warehouseFk"]', agencyAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.ticket.agencyModeFk"]', createButton: `${components.vnSubmit}` @@ -392,7 +392,7 @@ export default { firstQuantityInput: 'vn-input-number[label="Quantity"] input', firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', - clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] > div > div > div > vn-icon > i', + clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] .icons > vn-icon[icon=clear]', savePackagesButton: `${components.vnSubmit}` }, ticketSales: { @@ -408,7 +408,7 @@ export default { moreMenuReserve: '.vn-popover.shown .vn-drop-down li[name="Mark as reserved"]', moreMenuUnmarkReseved: '.vn-popover.shown .vn-drop-down li[name="Unmark as reserved"]', moreMenuUpdateDiscount: '.vn-popover.shown .vn-drop-down li[name="Update discount"]', - moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog form vn-ticket-sale-edit-discount vn-input-number[model="$ctrl.newDiscount"] input', + moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog form vn-ticket-sale-edit-discount vn-input-number[field="$ctrl.newDiscount"] input', transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text', transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable', firstSaleClaimIcon: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) vn-icon[icon="icon-claims"]', @@ -416,11 +416,11 @@ export default { firstSaleText: 'vn-table div > vn-tbody > vn-tr:nth-child(1)', firstSaleThumbnailImage: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) vn-td:nth-child(3) > img', firstSaleZoomedImage: 'body > div > div > img', - firstSaleQuantity: 'vn-input-number[model="sale.quantity"]:nth-child(1) input', + firstSaleQuantity: 'vn-input-number[field="sale.quantity"]:nth-child(1) input', firstSaleQuantityCell: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable:nth-child(5)', firstSaleQuantityClearInput: 'vn-textfield[model="sale.quantity"] div.suffix > i', - firstSaleIdInput: 'body > vn-app > div > ui-view > vn-ticket-card > vn-main-block > div > vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete > div > div > input', - firstSaleIdAutocomplete: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete', + firstSaleIdInput: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete input', + firstSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete', idAutocompleteFirstResult: '.vn-popover.shown .vn-drop-down li', firstSalePrice: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(7) > span', firstSalePriceInput: '.vn-popover.shown vn-input-number input', @@ -438,10 +438,10 @@ export default { secondSaleText: 'vn-table div > vn-tbody > vn-tr:nth-child(2)', secondSaleId: 'vn-ticket-sale:nth-child(2) vn-td-editable:nth-child(4) text > span', secondSaleIdCell: 'vn-ticket-sale vn-tr:nth-child(2) > vn-td-editable:nth-child(4)', - secondSaleIdInput: 'body > vn-app > div > ui-view > vn-ticket-card > vn-main-block > div > vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete > div > div > input', - secondSaleIdAutocomplete: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete', + secondSaleIdInput: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete input', + secondSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete', secondSaleQuantity: 'vn-ticket-sale vn-table vn-tr:nth-child(2) vn-input-number input', - secondSaleConceptCell: 'vn-ticket-sale vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)', + secondSaleConceptCell: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)', secondSaleConceptInput: 'vn-ticket-sale vn-table vn-tr:nth-child(2) > vn-td-editable.ng-isolate-scope.selected vn-textfield input', totalImport: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > vn-one > p:nth-child(3) > strong', selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check', @@ -485,8 +485,8 @@ export default { request: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr', descriptionInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(1) > vn-textfield > div > div > div.infix > input', atenderAutocomplete: 'vn-ticket-request-create vn-autocomplete[field="$ctrl.ticketRequest.atenderFk"]', - quantityInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(2) > vn-input-number:nth-child(1) > div > div > div.infix > input', - priceInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(2) > vn-input-number:nth-child(2) > div > div > div.infix > input', + quantityInput: 'vn-ticket-request-create vn-input-number input[name=quantity]', + priceInput: 'vn-ticket-request-create vn-input-number input[name=price]', firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)', saveButton: 'vn-ticket-request-create > form > div > vn-button-bar > vn-submit[label="Create"] input', firstDescription: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2)', @@ -514,7 +514,7 @@ export default { createStateView: { stateAutocomplete: 'vn-autocomplete[field="$ctrl.stateFk"]', workerAutocomplete: 'vn-autocomplete[field="$ctrl.workerFk"]', - clearStateInputButton: 'vn-autocomplete[field="$ctrl.stateFk"] > div > div > div > vn-icon > i', + clearStateInputButton: 'vn-autocomplete[field="$ctrl.stateFk"] .icons > vn-icon[icon=clear]', saveStateButton: `${components.vnSubmit}` }, claimsIndex: { @@ -548,12 +548,12 @@ export default { }, claimDetail: { secondItemDiscount: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(6) > span', - discountInput: '.vn-popover.shown vn-input-number[model="$ctrl.newDiscount"] > div > div > div.infix > input', + discountInput: '.vn-popover.shown vn-input-number[field="$ctrl.newDiscount"] > div > div > div.infix > input', discoutPopoverMana: '.vn-popover.shown .content > div > vn-horizontal > h5', addItemButton: 'vn-claim-detail a vn-float-button', firstClaimableSaleFromTicket: 'vn-claim-detail > vn-dialog vn-tbody > vn-tr', claimDetailLine: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr', - firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[model="saleClaimed.quantity"] input', + firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[field="saleClaimed.quantity"] input', totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > div > vn-label-value:nth-child(2) > section > span', secondItemDeleteButton: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(8) > vn-icon-button > button > vn-icon > i' }, @@ -597,7 +597,7 @@ export default { clientAutocomplete: 'vn-autocomplete[label="Client"]', addressAutocomplete: 'vn-autocomplete[label="Address"]', agencyAutocomplete: 'vn-autocomplete[label="Agency"]', - landedDatePicker: 'vn-date-picker[label="Landed"] input', + landedDatePicker: 'vn-date-picker[label="Landed"]', createButton: `${components.vnSubmit}`, cancelButton: 'vn-button[href="#!/client/index"]' }, @@ -633,7 +633,7 @@ export default { }, createRouteView: { workerAutocomplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.workerFk"]', - createdDatePicker: 'vn-route-create vn-date-picker[model="$ctrl.route.created"] > div > input', + createdDatePicker: 'vn-route-create vn-date-picker[field="$ctrl.route.created"]', vehicleAutoComplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.vehicleFk"]', agencyAutoComplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.agencyModeFk"]', descriptionInput: 'vn-route-create vn-textfield[field="$ctrl.route.description"] input', @@ -650,10 +650,10 @@ export default { vehicleAutoComplete: 'vn-route-basic-data vn-autocomplete[field="$ctrl.route.vehicleFk"]', agencyAutoComplete: 'vn-route-basic-data vn-autocomplete[field="$ctrl.route.agencyModeFk"]', kmStartInput: 'vn-route-basic-data vn-input-number[field="$ctrl.route.kmStart"] input', - kmEndInput: 'vn-route-basic-data vn-input-number[model="$ctrl.route.kmEnd"] input', - createdDateInput: 'vn-route-basic-data vn-date-picker[model="$ctrl.route.created"] > div > input', - startedHourInput: 'vn-route-basic-data vn-input-time[model="$ctrl.route.started"] input', - finishedHourInput: 'vn-route-basic-data vn-input-time[model="$ctrl.route.finished"] input', + kmEndInput: 'vn-route-basic-data vn-input-number[field="$ctrl.route.kmEnd"] input', + createdDateInput: 'vn-route-basic-data vn-date-picker[field="$ctrl.route.created"]', + startedHourInput: 'vn-route-basic-data vn-input-time[field="$ctrl.route.started"] input', + finishedHourInput: 'vn-route-basic-data vn-input-time[field="$ctrl.route.finished"] input', saveButton: 'vn-route-basic-data vn-submit[label="Save"] input' }, routeTickets: { diff --git a/front/core/components/autocomplete/autocomplete.html b/front/core/components/autocomplete/autocomplete.html deleted file mode 100755 index 4caca44bc..000000000 --- a/front/core/components/autocomplete/autocomplete.html +++ /dev/null @@ -1,27 +0,0 @@ -
-
- -
- - -
- -
-
- - \ No newline at end of file diff --git a/front/core/components/autocomplete/index.html b/front/core/components/autocomplete/index.html new file mode 100755 index 000000000..90f936801 --- /dev/null +++ b/front/core/components/autocomplete/index.html @@ -0,0 +1,46 @@ +
+
+
+
+
+
+ + +
+
+ +
+
+ + + + +
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/front/core/components/autocomplete/autocomplete.js b/front/core/components/autocomplete/index.js similarity index 80% rename from front/core/components/autocomplete/autocomplete.js rename to front/core/components/autocomplete/index.js index 469bb9e93..f799ee3a9 100755 --- a/front/core/components/autocomplete/autocomplete.js +++ b/front/core/components/autocomplete/index.js @@ -1,5 +1,5 @@ import ngModule from '../../module'; -import Input from '../../lib/input'; +import Field from '../field'; import assignProps from '../../lib/assign-props'; import {mergeWhere} from 'vn-loopback/util/filter'; import './style.scss'; @@ -16,23 +16,18 @@ import './style.scss'; * * @event change Thrown when value is changed */ -export default class Autocomplete extends Input { - constructor($element, $scope, $http, $transclude, $translate, $interpolate) { - super($element, $scope); - this.$http = $http; - this.$interpolate = $interpolate; - this.$transclude = $transclude; - this.$translate = $translate; - this._field = undefined; +export default class Autocomplete extends Field { + constructor($element, $scope, $compile, $http, $transclude, $translate, $interpolate) { + super($element, $scope, $compile); + Object.assign(this, { + $http, + $interpolate, + $transclude, + $translate + }); + this._selection = null; - this.readonly = true; - this.form = null; - this.input = this.element.querySelector('.mdl-textfield__input'); - - componentHandler.upgradeElement( - this.element.querySelector('.mdl-textfield')); - - this.registerEvents(); + this.input = this.element.querySelector('input'); } $postLink() { @@ -44,12 +39,16 @@ export default class Autocomplete extends Input { } /** - * Registers all event emitters + * @type {any} The autocomplete value. */ - registerEvents() { - this.input.addEventListener('focus', event => { - this.emit('focus', {event}); - }); + get field() { + return super.field; + } + + set field(value) { + super.field = value; + this.refreshSelection(); + this.emit('change', {value}); } get model() { @@ -83,20 +82,6 @@ export default class Autocomplete extends Input { Object.assign(this.$.dropDown, props); } - /** - * @type {any} The autocomplete value. - */ - get field() { - return this._field; - } - - set field(value) { - this._field = value; - - this.refreshSelection(); - this.emit('change', {value}); - } - /** * @type {Object} The selected data object, you can use this property * to prevent requests to display the initial value. @@ -216,33 +201,15 @@ export default class Autocomplete extends Input { if (this.translateFields.indexOf(this.showField) > -1) this.input.value = this.$translate.instant(display); } - - this.mdlUpdate(); - } - - mdlUpdate() { - let field = this.element.querySelector('.mdl-textfield'); - let mdlField = field.MaterialTextfield; - if (mdlField) mdlField.updateClasses_(); - } - - setValue(value) { - this.field = value; - if (this.form) this.form.$setDirty(); } onDropDownSelect(item) { const value = item[this.valueField]; this.selection = item; - this.setValue(value); + this.field = value; } - onClearClick(event) { - event.preventDefault(); - this.setValue(null); - } - - onKeyDown(event) { + onInputKeyDown(event) { // if (event.defaultPrevented) return; switch (event.keyCode) { @@ -261,7 +228,8 @@ export default class Autocomplete extends Input { event.preventDefault(); } - onMouseDown(event) { + onInputMouseDown(event) { + if (event.defaultPrevented) return; event.preventDefault(); this.showDropDown(); } @@ -307,16 +275,12 @@ export default class Autocomplete extends Input { this.refreshSelection(); } } -Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude', '$translate', '$interpolate']; +Autocomplete.$inject = ['$element', '$scope', '$compile', '$http', '$transclude', '$translate', '$interpolate']; -ngModule.component('vnAutocomplete', { - template: require('./autocomplete.html'), +ngModule.vnComponent('vnAutocomplete', { + template: require('./index.html'), controller: Autocomplete, bindings: { - label: '@', - field: '=?', - disabled: ' div > .mdl-textfield { - position: relative; - width: 100%; +vn-autocomplete.vn-field { + & > .container > .infix > .control { + overflow: hidden; & > input { cursor: pointer; - height: 30px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; + text-align: left; + padding-left: 0; + padding-right: 0; } - & > .icons { - display: none; - position: absolute; - right: 0; - top: 1.3em; - height: 1em; - color: $color-font-secondary; - border-radius: .2em; - - & > vn-icon { - cursor: pointer; - font-size: 18px; - - &:hover { - color: $color-font; - } - } - } - &:hover > .icons, - & > input:focus + .icons { - display: block; - } - } - - label span:nth-child(2) { - color: $color-alert } } - -ul.vn-autocomplete { - list-style-type: none; - padding: 1em; - margin: 0; - padding: 0; - overflow: auto; - max-height: 300px; - - li { - @extend %clickable; - display: block; - padding: .8em; - margin: 0; - - &.load-more { - color: $color-main; - font-family: vn-font-bold; - padding: .4em .8em; - } - } -} \ No newline at end of file diff --git a/front/core/components/check/index.js b/front/core/components/check/index.js index 35ff07e8a..8ebb784f3 100644 --- a/front/core/components/check/index.js +++ b/front/core/components/check/index.js @@ -64,14 +64,10 @@ export default class Check extends Toggle { } } -ngModule.component('vnCheck', { +ngModule.vnComponent('vnCheck', { template: require('./index.html'), controller: Check, bindings: { - label: '@?', - field: '=?', - disabled: ' { })); beforeEach(inject(($compile, $rootScope) => { - $element = $compile(``)($rootScope); $ctrl = $element.controller('vnCheck'); element = $element[0]; })); diff --git a/front/core/components/date-picker/date-picker.html b/front/core/components/date-picker/date-picker.html deleted file mode 100644 index 67fcd880b..000000000 --- a/front/core/components/date-picker/date-picker.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
- - clear - -
- -
\ No newline at end of file diff --git a/front/core/components/date-picker/date-picker.js b/front/core/components/date-picker/date-picker.js deleted file mode 100644 index 1156ab09a..000000000 --- a/front/core/components/date-picker/date-picker.js +++ /dev/null @@ -1,107 +0,0 @@ -import ngModule from '../../module'; -import Component from '../../lib/component'; -import {Flatpickr} from '../../vendor'; -import './style.scss'; - -class DatePicker extends Component { - constructor($element, $scope, $translate, $attrs) { - super($element, $scope); - this.input = $element[0].querySelector('input'); - this.$translate = $translate; - this.$attrs = $attrs; - this._model = undefined; - this.dateValue = undefined; - this.hasMouseIn = false; - let locale = this.$translate.use(); - this.defaultOptions = { - locale: locale, - dateFormat: locale == 'es' ? 'd-m-Y' : 'Y-m-d', - enableTime: false, - disableMobile: true, - onValueUpdate: () => this.onValueUpdate() - }; - this.userOptions = {}; - this._iniOptions = this.defaultOptions; - componentHandler.upgradeElement($element[0].firstChild); - this.vp = new Flatpickr(this.input, this._iniOptions); - } - - onValueUpdate() { - if (this.vp.selectedDates.length) { - let date = this.vp.selectedDates[0]; - let offset = date.getTimezoneOffset() * 60000; - date.setTime(date.getTime() - offset); - this._model = date; - } else - this.model = null; - this.$.$apply(); - } - - set iniOptions(value) { - this.userOptions = value; - let options = Object.assign({}, this.defaultOptions, value); - this._iniOptions = options; - - // TODO: When some properties change Flatpickr doesn't refresh the view - // for (let option in options) - // this.vp.set(option, options[option]); - - if (this.vp) this.vp.destroy(); - this.vp = new Flatpickr(this.input, this._iniOptions); - this.vp.setDate(this.dateValue); - this.mdlUpdate(); - } - - get iniOptions() { - return this.userOptions; - } - - get model() { - return this._model; - } - - set model(value) { - this._model = value; - this.dateValue = value; - let date; - if (value && this.iniOptions.enableTime) { - date = new Date(value); - let offset = date.getTimezoneOffset() * 60000; - date.setTime(date.getTime() + offset); - } else - date = value; - - this.vp.setDate(date); - this.mdlUpdate(); - } - - onClear() { - this.model = null; - } - - mdlUpdate() { - let mdlField = this.element.firstChild.MaterialTextfield; - if (mdlField) - mdlField.updateClasses_(); - } - - $onDestroy() { - this.vp.destroy(); - this.dateValue = undefined; - } -} -DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs']; - -ngModule.component('vnDatePicker', { - template: require('./date-picker.html'), - bindings: { - iniOptions: ' { - let controller; - let $attrs; - let $element; - let today = new Date(); - today.setHours(0, 0, 0, 0); - - beforeEach(angular.mock.module('vnCore', $translateProvider => { - $translateProvider.translations('en', {}); - })); - - beforeEach(angular.mock.inject(($componentController, $translate) => { - $attrs = {}; - $element = angular.element(`
`); - controller = $componentController('vnDatePicker', {$element, $attrs, $translate}); - })); - - describe('onValueUpdate() while date is selected', () => { - it(`should store the selected date in the controller`, () => { - controller.vp = {selectedDates: [today]}; - controller.isLocale = true; - controller.onValueUpdate(); - - expect(controller._model).toEqual(today); - }); - - it(`should format the date`, () => { - controller.vp = {selectedDates: [today], destroy: () => {}}; - controller.isLocale = undefined; - controller._iniOptions.enableTime = undefined; - - controller.onValueUpdate(); - - expect(controller._model).toEqual(today); - }); - }); -}); diff --git a/front/core/components/date-picker/index.js b/front/core/components/date-picker/index.js new file mode 100644 index 000000000..96417f980 --- /dev/null +++ b/front/core/components/date-picker/index.js @@ -0,0 +1,101 @@ +import ngModule from '../../module'; +import Field from '../field'; +import {Flatpickr} from '../../vendor'; +import './style.scss'; + +class DatePicker extends Field { + constructor($element, $scope, $compile, $translate) { + super($element, $scope, $compile); + this.$translate = $translate; + + this.input = $compile(``)($scope)[0]; + this.control.appendChild(this.input); + + this.initPicker(); + } + + get field() { + return super.field; + } + + set field(value) { + super.field = value; + + let date = value; + if (date && !(date instanceof Date)) + date = new Date(date); + + this.picker.setDate(fixDate(date)); + } + + set options(value) { + let selectedDates = this.picker.selectedDates || []; + this._options = value; + this.initPicker(); + this.picker.setDate(selectedDates[0]); + } + + get options() { + return this._options; + } + + initPicker() { + let locale = this.$translate.use(); + let format = locale == 'es' ? 'd-m-Y' : 'Y-m-d'; + + let options = this.options || {}; + let defaultOptions = { + locale: locale, + dateFormat: format, + enableTime: false, + disableMobile: true, + onValueUpdate: () => this.onValueUpdate() + }; + + if (options.enableTime) { + Object.assign(defaultOptions, { + dateFormat: `${format} h:i`, + time_24hr: true + }); + } + + let mergedOptions = Object.assign({}, + defaultOptions, + options + ); + + if (this.picker) this.picker.destroy(); + this.picker = new Flatpickr(this.input, mergedOptions); + } + + onValueUpdate() { + let date = null; + + if (this.picker.selectedDates.length) + date = this.picker.selectedDates[0]; + + super.field = fixDate(date, -1); + this.$.$applyAsync(); + } + + $onDestroy() { + this.picker.destroy(); + } +} +DatePicker.$inject = ['$element', '$scope', '$compile', '$translate']; + +ngModule.vnComponent('vnDatePicker', { + controller: DatePicker, + bindings: { + options: ' { + let $filter; + let $element; + let $ctrl; + let today; + + beforeEach(angular.mock.module('vnCore', $translateProvider => { + $translateProvider.translations('en', {}); + })); + + beforeEach(angular.mock.inject(($compile, $rootScope, _$filter_) => { + $filter = _$filter_; + + $element = $compile(``)($rootScope); + $ctrl = $element.controller('vnDatePicker'); + + today = new Date(); + today.setUTCHours(0, 0, 0, 0); + })); + + afterEach(() => { + $element.remove(); + }); + + describe('field() setter', () => { + it(`should display the formated the date`, () => { + $ctrl.field = today; + + let displayed = $filter('dateTime')(today, 'yyyy-MM-dd'); + + expect($ctrl.value).toEqual(displayed); + }); + }); + + describe('options() setter', () => { + it(`should display the date with the new format`, () => { + $ctrl.options = {dateFormat: 'Y-m'}; + $ctrl.field = today; + + let displayed = $filter('dateTime')(today, 'yyyy-MM'); + + expect($ctrl.value).toEqual(displayed); + }); + }); +}); diff --git a/front/core/components/date-picker/style.scss b/front/core/components/date-picker/style.scss index d33f27b5d..6af4580f6 100644 --- a/front/core/components/date-picker/style.scss +++ b/front/core/components/date-picker/style.scss @@ -1,24 +1,5 @@ @import "variables"; -vn-date-picker { - .mdl-chip__action { - position: absolute; - width: auto; - top: 0px; - right: -6px; - margin: 22px 0px; - background-color: white; - } - .mdl-textfield { - width: 100%; - } - .material-icons { - font-size: 18px; - float: right; - margin-right: 5px; - } -} - .flatpickr-months .flatpickr-month, .flatpickr-weekdays, span.flatpickr-weekday { diff --git a/front/core/components/drop-down/drop-down.js b/front/core/components/drop-down/drop-down.js index 8422a60de..182ea49e0 100755 --- a/front/core/components/drop-down/drop-down.js +++ b/front/core/components/drop-down/drop-down.js @@ -194,10 +194,12 @@ export default class DropDown extends Component { this.document.addEventListener('keydown', this.docKeyDownHandler); this.$.list.scrollTop = 0; this.$.input.focus(); + this.emit('open'); } onClose() { this.document.removeEventListener('keydown', this.docKeyDownHandler); + this.emit('close'); } onClearClick() { diff --git a/front/core/components/field/index.html b/front/core/components/field/index.html index a2401ee4f..5e27c1fb3 100644 --- a/front/core/components/field/index.html +++ b/front/core/components/field/index.html @@ -5,9 +5,7 @@
-
- -
+