From 5bf20683445bf3ef82374a063b259f8728041a79 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 13:51:16 +0200 Subject: [PATCH 01/41] added invoiceOut alias --- modules/invoiceOut/back/methods/invoiceOut/filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index 001fe077d..092d298d0 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -86,8 +86,9 @@ module.exports = Self => { return {'i.hasPdf': value}; case 'created': return {'i.created': value}; - case 'amount': case 'clientFk': + return {'i.clientFk': value}; + case 'amount': case 'companyFk': case 'issued': case 'dued': From f8ba4d38b786e8a83eb7c6ee174da420dc7dbc08 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 14:36:02 +0200 Subject: [PATCH 02/41] stowaway changed to correct field name --- modules/ticket/back/methods/ticket/getPossibleStowaways.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/getPossibleStowaways.js b/modules/ticket/back/methods/ticket/getPossibleStowaways.js index f692c9f23..3565d64ab 100644 --- a/modules/ticket/back/methods/ticket/getPossibleStowaways.js +++ b/modules/ticket/back/methods/ticket/getPossibleStowaways.js @@ -45,7 +45,7 @@ module.exports = Self => { clientFk: ship.clientFk, addressFk: ship.addressFk, agencyModeFk: ship.agencyModeFk, - warehouse: {neq: ship.warehouseFk}, + warehouseFk: {neq: ship.warehouseFk}, shipped: { between: [lowestDate.toJSON(), highestDate.toJSON()] } From 0c097718c15cfc0d364a82d9091aa19e60b976e4 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 10 Oct 2019 08:33:22 +0200 Subject: [PATCH 03/41] added transaction options to findOne() --- back/methods/dms/uploadFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/dms/uploadFile.js b/back/methods/dms/uploadFile.js index b50aaf824..41d551f2b 100644 --- a/back/methods/dms/uploadFile.js +++ b/back/methods/dms/uploadFile.js @@ -94,7 +94,7 @@ module.exports = Self => { const models = Self.app.models; const storageConnector = Self.app.dataSources.storage.connector; const myUserId = ctx.req.accessToken.userId; - const myWorker = await models.Worker.findOne({where: {userFk: myUserId}}); + const myWorker = await models.Worker.findOne({where: {userFk: myUserId}}, myOptions); const args = ctx.args; const newDms = await Self.create({ From 777baf38a84f1f54376b27a25edce7b11ffd60fd Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 10 Oct 2019 09:58:34 +0200 Subject: [PATCH 04/41] changed warehouse from ticket id 17 --- db/dump/fixtures.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index f701c4121..f00a98759 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -471,7 +471,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF (14, 1, 2, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()), (15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()), (16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), - (17, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), + (17, 1, 7, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), (18, 1, 4, 4, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()), (19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()), (20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), From 9899edffc63090d9913b7f730885a2f8bc996208 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 10 Oct 2019 09:59:28 +0200 Subject: [PATCH 05/41] changed state to stowaway ticket --- modules/ticket/back/models/stowaway.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/models/stowaway.js b/modules/ticket/back/models/stowaway.js index aa21e8680..780b6b31c 100644 --- a/modules/ticket/back/models/stowaway.js +++ b/modules/ticket/back/models/stowaway.js @@ -14,7 +14,7 @@ module.exports = function(Self) { code: 'BOARDING' }; let state = await models.State.findOne({where}); - let params = {ticketFk: ctx.instance.id, stateFk: state.id}; + let params = {ticketFk: ctx.instance.shipFk, stateFk: state.id}; const loopBackContext = LoopBackContext.getCurrentContext(); let httpCtx = {req: loopBackContext.active}; From 2a3d6dcd76ee5e5e3005ded1c524533c769f12b4 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Mon, 14 Oct 2019 11:50:45 +0200 Subject: [PATCH 06/41] fixed transaction params --- back/methods/message/send.js | 4 ++-- modules/client/back/methods/address/createDefaultAddress.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/back/methods/message/send.js b/back/methods/message/send.js index f7b7ad76e..c8849774b 100644 --- a/back/methods/message/send.js +++ b/back/methods/message/send.js @@ -29,8 +29,8 @@ module.exports = Self => { const accessToken = ctx.options && ctx.options.accessToken || ctx.req && ctx.req.accessToken; const userId = accessToken.userId; const models = Self.app.models; - const sender = await models.Account.findById(userId, options); - const recipient = await models.Account.findById(data.recipientFk, options); + const sender = await models.Account.findById(userId, null, options); + const recipient = await models.Account.findById(data.recipientFk, null, options); await Self.create({ sender: sender.name, diff --git a/modules/client/back/methods/address/createDefaultAddress.js b/modules/client/back/methods/address/createDefaultAddress.js index c757f9f85..e524a6017 100644 --- a/modules/client/back/methods/address/createDefaultAddress.js +++ b/modules/client/back/methods/address/createDefaultAddress.js @@ -26,7 +26,7 @@ module.exports = function(Self) { let address = data.address; let newAddress = await Address.create(address, options); - let client = await Client.findById(address.clientFk, options); + let client = await Client.findById(address.clientFk, null, options); if (data.isDefaultAddress) { await client.updateAttributes({ From 3bf44d08de5786163f4b3aa2c1bd1b7d2d16d90f Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 15 Oct 2019 16:19:35 +0200 Subject: [PATCH 07/41] vnDatePicker refactor --- e2e/helpers/extensions.js | 219 ++++++++---------- e2e/helpers/nightmare.js | 4 +- e2e/helpers/selectors.js | 1 - e2e/paths/01-login/01_login.spec.js | 2 - front/core/components/autocomplete/index.html | 4 +- front/core/components/autocomplete/index.js | 3 +- front/core/components/autocomplete/style.scss | 3 + front/core/components/date-picker/index.js | 105 +++------ .../core/components/date-picker/index.spec.js | 20 +- .../core/components/drop-down/drop-down.html | 3 +- front/core/components/drop-down/drop-down.js | 2 +- front/core/components/field/index.js | 6 +- front/core/components/field/style.scss | 39 +++- front/core/components/input-time/index.js | 5 +- front/core/components/popover/popover.js | 3 +- front/core/components/searchbar/searchbar.js | 2 +- front/core/directives/focus.js | 6 +- front/core/vendor.js | 7 - front/package-lock.json | 28 --- front/package.json | 1 - modules/claim/front/basic-data/index.html | 21 +- modules/client/front/fiscal-data/index.html | 13 +- modules/order/front/filter/index.js | 2 +- .../front/basic-data/step-one/index.html | 30 ++- .../front/basic-data/step-one/style.scss | 9 +- webpack.config.js | 2 +- 26 files changed, 237 insertions(+), 303 deletions(-) diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index fb36e3279..022b282d3 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -6,6 +6,93 @@ import config from './config.js'; let currentUser; +let asyncActions = { + // Generic extensions + + clickIfExists: async function(selector) { + let exists = await this.exists(selector); + if (exists) await this.click(selector); + }, + + // Salix specific extensions + + changeLanguageToEnglish: async function() { + let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]'; + + let lang = await this.waitToClick('#user') + .wait(langSelector) + .waitToGetProperty(`${langSelector} input`, 'value'); + + if (lang !== 'English') + await this.autocompleteSearch(langSelector, 'English'); + }, + + login: async function(userName) { + if (currentUser !== userName) { + this.clickIfExists('#logout') + .clickIfExists('.vn-dialog.shown button[response=ACCEPT]'); + + try { + await this.waitForURL('#!/login'); + } catch (e) { + this.goto(`${config.url}/#!/login`); + } + + await this.wait(`vn-login input[name=user]`) + .clearInput(`vn-login input[name=user]`) + .write(`vn-login input[name=user]`, userName) + .write(`vn-login input[name=password]`, 'nightmare') + .click(`vn-login input[type=submit]`) + .waitForURL('#!/') + .changeLanguageToEnglish(); + + currentUser = userName; + } else + await this.waitToClick('vn-topbar a[ui-sref="home"]'); + }, + + waitForLogin: async function(userName) { + await this.login(userName); + }, + + selectModule: async function(moduleName) { + let snakeName = moduleName.replace(/[\w]([A-Z])/g, m => { + return m[0] + '-' + m[1]; + }).toLowerCase(); + + await this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`) + .waitForURL(snakeName); + }, + + loginAndModule: async function(userName, moduleName) { + await this.login(userName) + .selectModule(moduleName); + }, + + datePicker: async function(selector, changeMonth, day) { + let date = new Date(); + if (changeMonth) date.setMonth(date.getMonth() + changeMonth); + date.setDate(day ? day : 16); + date = date.toISOString().substr(0, 10); + + await this.wait(selector) + .evaluate((selector, date) => { + let input = document.querySelector(selector).$ctrl.input; + input.value = date; + input.dispatchEvent(new Event('change')); + }, selector, date); + }, + + pickTime: async function(selector, time) { + await this.wait(selector) + .evaluate((selector, time) => { + let input = document.querySelector(selector); + input.value = time; + input.dispatchEvent(new Event('change')); + }, selector, time); + } +}; + let actions = { clearTextarea: function(selector, done) { this.wait(selector) @@ -28,48 +115,6 @@ let actions = { .catch(done); }, - login: function(userName, done) { - if (currentUser) - this.waitToClick('#logout'); - - let doLogin = () => { - this.wait(`vn-login input[name=user]`) - .clearInput(`vn-login input[name=user]`) - .write(`vn-login input[name=user]`, userName) - .write(`vn-login input[name=password]`, 'nightmare') - .click(`vn-login input[type=submit]`) - .then(() => { - currentUser = userName; - done(); - }) - .catch(done); - }; - - this.waitForURL('#!/login') - .then(doLogin) - .catch(() => { - this.goto(`${config.url}/#!/login`) - .then(doLogin) - .catch(done); - }); - }, - - waitForLogin: function(userName, done) { - if (currentUser === userName) { - return this.waitToClick('vn-topbar a[ui-sref="home"]') - .waitForURL('#!/') - .changeLanguageToEnglish() - .then(done) - .catch(done); - } - return this.login(userName) - .waitForURL('#!/') - .url() - .changeLanguageToEnglish() - .then(done) - .catch(done); - }, - resetLogin: function(done) { this.then(() => { currentUser = undefined; @@ -78,41 +123,6 @@ let actions = { .catch(done); }, - changeLanguageToEnglish: function(done) { - let langSelector = '.user-popover vn-autocomplete[ng-model="$ctrl.lang"]'; - - this.waitToClick('#user') - .wait(langSelector) - .waitToGetProperty(`${langSelector} input`, 'value') - .then(lang => { - if (lang === 'English') { - this.then(done) - .catch(done); - } else { - this.autocompleteSearch(langSelector, 'English') - .then(done) - .catch(done); - } - }); - }, - - selectModule: function(moduleName, done) { - let snakeName = moduleName.replace(/[\w]([A-Z])/g, m => { - return m[0] + '-' + m[1]; - }).toLowerCase(); - this.waitToClick(`vn-home a[ui-sref="${moduleName}.index"]`) - .waitForURL(snakeName) - .then(done) - .catch(done); - }, - - loginAndModule: function(userName, moduleName, done) { - this.waitForLogin(userName) - .selectModule(moduleName) - .then(done) - .catch(done); - }, - parsedUrl: function(done) { this.url() .then(url => { @@ -419,51 +429,6 @@ let actions = { }); }, - pickTime: function(selector, time, done) { - this.wait(selector) - .evaluate((selector, time) => { - let input = document.querySelector(selector); - input.value = time; - input.dispatchEvent(new Event('change')); - }, selector, time) - .then(done) - .catch(done); - }, - - datePicker: function(selector, changeMonth, day, done) { - this.wait(selector) - .mousedown(`${selector} input`) - .wait('.flatpickr-calendar.open'); - - if (changeMonth > 0) - this.mousedown(`.flatpickr-calendar.open .flatpickr-next-month`); - if (changeMonth < 0) - this.mousedown(`.flatpickr-calendar.open .flatpickr-prev-month`); - - let daySelector; - - if (!day) - daySelector = `.flatpickr-calendar.open .flatpickr-day:nth-child(16)`; - if (day) - daySelector = `.flatpickr-calendar.open .flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`; - - this.wait(selector => { - return document.querySelector(selector); - }, daySelector) - .evaluate(selector => { - let event = new MouseEvent('mousedown', { - bubbles: true, - cancelable: true, - view: window - }); - document.querySelector(selector).dispatchEvent(event); - }, daySelector) - .then(done) - .catch(() => { - done(new Error(`.datePicker(), for ${daySelector} timed out`)); - }); - }, - reloadSection: function(sectionRoute, done) { this.waitToClick('vn-icon[icon="desktop_windows"]') .wait('vn-card.summary') @@ -520,3 +485,13 @@ Object.keys(actions).forEach(function(name) { let fn = actions[name]; Nightmare.action(name, fn); }); + +for (let name in asyncActions) { + let fn = asyncActions[name]; + + Nightmare.action(name, function(...args) { + let done = args[args.length - 1]; + fn.apply(this, args) + .then(res => done(null, res), done); + }); +} diff --git a/e2e/helpers/nightmare.js b/e2e/helpers/nightmare.js index a76b50093..f93523856 100644 --- a/e2e/helpers/nightmare.js +++ b/e2e/helpers/nightmare.js @@ -1,4 +1,6 @@ const Nightmare = require('nightmare'); +const config = require('./config.js'); + let nightmare; module.exports = function createNightmare(width = 1280, height = 720) { @@ -22,5 +24,5 @@ module.exports = function createNightmare(width = 1280, height = 720) { }); nightmare.header('Accept-Language', 'en'); - return nightmare; + return nightmare.goto(config.url); }; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 81ad3a0dc..5a3f131a8 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -420,7 +420,6 @@ export default { firstSaleQuantity: 'vn-input-number[ng-model="sale.quantity"]:nth-child(1) input', firstSaleQuantityCell: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable:nth-child(5)', firstSaleQuantityClearInput: 'vn-textfield[ng-model="sale.quantity"] div.suffix > i', - 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', diff --git a/e2e/paths/01-login/01_login.spec.js b/e2e/paths/01-login/01_login.spec.js index a33be0c25..e5a70703e 100644 --- a/e2e/paths/01-login/01_login.spec.js +++ b/e2e/paths/01-login/01_login.spec.js @@ -1,5 +1,4 @@ import createNightmare from '../../helpers/nightmare'; -import config from '../../helpers/config.js'; describe('Login path', () => { @@ -10,7 +9,6 @@ describe('Login path', () => { const password = 'nightmare'; const result = await nightmare - .goto(`${config.url}/#!/login`) .wait(`vn-login input[name=user]`) .write(`vn-login input[name=user]`, username) .write(`vn-login input[name=password]`, password) diff --git a/front/core/components/autocomplete/index.html b/front/core/components/autocomplete/index.html index 2e5cc39f6..c0caf061b 100755 --- a/front/core/components/autocomplete/index.html +++ b/front/core/components/autocomplete/index.html @@ -1,6 +1,6 @@
+ on-close-start="$ctrl.focus()"> \ No newline at end of file diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 69114d028..49dd14b07 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -228,7 +228,7 @@ export default class Autocomplete extends Field { event.preventDefault(); } - onContainerMouseDown(event) { + onContainerClick(event) { if (event.defaultPrevented) return; event.preventDefault(); this.showDropDown(); @@ -260,6 +260,7 @@ export default class Autocomplete extends Field { } showDropDown(search) { + if (this.readonly) return; this.assignDropdownProps(); this.$.dropDown.show(this.container, search); } diff --git a/front/core/components/autocomplete/style.scss b/front/core/components/autocomplete/style.scss index af45902cc..6be42c3bc 100755 --- a/front/core/components/autocomplete/style.scss +++ b/front/core/components/autocomplete/style.scss @@ -20,4 +20,7 @@ vn-autocomplete.vn-field { } } } + &.readonly > .container > .icons.post { + display: none; + } } diff --git a/front/core/components/date-picker/index.js b/front/core/components/date-picker/index.js index e46cde17e..933123485 100644 --- a/front/core/components/date-picker/index.js +++ b/front/core/components/date-picker/index.js @@ -1,15 +1,40 @@ import ngModule from '../../module'; import Field from '../field'; -import {Flatpickr} from '../../vendor'; import './style.scss'; class DatePicker extends Field { - constructor($element, $scope, $compile, $translate) { + constructor($element, $scope, $compile, $translate, $filter) { super($element, $scope, $compile); this.$translate = $translate; + this.$filter = $filter; - this.input = $compile(``)($scope)[0]; - this.initPicker(); + this.input = $compile(``)($scope)[0]; + this.input.addEventListener('change', () => this.onValueUpdate()); + } + + onValueUpdate() { + let date = null; + let value = this.input.value; + + if (value) { + date = new Date(value); + + if (this.field) { + let orgDate = this.field instanceof Date + ? this.field + : new Date(this.field); + + date.setHours( + orgDate.getHours(), + orgDate.getMinutes(), + orgDate.getSeconds(), + orgDate.getMilliseconds() + ); + } + } + + super.field = date; + this.$.$applyAsync(); } get field() { @@ -18,69 +43,10 @@ class DatePicker extends 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(); + this.input.value = this.$filter('dateTime')(value, 'yyyy-MM-dd'); } } -DatePicker.$inject = ['$element', '$scope', '$compile', '$translate']; +DatePicker.$inject = ['$element', '$scope', '$compile', '$translate', '$filter']; ngModule.vnComponent('vnDatePicker', { controller: DatePicker, @@ -88,12 +54,3 @@ ngModule.vnComponent('vnDatePicker', { options: ' { let $filter; let $element; let $ctrl; - let today; beforeEach(angular.mock.module('vnCore', $translateProvider => { $translateProvider.translations('en', {}); @@ -13,9 +12,6 @@ describe('Component vnDatePicker', () => { $element = $compile(``)($rootScope); $ctrl = $element.controller('vnDatePicker'); - - today = new Date(); - today.setUTCHours(0, 0, 0, 0); })); afterEach(() => { @@ -24,22 +20,14 @@ describe('Component vnDatePicker', () => { describe('field() setter', () => { it(`should display the formated the date`, () => { - $ctrl.field = today; + let today; + today = new Date(); + today.setUTCHours(0, 0, 0, 0); + $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/drop-down/drop-down.html b/front/core/components/drop-down/drop-down.html index e9a37a675..2e4db921d 100755 --- a/front/core/components/drop-down/drop-down.html +++ b/front/core/components/drop-down/drop-down.html @@ -1,7 +1,8 @@ + on-close="$ctrl.onClose()" + on-close-start="$ctrl.emit('closeStart')">
this.$.input.focus()); this.emit('open'); } diff --git a/front/core/components/field/index.js b/front/core/components/field/index.js index bc60af0d3..1004aeb05 100644 --- a/front/core/components/field/index.js +++ b/front/core/components/field/index.js @@ -69,10 +69,12 @@ export default class Field extends FormInput { } set name(value) { + // super.name = value; this.input.name = value; } get name() { + // return super.name; return this.input.name; } @@ -181,8 +183,8 @@ export default class Field extends FormInput { } onClick() { - if (event.defaultPrevented) return; - event.preventDefault(); + // if (event.defaultPrevented) return; + // event.preventDefault(); if (this.input !== document.activeElement) this.focus(); diff --git a/front/core/components/field/style.scss b/front/core/components/field/style.scss index 30b33a5df..9d45da3d2 100644 --- a/front/core/components/field/style.scss +++ b/front/core/components/field/style.scss @@ -64,12 +64,33 @@ color: inherit; box-sizing: border-box; min-height: 56px; - + } + & > input { + position: relative; + + &[type=time], + &[type=date], + &[type=password] { + opacity: 0; + transition: opacity 200ms ease-in-out; + cursor: pointer; + } &[type=time], &[type=date] { clip-path: inset(0 20px 0 0); - opacity: 0; - transition: opacity 200ms ease-in-out; + + &::-webkit-inner-spin-button, + &::-webkit-clear-button { + display: none; + -webkit-appearance: none; + } + &::-webkit-calendar-picker-indicator { + position: absolute; + height: 100%; + width: 100%; + opacity: 0; + cursor: pointer; + } } &[type=number] { -moz-appearance: textfield; @@ -83,6 +104,15 @@ &:invalid { box-shadow: none; } + &:-internal-autofill-selected { + &, + &:hover, + &:focus, + &:active, + &:valid { + box-shadow: 0 0 0 40px $color-bg-panel inset; + } + } } } } @@ -172,7 +202,8 @@ } & > .control > * { &[type=time], - &[type=date] { + &[type=date], + &[type=password] { opacity: 1; } } diff --git a/front/core/components/input-time/index.js b/front/core/components/input-time/index.js index 9c6ae0e4a..3dc01e0c7 100644 --- a/front/core/components/input-time/index.js +++ b/front/core/components/input-time/index.js @@ -25,7 +25,10 @@ export default class InputTime extends Field { if (value) { let split = value.split(':').map(i => parseInt(i) || null); - date = new Date(this.field || null); + + date = this.field instanceof Date + ? this.field + : new Date(this.field || null); date.setHours(split[0], split[1], 0, 0); } diff --git a/front/core/components/popover/popover.js b/front/core/components/popover/popover.js index af6edb79a..39b44e206 100644 --- a/front/core/components/popover/popover.js +++ b/front/core/components/popover/popover.js @@ -109,6 +109,7 @@ export default class Popover extends Component { this.showTimeout = null; this.element.style.display = 'none'; this.document.body.removeChild(this.element); + this.emit('close'); }, 250); this.document.removeEventListener('keydown', this.docKeyDownHandler); @@ -118,7 +119,7 @@ export default class Popover extends Component { this.bgMouseDownHandler = null; if (this.deregisterCallback) this.deregisterCallback(); - this.emit('close'); + this.emit('closeStart'); } /** diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index 9384b712b..b2275af0d 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -69,7 +69,7 @@ export default class Controller extends Component { this.$panelScope = this.$.$new(); this.$panel = this.$compile(`<${this.panel}/>`)(this.$panelScope); - let panel = this.$panel.isolateScope().$ctrl; + let panel = this.$panel[0].$ctrl; if (this.shownFilter) panel.filter = JSON.parse(JSON.stringify(this.shownFilter)); panel.onSubmit = filter => this.onPanelSubmit(filter); diff --git a/front/core/directives/focus.js b/front/core/directives/focus.js index b57241078..55e7d3496 100644 --- a/front/core/directives/focus.js +++ b/front/core/directives/focus.js @@ -1,6 +1,11 @@ import ngModule from '../module'; +const regex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i; +export const isMobile = regex.test(navigator.userAgent); + export function focus(input) { + if (isMobile) return; + const element = input; let selector = 'input, textarea, button, submit'; @@ -14,7 +19,6 @@ export function focus(input) { view: window }); element.dispatchEvent(focusEvent); - return; } diff --git a/front/core/vendor.js b/front/core/vendor.js index ac4364feb..bd368dac2 100644 --- a/front/core/vendor.js +++ b/front/core/vendor.js @@ -22,10 +22,3 @@ import 'material-design-lite/dist/material.orange-deep_orange.min.css'; import * as validator from 'validator'; export {validator}; - -import Flatpickr from 'flatpickr'; -import 'flatpickr/dist/flatpickr.css'; -import 'flatpickr/dist/themes/material_orange.css'; -import l10ns from 'flatpickr/dist/l10n'; -Flatpickr.l10ns = l10ns; -export {Flatpickr}; diff --git a/front/package-lock.json b/front/package-lock.json index 15ac9e49c..31fc844b9 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -88,21 +88,6 @@ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz", "integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA==" }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "graceful-fs": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz", - "integrity": "sha1-8tcgwiCS90Mih3XHXjYSYyUB8TE=" - }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -112,14 +97,6 @@ "esprima": "^4.0.0" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, "material-design-lite": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/material-design-lite/-/material-design-lite-1.3.0.tgz", @@ -3229,11 +3206,6 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, - "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" - }, "validator": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz", diff --git a/front/package.json b/front/package.json index bfd8edfc4..82798b28c 100644 --- a/front/package.json +++ b/front/package.json @@ -18,7 +18,6 @@ "angular-translate": "^2.18.1", "angular-translate-loader-partial": "^2.18.1", "flatpickr": "^4.5.2", - "fs-extra": "^5.0.0", "js-yaml": "^3.13.1", "material-design-lite": "^1.3.0", "mg-crud": "^1.1.2", diff --git a/modules/claim/front/basic-data/index.html b/modules/claim/front/basic-data/index.html index 953441581..289f8f197 100644 --- a/modules/claim/front/basic-data/index.html +++ b/modules/claim/front/basic-data/index.html @@ -8,23 +8,18 @@
- - - + + - + field="::$ctrl.claim.created | dateTime:'yyyy-MM-dd hh:mm'" + readonly="true"> + - + label="Country" + rule> - + label="Province" + rule> diff --git a/modules/order/front/filter/index.js b/modules/order/front/filter/index.js index 4305f2506..780bf798b 100644 --- a/modules/order/front/filter/index.js +++ b/modules/order/front/filter/index.js @@ -151,7 +151,7 @@ class Controller { this.$panelScope = this.$scope.$new(); this.$panel = this.$compile(``)(this.$panelScope); - const panel = this.$panel.isolateScope().$ctrl; + const panel = this.$panel[0].$ctrl; panel.filter = this.filter; panel.onSubmit = filter => this.onPanelSubmit(filter); diff --git a/modules/ticket/front/basic-data/step-one/index.html b/modules/ticket/front/basic-data/step-one/index.html index f545e7131..95cbcccf6 100644 --- a/modules/ticket/front/basic-data/step-one/index.html +++ b/modules/ticket/front/basic-data/step-one/index.html @@ -26,9 +26,12 @@ value-field="id" ng-model="$ctrl.addressId" order="isActive DESC"> - - {{::isActive ? '' : 'INACTIVE'}} {{::nickname}} - - {{::street}} - {{::city}} - {{::province.name}} - {{::agencyMode.name}} + + {{::!isActive ? '(Inactive)' : ''}} + {{::nickname}} + + , {{::street}}, {{::city}}, {{::province.name}} - {{::agencyMode.name}} + + ng-model="$ctrl.shipped"> + + - + + - - - - .inactive { - text-transform: uppercase; - } } diff --git a/webpack.config.js b/webpack.config.js index 227c0ada2..79ea19e50 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -107,8 +107,8 @@ let baseConfig = { ], devtool: 'source-map', stats: { - modules: false, assets: false, + modules: false, children: false, entrypoints: false, colors: true From c33906ca103b843864c7ba0ec5150a2f1f61cdef Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 15 Oct 2019 08:50:11 +0200 Subject: [PATCH 08/41] descuadre de horas #1766 rollback --- .../worker/back/methods/worker-time-control/addTime.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/addTime.js b/modules/worker/back/methods/worker-time-control/addTime.js index 9864142bf..5548654bc 100644 --- a/modules/worker/back/methods/worker-time-control/addTime.js +++ b/modules/worker/back/methods/worker-time-control/addTime.js @@ -33,7 +33,13 @@ module.exports = Self => { const subordinate = await Worker.findById(data.workerFk); - return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ - subordinate.userFk, null, data.timed, true]); + return Self.create({ + userFk: subordinate.userFk, + timed: data.timed, + manual: 1 + }); + + /* return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ + subordinate.userFk, null, data.timed, true]); */ }; }; From b37e308a4b4b5e2ed32f7816bbe265e260526687 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez Ruiz Date: Wed, 16 Oct 2019 08:01:34 +0200 Subject: [PATCH 09/41] #1811 send.js unit test --- modules/client/back/methods/sms/send.spec.js | 74 ++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 modules/client/back/methods/sms/send.spec.js diff --git a/modules/client/back/methods/sms/send.spec.js b/modules/client/back/methods/sms/send.spec.js new file mode 100644 index 000000000..19dd8589f --- /dev/null +++ b/modules/client/back/methods/sms/send.spec.js @@ -0,0 +1,74 @@ +const app = require('vn-loopback/server/server'); +const soap = require('soap'); + +describe('sms send()', () => { + it('should return the expected message and status code', async() => { + const code = 200; + const smsConfig = await app.models.SmsConfig.findOne(); + const soapClient = await soap.createClientAsync(smsConfig.uri); + spyOn(soap, 'createClientAsync').and.returnValue(soapClient); + spyOn(soapClient, 'sendSMSAsync').and.returnValue([{ + result: { + $value: + ` + + + ${code} + + + Envio en procesamiento + + + 1 + + + + 444328681 + + ` + } + }]); + let ctx = {req: {accessToken: {userId: 1}}}; + let result = await app.models.Sms.send(ctx, 105, 'destination', 'My SMS Body'); + + expect(result.statusCode).toEqual(200); + expect(result.status).toContain('Envio en procesamiento'); + }); + + it(`should throw if the response code isn't 200`, async() => { + let error; + const code = 400; + const smsConfig = await app.models.SmsConfig.findOne(); + const soapClient = await soap.createClientAsync(smsConfig.uri); + spyOn(soap, 'createClientAsync').and.returnValue(soapClient); + spyOn(soapClient, 'sendSMSAsync').and.returnValue([{ + result: { + $value: + ` + + + ${code} + + + Envio en procesamiento + + + 1 + + + + 444328681 + + ` + } + }]); + let ctx = {req: {accessToken: {userId: 1}}}; + try { + await app.models.Sms.send(ctx, 105, 'destination', 'My SMS Body'); + } catch (err) { + error = err; + } + + expect(error.message).toEqual(`We weren't able to send this SMS`); + }); +}); From 061e978a26b8fc448890eb32cb0cc27bde72f9dd Mon Sep 17 00:00:00 2001 From: Bernat Date: Wed, 16 Oct 2019 08:08:10 +0200 Subject: [PATCH 10/41] =?UTF-8?q?#1758=20=20A=C3=B1adir=20los=20alias=20co?= =?UTF-8?q?mo=20prefijos=20en=20los=20filtros?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/invoiceOut/back/methods/invoiceOut/filter.js | 1 + modules/route/back/methods/route/filter.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index a0da914f8..8b6d00763 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -92,6 +92,7 @@ module.exports = Self => { case 'companyFk': case 'issued': case 'dued': + param = `i.${param}`; return {[param]: value}; } }); diff --git a/modules/route/back/methods/route/filter.js b/modules/route/back/methods/route/filter.js index 1ea962bed..eeeef1dac 100644 --- a/modules/route/back/methods/route/filter.js +++ b/modules/route/back/methods/route/filter.js @@ -85,10 +85,13 @@ module.exports = Self => { return {'r.m3': value}; case 'description': return {'r.description': {like: `%${value}%`}}; - case 'workerFk': case 'warehouseFk': + param = `v.${param}`; + return {[param]: value}; + case 'workerFk': case 'vehicleFk': case 'agencyModeFk': + param = `r.${param}`; return {[param]: value}; } }); From 7aaa8f4a5e3d83a8cd84929f78a347b04083bfe1 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Wed, 16 Oct 2019 08:56:13 +0200 Subject: [PATCH 11/41] refactor drag & drop treeview --- front/core/components/treeview/child.html | 20 +++ .../treeview/{content.js => child.js} | 30 +++- front/core/components/treeview/childs.html | 33 +---- front/core/components/treeview/index.js | 129 ++++++++++++++++-- front/core/components/treeview/style.scss | 41 +++--- front/core/directives/draggable.js | 43 ------ front/core/directives/droppable.js | 93 +++++-------- front/core/directives/droppable.scss | 18 ++- front/core/directives/index.js | 1 - front/core/lib/event-emitter.js | 15 +- loopback/locale/es.json | 4 +- modules/claim/front/dms/index/index.html | 2 +- modules/claim/front/dms/index/index.js | 5 +- .../back/methods/department/moveChild.js | 42 ++++++ modules/worker/back/models/department.js | 1 + modules/worker/back/models/department.json | 9 ++ modules/worker/front/department/index.html | 5 +- modules/worker/front/department/index.js | 29 ++-- 18 files changed, 331 insertions(+), 189 deletions(-) create mode 100644 front/core/components/treeview/child.html rename front/core/components/treeview/{content.js => child.js} (51%) delete mode 100644 front/core/directives/draggable.js create mode 100644 modules/worker/back/methods/department/moveChild.js diff --git a/front/core/components/treeview/child.html b/front/core/components/treeview/child.html new file mode 100644 index 000000000..1b928d5ea --- /dev/null +++ b/front/core/components/treeview/child.html @@ -0,0 +1,20 @@ +
+ + +
+
+ + + + +
+
diff --git a/front/core/components/treeview/content.js b/front/core/components/treeview/child.js similarity index 51% rename from front/core/components/treeview/content.js rename to front/core/components/treeview/child.js index 506117d4f..9e4edef35 100644 --- a/front/core/components/treeview/content.js +++ b/front/core/components/treeview/child.js @@ -2,22 +2,33 @@ import ngModule from '../../module'; class Controller { constructor($element, $scope, $compile) { - this.$element = $element; this.$scope = $scope; this.$compile = $compile; + this.element = $element[0]; + + this.element.$ctrl = this; + this.element.droppable = true; + this.dropCount = 0; + this.element.classList.add('vn-droppable'); } $onInit() { + const transcludeElement = this.element.querySelector('.content'); + const content = angular.element(transcludeElement); + if (this.item.parent) { this.treeview.$transclude(($clone, $scope) => { this.$contentScope = $scope; $scope.item = this.item; - this.$element.append($clone); + content.append($clone); }); + + this.element.draggable = true; + this.element.classList.add('vn-draggable'); } else { let template = `{{$ctrl.treeview.rootLabel}}`; let $clone = this.$compile(template)(this.$scope); - this.$element.append($clone); + content.append($clone); } } @@ -25,10 +36,21 @@ class Controller { if (this.$contentScope) this.$contentScope.$destroy(); } + + dragEnter() { + this.dropCount++; + + if (element != this.dropping) { + this.undrop(); + if (element) element.classList.add('dropping'); + this.dropping = element; + } + } } Controller.$inject = ['$element', '$scope', '$compile']; -ngModule.component('vnTreeviewContent', { +ngModule.component('vnTreeviewChild', { + template: require('./child.html'), controller: Controller, bindings: { item: '<' diff --git a/front/core/components/treeview/childs.html b/front/core/components/treeview/childs.html index 2dd7e77ef..de69ffb89 100644 --- a/front/core/components/treeview/childs.html +++ b/front/core/components/treeview/childs.html @@ -1,34 +1,11 @@
    -
  • -
    - - - - -
    - - - - -
    -
    +
  • + + + items="item.childs">
\ No newline at end of file diff --git a/front/core/components/treeview/index.js b/front/core/components/treeview/index.js index d9da39215..22d6739f7 100644 --- a/front/core/components/treeview/index.js +++ b/front/core/components/treeview/index.js @@ -1,18 +1,113 @@ import ngModule from '../../module'; import Component from '../../lib/component'; import './style.scss'; - import './childs'; -import './content'; +import './child'; /** * Treeview */ export default class Treeview extends Component { - constructor($element, $scope, $transclude) { + constructor($element, $scope, $transclude, $window) { super($element, $scope); this.$transclude = $transclude; + this.$window = $window; this.readOnly = true; + + this.element.addEventListener('dragstart', + event => this.dragStart(event)); + this.element.addEventListener('dragend', + event => this.dragEnd(event)); + + this.element.addEventListener('dragover', + event => this.dragOver(event)); + this.element.addEventListener('drop', + event => this.drop(event)); + this.element.addEventListener('dragenter', + event => this.dragEnter(event)); + this.element.addEventListener('dragleave', + event => this.dragLeave(event)); + + this.dropCount = 0; + } + + undrop() { + if (!this.dropping) return; + this.dropping.classList.remove('dropping'); + this.dropping = null; + } + + findDroppable(event) { + let element = event.target; + while (element != this.element && !element.droppable) + element = element.parentNode; + if (element == this.element) + return null; + return element; + } + + dragOver(event) { + let scrollY = this.$window.scrollY; + + if (event.clientY < this.draggingY) + scrollY -= 2; + else scrollY += 2; + + this.draggingY = event.clientY; + this.$window.scrollTo(0, scrollY); + + // Prevents page reload + event.preventDefault(); + } + + dragStart(event) { + event.target.classList.add('dragging'); + event.dataTransfer.setData('text', event.target.id); + + const element = this.findDroppable(event); + this.dragging = element; + } + + dragEnd(event) { + event.target.classList.remove('dragging'); + this.undrop(); + this.dropCount = 0; + this.dragging = null; + } + + dragEnter(event) { + let element = this.findDroppable(event); + if (element) this.dropCount++; + + if (element != this.dropping) { + this.undrop(); + if (element) element.classList.add('dropping'); + this.dropping = element; + } + } + + dragLeave(event) { + let element = this.findDroppable(event); + + if (element) { + this.dropCount--; + if (this.dropCount == 0) this.undrop(); + } + } + + drop(event) { + event.preventDefault(); + this.element.classList.remove('dropping'); + + const $dropped = this.dropping.$ctrl.item; + const $dragged = this.dragging.$ctrl.item; + + if (!$dropped.active && $dropped.sons) { + this.unfold($dropped).then(() => { + this.emit('drop', {$dropped, $dragged}); + }); + } else + this.emit('drop', {$dropped, $dragged}); } get data() { @@ -100,8 +195,14 @@ export default class Treeview extends Component { } onCreate(parent) { - if (this.createFunc) - this.createFunc({$parent: parent}); + if (this.createFunc) { + if (!parent.active && parent.sons) { + this.unfold(parent).then(() => { + this.createFunc({$parent: parent}); + }); + } else + this.createFunc({$parent: parent}); + } } create(item) { @@ -120,12 +221,24 @@ export default class Treeview extends Component { if (parent) parent.sons++; } - onDrop(item, dragged, dropped) { - this.emit('drop', {item, dragged, dropped}); + move(item, newParent) { + if (newParent == item) return; + + if (item.parent) { + const parent = item.parent; + const childs = parent.childs; + const index = childs.indexOf(item); + parent.sons--; + + childs.splice(index, 1); + } + + item.parent = newParent; + this.create(item); } } -Treeview.$inject = ['$element', '$scope', '$transclude']; +Treeview.$inject = ['$element', '$scope', '$transclude', '$window']; ngModule.component('vnTreeview', { template: require('./index.html'), diff --git a/front/core/components/treeview/style.scss b/front/core/components/treeview/style.scss index b3724a9f1..e39d1708d 100644 --- a/front/core/components/treeview/style.scss +++ b/front/core/components/treeview/style.scss @@ -10,22 +10,6 @@ vn-treeview-childs { li { list-style: none; - & > .node { - @extend %clickable; - display: flex; - padding: 5px; - align-items: center; - } - - & > div > .arrow { - min-width: 24px; - margin-right: 10px; - transition: transform 200ms; - } - - & > div.expanded > .arrow { - transform: rotate(180deg); - } ul { padding-left: 2.2em; } @@ -45,8 +29,27 @@ vn-treeview-childs { .node:hover > .buttons { display: block } + + .content { + flex-grow: 1 + } } -vn-treeview-content { - flex-grow: 1 -} \ No newline at end of file +vn-treeview-child { + display: block; + + .node { + @extend %clickable; + display: flex; + padding: 5px; + align-items: center; + } + & > div > .arrow { + min-width: 24px; + margin-right: 10px; + transition: transform 200ms; + } + &.expanded > div > .arrow { + transform: rotate(180deg); + } +} \ No newline at end of file diff --git a/front/core/directives/draggable.js b/front/core/directives/draggable.js deleted file mode 100644 index 3b68a6cb6..000000000 --- a/front/core/directives/draggable.js +++ /dev/null @@ -1,43 +0,0 @@ -import ngModule from '../module'; - -/** - * Enables a draggable element and his drag events - * - * @return {Object} The directive - */ -export function directive() { - return { - restrict: 'A', - link: function($scope, $element, $attrs) { - const element = $element[0]; - const isDraggable = $attrs.vnDraggable === 'true'; - - if (!isDraggable) return; - - // Set draggable style properties - element.style.cursor = 'move'; - - - // Enable as draggable element - element.setAttribute('draggable', true); - - /** - * Fires when a drag event starts - */ - element.addEventListener('dragstart', event => { - element.style.opacity = 0.5; - event.stopPropagation(); - }); - - /** - * Fires when a drag event ends - */ - element.addEventListener('dragend', event => { - element.style.opacity = 1; - event.stopPropagation(); - }); - } - }; -} - -ngModule.directive('vnDraggable', directive); diff --git a/front/core/directives/droppable.js b/front/core/directives/droppable.js index 483282418..929b64be7 100644 --- a/front/core/directives/droppable.js +++ b/front/core/directives/droppable.js @@ -1,68 +1,43 @@ import ngModule from '../module'; import './droppable.scss'; -export function directive($parse) { - return { - restrict: 'A', - link: function($scope, $element, $attrs) { - const element = $element[0]; - const onDropEvent = $parse($attrs.onDrop); - const isDroppable = $attrs.vnDroppable === 'true'; +class Controller { + constructor($element, $, $attrs) { + this.element = $element[0]; + this.$ = $; + this.$attrs = $attrs; - if (!isDroppable) return; + this.element.addEventListener('dragover', + event => event.preventDefault()); // Prevents page reload + this.element.addEventListener('drop', + event => this.drop(event)); + this.element.addEventListener('dragenter', + event => this.dragEnter(event)); + this.element.addEventListener('dragleave', + event => this.dragLeave(event)); + } - /** - * Captures current dragging element - */ - element.addEventListener('dragstart', () => { - this.dragged = element; - }); + dragEnter(event) { + this.droppedElement = event.target; + this.element.classList.add('dropping'); + } - /** - * Enter droppable area event - */ - element.addEventListener('dragenter', event => { - element.classList.add('active'); + dragLeave(event) { + if (this.droppedElement === event.target) + this.element.classList.remove('dropping'); + } - event.stopImmediatePropagation(); - event.preventDefault(); - }, false); - - - /** - * Exit droppable area event - */ - element.addEventListener('dragleave', event => { - element.classList.remove('active'); - - event.stopImmediatePropagation(); - event.preventDefault(); - }); - - /** - * Prevent dragover for allowing - * dispatch drop event - */ - element.addEventListener('dragover', event => { - event.stopPropagation(); - event.preventDefault(); - }); - - /** - * Fires when a drop events - */ - element.addEventListener('drop', event => { - element.classList.remove('active'); - - onDropEvent($scope, {event}); - - event.stopPropagation(); - event.preventDefault(); - }); - } - }; + drop(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + this.element.classList.remove('dropping'); + this.$.$eval(this.$attrs.vnDroppable, {$event: event}); + } } +Controller.$inject = ['$element', '$scope', '$attrs']; -directive.$inject = ['$parse']; - -ngModule.directive('vnDroppable', directive); +ngModule.directive('vnDroppable', () => { + return { + controller: Controller + }; +}); diff --git a/front/core/directives/droppable.scss b/front/core/directives/droppable.scss index 749bc9a12..97e6f8a19 100644 --- a/front/core/directives/droppable.scss +++ b/front/core/directives/droppable.scss @@ -1,11 +1,25 @@ @import "./variables"; + +.vn-droppable, +.vn-draggable, [vn-droppable] { border: 2px dashed transparent; + border-radius: 0.5em; transition: all 0.5s; +} - &.active { +.vn-droppable, +[vn-droppable] { + display: block; + + &.dropping { background-color: $color-hover-cd; - border: 2px dashed $color-bg-dark; + border-color: $color-bg-dark; } +} + +.vn-draggable.dragging { + background-color: $color-main-light; + border-color: $color-main; } \ No newline at end of file diff --git a/front/core/directives/index.js b/front/core/directives/index.js index 08adfac07..7ee63220b 100644 --- a/front/core/directives/index.js +++ b/front/core/directives/index.js @@ -11,7 +11,6 @@ import './bind'; import './repeat-last'; import './title'; import './uvc'; -import './draggable'; import './droppable'; import './http-click'; import './http-submit'; diff --git a/front/core/lib/event-emitter.js b/front/core/lib/event-emitter.js index 2dede42ab..022e4e98c 100644 --- a/front/core/lib/event-emitter.js +++ b/front/core/lib/event-emitter.js @@ -24,10 +24,12 @@ export default class EventEmitter { */ off(callback) { if (!this.$events) return; - for (let event in this.$events) - for (let i = 0; i < event.length; i++) + for (let event in this.$events) { + for (let i = 0; i < event.length; i++) { if (event[i].callback === callback) event.splice(i--, 1); + } + } } /** @@ -37,10 +39,12 @@ export default class EventEmitter { */ disconnect(thisArg) { if (!this.$events) return; - for (let event in this.$events) - for (let i = 0; i < event.length; i++) + for (let event in this.$events) { + for (let i = 0; i < event.length; i++) { if (event[i].thisArg === thisArg) event.splice(i--, 1); + } + } } /** @@ -72,9 +76,10 @@ export default class EventEmitter { if (this[prop]) this[prop].disconnect(this); this[prop] = value; - if (value) + if (value) { for (let event in handlers) value.on(event, handlers[event], this); + } } } } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 07c95af32..aa135d520 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -108,5 +108,7 @@ "This postal code is not valid": "This postal code is not valid", "is invalid": "is invalid", "The postcode doesn't exists. Ensure you put the correct format": "El cĆ³digo postal no existe. AsegĆŗrate de ponerlo con el formato correcto", - "The department name can't be repeated": "El nombre del departamento no puede repetirse" + "The department name can't be repeated": "El nombre del departamento no puede repetirse", + "You cannot move a parent to any of its sons": "You cannot move a parent to any of its sons", + "You cannot move a parent to its own sons": "You cannot move a parent to its own sons" } \ No newline at end of file diff --git a/modules/claim/front/dms/index/index.html b/modules/claim/front/dms/index/index.html index 10e35e58e..81bd088a7 100644 --- a/modules/claim/front/dms/index/index.html +++ b/modules/claim/front/dms/index/index.html @@ -5,7 +5,7 @@ data="$ctrl.photos"> -
+
Drag & Drop files here...
diff --git a/modules/claim/front/dms/index/index.js b/modules/claim/front/dms/index/index.js index f60feab6c..f382e4d67 100644 --- a/modules/claim/front/dms/index/index.js +++ b/modules/claim/front/dms/index/index.js @@ -35,8 +35,9 @@ class Controller { } } - onDrop(event) { - const files = event.dataTransfer.files; + onDrop($event) { + console.log($event); + const files = $event.dataTransfer.files; this.setDefaultParams().then(() => { this.dms.files = files; this.create(); diff --git a/modules/worker/back/methods/department/moveChild.js b/modules/worker/back/methods/department/moveChild.js new file mode 100644 index 000000000..97206f198 --- /dev/null +++ b/modules/worker/back/methods/department/moveChild.js @@ -0,0 +1,42 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethod('moveChild', { + description: 'Changes the parent of a child department', + accessType: 'WRITE', + accepts: [{ + arg: 'id', + type: 'Number', + description: 'The department id', + http: {source: 'path'} + }, { + arg: 'parentId', + type: 'Number', + description: 'New parent id', + }], + returns: { + type: 'Object', + root: true + }, + http: { + path: `/:id/moveChild`, + verb: 'POST' + } + }); + + Self.moveChild = async(id, parentId = null) => { + const models = Self.app.models; + const child = await models.Department.findById(id); + + if (id == parentId) return; + + if (parentId) { + const parent = await models.Department.findById(parentId); + + if (child.lft < parent.lft && child.rgt > parent.rgt) + throw new UserError('You cannot move a parent to its own sons'); + } + + return child.updateAttribute('parentFk', parentId); + }; +}; diff --git a/modules/worker/back/models/department.js b/modules/worker/back/models/department.js index e6905d273..5a927fc64 100644 --- a/modules/worker/back/models/department.js +++ b/modules/worker/back/models/department.js @@ -2,4 +2,5 @@ module.exports = Self => { require('../methods/department/getLeaves')(Self); require('../methods/department/createChild')(Self); require('../methods/department/removeChild')(Self); + require('../methods/department/moveChild')(Self); }; diff --git a/modules/worker/back/models/department.json b/modules/worker/back/models/department.json index bb5d5e943..7de76e039 100644 --- a/modules/worker/back/models/department.json +++ b/modules/worker/back/models/department.json @@ -16,6 +16,15 @@ }, "parentFk": { "type": "Number" + }, + "lft": { + "type": "Number" + }, + "rgt": { + "type": "Number" + }, + "sons": { + "type": "Number" } } } diff --git a/modules/worker/front/department/index.html b/modules/worker/front/department/index.html index 773662032..c7abaf3f8 100644 --- a/modules/worker/front/department/index.html +++ b/modules/worker/front/department/index.html @@ -10,7 +10,10 @@ fetch-func="$ctrl.onFetch($item)" remove-func="$ctrl.onRemove($item)" create-func="$ctrl.onCreate($parent)" - sort-func="$ctrl.onSort($a, $b)"> + sort-func="$ctrl.onSort($a, $b)" + on-drop="$ctrl.onDrop($dropped, $dragged)" + on-drag-start="$ctrl.onDragStart(item)" + on-drag-end="$ctrl.onDragEnd(item)"> {{::item.name}} diff --git a/modules/worker/front/department/index.js b/modules/worker/front/department/index.js index 1a72681bc..b103efff9 100644 --- a/modules/worker/front/department/index.js +++ b/modules/worker/front/department/index.js @@ -23,19 +23,21 @@ class Controller { return a.name.localeCompare(b.name); } - /* onDrop(item, dragged, dropped) { - if (dropped.scope.item) { - const droppedItem = dropped.scope.item; - const draggedItem = dragged.scope.item; + onDrop(dropped, dragged) { + if (!dropped.active) { + this.$.treeview.unfold(dropped).then(() => + this.move(dropped, dragged)); + } else + this.move(dropped, dragged); + } - if (droppedItem.childs) - droppedItem.childs.push(Object.assign({}, draggedItem)); - - dragged.element.remove(); - - this.$scope.$apply(); - } - } */ + move(dropped, dragged) { + const params = dropped ? {parentId: dropped.id} : null; + const query = `/api/departments/${dragged.id}/moveChild`; + this.$http.post(query, params).then(() => { + this.$.treeview.move(dragged, dropped); + }); + } onCreate(parent) { this.newChild = { @@ -62,9 +64,6 @@ class Controller { if (parent && parent.id) params.parentId = parent.id; - if (!parent.active) - this.$.treeview.unfold(parent); - const query = `/api/departments/createChild`; this.$http.post(query, params).then(res => { const parent = this.newChild.parent; From 6d159c50a082076248460ceabb78a9d52c19de27 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Wed, 16 Oct 2019 09:52:46 +0200 Subject: [PATCH 12/41] css fixes --- front/core/components/treeview/index.js | 47 +++++++++++------------ front/core/components/treeview/style.scss | 1 + modules/agency/front/location/style.scss | 6 +-- modules/worker/front/department/index.js | 9 ----- 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/front/core/components/treeview/index.js b/front/core/components/treeview/index.js index 22d6739f7..9ecbf52e6 100644 --- a/front/core/components/treeview/index.js +++ b/front/core/components/treeview/index.js @@ -47,25 +47,25 @@ export default class Treeview extends Component { } dragOver(event) { - let scrollY = this.$window.scrollY; - - if (event.clientY < this.draggingY) - scrollY -= 2; - else scrollY += 2; - - this.draggingY = event.clientY; - this.$window.scrollTo(0, scrollY); + this.dragClientY = event.clientY; // Prevents page reload event.preventDefault(); } + onDragInterval() { + if (this.dragClientY > 0 && this.dragClientY < 75) + this.$window.scrollTo(0, this.$window.scrollY - 25); + } + dragStart(event) { event.target.classList.add('dragging'); event.dataTransfer.setData('text', event.target.id); const element = this.findDroppable(event); this.dragging = element; + + this.interval = setInterval(() => this.onDragInterval(), 100); } dragEnd(event) { @@ -73,6 +73,7 @@ export default class Treeview extends Component { this.undrop(); this.dropCount = 0; this.dragging = null; + clearInterval(this.interval); } dragEnter(event) { @@ -102,12 +103,7 @@ export default class Treeview extends Component { const $dropped = this.dropping.$ctrl.item; const $dragged = this.dragging.$ctrl.item; - if (!$dropped.active && $dropped.sons) { - this.unfold($dropped).then(() => { - this.emit('drop', {$dropped, $dragged}); - }); - } else - this.emit('drop', {$dropped, $dragged}); + this.emit('drop', {$dropped, $dragged}); } get data() { @@ -195,14 +191,8 @@ export default class Treeview extends Component { } onCreate(parent) { - if (this.createFunc) { - if (!parent.active && parent.sons) { - this.unfold(parent).then(() => { - this.createFunc({$parent: parent}); - }); - } else - this.createFunc({$parent: parent}); - } + if (this.createFunc) + this.createFunc({$parent: parent}); } create(item) { @@ -210,7 +200,10 @@ export default class Treeview extends Component { let childs = parent.childs; if (!childs) childs = []; - childs.push(item); + if (!parent.active) + this.unfold(parent); + else + childs.push(item); if (this.sortFunc) { childs = childs.sort((a, b) => @@ -234,7 +227,13 @@ export default class Treeview extends Component { } item.parent = newParent; - this.create(item); + + if (!newParent.active) { + this.unfold(newParent).then(() => { + item.parent.sons++; + }); + } else + this.create(item); } } diff --git a/front/core/components/treeview/style.scss b/front/core/components/treeview/style.scss index e39d1708d..bd6175021 100644 --- a/front/core/components/treeview/style.scss +++ b/front/core/components/treeview/style.scss @@ -36,6 +36,7 @@ vn-treeview-childs { } vn-treeview-child { + font-size: 16px; display: block; .node { diff --git a/modules/agency/front/location/style.scss b/modules/agency/front/location/style.scss index a3b237b13..d1597e460 100644 --- a/modules/agency/front/location/style.scss +++ b/modules/agency/front/location/style.scss @@ -1,14 +1,14 @@ @import "variables"; -vn-treeview-content { - & > vn-check:not(.indeterminate) { +vn-treeview-child { + .content > vn-check:not(.indeterminate) { color: $color-main; & > .btn { border-color: $color-main; } } - & > vn-check.checked { + .content > vn-check.checked { color: $color-main; } } \ No newline at end of file diff --git a/modules/worker/front/department/index.js b/modules/worker/front/department/index.js index b103efff9..383fee74b 100644 --- a/modules/worker/front/department/index.js +++ b/modules/worker/front/department/index.js @@ -24,14 +24,6 @@ class Controller { } onDrop(dropped, dragged) { - if (!dropped.active) { - this.$.treeview.unfold(dropped).then(() => - this.move(dropped, dragged)); - } else - this.move(dropped, dragged); - } - - move(dropped, dragged) { const params = dropped ? {parentId: dropped.id} : null; const query = `/api/departments/${dragged.id}/moveChild`; this.$http.post(query, params).then(() => { @@ -66,7 +58,6 @@ class Controller { const query = `/api/departments/createChild`; this.$http.post(query, params).then(res => { - const parent = this.newChild.parent; const item = res.data; item.parent = parent; From dbe6161c69b1961446f0d5670e0df6f70ef83fc8 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Wed, 16 Oct 2019 09:54:02 +0200 Subject: [PATCH 13/41] Tests fixed --- e2e/helpers/extensions.js | 25 +++++++++++++------ e2e/helpers/selectors.js | 4 +-- .../05-ticket-module/12_descriptor.spec.js | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index 022b282d3..ee964b534 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -12,6 +12,7 @@ let asyncActions = { clickIfExists: async function(selector) { let exists = await this.exists(selector); if (exists) await this.click(selector); + return exists; }, // Salix specific extensions @@ -29,8 +30,16 @@ let asyncActions = { login: async function(userName) { if (currentUser !== userName) { - this.clickIfExists('#logout') - .clickIfExists('.vn-dialog.shown button[response=ACCEPT]'); + let logoutClicked = await this.clickIfExists('#logout'); + + if (logoutClicked) { + let buttonSelector = '.vn-dialog.shown button[response=ACCEPT]'; + this.wait(buttonSelector => { + return document.querySelector(buttonSelector) != null + || location.hash == '#!/login'; + }, buttonSelector); + await this.clickIfExists(buttonSelector); + } try { await this.waitForURL('#!/login'); @@ -86,7 +95,7 @@ let asyncActions = { pickTime: async function(selector, time) { await this.wait(selector) .evaluate((selector, time) => { - let input = document.querySelector(selector); + let input = document.querySelector(selector).$ctrl.input; input.value = time; input.dispatchEvent(new Event('change')); }, selector, time); @@ -481,11 +490,6 @@ let actions = { }, }; -Object.keys(actions).forEach(function(name) { - let fn = actions[name]; - Nightmare.action(name, fn); -}); - for (let name in asyncActions) { let fn = asyncActions[name]; @@ -495,3 +499,8 @@ for (let name in asyncActions) { .then(res => done(null, res), done); }); } + +Object.keys(actions).forEach(function(name) { + let fn = actions[name]; + Nightmare.action(name, fn); +}); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 4d1c4f3e9..bc68f96e4 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -363,7 +363,7 @@ export default { moreMenuMakeInvoice: '.vn-popover.shown .vn-drop-down li[name="Make invoice"]', moreMenuChangeShippedHour: '.vn-popover.shown .vn-drop-down li[name="Change shipped hour"]', changeShippedHourDialog: 'vn-ticket-descriptor vn-dialog[vn-id="changeShippedDialog"]', - changeShippedHourInput: 'vn-ticket-descriptor vn-dialog[vn-id="changeShippedDialog"] vn-input-time[vn-id="newShipped"]', + changeShippedHourInput: 'vn-dialog[vn-id="changeShippedDialog"] [ng-model="$ctrl.newShipped"]', addStowawayDialogFirstTicket: 'vn-ticket-descriptor > vn-add-stowaway > vn-dialog vn-table vn-tbody vn-tr', shipButton: 'vn-ticket-descriptor > div > div.body > div.quicklinks vn-icon[icon="icon-stowaway"]', thursdayButton: 'vn-ticket-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-tool-bar > vn-button:nth-child(4)', @@ -671,7 +671,7 @@ export default { saveButton: 'vn-worker-pbx vn-submit[label="Save"] input' }, workerTimeControl: { - timeDialogInput: 'vn-worker-time-control > vn-dialog input', + timeDialogInput: '.vn-dialog.shown [ng-model="$ctrl.newTime"]', mondayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(1) > vn-icon-button > button > vn-icon', tuesdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(2) > vn-icon-button > button > vn-icon', wednesdayAddTimeButton: 'vn-worker-time-control > div > vn-card > div > vn-horizontal > vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(3) > vn-icon-button > button > vn-icon', diff --git a/e2e/paths/05-ticket-module/12_descriptor.spec.js b/e2e/paths/05-ticket-module/12_descriptor.spec.js index 5c80bbfe8..b9c6c7c87 100644 --- a/e2e/paths/05-ticket-module/12_descriptor.spec.js +++ b/e2e/paths/05-ticket-module/12_descriptor.spec.js @@ -34,7 +34,7 @@ describe('Ticket descriptor path', () => { const result = await nightmare .waitToClick(selectors.ticketDescriptor.moreMenu) .waitToClick(selectors.ticketDescriptor.moreMenuChangeShippedHour) - .write(selectors.ticketDescriptor.changeShippedHourInput, '08:15') + .pickTime(selectors.ticketDescriptor.changeShippedHourInput, '08:15') .waitToClick(selectors.ticketDescriptor.acceptChangeHourButton) .waitForLastSnackbar(); From e0d9f69aefbcb082b6fca92ec390080bffbaa8db Mon Sep 17 00:00:00 2001 From: Carlos Jimenez Ruiz Date: Wed, 16 Oct 2019 10:59:42 +0200 Subject: [PATCH 14/41] corrected a description --- modules/ticket/front/routes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/front/routes.json b/modules/ticket/front/routes.json index cda0b7536..55922fdde 100644 --- a/modules/ticket/front/routes.json +++ b/modules/ticket/front/routes.json @@ -216,7 +216,7 @@ "url" : "/create", "state": "ticket.card.request.create", "component": "vn-ticket-request-create", - "description": "Purchase request", + "description": "New purchase request", "acl": ["salesPerson"] }, { "url": "/create?clientFk", From 79f9e616d21a2b8fcd9a745df5d2c8a3fcccd163 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 17 Oct 2019 11:08:40 +0200 Subject: [PATCH 15/41] added treeview unit tests --- front/core/components/treeview/childs.js | 4 - front/core/components/treeview/index.js | 3 +- front/core/components/treeview/index.spec.js | 260 +++++++++++++++++++ modules/claim/front/action/index.html | 2 + 4 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 front/core/components/treeview/index.spec.js diff --git a/front/core/components/treeview/childs.js b/front/core/components/treeview/childs.js index a9bd42077..d94c88df9 100644 --- a/front/core/components/treeview/childs.js +++ b/front/core/components/treeview/childs.js @@ -7,10 +7,6 @@ class Controller extends Component { event.preventDefault(); this.treeview.onToggle(item); } - - onDrop(item, dragged, dropped) { - this.treeview.onDrop(item, dragged, dropped); - } } ngModule.component('vnTreeviewChilds', { diff --git a/front/core/components/treeview/index.js b/front/core/components/treeview/index.js index 9ecbf52e6..728ea182e 100644 --- a/front/core/components/treeview/index.js +++ b/front/core/components/treeview/index.js @@ -103,7 +103,8 @@ export default class Treeview extends Component { const $dropped = this.dropping.$ctrl.item; const $dragged = this.dragging.$ctrl.item; - this.emit('drop', {$dropped, $dragged}); + if ($dropped != $dragged.parent) + this.emit('drop', {$dropped, $dragged}); } get data() { diff --git a/front/core/components/treeview/index.spec.js b/front/core/components/treeview/index.spec.js new file mode 100644 index 000000000..75c35fb25 --- /dev/null +++ b/front/core/components/treeview/index.spec.js @@ -0,0 +1,260 @@ +describe('Component vnTreeview', () => { + let controller; + let $element; + + beforeEach(angular.mock.module('vnCore', $translateProvider => { + $translateProvider.translations('en', {}); + })); + + beforeEach(inject(($compile, $rootScope) => { + $element = $compile(``)($rootScope); + controller = $element.controller('vnTreeview'); + + const promise = new Promise(() => { + return {name: 'My item'}; + }); + + controller.fetchFunc = () => { + return promise; + }; + + controller.createFunc = () => { + return promise; + }; + + controller.removeFunc = () => { + return promise; + }; + + controller.sortFunc = () => { + return promise; + }; + })); + + afterEach(() => { + $element.remove(); + }); + + // See how to test DOM element in Jest + xdescribe('undrop()', () => { + it(`should reset all drop events and properties`, () => { + controller.dropping = angular.element(``); + spyOn(controller.dropping.classList, 'remove'); + + controller.undrop(); + + expect(controller.dropping).toBeNull(); + }); + }); + + describe('dragOver()', () => { + it(`should set the dragClientY property`, () => { + const event = new Event('dragover'); + event.clientY = 100; + + controller.dragOver(event); + + expect(controller.dragClientY).toEqual(100); + }); + }); + + describe('data() setter', () => { + it(`should set the items property nested into a root element`, () => { + const items = [{name: 'Item1'}, {name: 'Item2'}]; + controller.data = items; + + const rootItem = controller.items[0]; + + expect(rootItem.childs).toEqual(items); + }); + }); + + describe('fetch()', () => { + it(`should call the fetchFunc() method`, () => { + spyOn(controller, 'fetchFunc').and.returnValue( + new Promise(resolve => resolve()) + ); + controller.fetch().then(() => { + expect(controller.data).toBeDefined(); + }); + + expect(controller.fetchFunc).toHaveBeenCalledWith(); + }); + }); + + describe('setParent()', () => { + it(`should set the parent property recursively to each element of an item list`, () => { + spyOn(controller, 'setParent').and.callThrough(); + const items = [{name: 'Item1'}, {name: 'Item2', childs: [ + {name: 'Item3'} + ]}]; + const rootItem = {name: 'Nested tree', sons: items}; + controller.setParent(rootItem, items); + + expect(items[0].parent).toEqual(rootItem); + expect(items[1].parent).toEqual(rootItem); + expect(controller.setParent).toHaveBeenCalledWith(rootItem, items[1].childs); + }); + }); + + describe('onToggle()', () => { + it(`should call the fold() or unfold() methods`, () => { + spyOn(controller, 'fold'); + spyOn(controller, 'unfold'); + + const item = {name: 'My item'}; + + controller.onToggle(item); + item.active = true; + controller.onToggle(item); + + expect(controller.unfold).toHaveBeenCalledWith(item); + expect(controller.fold).toHaveBeenCalledWith(item); + }); + }); + + describe('fold()', () => { + it(`should remove the childs and set the active property to false`, () => { + const item = {name: 'My item', childs: [{name: 'Item 1'}], active: true}; + + controller.fold(item); + + expect(item.childs).toBeUndefined(); + expect(item.active).toBeFalsy(); + }); + }); + + describe('unfold()', () => { + it(`should unfold a parent item`, () => { + const expectedResponse = [{name: 'Item 1'}, {name: 'Item 2'}]; + spyOn(controller, 'fetchFunc').and.returnValue( + new Promise(resolve => resolve(expectedResponse)) + ); + spyOn(controller, 'setParent'); + spyOn(controller, 'sortFunc'); + const parent = {name: 'My item', sons: 1}; + const child = {name: 'Item 1'}; + child.parent = parent; + parent.childs = [child]; + + controller.unfold(parent).then(() => { + expect(controller.fetchFunc).toHaveBeenCalledWith({$item: parent}); + expect(controller.setParent).toHaveBeenCalledWith(parent, expectedResponse); + expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object)); + expect(parent.active).toBeTruthy(); + }); + }); + }); + + describe('onRemove()', () => { + it(`should call the removeFunc() method`, () => { + spyOn(controller, 'removeFunc'); + const item = {name: 'My item'}; + controller.onRemove(item); + + expect(controller.removeFunc).toHaveBeenCalledWith({$item: item}); + }); + }); + + describe('remove()', () => { + it(`should remove a child element`, () => { + const parent = {name: 'My item', sons: 1}; + const child = {name: 'Item 1'}; + child.parent = parent; + parent.childs = [child]; + + controller.remove(child); + + expect(parent.childs).toEqual([]); + expect(parent.sons).toEqual(0); + }); + }); + + describe('onCreate()', () => { + it(`should call the createFunc() method`, () => { + spyOn(controller, 'createFunc'); + const parent = {name: 'My item'}; + controller.onCreate(parent); + + expect(controller.createFunc).toHaveBeenCalledWith({$parent: parent}); + }); + }); + + describe('create()', () => { + it(`should unfold an inactive parent and then create a child`, () => { + spyOn(controller, 'unfold'); + spyOn(controller, 'sortFunc'); + const parent = {name: 'My item', sons: 2, childs: [ + {name: 'Item 1'}, + {name: 'Item 2'} + ]}; + const child = {name: 'Item 3'}; + child.parent = parent; + parent.childs.push(child); + + controller.create(child); + + expect(parent.sons).toEqual(3); + expect(controller.unfold).toHaveBeenCalledWith(parent); + expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object)); + expect(controller.sortFunc).toHaveBeenCalledTimes(2); + }); + + it(`should create a child on an active parent`, () => { + spyOn(controller, 'unfold'); + spyOn(controller, 'sortFunc'); + const parent = {name: 'My item', sons: 2, childs: [ + {name: 'Item 1'}, + {name: 'Item 2'} + ], active: true}; + const child = {name: 'Item 3'}; + child.parent = parent; + + controller.create(child); + + expect(parent.sons).toEqual(3); + expect(controller.unfold).not.toHaveBeenCalledWith(parent); + expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object)); + expect(controller.sortFunc).toHaveBeenCalledTimes(2); + }); + }); + + describe('move()', () => { + it(`should move an item to anocher parent and then unfold the parent`, () => { + spyOn(controller, 'unfold').and.returnValue( + new Promise(resolve => resolve()) + ); + const newParent = {name: 'My item 2', sons: 0}; + const parent = {name: 'My item', sons: 3, childs: [ + {name: 'Item 1'}, + {name: 'Item 2'} + ]}; + const child = {name: 'Item 3'}; + child.parent = parent; + parent.childs.push(child); + + controller.move(child, newParent); + + expect(parent.sons).toEqual(2); + expect(controller.unfold).toHaveBeenCalledWith(newParent); + }); + + it(`should move an item to anocher parent`, () => { + spyOn(controller, 'unfold'); + spyOn(controller, 'create'); + const newParent = {name: 'My item 2', sons: 0, active: true}; + const parent = {name: 'My item', sons: 3, childs: [ + {name: 'Item 1'}, + {name: 'Item 2'} + ]}; + const child = {name: 'Item 3'}; + child.parent = parent; + parent.childs.push(child); + + controller.move(child, newParent); + + expect(parent.sons).toEqual(2); + expect(controller.unfold).not.toHaveBeenCalledWith(newParent); + }); + }); +}); diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 65467d349..35a0e56e2 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -50,6 +50,7 @@ + @@ -114,6 +115,7 @@ + From b2b76b05d81fd42a460ec9afd2aeafad40e5fd08 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 17 Oct 2019 13:27:50 +0200 Subject: [PATCH 16/41] css fixes + back unit tests --- front/core/components/treeview/index.spec.js | 2 +- modules/claim/front/action/index.html | 227 +++++++++--------- modules/claim/front/action/style.scss | 15 ++ modules/ticket/front/services/index.spec.js | 2 +- .../department/specs/createChild.spec.js | 18 ++ .../department/specs/moveChild.spec.js | 23 ++ .../department/specs/removeChild.spec.js | 21 ++ 7 files changed, 187 insertions(+), 121 deletions(-) create mode 100644 modules/worker/back/methods/department/specs/createChild.spec.js create mode 100644 modules/worker/back/methods/department/specs/moveChild.spec.js create mode 100644 modules/worker/back/methods/department/specs/removeChild.spec.js diff --git a/front/core/components/treeview/index.spec.js b/front/core/components/treeview/index.spec.js index 75c35fb25..12cdc16e7 100644 --- a/front/core/components/treeview/index.spec.js +++ b/front/core/components/treeview/index.spec.js @@ -72,7 +72,7 @@ describe('Component vnTreeview', () => { describe('fetch()', () => { it(`should call the fetchFunc() method`, () => { spyOn(controller, 'fetchFunc').and.returnValue( - new Promise(resolve => resolve()) + new Promise(resolve => resolve([{name: 'My item'}])) ); controller.fetch().then(() => { expect(controller.data).toBeDefined(); diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 35a0e56e2..d12399c55 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -1,123 +1,116 @@ - - - - - -
- - -
-
- - - - - - - - - - - - - - - - - - - Id - Ticket - Destination - Landed - Quantity - Description - Price - Disc. - Total - - - - - - - {{saleClaimed.sale.itemFk | zeroFill:6}} - - - - - {{::saleClaimed.sale.ticketFk}} + + + + + + + +
+ + + + + + + + + + +
+ + + + + + Id + Ticket + Destination + Landed + Quantity + Description + Price + Disc. + Total + + + + + + + {{::saleClaimed.sale.itemFk | zeroFill:6}} - - - - - - {{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} - {{saleClaimed.sale.quantity}} - {{saleClaimed.sale.concept}} - {{saleClaimed.sale.price | currency: 'EUR':2}} - {{saleClaimed.sale.discount}} % - - {{saleClaimed.sale.quantity * saleClaimed.sale.price * - ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}} - - - - - - - - - -
-
+ + + + {{::saleClaimed.sale.ticketFk}} + + + + + + + {{::saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} + {{::saleClaimed.sale.quantity}} + {{::saleClaimed.sale.concept}} + {{::saleClaimed.sale.price | currency: 'EUR':2}} + {{::saleClaimed.sale.discount}} % + + {{saleClaimed.sale.quantity * saleClaimed.sale.price * + ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}} + + + + + + + + + + - + diff --git a/modules/claim/front/action/style.scss b/modules/claim/front/action/style.scss index 3d54485e7..0124b716b 100644 --- a/modules/claim/front/action/style.scss +++ b/modules/claim/front/action/style.scss @@ -1,4 +1,19 @@ vn-claim-action { + .header { + display: flex; + justify-content: space-between; + align-items: center; + align-content: center; + + vn-tool-bar { + flex: 1 + } + + vn-check { + flex: none; + } + } + vn-dialog[vn-id=addSales] { tpl-body { width: 950px; diff --git a/modules/ticket/front/services/index.spec.js b/modules/ticket/front/services/index.spec.js index 97ce890d9..cf416f84d 100644 --- a/modules/ticket/front/services/index.spec.js +++ b/modules/ticket/front/services/index.spec.js @@ -1,6 +1,6 @@ import './index.js'; -fdescribe('Ticket component vnTicketService', () => { +describe('Ticket component vnTicketService', () => { let controller; let $httpBackend; let $httpParamSerializer; diff --git a/modules/worker/back/methods/department/specs/createChild.spec.js b/modules/worker/back/methods/department/specs/createChild.spec.js new file mode 100644 index 000000000..305732f58 --- /dev/null +++ b/modules/worker/back/methods/department/specs/createChild.spec.js @@ -0,0 +1,18 @@ +const app = require('vn-loopback/server/server'); + +describe('department createChild()', () => { + let createdChild; + + afterAll(async done => { + await createdChild.destroy(); + done(); + }); + + it('should create a new child', async() => { + const parentId = null; + createdChild = await app.models.Department.createChild(parentId, 'My new department'); + + expect(createdChild.name).toEqual('My new department'); + expect(createdChild.parentFk).toBeNull(); + }); +}); diff --git a/modules/worker/back/methods/department/specs/moveChild.spec.js b/modules/worker/back/methods/department/specs/moveChild.spec.js new file mode 100644 index 000000000..3358ebf77 --- /dev/null +++ b/modules/worker/back/methods/department/specs/moveChild.spec.js @@ -0,0 +1,23 @@ +const app = require('vn-loopback/server/server'); + +describe('department moveChild()', () => { + let updatedChild; + + afterAll(async done => { + const child = await app.models.Department.findById(updatedChild.id); + await child.updateAttribute('parentFk', null); + done(); + }); + + it('should move a child department to a new parent', async() => { + const childId = 22; + const parentId = 1; + + const child = await app.models.Department.findById(childId); + + expect(child.parentFk).toBeNull(); + updatedChild = await app.models.Department.moveChild(childId, parentId); + + expect(updatedChild.parentFk).toEqual(1); + }); +}); diff --git a/modules/worker/back/methods/department/specs/removeChild.spec.js b/modules/worker/back/methods/department/specs/removeChild.spec.js new file mode 100644 index 000000000..1fe3d10ef --- /dev/null +++ b/modules/worker/back/methods/department/specs/removeChild.spec.js @@ -0,0 +1,21 @@ +const app = require('vn-loopback/server/server'); + +describe('department removeChild()', () => { + let removedChild; + + afterAll(async done => { + await app.models.Department.create(removedChild); + done(); + }); + + it('should remove a child department', async() => { + const childId = 1; + + removedChild = await app.models.Department.findById(childId); + const result = await app.models.Department.removeChild(childId); + const existsChild = await app.models.Department.findById(childId); + + expect(result.count).toEqual(1); + expect(existsChild).toBeNull(); + }); +}); From e1cea99cc09f093d693cc971fad95b417e7d8901 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 17 Oct 2019 14:01:23 +0200 Subject: [PATCH 17/41] insert timeControl from procedure --- .../back/methods/worker-time-control/addTime.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/addTime.js b/modules/worker/back/methods/worker-time-control/addTime.js index 5548654bc..516519359 100644 --- a/modules/worker/back/methods/worker-time-control/addTime.js +++ b/modules/worker/back/methods/worker-time-control/addTime.js @@ -32,14 +32,12 @@ module.exports = Self => { throw new UserError(`You don't have enough privileges`); const subordinate = await Worker.findById(data.workerFk); + const timed = new Date(data.timed); - return Self.create({ - userFk: subordinate.userFk, - timed: data.timed, - manual: 1 - }); + let offset = timed.getTimezoneOffset() * 60000; + timed.setTime(timed.getTime() - offset); - /* return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ - subordinate.userFk, null, data.timed, true]); */ + return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ + subordinate.userFk, null, timed, true]); }; }; From 6f691353a384cee36e7831494e6c9a68014126e4 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 17 Oct 2019 14:01:23 +0200 Subject: [PATCH 18/41] solved conflicts --- .../back/methods/worker-time-control/addTime.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/addTime.js b/modules/worker/back/methods/worker-time-control/addTime.js index cb639f9af..516519359 100644 --- a/modules/worker/back/methods/worker-time-control/addTime.js +++ b/modules/worker/back/methods/worker-time-control/addTime.js @@ -32,11 +32,12 @@ module.exports = Self => { throw new UserError(`You don't have enough privileges`); const subordinate = await Worker.findById(data.workerFk); + const timed = new Date(data.timed); - return Self.create({ - userFk: subordinate.userFk, - timed: data.timed, - manual: 1 - }); + let offset = timed.getTimezoneOffset() * 60000; + timed.setTime(timed.getTime() - offset); + + return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ + subordinate.userFk, null, timed, true]); }; }; From 43a2c2e939b7dcf2fe4b2378b6566fd818e58ee1 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 17 Oct 2019 14:01:23 +0200 Subject: [PATCH 19/41] insert timeControl from procedure --- .../back/methods/worker-time-control/addTime.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/addTime.js b/modules/worker/back/methods/worker-time-control/addTime.js index 5548654bc..516519359 100644 --- a/modules/worker/back/methods/worker-time-control/addTime.js +++ b/modules/worker/back/methods/worker-time-control/addTime.js @@ -32,14 +32,12 @@ module.exports = Self => { throw new UserError(`You don't have enough privileges`); const subordinate = await Worker.findById(data.workerFk); + const timed = new Date(data.timed); - return Self.create({ - userFk: subordinate.userFk, - timed: data.timed, - manual: 1 - }); + let offset = timed.getTimezoneOffset() * 60000; + timed.setTime(timed.getTime() - offset); - /* return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ - subordinate.userFk, null, data.timed, true]); */ + return Self.rawSql('CALL vn.workerTimeControl_add(?, ?, ?, ?)', [ + subordinate.userFk, null, timed, true]); }; }; From bdbadaf61afed8cea94f7ad5489b080e34112620 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez Ruiz Date: Thu, 17 Oct 2019 14:30:52 +0200 Subject: [PATCH 20/41] #1819 fixtures --- db/dump/fixtures.sql | 68 +++++++++---------- .../03-worker-module/02_time_control.spec.js | 2 +- .../06_basic_data_steps.spec.js | 1 + .../back/methods/route/specs/filter.spec.js | 2 +- .../methods/route/specs/getTickets.spec.js | 2 +- .../methods/route/specs/guessPriority.spec.js | 24 +++---- .../back/methods/route/specs/summary.spec.js | 4 +- .../methods/route/specs/updateVolume.spec.js | 13 ++-- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2624f1768..3aec7d82c 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -351,16 +351,6 @@ INSERT INTO `vn`.`creditInsurance`(`id`, `creditClassification`, `credit`, `crea (2, 2, 6000, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL), (3, 3, 10000, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL); -INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`) - VALUES - (1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 7, 'first route', 2.7, 10, CURDATE(), CURDATE()), - (2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 7, 'second route', 0.9, 20, CURDATE(), CURDATE()), - (3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 7, 'third route', 1.1, 30, CURDATE(), CURDATE()), - (4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 7, 'fourth route', 0.1, 40, CURDATE(), CURDATE()), - (5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 8, 'fifth route', NULL, 50, CURDATE(), CURDATE()), - (6, NULL, 57, CURDATE(), 5, 8, 'sixth route', NULL, 60, CURDATE(), CURDATE()), - (7, NULL, 57, CURDATE(), 6, NULL, 'seventh route', NULL, 70, CURDATE(), CURDATE()); - INSERT INTO `vn2008`.`empresa_grupo`(`empresa_grupo_id`, `grupo`) VALUES (1, 'Wayne Industries'); @@ -456,32 +446,42 @@ INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `warehouseFk`, `agencyModeFk`, `t (12, 'Zone entanglement', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 4, 4, 0, 0, 0), (13, 'Zone quantum break', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 5, 5, 0, 0, 0); +INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`) + VALUES + (1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 1, 'first route', 1.8, 10, CURDATE(), CURDATE(), 1), + (2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 2, 'second route', 0.2, 20, CURDATE(), CURDATE(), 9), + (3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 3, 'third route', 0.5, 30, CURDATE(), CURDATE(), 10), + (4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 4, 'fourth route', 0, 40, CURDATE(), CURDATE(), 12), + (5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 5, 'fifth route', 0.1, 50, CURDATE(), CURDATE(), 13), + (6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), CURDATE(), 3), + (7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), CURDATE(), 5); + INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `created`) VALUES - (1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), - (2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), - (3 , 1, 7, 1, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)), - (4 , 3, 2, 1, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)), - (5 , 3, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)), - (6 , 1, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), - (7 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()), - (8 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()), - (9 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()), - (10, 1, 1, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 11, CURDATE()), - (11, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()), - (12, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()), - (13, 1, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()), - (14, 1, 2, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()), - (15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()), - (16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), - (17, 1, 7, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), - (18, 1, 4, 4, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()), - (19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()), - (20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), - (21, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), - (22, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), - (23, NULL, 10, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 8, CURDATE()), - (24 ,NULL, 10, 1, NULL, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 8, CURDATE()); + (1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), + (2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), + (3 , 1, 7, 1, 6, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)), + (4 , 3, 2, 1, 2, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)), + (5 , 3, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)), + (6 , 1, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)), + (7 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()), + (8 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()), + (9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()), + (10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 1, CURDATE()), + (11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()), + (12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()), + (13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, CURDATE()), + (14, 1, 2, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()), + (15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()), + (16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), + (17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()), + (18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()), + (19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()), + (20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), + (21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), + (22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)), + (23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 5, CURDATE()), + (24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 5, CURDATE()); INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES diff --git a/e2e/paths/03-worker-module/02_time_control.spec.js b/e2e/paths/03-worker-module/02_time_control.spec.js index 42be3e9e0..be48b13dd 100644 --- a/e2e/paths/03-worker-module/02_time_control.spec.js +++ b/e2e/paths/03-worker-module/02_time_control.spec.js @@ -358,7 +358,7 @@ describe('Worker time control path', () => { it(`should check Hank Pym doesn't have hours set on the next months first week`, async() => { const wholeWeekHours = await nightmare .waitToClick(selectors.workerTimeControl.nextMonthButton) - .waitToClick(selectors.workerTimeControl.nextMonthButton) + .waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 Hours') .waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText'); expect(wholeWeekHours).toEqual('00:00 Hours'); diff --git a/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js b/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js index 0f02c6af7..3dcac0765 100644 --- a/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js +++ b/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js @@ -30,6 +30,7 @@ describe('Ticket Edit basic data path', () => { it(`should confirm the zone autocomplete is enabled for the role productionBoss`, async() => { const disabled = await nightmare + .waitForSpinnerLoad() .wait(selectors.ticketBasicData.zoneAutocomplete) .evaluate(selector => { return document.querySelector(selector).disabled; diff --git a/modules/route/back/methods/route/specs/filter.spec.js b/modules/route/back/methods/route/specs/filter.spec.js index ba32c956c..a4742c128 100644 --- a/modules/route/back/methods/route/specs/filter.spec.js +++ b/modules/route/back/methods/route/specs/filter.spec.js @@ -117,6 +117,6 @@ describe('Route filter()', () => { let result = await app.models.Route.filter(ctx); - expect(result.length).toEqual(4); + expect(result.length).toEqual(1); }); }); diff --git a/modules/route/back/methods/route/specs/getTickets.spec.js b/modules/route/back/methods/route/specs/getTickets.spec.js index 3888156b6..15028309f 100644 --- a/modules/route/back/methods/route/specs/getTickets.spec.js +++ b/modules/route/back/methods/route/specs/getTickets.spec.js @@ -4,6 +4,6 @@ describe('route getTickets()', () => { it('should return the tickets for a given route', async() => { let result = await app.models.Route.getTickets(2); - expect(result.length).toEqual(4); + expect(result.length).toEqual(1); }); }); diff --git a/modules/route/back/methods/route/specs/guessPriority.spec.js b/modules/route/back/methods/route/specs/guessPriority.spec.js index cc536787a..075ea05c8 100644 --- a/modules/route/back/methods/route/specs/guessPriority.spec.js +++ b/modules/route/back/methods/route/specs/guessPriority.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); describe('route guessPriority()', () => { - const targetRouteId = 2; + const targetRouteId = 7; let routeTicketsToRestore; afterAll(async done => { @@ -17,25 +17,23 @@ describe('route guessPriority()', () => { it('should confirm the tickets in the target route have no priority yet', async() => { routeTicketsToRestore = await app.models.Ticket.find({where: {routeFk: targetRouteId}}); - expect(routeTicketsToRestore.length).toEqual(4); + expect(routeTicketsToRestore.length).toEqual(2); + + expect(routeTicketsToRestore[0].id).toEqual(23); expect(routeTicketsToRestore[0].priority).toBeNull(); - expect(routeTicketsToRestore[0].id).toEqual(7); + expect(routeTicketsToRestore[1].id).toEqual(24); expect(routeTicketsToRestore[1].priority).toBeNull(); - expect(routeTicketsToRestore[1].id).toEqual(8); - expect(routeTicketsToRestore[2].priority).toBeNull(); - expect(routeTicketsToRestore[2].id).toEqual(9); }); it('should call guessPriority() and then check the tickets in the target route now have their priorities defined', async() => { await app.models.Route.guessPriority(targetRouteId); let routeTickets = await app.models.Ticket.find({where: {routeFk: targetRouteId}, fields: ['id', 'priority']}); - expect(routeTickets.length).toEqual(4); - expect(routeTickets[0].priority).toEqual(1); - expect(routeTickets[0].id).toEqual(7); - expect(routeTickets[1].priority).toEqual(3); - expect(routeTickets[1].id).toEqual(8); - expect(routeTickets[2].priority).toEqual(2); - expect(routeTickets[2].id).toEqual(9); + expect(routeTickets.length).toEqual(2); + + expect(routeTickets[0].id).toEqual(23); + expect(routeTickets[0].priority).toEqual(3); + expect(routeTickets[1].id).toEqual(24); + expect(routeTickets[1].priority).toEqual(1); }); }); diff --git a/modules/route/back/methods/route/specs/summary.spec.js b/modules/route/back/methods/route/specs/summary.spec.js index 5b31ff19f..ba976ae94 100644 --- a/modules/route/back/methods/route/specs/summary.spec.js +++ b/modules/route/back/methods/route/specs/summary.spec.js @@ -11,7 +11,7 @@ describe('route summary()', () => { const result = await app.models.Route.summary(1); const agency = result.route.agencyMode(); - expect(agency.name).toEqual('Silla247'); + expect(agency.name).toEqual('inhouse pickup'); }); it(`should return a summary object containing it's vehicle`, async() => { @@ -31,6 +31,6 @@ describe('route summary()', () => { it(`should return a summary object containing data from the tickets`, async() => { const result = await app.models.Route.summary(2); - expect(result.tickets.length).toEqual(4); + expect(result.tickets.length).toEqual(1); }); }); diff --git a/modules/route/back/methods/route/specs/updateVolume.spec.js b/modules/route/back/methods/route/specs/updateVolume.spec.js index 75ee3c139..a1ff67acc 100644 --- a/modules/route/back/methods/route/specs/updateVolume.spec.js +++ b/modules/route/back/methods/route/specs/updateVolume.spec.js @@ -10,8 +10,8 @@ describe('route updateVolume()', () => { afterAll(async done => { - await originalRoute.updateAttributes({m3: 2.7}); - await ticketToRestore.updateAttributes({routeFk: 2}); + await originalRoute.updateAttributes({m3: 1.8}); + await ticketToRestore.updateAttributes({routeFk: null}); await app.models.RouteLog.destroyById(logIdToDestroy); done(); }); @@ -19,12 +19,12 @@ describe('route updateVolume()', () => { it('should confirm the original volume of the route is the expected', async() => { originalRoute = await app.models.Route.findById(routeId); - expect(originalRoute.m3).toEqual(2.7); + expect(originalRoute.m3).toEqual(1.8); }); it('should confirm the route volume is updated when a ticket is added', async() => { - ticketToRestore = await app.models.Ticket.findById(8); - let updatedTicket = await app.models.Ticket.findById(8); + ticketToRestore = await app.models.Ticket.findById(14); + let updatedTicket = await app.models.Ticket.findById(14); await updatedTicket.updateAttributes({routeFk: routeId}); await app.models.Route.updateVolume(ctx, routeId); @@ -36,8 +36,9 @@ describe('route updateVolume()', () => { it('should confirm the change is logged', async() => { let logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']}); + let m3Log = logs.filter(log => { - return log.newInstance.m3 === 3.1; + return log.newInstance.m3 === 1.9; }); logIdToDestroy = m3Log[0].id; From 7a89ab533567b29e0999587d27d513e403721905 Mon Sep 17 00:00:00 2001 From: Bernat Date: Fri, 18 Oct 2019 08:36:33 +0200 Subject: [PATCH 21/41] #1778 Refactor worker.phone --- back/model-config.json | 9 ++++ .../worker/back => back}/models/user-log.json | 0 .../back => back}/models/user-phone-type.json | 0 back/models/user-phone.js | 9 ++++ .../back => back}/models/user-phone.json | 9 +++- db/changes/10100-AllSaints/00-userLog.sql | 4 +- db/changes/10100-AllSaints/01-userPhone.sql | 4 +- db/dump/fixtures.sql | 44 ++++++++++++++- loopback/locale/es.json | 3 +- modules/item/front/tags/index.js | 2 +- modules/worker/back/model-config.json | 9 ---- modules/worker/back/models/worker.json | 6 +++ modules/worker/front/basic-data/index.html | 8 --- modules/worker/front/card/index.js | 6 +++ modules/worker/front/descriptor/index.html | 5 +- modules/worker/front/index.js | 1 + modules/worker/front/phones/index.html | 54 +++++++++++++++++++ modules/worker/front/phones/index.js | 46 ++++++++++++++++ modules/worker/front/phones/locale/es.yml | 4 ++ modules/worker/front/routes.json | 12 ++++- modules/worker/front/summary/index.html | 5 +- modules/worker/front/summary/index.js | 6 +++ 22 files changed, 215 insertions(+), 31 deletions(-) rename {modules/worker/back => back}/models/user-log.json (100%) rename {modules/worker/back => back}/models/user-phone-type.json (100%) create mode 100644 back/models/user-phone.js rename {modules/worker/back => back}/models/user-phone.json (75%) create mode 100644 modules/worker/front/phones/index.html create mode 100644 modules/worker/front/phones/index.js create mode 100644 modules/worker/front/phones/locale/es.yml diff --git a/back/model-config.json b/back/model-config.json index b24226507..89f517812 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -52,6 +52,15 @@ }, "Postcode": { "dataSource": "vn" + }, + "UserPhoneType": { + "dataSource": "vn" + }, + "UserPhone": { + "dataSource": "vn" + }, + "UserLog": { + "dataSource": "vn" } } diff --git a/modules/worker/back/models/user-log.json b/back/models/user-log.json similarity index 100% rename from modules/worker/back/models/user-log.json rename to back/models/user-log.json diff --git a/modules/worker/back/models/user-phone-type.json b/back/models/user-phone-type.json similarity index 100% rename from modules/worker/back/models/user-phone-type.json rename to back/models/user-phone-type.json diff --git a/back/models/user-phone.js b/back/models/user-phone.js new file mode 100644 index 000000000..6f6c20049 --- /dev/null +++ b/back/models/user-phone.js @@ -0,0 +1,9 @@ +let UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`This phone already exists`); + return err; + }); +}; diff --git a/modules/worker/back/models/user-phone.json b/back/models/user-phone.json similarity index 75% rename from modules/worker/back/models/user-phone.json rename to back/models/user-phone.json index c869a808d..f264ff28f 100644 --- a/modules/worker/back/models/user-phone.json +++ b/back/models/user-phone.json @@ -2,7 +2,8 @@ "name": "UserPhone", "base": "Loggable", "log": { - "model":"UserLog" + "model":"UserLog", + "relation": "user" }, "options": { "mysql": { @@ -12,11 +13,15 @@ "properties": { "id": { "id": true, - "type": "String" + "type": "Number" }, "phone": { "type": "Number", "required": true + }, + "typeFk": { + "type": "String", + "required": true } }, "relations": { diff --git a/db/changes/10100-AllSaints/00-userLog.sql b/db/changes/10100-AllSaints/00-userLog.sql index 2e541eaf4..f6972796d 100644 --- a/db/changes/10100-AllSaints/00-userLog.sql +++ b/db/changes/10100-AllSaints/00-userLog.sql @@ -1,6 +1,6 @@ CREATE TABLE `vn`.`userLog` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `originFk` int(11) NOT NULL, + `originFk` int(10) unsigned NOT NULL, `userFk` int(10) unsigned DEFAULT NULL, `action` set('insert','update','delete') COLLATE utf8_unicode_ci NOT NULL, `creationDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP, @@ -13,6 +13,6 @@ CREATE TABLE `vn`.`userLog` ( PRIMARY KEY (`id`), KEY `originFk` (`originFk`), KEY `userFk` (`userFk`), - CONSTRAINT `userLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `userLog_ibfk_1` FOREIGN KEY (`originFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `userLog_ibfk_2` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; \ No newline at end of file diff --git a/db/changes/10100-AllSaints/01-userPhone.sql b/db/changes/10100-AllSaints/01-userPhone.sql index 488bbb112..e82b48000 100644 --- a/db/changes/10100-AllSaints/01-userPhone.sql +++ b/db/changes/10100-AllSaints/01-userPhone.sql @@ -2,7 +2,7 @@ CREATE TABLE `vn`.`userPhone` ( `id` INT NOT NULL AUTO_INCREMENT, `userFk` INT(10) UNSIGNED NOT NULL, `typeFk` VARCHAR(45) NOT NULL, - `phone` INT(15) NOT NULL, + `phone` VARCHAR(15) NOT NULL, PRIMARY KEY (`id`), UNIQUE INDEX `UserFK_Phone` (`userFk` ASC, `phone` ASC)); @@ -22,7 +22,7 @@ ADD CONSTRAINT `fgnUserFk` ON UPDATE CASCADE; insert into vn.userPhone(userFk,typeFk,phone) - select id,'PersonalPhone', phone + select id,'personalPhone', phone from vn.client where phone is not null; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2624f1768..619e5ae2c 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1862,4 +1862,46 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`) VALUES (1, 'Alta'), (2, 'Normal'), - (3, 'Baja'); \ No newline at end of file + (3, 'Baja'); + +-- Fixtures para userPhone, #1814 + +insert into vn.userPhone(userFk,typeFk,phone) + select id,'personalPhone', phone + from vn.client + where phone is not null; + +insert into vn.userPhone(userFk,typeFk,phone) + select id,'businessPhone', phone + from vn.worker + where phone is not null AND phone > ''; + +insert into vn.userPhone(userFk,typeFk,phone) + SELECT + `w`.`userFk`, + 'businessPhone', + `m`.`value` AS `mediaValue` + FROM + (((((`postgresql`.`person` `p` + JOIN `postgresql`.`profile` `po` ON ((`po`.`person_id` = `p`.`person_id`))) + JOIN `postgresql`.`profile_media` `pom` ON ((`pom`.`profile_id` = `po`.`profile_id`))) + JOIN `postgresql`.`media` `m` ON ((`m`.`media_id` = `pom`.`media_id`))) + JOIN `postgresql`.`media_type` `mt` ON ((`mt`.`media_type_id` = `m`.`media_type_id`))) + JOIN `vn`.`worker` `w` ON ((`w`.`id` = `p`.`id_trabajador`))) + WHERE + (`mt`.`name` = 'movil empresa'); + +insert into vn.userPhone(userFk,typeFk,phone) + SELECT + `w`.`userFk`, + 'personalPhone', + `m`.`value` AS `mediaValue` + FROM + (((((`postgresql`.`person` `p` + JOIN `postgresql`.`profile` `po` ON ((`po`.`person_id` = `p`.`person_id`))) + JOIN `postgresql`.`profile_media` `pom` ON ((`pom`.`profile_id` = `po`.`profile_id`))) + JOIN `postgresql`.`media` `m` ON ((`m`.`media_id` = `pom`.`media_id`))) + JOIN `postgresql`.`media_type` `mt` ON ((`mt`.`media_type_id` = `m`.`media_type_id`))) + JOIN `vn`.`worker` `w` ON ((`w`.`id` = `p`.`id_trabajador`))) + WHERE + (`mt`.`name` = 'movil personal'); \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index a6904074a..587d5e9c4 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -109,5 +109,6 @@ "is invalid": "is invalid", "The postcode doesn't exists. Ensure you put the correct format": "El cĆ³digo postal no existe. AsegĆŗrate de ponerlo con el formato correcto", "The department name can't be repeated": "El nombre del departamento no puede repetirse", - "You can't create a claim for a removed ticket": "No puedes crear una reclamaciĆ³n para un ticket eliminado" + "You can't create a claim for a removed ticket": "No puedes crear una reclamaciĆ³n para un ticket eliminado", + "This phone already exists": "Este telĆ©fono ya existe" } \ No newline at end of file diff --git a/modules/item/front/tags/index.js b/modules/item/front/tags/index.js index b187e5baf..c5e120d82 100644 --- a/modules/item/front/tags/index.js +++ b/modules/item/front/tags/index.js @@ -66,7 +66,7 @@ class Controller { this.$scope.watcher.check(); this.$scope.model.save().then(() => { this.$scope.watcher.notifySaved(); - this.$scope.model.refresh(); + this.$scope.watcher.updateOriginalData(); this.card.reload(); }); } diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index df2b776fb..35a039d3c 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -49,14 +49,5 @@ }, "Device": { "dataSource": "vn" - }, - "UserPhoneType": { - "dataSource": "vn" - }, - "UserPhone": { - "dataSource": "vn" - }, - "UserLog": { - "dataSource": "vn" } } diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 7456a3caa..c5c770fcd 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -54,6 +54,12 @@ "type": "hasMany", "model": "WorkerTeamCollegues", "foreignKey": "workerFk" + }, + "phones": { + "type": "hasMany", + "model": "UserPhone", + "foreignKey": "userFk", + "primaryKey": "userFk" } } } \ No newline at end of file diff --git a/modules/worker/front/basic-data/index.html b/modules/worker/front/basic-data/index.html index 7303bccc1..0ba32eff9 100644 --- a/modules/worker/front/basic-data/index.html +++ b/modules/worker/front/basic-data/index.html @@ -23,14 +23,6 @@ rule> - - - -
diff --git a/modules/worker/front/card/index.js b/modules/worker/front/card/index.js index 5e1e33510..eefa6360a 100644 --- a/modules/worker/front/card/index.js +++ b/modules/worker/front/card/index.js @@ -40,6 +40,12 @@ class Controller { relation: 'department' } } + }, { + relation: 'phones', + scope: { + fields: ['phone'], + order: 'typeFk ASC' + } } ] }; diff --git a/modules/worker/front/descriptor/index.html b/modules/worker/front/descriptor/index.html index 5bb9b22e5..0ff8563c5 100644 --- a/modules/worker/front/descriptor/index.html +++ b/modules/worker/front/descriptor/index.html @@ -26,8 +26,9 @@ - + diff --git a/modules/worker/front/index.js b/modules/worker/front/index.js index 71c529ea8..6f4a7fe34 100644 --- a/modules/worker/front/index.js +++ b/modules/worker/front/index.js @@ -12,3 +12,4 @@ import './department'; import './calendar'; import './time-control'; import './log'; +import './phones'; diff --git a/modules/worker/front/phones/index.html b/modules/worker/front/phones/index.html new file mode 100644 index 000000000..2c172bc2f --- /dev/null +++ b/modules/worker/front/phones/index.html @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/worker/front/phones/index.js b/modules/worker/front/phones/index.js new file mode 100644 index 000000000..b4eb8df71 --- /dev/null +++ b/modules/worker/front/phones/index.js @@ -0,0 +1,46 @@ +import ngModule from '../module'; + +class Controller { + constructor($scope, $stateParams) { + this.$scope = $scope; + this.$stateParams = $stateParams; + } + + get worker() { + return this._worker; + } + + set worker(value) { + this._worker = value; + if (value) { + this.$scope.$applyAsync(()=> { + this.$scope.model.link = {userFk: value.userFk}; + this.$scope.model.refresh(); + }); + } + } + + onSubmit() { + this.$scope.watcher.check(); + this.$scope.model.save().then(() => { + this.$scope.watcher.updateOriginalData(); + this.$scope.watcher.notifySaved(); + this.card.reload(); + }); + } + + add() { + this.$scope.model.insert(); + } +} + +Controller.$inject = ['$scope', '$stateParams']; + +ngModule.component('vnWorkerPhones', { + template: require('./index.html'), + controller: Controller, + require: {card: '^vnWorkerCard'}, + bindings: { + worker: '<' + } +}); diff --git a/modules/worker/front/phones/locale/es.yml b/modules/worker/front/phones/locale/es.yml new file mode 100644 index 000000000..8628f38ee --- /dev/null +++ b/modules/worker/front/phones/locale/es.yml @@ -0,0 +1,4 @@ +Phones: TelƩfonos +Type: Tipo +Remove phone: Eliminar telƩfono +Add phone: AƱadir telƩfono \ No newline at end of file diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 1b4f9ec2a..c92ccc94d 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -7,7 +7,8 @@ {"state": "worker.card.basicData", "icon": "settings"}, {"state": "worker.card.pbx", "icon": "icon-pbx"}, {"state": "worker.card.calendar", "icon": "icon-calendar"}, - {"state": "worker.card.timeControl", "icon": "access_time"} + {"state": "worker.card.timeControl", "icon": "access_time"}, + {"state": "worker.card.phones", "icon": "icon-pbx"} ], "routes": [ { @@ -79,6 +80,15 @@ "state": "worker.department", "component": "vn-worker-department", "description": "Departments" + }, + { + "url": "/phones", + "state": "worker.card.phones", + "component": "vn-worker-phones", + "description": "Phones", + "params": { + "worker": "$ctrl.worker" + } } ] } \ No newline at end of file diff --git a/modules/worker/front/summary/index.html b/modules/worker/front/summary/index.html index e2c93ea48..de86c1f84 100644 --- a/modules/worker/front/summary/index.html +++ b/modules/worker/front/summary/index.html @@ -12,8 +12,9 @@ - + diff --git a/modules/worker/front/summary/index.js b/modules/worker/front/summary/index.js index 24656d601..f9f4e688b 100644 --- a/modules/worker/front/summary/index.js +++ b/modules/worker/front/summary/index.js @@ -50,6 +50,12 @@ class Controller { relation: 'department' } } + }, { + relation: 'phones', + scope: { + fields: ['phone'], + order: 'typeFk ASC' + } } ] }; From 18b0ae034c181710e771e77af248c92253efaca3 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Fri, 18 Oct 2019 09:53:30 +0200 Subject: [PATCH 22/41] #1815 - show summary correct photos on claim index --- e2e/helpers/selectors.js | 6 +- modules/claim/front/detail/index.html | 152 +++++++-------- modules/claim/front/summary/index.html | 222 +++++++++++----------- modules/claim/front/summary/index.js | 20 ++ modules/claim/front/summary/index.spec.js | 2 + modules/worker/front/log/index.html | 2 +- 6 files changed, 215 insertions(+), 189 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index bc68f96e4..1abe93ace 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -530,13 +530,13 @@ export default { header: 'vn-claim-summary > vn-card > div > h5', state: 'vn-claim-summary vn-label-value[label="State"] > section > span', observation: 'vn-claim-summary vn-textarea[ng-model="$ctrl.summary.claim.observation"] textarea', - firstSaleItemId: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(4) > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(1) > span', + firstSaleItemId: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(4) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(1) > span', firstSaleDescriptorImage: '.vn-popover.shown vn-item-descriptor img', itemDescriptorPopover: '.vn-popover.shown vn-item-descriptor', itemDescriptorPopoverItemDiaryButton: '.vn-popover.shown vn-item-descriptor a[href="#!/item/2/diary"]', - firstDevelopmentWorker: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(5) > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > span', + firstDevelopmentWorker: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(5) vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > span', firstDevelopmentWorkerGoToClientButton: '.vn-popover.shown vn-worker-descriptor div.quicklinks > a[href="#!/client/21/summary"]', - firstActionTicketId: 'vn-claim-summary > vn-card > div > vn-horizontal > vn-auto:nth-child(6) > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span', + firstActionTicketId: 'vn-claim-summary > vn-card > div > vn-horizontal > vn-auto:nth-child(6) vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span', firstActionTicketDescriptor: '.vn-popover.shown vn-ticket-descriptor' }, claimBasicData: { diff --git a/modules/claim/front/detail/index.html b/modules/claim/front/detail/index.html index 90e7b5914..4a5767194 100644 --- a/modules/claim/front/detail/index.html +++ b/modules/claim/front/detail/index.html @@ -1,84 +1,84 @@ - - - - - -
- - - - -
-
- - - - Landed - Quantity - Claimed - Description - Price - Disc. - Total - - - - - - {{::saleClaimed.sale.ticket.landed | dateTime:'dd/MM/yyyy'}} - {{::saleClaimed.sale.quantity}} - - - - - - - {{::saleClaimed.sale.concept}} - - - {{::saleClaimed.sale.price | currency: 'EUR':2}} - - - {{::saleClaimed.sale.discount}} % - - - - {{::$ctrl.getSaleTotal(saleClaimed.sale) | currency: 'EUR':2}} - - - - - - - - -
-
- - - -
+ + + + + + + + + + + + + + Landed + Quantity + Claimed + Description + Price + Disc. + Total + + + + + + {{::saleClaimed.sale.ticket.landed | dateTime:'dd/MM/yyyy'}} + {{::saleClaimed.sale.quantity}} + + + + + + + {{::saleClaimed.sale.concept}} + + + {{::saleClaimed.sale.price | currency: 'EUR':2}} + + + {{::saleClaimed.sale.discount}} % + + + + {{::$ctrl.getSaleTotal(saleClaimed.sale) | currency: 'EUR':2}} + + + + + + + + + + + + + + + diff --git a/modules/claim/front/summary/index.html b/modules/claim/front/summary/index.html index 314d71bc9..8d837dd73 100644 --- a/modules/claim/front/summary/index.html +++ b/modules/claim/front/summary/index.html @@ -1,11 +1,9 @@ - + data="photos"> -
{{$ctrl.summary.claim.id}} - {{$ctrl.summary.claim.client.name}}
+
{{::$ctrl.summary.claim.id}} - {{::$ctrl.summary.claim.client.name}}

Detail

- - - - Item - Landed - Quantity - Claimed - Description - Price - Disc. - Total - - - - - - - {{saleClaimed.sale.itemFk | zeroFill:6}} - - - {{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} - {{saleClaimed.sale.quantity}} - {{saleClaimed.quantity}} - {{saleClaimed.sale.concept}} - {{saleClaimed.sale.price | currency: 'EUR':2}} - {{saleClaimed.sale.discount}} % - - {{saleClaimed.sale.quantity * saleClaimed.sale.price * - ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}} - - - - + + + + + Item + Landed + Quantity + Claimed + Description + Price + Disc. + Total + + + + + + + {{::saleClaimed.sale.itemFk | zeroFill:6}} + + + {{::saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} + {{::saleClaimed.sale.quantity}} + {{::saleClaimed.quantity}} + {{::saleClaimed.sale.concept}} + {{::saleClaimed.sale.price | currency: 'EUR':2}} + {{::saleClaimed.sale.discount}} % + + {{saleClaimed.sale.quantity * saleClaimed.sale.price * + ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}} + + + + +

Photos

@@ -92,78 +92,82 @@

Development

- - - - Reason - Result - Responsible - Worker - Redelivery - - - - - {{development.claimReason.description}} - {{development.claimResult.description}} - {{development.claimResponsible.description}} - - - {{::development.worker.user.nickname}} - - - {{development.claimRedelivery.description}} - - - + + + + + Reason + Result + Responsible + Worker + Redelivery + + + + + {{::development.claimReason.description}} + {{::development.claimResult.description}} + {{::development.claimResponsible.description}} + + + {{::development.worker.user.nickname}} + + + {{::development.claimRedelivery.description}} + + + +

Action

- - - - Item - Ticket - Destination - Landed - Quantity - Description - Price - Disc. - Total - - - - - - - {{action.sale.itemFk | zeroFill:6}} - - - - - {{action.sale.ticket.id | zeroFill:6}} - - - {{action.claimBeggining.description}} - {{action.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} - {{action.sale.quantity}} - {{action.sale.concept}} - {{action.sale.price}} - {{action.sale.discount}} % - - {{action.sale.quantity * action.sale.price * - ((100 - action.sale.discount) / 100) | currency: 'EUR':2}} - - - - + + + + + Item + Ticket + Destination + Landed + Quantity + Description + Price + Disc. + Total + + + + + + + {{::action.sale.itemFk | zeroFill:6}} + + + + + {{::action.sale.ticket.id | zeroFill:6}} + + + {{::action.claimBeggining.description}} + {{::action.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}} + {{::action.sale.quantity}} + {{::action.sale.concept}} + {{::action.sale.price}} + {{::action.sale.discount}} % + + {{action.sale.quantity * action.sale.price * + ((100 - action.sale.discount) / 100) | currency: 'EUR':2}} + + + + +
diff --git a/modules/claim/front/summary/index.js b/modules/claim/front/summary/index.js index 257be55e0..7d9e3716f 100644 --- a/modules/claim/front/summary/index.js +++ b/modules/claim/front/summary/index.js @@ -9,6 +9,26 @@ class Controller { this.accessToken = vnToken.token; } + get claim() { + return this._claim; + } + + + set claim(value) { + this._claim = value; + + // Get DMS on summary load + /* if (value) + this.$.$applyAsync(() => this.loadDms()); */ + } + + loadDms() { + this.$.model.where = { + claimFk: this.claim.id + }; + this.$.model.refresh(); + } + getSummary() { this.$http.get(`/claim/api/Claims/${this.claim.id}/getSummary`).then(response => { this.summary = response.data; diff --git a/modules/claim/front/summary/index.spec.js b/modules/claim/front/summary/index.spec.js index c56b91251..87b3caac0 100644 --- a/modules/claim/front/summary/index.spec.js +++ b/modules/claim/front/summary/index.spec.js @@ -1,4 +1,5 @@ import './index.js'; +import crudModel from 'core/mocks/crud-model'; describe('Claim', () => { describe('Component summary', () => { @@ -13,6 +14,7 @@ describe('Claim', () => { $httpBackend = _$httpBackend_; controller = $componentController('vnClaimSummary'); controller.claim = {id: 1}; + controller.$.model = crudModel; })); describe('getSummary()', () => { diff --git a/modules/worker/front/log/index.html b/modules/worker/front/log/index.html index 4f170ac35..91166f045 100644 --- a/modules/worker/front/log/index.html +++ b/modules/worker/front/log/index.html @@ -88,7 +88,7 @@ ng-if="!log.newProperties" id="description">
- {{log.description}} + {{::log.description}}
From 85bcb356d4984377bd06b8f5c7e8e55911c02ac5 Mon Sep 17 00:00:00 2001 From: Bernat Date: Fri, 18 Oct 2019 13:52:15 +0200 Subject: [PATCH 23/41] 1778 Refactor worker.phone --- modules/worker/front/phones/index.js | 20 +++++++++++--------- modules/worker/front/routes.json | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/modules/worker/front/phones/index.js b/modules/worker/front/phones/index.js index b4eb8df71..3810832d9 100644 --- a/modules/worker/front/phones/index.js +++ b/modules/worker/front/phones/index.js @@ -1,9 +1,8 @@ import ngModule from '../module'; class Controller { - constructor($scope, $stateParams) { + constructor($scope) { this.$scope = $scope; - this.$stateParams = $stateParams; } get worker() { @@ -12,12 +11,15 @@ class Controller { set worker(value) { this._worker = value; - if (value) { - this.$scope.$applyAsync(()=> { - this.$scope.model.link = {userFk: value.userFk}; - this.$scope.model.refresh(); - }); - } + if (value) + this.setLink(value); + } + + setLink(value) { + this.$scope.$applyAsync(()=> { + this.$scope.model.link = {userFk: value.userFk}; + this.$scope.model.refresh(); + }); } onSubmit() { @@ -34,7 +36,7 @@ class Controller { } } -Controller.$inject = ['$scope', '$stateParams']; +Controller.$inject = ['$scope']; ngModule.component('vnWorkerPhones', { template: require('./index.html'), diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index c92ccc94d..e2fa9c165 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -8,7 +8,7 @@ {"state": "worker.card.pbx", "icon": "icon-pbx"}, {"state": "worker.card.calendar", "icon": "icon-calendar"}, {"state": "worker.card.timeControl", "icon": "access_time"}, - {"state": "worker.card.phones", "icon": "icon-pbx"} + {"state": "worker.card.phones", "icon": "contact_phone"} ], "routes": [ { From 457034daad102e5ae94e9d728c396dfae21c3abd Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Fri, 18 Oct 2019 21:36:30 +0200 Subject: [PATCH 24/41] Tests fixed --- e2e/helpers/components_selectors.js | 6 - e2e/helpers/extensions.js | 44 +++-- e2e/helpers/selectors.js | 179 +++++++++--------- e2e/paths/01-login/01_login.spec.js | 29 +-- .../03_edit_fiscal_data.spec.js | 4 +- .../12_lock_of_verified_data.spec.js | 4 +- .../05-ticket-module/13_services.spec.js | 4 +- e2e/paths/07-order-module/02_catalog.spec.js | 2 +- .../01_descriptor.spec.js | 2 +- .../components/button-menu/button-menu.html | 13 -- front/core/components/button-menu/index.html | 20 ++ .../button-menu/{button-menu.js => index.js} | 22 +-- .../{button-menu.spec.js => index.spec.js} | 0 front/core/components/button-menu/style.scss | 16 -- front/core/components/button/button.html | 6 - front/core/components/button/button.js | 34 ---- front/core/components/button/index.html | 11 ++ front/core/components/button/index.js | 46 +++++ front/core/components/button/style.scss | 86 ++++++++- front/core/components/card/card.js | 2 +- front/core/components/chip/index.html | 15 +- front/core/components/chip/index.js | 15 +- front/core/components/chip/index.spec.js | 12 +- front/core/components/chip/style.scss | 53 +++++- front/core/components/color-legend/index.html | 8 - front/core/components/color-legend/index.js | 24 --- front/core/components/color-legend/style.scss | 13 -- front/core/components/field/index.js | 48 +---- front/core/components/field/style.scss | 4 +- .../components/float-button/float-button.html | 3 - .../components/float-button/float-button.js | 8 - front/core/components/float-button/index.js | 13 ++ front/core/components/form-input/index.js | 54 +++++- .../components/icon-button/icon-button.html | 3 - .../components/icon-button/icon-button.js | 39 ---- front/core/components/icon-button/index.js | 14 ++ front/core/components/icon-button/style.scss | 25 +-- .../icon-focusable/icon-focusable.html | 1 - .../icon-focusable/icon-focusable.js | 29 --- .../core/components/icon-focusable/style.scss | 10 - .../core/components/icon-menu/icon-menu.html | 11 -- front/core/components/icon-menu/icon-menu.js | 41 ---- front/core/components/icon-menu/index.html | 11 ++ front/core/components/icon-menu/index.js | 14 ++ front/core/components/icon-menu/style.scss | 8 - front/core/components/index.js | 15 +- front/core/components/input-file/index.html | 83 ++++---- front/core/components/input-file/index.js | 26 +-- front/core/components/input-file/style.scss | 156 +-------------- front/core/components/input-range/index.html | 9 - front/core/components/input-range/index.js | 79 -------- front/core/components/input-range/style.scss | 14 -- front/core/components/list/style.scss | 3 +- .../components/multi-check/multi-check.js | 4 +- front/core/components/range/index.html | 4 + front/core/components/range/index.js | 50 +++++ front/core/components/range/style.scss | 84 ++++++++ .../core/components/scroll-up/scroll-up.html | 9 +- front/core/components/scroll-up/style.scss | 4 +- front/core/components/searchbar/style.scss | 1 + front/core/components/spinner/spinner.html | 12 +- front/core/components/spinner/spinner.js | 11 +- front/core/components/spinner/spinner.spec.js | 36 ++-- front/core/components/spinner/style.css | 3 - front/core/components/spinner/style.scss | 60 ++++++ front/core/components/step-control/style.scss | 6 - front/core/components/submit/index.js | 13 ++ front/core/components/submit/submit.html | 6 - front/core/components/submit/submit.js | 25 --- front/core/components/td-editable/index.js | 4 +- front/core/components/toggle/index.js | 13 +- front/core/components/toggle/style.scss | 3 + front/core/components/tooltip/tooltip.js | 2 +- front/core/directives/acl.js | 113 +++-------- front/core/directives/specs/acl.spec.js | 105 +++++++--- front/core/lib/input.js | 42 ---- front/core/module.js | 4 +- front/core/styles/background.scss | 6 + front/core/styles/font-family.scss | 23 +++ front/core/styles/global.scss | 40 ++++ front/core/styles/index.js | 3 +- front/core/styles/mdl-override.scss | 61 ------ front/core/styles/text.scss | 2 - front/core/styles/util.scss | 6 + front/core/styles/variables.scss | 2 + front/core/vendor.js | 7 +- front/package-lock.json | 41 ---- front/package.json | 6 - front/salix/components/app/style.scss | 41 ---- front/salix/components/descriptor/index.html | 24 +++ front/salix/components/descriptor/index.js | 11 ++ front/salix/components/descriptor/style.scss | 23 +-- front/salix/components/home/home.html | 2 +- front/salix/components/index.js | 14 +- front/salix/components/login/login.html | 2 - front/salix/components/main-menu/style.scss | 12 +- front/salix/components/summary/style.scss | 4 +- front/salix/styles/misc.scss | 70 ++++--- modules/agency/front/index/index.html | 3 +- modules/claim/front/action/index.html | 8 +- modules/claim/front/descriptor/index.html | 29 +-- modules/claim/front/dms/index/index.html | 11 +- modules/claim/front/summary/index.html | 8 +- .../client/front/address/create/index.html | 8 +- modules/client/front/basic-data/index.html | 130 +++++++------ .../insurance/create/index.html | 8 +- modules/client/front/descriptor/index.html | 29 +-- .../invoiceOut/front/descriptor/index.html | 21 +- modules/item/front/create/index.html | 14 +- modules/item/front/descriptor/index.html | 29 +-- modules/item/front/index/index.html | 3 +- modules/item/front/index/style.scss | 11 -- modules/item/front/last-entries/style.scss | 4 - modules/item/front/search-panel/index.js | 6 +- modules/order/front/descriptor/index.html | 29 +-- modules/order/front/filter/index.html | 19 +- modules/order/front/filter/style.scss | 4 +- modules/order/front/prices-popover/index.html | 35 +--- modules/route/front/descriptor/index.html | 29 +-- modules/ticket/front/descriptor/index.html | 38 +--- modules/ticket/front/index/index.html | 2 +- modules/ticket/front/index/style.scss | 13 -- modules/ticket/front/sale/index.html | 2 - modules/ticket/front/sale/style.scss | 7 - modules/ticket/front/services/index.html | 17 +- modules/ticket/front/services/index.js | 3 +- modules/ticket/front/services/index.spec.js | 2 +- modules/ticket/front/summary/index.html | 2 + modules/worker/front/calendar/index.html | 9 +- modules/worker/front/descriptor/index.html | 8 +- modules/worker/front/index/index.html | 3 +- modules/worker/front/index/index.js | 1 - modules/worker/front/index/style.scss | 11 -- 133 files changed, 1259 insertions(+), 1702 deletions(-) delete mode 100644 e2e/helpers/components_selectors.js delete mode 100644 front/core/components/button-menu/button-menu.html create mode 100644 front/core/components/button-menu/index.html rename front/core/components/button-menu/{button-menu.js => index.js} (83%) rename front/core/components/button-menu/{button-menu.spec.js => index.spec.js} (100%) delete mode 100644 front/core/components/button/button.html delete mode 100644 front/core/components/button/button.js create mode 100644 front/core/components/button/index.html create mode 100644 front/core/components/button/index.js delete mode 100644 front/core/components/color-legend/index.html delete mode 100644 front/core/components/color-legend/index.js delete mode 100644 front/core/components/color-legend/style.scss delete mode 100644 front/core/components/float-button/float-button.html delete mode 100644 front/core/components/float-button/float-button.js create mode 100644 front/core/components/float-button/index.js delete mode 100644 front/core/components/icon-button/icon-button.html delete mode 100644 front/core/components/icon-button/icon-button.js create mode 100644 front/core/components/icon-button/index.js delete mode 100644 front/core/components/icon-focusable/icon-focusable.html delete mode 100644 front/core/components/icon-focusable/icon-focusable.js delete mode 100644 front/core/components/icon-focusable/style.scss delete mode 100644 front/core/components/icon-menu/icon-menu.html delete mode 100644 front/core/components/icon-menu/icon-menu.js create mode 100644 front/core/components/icon-menu/index.html create mode 100644 front/core/components/icon-menu/index.js delete mode 100644 front/core/components/icon-menu/style.scss delete mode 100644 front/core/components/input-range/index.html delete mode 100644 front/core/components/input-range/index.js delete mode 100644 front/core/components/input-range/style.scss create mode 100644 front/core/components/range/index.html create mode 100644 front/core/components/range/index.js create mode 100644 front/core/components/range/style.scss delete mode 100644 front/core/components/spinner/style.css create mode 100644 front/core/components/spinner/style.scss create mode 100644 front/core/components/submit/index.js delete mode 100644 front/core/components/submit/submit.html delete mode 100644 front/core/components/submit/submit.js delete mode 100644 front/core/lib/input.js create mode 100644 front/core/styles/global.scss delete mode 100644 front/core/styles/mdl-override.scss create mode 100644 front/core/styles/util.scss create mode 100644 front/salix/components/descriptor/index.html delete mode 100644 modules/worker/front/index/style.scss diff --git a/e2e/helpers/components_selectors.js b/e2e/helpers/components_selectors.js deleted file mode 100644 index 3e2715ba2..000000000 --- a/e2e/helpers/components_selectors.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - 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 ee964b534..4148a4a05 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -15,6 +15,16 @@ let asyncActions = { return exists; }, + hasClass: async function(selector, className) { + return await this.evaluate((selector, className) => { + document.querySelector(selector).classList.contains(className); + }, selector, className); + }, + + parsedUrl: async function() { + return new URL(await this.url()); + }, + // Salix specific extensions changeLanguageToEnglish: async function() { @@ -28,6 +38,15 @@ let asyncActions = { await this.autocompleteSearch(langSelector, 'English'); }, + doLogin: async function(userName, password) { + if (password == null) password = 'nightmare'; + await this.wait(`vn-login [name=user]`) + .clearInput(`vn-login [name=user]`) + .write(`vn-login [name=user]`, userName) + .write(`vn-login [name=password]`, password) + .click(`vn-login button[type=submit]`); + }, + login: async function(userName) { if (currentUser !== userName) { let logoutClicked = await this.clickIfExists('#logout'); @@ -47,11 +66,7 @@ let asyncActions = { this.goto(`${config.url}/#!/login`); } - await this.wait(`vn-login input[name=user]`) - .clearInput(`vn-login input[name=user]`) - .write(`vn-login input[name=user]`, userName) - .write(`vn-login input[name=password]`, 'nightmare') - .click(`vn-login input[type=submit]`) + await this.doLogin(userName, null) .waitForURL('#!/') .changeLanguageToEnglish(); @@ -99,6 +114,10 @@ let asyncActions = { input.value = time; input.dispatchEvent(new Event('change')); }, selector, time); + }, + + isDisabled: async function(selector) { + return await this.hasClass(selector, 'disabled'); } }; @@ -124,21 +143,6 @@ let actions = { .catch(done); }, - resetLogin: function(done) { - this.then(() => { - currentUser = undefined; - done(); - }) - .catch(done); - }, - - parsedUrl: function(done) { - this.url() - .then(url => { - done(null, new URL(url)); - }).catch(done); - }, - getProperty: function(selector, property, done) { this.evaluate_now((selector, property) => { return document.querySelector(selector)[property].replace(/\s+/g, ' ').trim(); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index bc68f96e4..96c2fe768 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1,4 +1,3 @@ -import components from './components_selectors.js'; export default { globalItems: { @@ -22,29 +21,29 @@ export default { acceptButton: 'vn-confirm button[response=ACCEPT]' }, clientsIndex: { - searchClientInput: `${components.vnTextfield}`, + searchClientInput: `vn-textfield input`, searchButton: 'vn-searchbar vn-icon[icon="search"]', searchResult: 'vn-client-index .vn-list-item', - createClientButton: `${components.vnFloatButton}`, + createClientButton: `vn-float-button`, othersButton: 'vn-left-menu li[name="Others"] > a' }, createClientView: { - name: `${components.vnTextfield}[name="name"]`, - taxNumber: `${components.vnTextfield}[name="fi"]`, - socialName: `${components.vnTextfield}[name="socialName"]`, - street: `${components.vnTextfield}[name="street"]`, - postcode: `${components.vnTextfield}[name="postcode"]`, - city: `${components.vnTextfield}[name="city"]`, + name: `vn-textfield input[name="name"]`, + taxNumber: `vn-textfield input[name="fi"]`, + socialName: `vn-textfield input[name="socialName"]`, + street: `vn-textfield input[name="street"]`, + postcode: `vn-textfield input[name="postcode"]`, + city: `vn-textfield input[name="city"]`, province: `vn-autocomplete[ng-model="$ctrl.client.provinceFk"]`, country: `vn-autocomplete[ng-model="$ctrl.client.countryFk"]`, - userName: `${components.vnTextfield}[name="userName"]`, - email: `${components.vnTextfield}[name="email"]`, + userName: `vn-textfield input[name="userName"]`, + email: `vn-textfield input[name="email"]`, salesPersonAutocomplete: `vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]`, - createButton: `${components.vnSubmit}`, + createButton: `button[type=submit]`, cancelButton: 'vn-button[href="#!/client/index"]' }, clientDescriptor: { - moreMenu: 'vn-client-descriptor vn-icon-menu > div > vn-icon', + moreMenu: 'vn-client-descriptor vn-icon-menu[icon=more_vert]', simpleTicketButton: '.vn-popover.shown .vn-drop-down li' }, clientBasicData: { @@ -56,17 +55,17 @@ export default { emailInput: 'vn-textfield[ng-model="$ctrl.client.email"] input', salesPersonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', channelAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.contactChannelFk"]', - saveButton: `${components.vnSubmit}` + saveButton: `button[type=submit]` }, clientFiscalData: { fiscalDataButton: 'vn-left-menu a[ui-sref="client.card.fiscalData"]', - socialNameInput: `${components.vnTextfield}[name="socialName"]`, - fiscalIdInput: `${components.vnTextfield}[name="fi"]`, + socialNameInput: `vn-textfield input[name="socialName"]`, + fiscalIdInput: `vn-textfield input[name="fi"]`, equalizationTaxCheckbox: 'vn-check[label="Is equalizated"]', acceptPropagationButton: 'vn-client-fiscal-data > vn-confirm button[response=ACCEPT]', - addressInput: `${components.vnTextfield}[name="street"]`, - postcodeInput: `${components.vnTextfield}[name="postcode"]`, - cityInput: `${components.vnTextfield}[name="city"]`, + addressInput: `vn-textfield input[name="street"]`, + postcodeInput: `vn-textfield input[name="postcode"]`, + cityInput: `vn-textfield input[name="city"]`, provinceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.provinceFk"]', countryAutocomplete: 'vn-autocomplete[ng-model="$ctrl.client.countryFk"]', activeCheckbox: 'vn-check[label="Active"]', @@ -76,12 +75,12 @@ export default { hasToInvoiceCheckbox: 'vn-check[label="Has to invoice"]', invoiceByMailCheckbox: 'vn-check[label="Invoice by mail"]', viesCheckbox: 'vn-check[label="Vies"]', - saveButton: `${components.vnSubmit}` + saveButton: `button[type=submit]` }, clientBillingData: { payMethodAutocomplete: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.payMethodFk"]', - IBANInput: `vn-client-billing-data ${components.vnTextfield}[name="iban"]`, - dueDayInput: `vn-client-billing-data ${components.vnInputNumber}[name="dueDay"]`, + IBANInput: `vn-client-billing-data vn-textfield input[name="iban"]`, + dueDayInput: `vn-client-billing-data vn-input-number input[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"]', @@ -92,20 +91,20 @@ export default { newBankEntityBIC: 'vn-client-billing-data > vn-dialog vn-textfield[label="Swift / BIC"] input', newBankEntityCode: 'vn-client-billing-data > vn-dialog vn-textfield[label="Entity Code"] input', acceptBankEntityButton: 'vn-client-billing-data > vn-dialog button[response="ACCEPT"]', - saveButton: `${components.vnSubmit}` + saveButton: `button[type=submit]` }, clientAddresses: { addressesButton: 'vn-left-menu a[ui-sref="client.card.address.index"]', - createAddress: `vn-client-address-index ${components.vnFloatButton}`, + createAddress: `vn-client-address-index vn-float-button`, defaultCheckboxInput: 'vn-check[label="Default"]', - consigneeInput: `${components.vnTextfield}[name="nickname"]`, - streetAddressInput: `${components.vnTextfield}[name="street"]`, - postcodeInput: `${components.vnTextfield}[name="postalCode"]`, - cityInput: `${components.vnTextfield}[name="city"]`, + consigneeInput: `vn-textfield input[name="nickname"]`, + streetAddressInput: `vn-textfield input[name="street"]`, + postcodeInput: `vn-textfield input[name="postalCode"]`, + cityInput: `vn-textfield input[name="city"]`, provinceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.address.provinceFk"]', agencyAutocomplete: 'vn-autocomplete[ng-model="$ctrl.address.agencyModeFk"]', - phoneInput: `${components.vnTextfield}[name="phone"]`, - mobileInput: `${components.vnTextfield}[name="mobile"]`, + phoneInput: `vn-textfield input[name="phone"]`, + mobileInput: `vn-textfield input[name="mobile"]`, defaultAddress: 'vn-client-address-index div:nth-child(1) div[name="street"]', secondMakeDefaultStar: 'vn-client-address-index vn-card div:nth-child(2) vn-icon-button[icon="star_border"]', firstEditAddress: 'vn-client-address-index div:nth-child(1) > a', @@ -117,34 +116,34 @@ export default { secondObservationTypeAutocomplete: 'vn-client-address-edit [name=observations] :nth-child(2) [ng-model="observation.observationTypeFk"]', secondObservationDescriptionInput: 'vn-client-address-edit [name=observations] :nth-child(2) [ng-model="observation.description"] input', addObservationButton: 'vn-client-address-edit div[name="observations"] vn-icon-button[icon="add_circle"]', - saveButton: `${components.vnSubmit}`, + saveButton: `button[type=submit]`, cancelCreateAddressButton: 'button[ui-sref="client.card.address.index"]', cancelEditAddressButton: 'vn-client-address-edit > form > vn-button-bar > vn-button > button' }, clientWebAccess: { webAccessButton: 'vn-left-menu a[ui-sref="client.card.webAccess"]', enableWebAccessCheckbox: 'vn-check[label="Enable web access"]', - userNameInput: `${components.vnTextfield}[name="name"]`, - saveButton: `${components.vnSubmit}` + userNameInput: `vn-textfield input[name="name"]`, + saveButton: `button[type=submit]` }, clientNotes: { - addNoteFloatButton: `${components.vnFloatButton}`, + addNoteFloatButton: `vn-float-button`, noteInput: 'vn-textarea[label="Note"]', - saveButton: `${components.vnSubmit}`, + saveButton: `button[type=submit]`, firstNoteText: 'vn-client-note .text' }, clientCredit: { - addCreditFloatButton: `${components.vnFloatButton}`, - creditInput: `${components.vnInputNumber}[name="credit"]`, - saveButton: `${components.vnSubmit}`, + addCreditFloatButton: `vn-float-button`, + creditInput: `vn-input-number input[name="credit"]`, + saveButton: `button[type=submit]`, firstCreditText: 'vn-client-credit-index vn-card > div vn-table vn-tbody > vn-tr' }, clientGreuge: { - addGreugeFloatButton: `${components.vnFloatButton}`, - amountInput: `${components.vnInputNumber}[name="amount"]`, - descriptionInput: `${components.vnTextfield}[name="description"]`, + addGreugeFloatButton: `vn-float-button`, + amountInput: `vn-input-number input[name="amount"]`, + descriptionInput: `vn-textfield input[name="description"]`, typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.greuge.greugeTypeFk"]', - saveButton: `${components.vnSubmit}`, + saveButton: `button[type=submit]`, firstGreugeText: 'vn-client-greuge-index vn-card > div vn-table vn-tbody > vn-tr' }, clientMandate: { @@ -163,7 +162,7 @@ export default { clientBalance: { balanceButton: 'vn-left-menu a[ui-sref="client.card.balance.index"]', companyAutocomplete: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyFk"]', - newPaymentButton: `${components.vnFloatButton}`, + newPaymentButton: `vn-float-button`, newPaymentBank: 'vn-client-balance-create vn-autocomplete[ng-model="$ctrl.receipt.bankFk"]', newPaymentAmountInput: 'vn-client-balance-create vn-input-number[ng-model="$ctrl.receipt.amountPaid"] input', saveButton: 'vn-client-balance-create vn-button[label="Save"]', @@ -182,7 +181,7 @@ export default { }, itemsIndex: { searchIcon: 'vn-item-index vn-searchbar vn-icon[icon="search"]', - createItemButton: `${components.vnFloatButton}`, + createItemButton: `vn-float-button`, searchResult: 'vn-item-index a.vn-tr', searchResultPreviewButton: 'vn-item-index .buttons > [icon="desktop_windows"]', searchResultCloneButton: 'vn-item-index .buttons > [icon="icon-clone"]', @@ -208,16 +207,16 @@ export default { saveFieldsButton: 'vn-item-index vn-dialog vn-horizontal:nth-child(16) > vn-button > button' }, itemCreateView: { - temporalName: `${components.vnTextfield}[name="provisionalName"]`, + temporalName: `vn-textfield input[name="provisionalName"]`, typeAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.typeFk"]', intrastatAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.intrastatFk"]', originAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]', - createButton: `${components.vnSubmit}`, - cancelButton: 'button[ui-sref="item.index"]' + createButton: `button[type=submit]`, + cancelButton: 'vn-button[ui-sref="item.index"]' }, itemDescriptor: { goBackToModuleIndexButton: 'vn-item-descriptor a[href="#!/item/index"]', - moreMenu: 'vn-item-descriptor vn-icon-menu > div > vn-icon', + moreMenu: 'vn-item-descriptor vn-icon-menu[icon=more_vert]', moreMenuRegularizeButton: '.vn-popover.shown .vn-drop-down li[name="Regularize stock"]', regularizeQuantityInput: 'vn-item-descriptor vn-dialog tpl-body > div > vn-textfield input', regularizeWarehouseAutocomplete: 'vn-item-descriptor vn-dialog vn-autocomplete[ng-model="$ctrl.warehouseFk"]', @@ -238,7 +237,7 @@ export default { longNameInput: 'vn-textfield[ng-model="$ctrl.item.longName"] input', isActiveCheckbox: 'vn-check[label="Active"]', priceInKgCheckbox: 'vn-check[label="Price in kg"]', - submitBasicDataButton: `${components.vnSubmit}` + submitBasicDataButton: `button[type=submit]` }, itemTags: { goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]', @@ -257,19 +256,19 @@ export default { seventhValueInput: 'vn-item-tags vn-horizontal:nth-child(7) > vn-textfield[label="Value"] input', seventhRelevancyInput: 'vn-item-tags vn-horizontal:nth-child(7) > vn-textfield[label="Relevancy"] input', addItemTagButton: 'vn-item-tags vn-icon-button[icon="add_circle"]', - submitItemTagsButton: `vn-item-tags ${components.vnSubmit}` + submitItemTagsButton: `vn-item-tags button[type=submit]` }, itemTax: { undoChangesButton: 'vn-item-tax vn-button-bar > vn-button[label="Undo changes"]', firstClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(1) > vn-autocomplete[ng-model="tax.taxClassFk"]', secondClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(2) > vn-autocomplete[ng-model="tax.taxClassFk"]', thirdClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="tax.taxClassFk"]', - submitTaxButton: `vn-item-tax ${components.vnSubmit}` + submitTaxButton: `vn-item-tax button[type=submit]` }, itemBarcodes: { addBarcodeButton: 'vn-item-barcode vn-icon[icon="add_circle"]', - thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(3) > ${components.vnTextfield}`, - submitBarcodesButton: `vn-item-barcode ${components.vnSubmit}`, + thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(3) > vn-textfield input`, + submitBarcodesButton: `vn-item-barcode button[type=submit]`, firstCodeRemoveButton: 'vn-item-barcode vn-horizontal vn-none vn-icon[icon="delete"]' }, itemNiches: { @@ -281,13 +280,13 @@ export default { secondNicheRemoveButton: 'vn-item-niche vn-horizontal:nth-child(2) > vn-none > vn-icon-button[icon="delete"]', thirdWarehouseAutocomplete: 'vn-item-niche vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="niche.warehouseFk"]', thirdCodeInput: 'vn-item-niche vn-horizontal:nth-child(3) > vn-textfield[label="Code"] input', - submitNichesButton: `vn-item-niche ${components.vnSubmit}` + submitNichesButton: `vn-item-niche button[type=submit]` }, itemBotanical: { - botanicalInput: `vn-item-botanical vn-horizontal:nth-child(1) > ${components.vnTextfield}`, + botanicalInput: `vn-item-botanical vn-horizontal:nth-child(1) > vn-textfield input`, genusAutocomplete: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]', speciesAutocomplete: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]', - submitBotanicalButton: `vn-item-botanical ${components.vnSubmit}` + submitBotanicalButton: `vn-item-botanical button[type=submit]` }, itemSummary: { basicData: 'vn-item-summary [name="basicData"]', @@ -330,13 +329,13 @@ export default { searchResult: 'vn-ticket-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr', searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr', searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)', - searchTicketInput: `vn-ticket-index ${components.vnTextfield}`, - searchWeeklyTicketInput: `vn-ticket-weekly-index ${components.vnTextfield}`, + searchTicketInput: `vn-ticket-index vn-textfield input`, + searchWeeklyTicketInput: `vn-ticket-weekly-index vn-textfield input`, searchWeeklyClearInput: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon=clear]', - advancedSearchButton: 'vn-ticket-search-panel vn-submit[label="Search"] input', + advancedSearchButton: 'vn-ticket-search-panel button[type=submit]', searchButton: 'vn-ticket-index vn-searchbar vn-icon[icon="search"]', searchWeeklyButton: 'vn-ticket-weekly-index vn-searchbar vn-icon[icon="search"]', - moreMenu: 'vn-ticket-index vn-icon-menu[vn-id="more-button"] > div > vn-icon', + moreMenu: 'vn-ticket-index vn-icon-menu[icon=more_vert]', moreMenuWeeklyTickets: '.vn-popover.shown .vn-drop-down li:nth-child(2)', sixthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tr:nth-child(6) vn-autocomplete[ng-model="weekly.weekDay"] input', weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr', @@ -349,13 +348,13 @@ export default { deliveryDateInput: 'vn-ticket-create vn-date-picker[ng-model="$ctrl.landed"]', warehouseAutocomplete: 'vn-ticket-create vn-autocomplete[ng-model="$ctrl.warehouseFk"]', agencyAutocomplete: 'vn-ticket-create vn-autocomplete[ng-model="$ctrl.ticket.agencyModeFk"]', - createButton: `${components.vnSubmit}` + createButton: `button[type=submit]` }, ticketDescriptor: { idLabelValue: 'vn-ticket-descriptor vn-label-value[label="Id"]', stateLabelValue: 'vn-ticket-descriptor vn-label-value[label="State"]', goBackToModuleIndexButton: 'vn-ticket-descriptor a[ui-sref="ticket.index"]', - moreMenu: 'vn-ticket-descriptor vn-icon-menu > div > vn-icon', + moreMenu: 'vn-ticket-descriptor vn-icon-menu[icon=more_vert]', moreMenuAddStowaway: '.vn-popover.shown .vn-drop-down li[name="Add stowaway"]', moreMenuDeleteStowawayButton: '.vn-popover.shown .vn-drop-down li[name="Remove stowaway"]', moreMenuAddToTurn: '.vn-popover.shown .vn-drop-down li[name="Add turn"]', @@ -365,7 +364,7 @@ export default { changeShippedHourDialog: 'vn-ticket-descriptor vn-dialog[vn-id="changeShippedDialog"]', changeShippedHourInput: 'vn-dialog[vn-id="changeShippedDialog"] [ng-model="$ctrl.newShipped"]', addStowawayDialogFirstTicket: 'vn-ticket-descriptor > vn-add-stowaway > vn-dialog vn-table vn-tbody vn-tr', - shipButton: 'vn-ticket-descriptor > div > div.body > div.quicklinks vn-icon[icon="icon-stowaway"]', + shipButton: 'vn-ticket-descriptor vn-icon[icon="icon-stowaway"]', thursdayButton: 'vn-ticket-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-tool-bar > vn-button:nth-child(4)', saturdayButton: 'vn-ticket-descriptor > vn-dialog > div > form > div.body > tpl-body > div > vn-tool-bar > vn-button:nth-child(6)', closeStowawayDialog: 'vn-ticket-descriptor > vn-add-stowaway > vn-dialog > div > button[class="close"]', @@ -380,7 +379,7 @@ export default { addNoteButton: 'vn-icon[icon="add_circle"]', firstNoteTypeAutocomplete: 'vn-autocomplete[ng-model="observation.observationTypeFk"]', firstDescriptionInput: 'vn-textfield[label="Description"] input', - submitNotesButton: `${components.vnSubmit}` + submitNotesButton: `button[type=submit]` }, ticketExpedition: { expeditionButton: 'vn-left-menu a[ui-sref="ticket.card.expedition"]', @@ -395,7 +394,7 @@ export default { firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] .icons > vn-icon[icon=clear]', - savePackagesButton: `${components.vnSubmit}` + savePackagesButton: `button[type=submit]` }, ticketSales: { saleButton: 'vn-left-menu a[ui-sref="ticket.card.sale"]', @@ -460,9 +459,9 @@ export default { }, ticketTracking: { trackingButton: 'vn-left-menu a[ui-sref="ticket.card.tracking.index"]', - createStateButton: `${components.vnFloatButton}`, + createStateButton: `vn-float-button`, stateAutocomplete: 'vn-ticket-tracking-edit vn-autocomplete[ng-model="$ctrl.stateFk"]', - saveButton: `${components.vnSubmit}`, + saveButton: `button[type=submit]`, cancelButton: 'vn-ticket-tracking-edit vn-button[ui-sref="ticket.card.tracking.index"]' }, ticketBasicData: { @@ -471,8 +470,8 @@ export default { addressAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.addressFk"]', agencyAutocomplete: 'vn-autocomplete[ng-model="$ctrl.agencyModeId"]', zoneAutocomplete: 'vn-autocomplete[ng-model="$ctrl.zoneId"]', - nextStepButton: 'vn-step-control > section > section.buttons > section:nth-child(2) > vn-button', - finalizeButton: 'vn-step-control > section > section.buttons > section:nth-child(2) > vn-submit', + nextStepButton: 'vn-step-control .buttons > section:last-child vn-button', + finalizeButton: 'vn-step-control .buttons > section:last-child button[type=submit]', stepTwoTotalPriceDif: 'vn-ticket-basic-data-step-two > form > vn-card > div > vn-horizontal > table > tfoot > tr > td:nth-child(4)', chargesReasonAutocomplete: 'vn-autocomplete[ng-model="$ctrl.ticket.option"]', }, @@ -487,7 +486,7 @@ export default { 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', + saveButton: 'vn-ticket-request-create button[type=submit]', firstDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(2)', }, @@ -499,7 +498,7 @@ export default { }, ticketService: { addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button', - firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"] > button', + firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]', firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.description"]', firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input', firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input', @@ -507,22 +506,22 @@ export default { fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]', newDescriptionInput: 'vn-ticket-service > vn-dialog vn-textfield[ng-model="$ctrl.newServiceType.name"] input', serviceLine: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(2) > vn-horizontal', - saveServiceButton: `${components.vnSubmit}`, + saveServiceButton: `button[type=submit]`, saveDescriptionButton: 'vn-ticket-service > vn-dialog[vn-id="createServiceTypeDialog"] > div > form > div.buttons > tpl-buttons > button' }, createStateView: { stateAutocomplete: 'vn-autocomplete[ng-model="$ctrl.stateFk"]', workerAutocomplete: 'vn-autocomplete[ng-model="$ctrl.workerFk"]', clearStateInputButton: 'vn-autocomplete[ng-model="$ctrl.stateFk"] .icons > vn-icon[icon=clear]', - saveStateButton: `${components.vnSubmit}` + saveStateButton: `button[type=submit]` }, claimsIndex: { - searchClaimInput: `vn-claim-index ${components.vnTextfield}`, + searchClaimInput: `vn-claim-index vn-textfield input`, searchResult: 'vn-claim-index vn-card > div > vn-table > div > vn-tbody > a', searchButton: 'vn-claim-index vn-searchbar vn-icon[icon="search"]' }, claimDescriptor: { - moreMenu: 'vn-claim-descriptor vn-icon-menu[vn-id="more-button"]', + moreMenu: 'vn-claim-descriptor vn-icon-menu[icon=more_vert]', moreMenuDeleteClaim: '.vn-popover.shown .vn-drop-down li[name="Delete claim"]', acceptDeleteClaim: 'vn-claim-descriptor > vn-confirm[vn-id="confirm-delete-claim"] button[response="ACCEPT"]' }, @@ -541,9 +540,9 @@ export default { }, claimBasicData: { claimStateAutocomplete: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]', - responsabilityInputRange: 'vn-input-range', + responsabilityInputRange: 'vn-range', observationInput: 'vn-textarea[ng-model="$ctrl.claim.observation"] textarea', - saveButton: `${components.vnSubmit}` + saveButton: `button[type=submit]` }, 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', @@ -569,7 +568,7 @@ export default { secondClaimResponsibleAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]', secondClaimWorkerAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.workerFk"]', secondClaimRedeliveryAutocomplete: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimRedeliveryFk"]', - saveDevelopmentButton: `${components.vnSubmit}` + saveDevelopmentButton: `button[type=submit]` }, claimAction: { importClaimButton: 'vn-claim-action vn-button[label="Import claim"]', @@ -584,9 +583,9 @@ export default { searchResult: 'vn-order-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr', searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)', searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)', - searchOrderInput: `vn-order-index ${components.vnTextfield}`, + searchOrderInput: `vn-order-index vn-textfield input`, searchButton: 'vn-order-index vn-searchbar vn-icon[icon="search"]', - createOrderButton: `${components.vnFloatButton}`, + createOrderButton: `vn-float-button`, }, orderDescriptor: { returnToModuleIndexButton: 'vn-order-descriptor a[ui-sref="order.index"]', @@ -597,7 +596,7 @@ export default { addressAutocomplete: 'vn-autocomplete[label="Address"]', agencyAutocomplete: 'vn-autocomplete[label="Agency"]', landedDatePicker: 'vn-date-picker[label="Landed"]', - createButton: `${components.vnSubmit}`, + createButton: `button[type=submit]`, cancelButton: 'vn-button[href="#!/client/index"]' }, orderCatalog: { @@ -609,16 +608,16 @@ export default { openTagSearch: 'vn-catalog-filter > div > vn-vertical > vn-textfield[ng-model="$ctrl.value"] .append i', tagAutocomplete: 'vn-order-catalog-search-panel vn-autocomplete[ng-model="filter.tagFk"]', tagValueInput: 'vn-order-catalog-search-panel vn-textfield[ng-model="filter.value"] input', - searchTagButton: 'vn-order-catalog-search-panel > div > form > vn-horizontal:nth-child(3) > vn-submit > input', - thirdFilterRemoveButton: 'vn-catalog-filter > div > vn-horizontal.chips > vn-chip:nth-child(3) button', - fourthFilterRemoveButton: 'vn-catalog-filter > div > vn-horizontal.chips > vn-chip:nth-child(4) button', + searchTagButton: 'vn-order-catalog-search-panel button[type=submit]', + thirdFilterRemoveButton: 'vn-catalog-filter .chips > vn-chip:nth-child(3) vn-icon[icon=cancel]', + fourthFilterRemoveButton: 'vn-catalog-filter .chips > vn-chip:nth-child(4) vn-icon[icon=cancel]', }, orderBasicData: { clientAutocomplete: 'vn-autocomplete[label="Client"]', addressAutocomplete: 'vn-autocomplete[label="Address"]', agencyAutocomplete: 'vn-autocomplete[label="Agency"]', observationInput: 'vn-textarea[label="Observation"] textarea', - saveButton: `${components.vnSubmit}`, + saveButton: `button[type=submit]`, acceptButton: 'vn-order-basic-data vn-confirm[vn-id="confirm"] button[response="ACCEPT"]' }, orderLine: { @@ -636,7 +635,7 @@ export default { vehicleAutoComplete: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]', agencyAutoComplete: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.agencyModeFk"]', descriptionInput: 'vn-route-create vn-textfield[ng-model="$ctrl.route.description"] input', - submitButton: 'vn-route-create vn-submit > input[type="submit"]' + submitButton: 'vn-route-create button[type=submit]' }, routeDescriptor: { volume: 'vn-route-descriptor vn-label-value[label="Volume"] > section > span' @@ -653,7 +652,7 @@ export default { createdDateInput: 'vn-route-basic-data vn-date-picker[ng-model="$ctrl.route.created"]', startedHourInput: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.started"] input', finishedHourInput: 'vn-route-basic-data vn-input-time[ng-model="$ctrl.route.finished"] input', - saveButton: 'vn-route-basic-data vn-submit[label="Save"] input' + saveButton: 'vn-route-basic-data button[type=submit]' }, routeTickets: { firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-textfield[ng-model="ticket.priority"] input', @@ -668,7 +667,7 @@ export default { }, workerPbx: { extensionInput: 'vn-worker-pbx vn-textfield[ng-model="$ctrl.worker.sip.extension"] input', - saveButton: 'vn-worker-pbx vn-submit[label="Save"] input' + saveButton: 'vn-worker-pbx button[type=submit]' }, workerTimeControl: { timeDialogInput: '.vn-dialog.shown [ng-model="$ctrl.newTime"]', @@ -720,12 +719,12 @@ export default { navigateBackToIndex: 'vn-worker-descriptor vn-icon[icon="chevron_left"]' }, invoiceOutIndex: { - searchInvoiceOutInput: `vn-invoice-out-index ${components.vnTextfield}`, + searchInvoiceOutInput: `vn-invoice-out-index vn-textfield input`, searchButton: 'vn-invoice-out-index vn-searchbar vn-icon[icon="search"]', searchResult: 'vn-invoice-out-index vn-card > div > vn-table > div > vn-tbody > a.vn-tr', }, invoiceOutDescriptor: { - moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[vn-id="more-button"]', + moreMenu: 'vn-invoice-out-descriptor vn-icon-menu[icon=more_vert]', moreMenuDeleteInvoiceOut: '.vn-popover.shown .vn-drop-down li[name="Delete Invoice"]', moreMenuBookInvoiceOut: '.vn-popover.shown .vn-drop-down li[name="Book invoice"]', moreMenuShowInvoiceOutPdf: '.vn-popover.shown .vn-drop-down li[name="Show invoice PDF"]', diff --git a/e2e/paths/01-login/01_login.spec.js b/e2e/paths/01-login/01_login.spec.js index e5a70703e..03acc98a8 100644 --- a/e2e/paths/01-login/01_login.spec.js +++ b/e2e/paths/01-login/01_login.spec.js @@ -1,56 +1,35 @@ import createNightmare from '../../helpers/nightmare'; - describe('Login path', () => { const nightmare = createNightmare(); it('should receive an error when the username is incorrect', async() => { - const username = 'nobody'; - const password = 'nightmare'; - const result = await nightmare - .wait(`vn-login input[name=user]`) - .write(`vn-login input[name=user]`, username) - .write(`vn-login input[name=password]`, password) - .click(`vn-login input[type=submit]`) + .doLogin('badUser', null) .waitForLastSnackbar(); expect(result.length).toBeGreaterThan(0); }); it('should receive an error when the username is blank', async() => { - const password = 'nightmare'; - const result = await nightmare - .clearInput(`vn-login input[name=user]`) - .write(`vn-login input[name=password]`, password) - .click(`vn-login input[type=submit]`) + .doLogin('', null) .waitForLastSnackbar(); expect(result.length).toBeGreaterThan(0); }); it('should receive an error when the password is incorrect', async() => { - const username = 'employee'; - const password = 'badpassword'; - const result = await nightmare - .write(`vn-login input[name=user]`, username) - .write(`vn-login input[name=password]`, password) - .click(`vn-login input[type=submit]`) + .doLogin('employee', 'badPassword') .waitForLastSnackbar(); expect(result.length).toBeGreaterThan(0); }); it('should log in', async() => { - const username = 'employee'; - const password = 'nightmare'; - const url = await nightmare - .write(`vn-login input[name=user]`, username) - .write(`vn-login input[name=password]`, password) - .click(`vn-login input[type=submit]`) + .doLogin('employee', null) .wait('#logout') .parsedUrl(); diff --git a/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js b/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js index ae3020d2a..cbe3722de 100644 --- a/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js +++ b/e2e/paths/02-client-module/03_edit_fiscal_data.spec.js @@ -42,9 +42,7 @@ describe('Client Edit fiscalData path', () => { it('should not be able to edit the verified data checkbox', async() => { const result = await nightmare .wait(selectors.clientFiscalData.verifiedDataCheckbox) - .evaluate(selector => { - return document.querySelector(selector).getAttribute('disabled'); - }, selectors.clientFiscalData.verifiedDataCheckbox); + .isDisabled(selectors.clientFiscalData.verifiedDataCheckbox); expect(result).toBeTruthy(); }); diff --git a/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js b/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js index 52e2db237..398185ba5 100644 --- a/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js +++ b/e2e/paths/02-client-module/12_lock_of_verified_data.spec.js @@ -16,9 +16,7 @@ describe('Client lock verified data path', () => { const result = await nightmare .wait(200) .wait(selectors.clientFiscalData.verifiedDataCheckbox) - .evaluate(selector => { - return document.querySelector(selector).getAttribute('disabled'); - }, selectors.clientFiscalData.verifiedDataCheckbox); + .isDisabled(selectors.clientFiscalData.verifiedDataCheckbox); expect(result).toBeTruthy(); }); diff --git a/e2e/paths/05-ticket-module/13_services.spec.js b/e2e/paths/05-ticket-module/13_services.spec.js index 31d262778..7172ab5a6 100644 --- a/e2e/paths/05-ticket-module/13_services.spec.js +++ b/e2e/paths/05-ticket-module/13_services.spec.js @@ -17,9 +17,7 @@ describe('Ticket services path', () => { const result = await nightmare .waitToClick(selectors.ticketService.addServiceButton) .wait(selectors.ticketService.firstAddDescriptionButton) - .evaluate(selector => { - return document.querySelector(selector).disabled; - }, selectors.ticketService.firstAddDescriptionButton); + .isDisabled(selectors.ticketService.firstAddDescriptionButton); expect(result).toBeTruthy(); }); diff --git a/e2e/paths/07-order-module/02_catalog.spec.js b/e2e/paths/07-order-module/02_catalog.spec.js index d2a862958..cad95741e 100644 --- a/e2e/paths/07-order-module/02_catalog.spec.js +++ b/e2e/paths/07-order-module/02_catalog.spec.js @@ -66,7 +66,7 @@ describe('Order catalog', () => { const result = await nightmare .waitToClick(selectors.orderCatalog.fourthFilterRemoveButton) .waitToClick(selectors.orderCatalog.thirdFilterRemoveButton) - .waitForNumberOfElements('section.product', 4) + .waitForNumberOfElements('.product', 4) .countElement('section.product'); expect(result).toEqual(4); diff --git a/e2e/paths/09-invoice-out-module/01_descriptor.spec.js b/e2e/paths/09-invoice-out-module/01_descriptor.spec.js index a00d6387d..fd3516d87 100644 --- a/e2e/paths/09-invoice-out-module/01_descriptor.spec.js +++ b/e2e/paths/09-invoice-out-module/01_descriptor.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/nightmare'; -describe('InvoiceOut descriptor path', () => { +fdescribe('InvoiceOut descriptor path', () => { const nightmare = createNightmare(); let bookedDate; diff --git a/front/core/components/button-menu/button-menu.html b/front/core/components/button-menu/button-menu.html deleted file mode 100644 index 5beeb12fb..000000000 --- a/front/core/components/button-menu/button-menu.html +++ /dev/null @@ -1,13 +0,0 @@ -
- - - -
\ No newline at end of file diff --git a/front/core/components/button-menu/index.html b/front/core/components/button-menu/index.html new file mode 100644 index 000000000..b0977bb93 --- /dev/null +++ b/front/core/components/button-menu/index.html @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/front/core/components/button-menu/button-menu.js b/front/core/components/button-menu/index.js similarity index 83% rename from front/core/components/button-menu/button-menu.js rename to front/core/components/button-menu/index.js index 99f3879ee..d31094d36 100644 --- a/front/core/components/button-menu/button-menu.js +++ b/front/core/components/button-menu/index.js @@ -1,17 +1,13 @@ import ngModule from '../../module'; -import Input from '../../lib/input'; +import Button from '../button'; import assignProps from '../../lib/assign-props'; import './style.scss'; -export default class ButtonMenu extends Input { +export default class ButtonMenu extends Button { constructor($element, $scope, $transclude) { super($element, $scope); this.$transclude = $transclude; - this.input = this.element.querySelector('.mdl-button'); - $element.on('click', e => { - if (!this.disabled) - this.onClick(e); - }); + $element.on('click', e => this.onClick(e)); } get model() { @@ -46,6 +42,7 @@ export default class ButtonMenu extends Input { } onClick(event) { + if (this.disabled) return; if (event.defaultPrevented) return; event.preventDefault(); this.emit('open'); @@ -85,15 +82,14 @@ export default class ButtonMenu extends Input { } ButtonMenu.$inject = ['$element', '$scope', '$transclude']; -ngModule.component('vnButtonMenu', { - template: require('./button-menu.html'), +ngModule.vnComponent('vnButtonMenu', { + template: require('./index.html'), + controller: ButtonMenu, bindings: { - label: '@', showField: '@?', selection: ' - {{$ctrl.label}} - - - \ No newline at end of file diff --git a/front/core/components/button/button.js b/front/core/components/button/button.js deleted file mode 100644 index 4e5cf50a2..000000000 --- a/front/core/components/button/button.js +++ /dev/null @@ -1,34 +0,0 @@ -import ngModule from '../../module'; -import Input from '../../lib/input'; -import './style.scss'; - -export default class Button extends Input { - constructor($element) { - super($element); - this.$element = $element; - this.input = this.element.querySelector('.mdl-button'); - - $element[0].addEventListener('click', event => { - if (this.disabled) - event.stopImmediatePropagation(); - }); - } - - $onInit() { - if (!this.type) - this.type = 'button'; - } -} -Button.$inject = ['$element']; - -ngModule.component('vnButton', { - controller: Button, - template: require('./button.html'), - bindings: { - label: '@?', - disabled: ' + + {{::$ctrl.label}} + + + + \ No newline at end of file diff --git a/front/core/components/button/index.js b/front/core/components/button/index.js new file mode 100644 index 000000000..e1a86eb5d --- /dev/null +++ b/front/core/components/button/index.js @@ -0,0 +1,46 @@ +import ngModule from '../../module'; +import FormInput from '../form-input'; +import './style.scss'; + +export default class Button extends FormInput { + constructor($element, $scope) { + super($element, $scope); + this.design = 'colored'; + this.input = this.element.querySelector('button'); + + let element = this.element; + element.tabIndex = 0; + element.classList.add('vn-button'); + this.element.addEventListener('keyup', e => this.onKeyup(e)); + this.element.addEventListener('click', e => this.onClick(e)); + } + + $onInit() { + this.element.classList.add(this.design); + if (!this.type) this.type = 'button'; + } + + onKeyup(event) { + if (event.code == 'Space') + this.onClick(event); + } + + onClick(event) { + if (event.defaultPrevented) return; + // event.preventDefault(); + + // FIXME: Don't stop event propagation + if (this.disabled) event.stopImmediatePropagation(); + } +} +Button.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnButton', { + controller: Button, + template: require('./index.html'), + bindings: { + icon: '@?', + type: '@?' + } +}); + diff --git a/front/core/components/button/style.scss b/front/core/components/button/style.scss index 84bd8659a..74dcbcf9b 100644 --- a/front/core/components/button/style.scss +++ b/front/core/components/button/style.scss @@ -1,5 +1,83 @@ -vn-button { - & > button > vn-icon { - vertical-align: middle; +@import "variables"; + +.vn-button { + display: inline-flex; + align-items: center; + justify-content: center; + height: 36px; + border: none; + border-radius: .1em; + font-family: vn-font-bold; + text-transform: uppercase; + font-size: 14px; + cursor: pointer; + box-sizing: border-box; + outline: none; + + & > button { + width: 100%; + padding: 0 12px; + box-sizing: border-box; + background-color: transparent; + border: none; + height: inherit; + color: inherit; + font: inherit; + display: block; + text-transform: inherit; + cursor: inherit; + outline: none; + display: flex; + align-items: center; + justify-content: center; + + & > vn-icon { + vertical-align: middle; + color: inherit; + font-size: 1.7em; + } } -} \ No newline at end of file + &.colored { + color: white; + background-color: $color-main; + box-shadow: 0 .15em .15em 0 rgba(0, 0, 0, .3); + transition: background 200ms ease-in-out; + + &:not(.disabled) { + &:hover, + &:focus { + background-color: lighten($color-main, 10%); + } + } + } + &.flat { + color: $color-main; + background-color: transparent; + box-shadow: none; + transition: background 200ms ease-in-out; + + &:not(.disabled) { + &:hover, + &:focus { + background-color: $color-hover-cd; + } + } + } + &:hover, + &:focus { + outline: none; + } + &.round { + border-radius: 50%; + height: 3.8em; + width: 3.8em; + + & > button > span { + display: none; + } + } + &.disabled { + opacity: .7; + cursor: initial; + } +} diff --git a/front/core/components/card/card.js b/front/core/components/card/card.js index b812ccf61..a37835995 100644 --- a/front/core/components/card/card.js +++ b/front/core/components/card/card.js @@ -7,7 +7,7 @@ export default function directive() { transclude: true, template: require('./card.html'), link: function($scope, $element, $attrs, $ctrl, $transclude) { - $element.addClass('demo-card-wide mdl-shadow--2dp bg-panel'); + $element.addClass('demo-card-wide vn-shadow bg-panel'); $transclude($scope, function(clone) { angular.element($element[0].querySelector('div')).append(clone); diff --git a/front/core/components/chip/index.html b/front/core/components/chip/index.html index 8696fd8bb..38a56923d 100644 --- a/front/core/components/chip/index.html +++ b/front/core/components/chip/index.html @@ -1,8 +1,7 @@ - - - - - - \ No newline at end of file +
+ + \ No newline at end of file diff --git a/front/core/components/chip/index.js b/front/core/components/chip/index.js index b35c00cbf..6a945559b 100644 --- a/front/core/components/chip/index.js +++ b/front/core/components/chip/index.js @@ -1,17 +1,12 @@ import ngModule from '../../module'; +import Component from '../../lib/component'; import './style.scss'; -export default class Chip { - -/** - * Remove chip event - */ - remove() { - if (this.onRemove) - this.onRemove(); +export default class Chip extends Component { + onRemove() { + if (!this.disabled) this.emit('remove'); } } - Chip.$inject = ['$element', '$scope', '$transclude']; ngModule.component('vnChip', { @@ -20,6 +15,6 @@ ngModule.component('vnChip', { transclude: true, bindings: { disabled: ' { controller = $componentController('vnChip', {$element, $scope, $transclude: () => {}}); })); - describe('remove()', () => { - it(`should call onRemove()`, () => { - controller.onRemove = () => {}; - spyOn(controller, 'onRemove'); - controller.remove(); + describe('onRemove()', () => { + it(`should emit remove event`, () => { + controller.emit = () => {}; + spyOn(controller, 'emit'); + controller.onRemove(); - expect(controller.onRemove).toHaveBeenCalledWith(); + expect(controller.emit).toHaveBeenCalledWith('remove'); }); }); }); diff --git a/front/core/components/chip/style.scss b/front/core/components/chip/style.scss index 81e81589c..ee7f46848 100644 --- a/front/core/components/chip/style.scss +++ b/front/core/components/chip/style.scss @@ -1,18 +1,53 @@ @import "variables"; vn-chip { + border-radius: 16px; + background-color: $color-bg; margin: 0 0.5em 0.5em 0; + color: $color-font; + font-size: 14px; + margin: .25em; + display: inline-flex; + align-items: center; + text-overflow: ellipsis; + white-space: nowrap; + height: 28px; + padding: 0 .7em; + overflow: hidden; - .mdl-chip { - background-color: rgba($color-main, 0.9); - color: #FFF + &.colored { + background-color: $color-main; + color: $color-font-dark; } - - .mdl-chip:active { - background-color: $color-main - } - - & > vn-one > span > span { + & > div { + display: flex; + align-items: center; max-width: 100%; + height: 100%; + + & > vn-avatar { + margin-left: -0.7em; + margin-right: .4em; + } } + & > vn-icon { + margin-left: .2em; + margin-right: -0.3em; + vertical-align: middle; + opacity: .6; + cursor: pointer; + transition: opacity 250ms ease-out; + + &:hover, + &:focus { + opacity: 1; + } + } +} + +vn-avatar { + display: inline-block; + height: 28px; + width: 28px; + border-radius: 50%; } \ No newline at end of file diff --git a/front/core/components/color-legend/index.html b/front/core/components/color-legend/index.html deleted file mode 100644 index 613fb2347..000000000 --- a/front/core/components/color-legend/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - - {{legend.name}} - \ No newline at end of file diff --git a/front/core/components/color-legend/index.js b/front/core/components/color-legend/index.js deleted file mode 100644 index f72a501a7..000000000 --- a/front/core/components/color-legend/index.js +++ /dev/null @@ -1,24 +0,0 @@ -import ngModule from '../../module'; -import Component from '../../lib/component'; -import './style.scss'; - -export default class Controller extends Component { - constructor($element, $scope, $attrs) { - super($element, $scope); - this.$attrs = $attrs; - } - - onClick(legend) { - this.emit('click', {legend}); - } -} - -Controller.$inject = ['$element', '$scope', '$attrs']; - -ngModule.component('vnColorLegend', { - template: require('./index.html'), - controller: Controller, - bindings: { - data: ' this.onClick(e)); @@ -43,9 +42,11 @@ export default class Field extends FormInput { } set input(value) { - if (this.input) this.control.removeChild(this.input); + if (this.input) + this.control.removeChild(this.input); this._input = value; - this.control.appendChild(value); + if (value) + this.control.appendChild(value); } get input() { @@ -69,12 +70,10 @@ export default class Field extends FormInput { } set name(value) { - // super.name = value; this.input.name = value; } get name() { - // return super.name; return this.input.name; } @@ -86,36 +85,8 @@ export default class Field extends FormInput { return this.input.placeholder; } - set tabIndex(value) { - this.input.tabIndex = value; - } - - get tabIndex() { - return this.input.tabIndex; - } - - 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); + this._required = value; let required = this.element.querySelector('.required'); display(required, this._required); } @@ -182,6 +153,10 @@ export default class Field extends FormInput { fix.innerText = text || ''; } + refreshTabIndex() { + this.input.tabIndex = this.disabled ? -1 : this.tabIndex; + } + onClick() { // if (event.defaultPrevented) return; // event.preventDefault(); @@ -252,15 +227,10 @@ ngModule.vnComponent('vnField', { suffix: '@?', hint: '@?', error: ' .hint { - z-index: -1; padding: 4px 0; height: 12px; color: rgba(0, 0, 0, .4); @@ -255,11 +254,12 @@ transition-duration: 200ms; transition-timing-function: ease-in-out; opacity: 0; + visibility: hidden; &.filled { - z-index: 0; opacity: 1; transform: translateY(0); + visibility: visible; } } &.invalid { diff --git a/front/core/components/float-button/float-button.html b/front/core/components/float-button/float-button.html deleted file mode 100644 index e74a1fce7..000000000 --- a/front/core/components/float-button/float-button.html +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/front/core/components/float-button/float-button.js b/front/core/components/float-button/float-button.js deleted file mode 100644 index beb3dd13b..000000000 --- a/front/core/components/float-button/float-button.js +++ /dev/null @@ -1,8 +0,0 @@ -import ngModule from '../../module'; - -ngModule.component('vnFloatButton', { - template: require('./float-button.html'), - bindings: { - icon: '@' - } -}); diff --git a/front/core/components/float-button/index.js b/front/core/components/float-button/index.js new file mode 100644 index 000000000..32ada7437 --- /dev/null +++ b/front/core/components/float-button/index.js @@ -0,0 +1,13 @@ +import ngModule from '../../module'; +import Button from '../button'; + +export default class FloatButton extends Button { + constructor($element, $scope) { + super($element, $scope); + this.element.classList.add('round'); + } +} + +ngModule.vnComponent('vnFloatButton', { + controller: FloatButton +}); diff --git a/front/core/components/form-input/index.js b/front/core/components/form-input/index.js index 74d98079c..0a1297788 100644 --- a/front/core/components/form-input/index.js +++ b/front/core/components/form-input/index.js @@ -9,6 +9,11 @@ import Component from '../../lib/component'; * @property {Boolean} disabled Put component in disabled mode */ export default class FormInput extends Component { + constructor($element, $scope) { + super($element, $scope); + this.classList = this.element.classList; + } + $onInit() { // XXX: Compatibility with old inputs let attrs = this.$element[0].attributes; @@ -41,6 +46,48 @@ export default class FormInput extends Component { get name() { return this.element.getAttribute('name'); } + + set disabled(value) { + this._disabled = boolTag(value); + this.input.disabled = this._disabled; + this.classList.toggle('disabled', this._disabled); + this.refreshTabIndex(); + } + + 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 tabIndex(value) { + this._tabIndex = value; + this.refreshTabIndex(); + } + + get tabIndex() { + return this._tabIndex; + } + + select() { + this.input.select(); + } + + focus() { + this.input.focus(); + } + + refreshTabIndex() { + this.element.tabIndex = this.disabled ? -1 : this.tabIndex; + } } ngModule.vnComponent('vnFormInput', { @@ -50,9 +97,14 @@ ngModule.vnComponent('vnFormInput', { field: '=?', name: '@?', disabled: ' - - \ No newline at end of file diff --git a/front/core/components/icon-button/icon-button.js b/front/core/components/icon-button/icon-button.js deleted file mode 100644 index ba3ccae3e..000000000 --- a/front/core/components/icon-button/icon-button.js +++ /dev/null @@ -1,39 +0,0 @@ -import ngModule from '../../module'; -import './style.scss'; - -export default class IconButton { - constructor($element) { - this.element = $element[0]; - - if (this.element.getAttribute('tabindex') == null) - this.element.tabIndex = 0; - - this.element.addEventListener('keyup', e => this.onKeyup(e)); - this.element.addEventListener('click', e => this.onClick(e)); - } - - onKeyup(event) { - if (event.code == 'Space') - this.onClick(event); - } - - onClick(event) { - if (event.defaultPrevented) return; - event.preventDefault(); - - // FIXME: Don't use Event.stopPropagation() - let button = this.element.querySelector('button'); - if (this.disabled || button.disabled) - event.stopImmediatePropagation(); - } -} - -IconButton.$inject = ['$element']; -ngModule.component('vnIconButton', { - controller: IconButton, - template: require('./icon-button.html'), - bindings: { - icon: '@', - disabled: ' button { - background-color: transparent; - display: block; - color: inherit; - border: 0; - padding: 0; - font-size: inherit; - &:hover { - background-color: initial; - } - & > vn-icon { - display: block; - font-size: inherit; - } + & > button { + padding: 0 !important; + } + &:focus { + opacity: .6; } } diff --git a/front/core/components/icon-focusable/icon-focusable.html b/front/core/components/icon-focusable/icon-focusable.html deleted file mode 100644 index 4bd8ad78a..000000000 --- a/front/core/components/icon-focusable/icon-focusable.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/front/core/components/icon-focusable/icon-focusable.js b/front/core/components/icon-focusable/icon-focusable.js deleted file mode 100644 index 691ee570f..000000000 --- a/front/core/components/icon-focusable/icon-focusable.js +++ /dev/null @@ -1,29 +0,0 @@ -import ngModule from '../../module'; -import './style.scss'; - -export default class IconFocusable { - constructor($element) { - $element[0].tabIndex = 0; - $element.on("keyup", event => this.onKeyDown(event, $element)); - } - - onKeyDown(event, $element) { - if (event.defaultPrevented) return; - if (event.keyCode == 32 || event.keyCode == 13) { - event.preventDefault(); - $element.triggerHandler('click'); - } - } -} - -IconFocusable.$inject = ['$element']; -ngModule.component('vnIconFocusable', { - controller: IconFocusable, - template: require('./icon-focusable.html'), - bindings: { - icon: '@', - className: '@?', - enabled: ' i, - & > i.material-icons { - display: block; - font-size: inherit; - } -} \ No newline at end of file diff --git a/front/core/components/icon-menu/icon-menu.html b/front/core/components/icon-menu/icon-menu.html deleted file mode 100644 index 93de718ff..000000000 --- a/front/core/components/icon-menu/icon-menu.html +++ /dev/null @@ -1,11 +0,0 @@ -
- - - - -
\ No newline at end of file diff --git a/front/core/components/icon-menu/icon-menu.js b/front/core/components/icon-menu/icon-menu.js deleted file mode 100644 index abc94504e..000000000 --- a/front/core/components/icon-menu/icon-menu.js +++ /dev/null @@ -1,41 +0,0 @@ -import ngModule from '../../module'; -import ButtonMenu from '../button-menu/button-menu'; -import './style.scss'; - -export default class IconMenu extends ButtonMenu { - constructor($element, $scope, $transclude) { - super($element, $scope); - this.$transclude = $transclude; - this.input = this.element.querySelector('.button'); - } -} -IconMenu.$inject = ['$element', '$scope', '$transclude']; - -ngModule.component('vnIconMenu', { - template: require('./icon-menu.html'), - bindings: { - label: '@', - showField: '@?', - selection: ' + + + + + \ No newline at end of file diff --git a/front/core/components/icon-menu/index.js b/front/core/components/icon-menu/index.js new file mode 100644 index 000000000..0549149a8 --- /dev/null +++ b/front/core/components/icon-menu/index.js @@ -0,0 +1,14 @@ +import ngModule from '../../module'; +import ButtonMenu from '../button-menu'; + +export default class IconMenu extends ButtonMenu { + constructor($element, $scope) { + super($element, $scope); + this.element.classList.add('flat'); + } +} + +ngModule.vnComponent('vnIconMenu', { + template: require('./index.html'), + controller: IconMenu +}); diff --git a/front/core/components/icon-menu/style.scss b/front/core/components/icon-menu/style.scss deleted file mode 100644 index df7a5e331..000000000 --- a/front/core/components/icon-menu/style.scss +++ /dev/null @@ -1,8 +0,0 @@ -vn-icon-menu { - cursor: pointer; - - vn-drop-down { - font-family: 'vn-font'; - outline: 0 - } -} \ No newline at end of file diff --git a/front/core/components/index.js b/front/core/components/index.js index 0433744f6..50c1a1bf8 100644 --- a/front/core/components/index.js +++ b/front/core/components/index.js @@ -10,36 +10,35 @@ import './subtitle/subtitle'; import './spinner/spinner'; import './snackbar/snackbar'; import './tooltip/tooltip'; -import './icon-menu/icon-menu'; -import './button-menu/button-menu'; import './popover/popover'; import './drop-down/drop-down'; import './menu/menu'; import './multi-check/multi-check'; -import './button/button'; -import './icon-button/icon-button'; -import './submit/submit'; import './card/card'; -import './float-button/float-button'; import './step-control/step-control'; import './label-value/label-value'; import './pagination/pagination'; import './searchbar/searchbar'; import './scroll-up/scroll-up'; import './autocomplete'; +import './button'; +import './button-menu'; import './calendar'; import './check'; import './chip'; -import './color-legend'; import './data-viewer'; import './date-picker'; import './field'; +import './float-button'; +import './icon-menu'; +import './icon-button'; import './input-number'; -import './input-range'; +import './range'; import './input-time'; import './input-file'; import './list'; import './radio'; +import './submit'; import './table'; import './td-editable'; import './textarea'; diff --git a/front/core/components/input-file/index.html b/front/core/components/input-file/index.html index 4e9c48631..58a2bea0c 100644 --- a/front/core/components/input-file/index.html +++ b/front/core/components/input-file/index.html @@ -1,42 +1,53 @@ -
-
-
-
-
+
+
+
+
+
+
+
{{$ctrl.value}}
- + type="file" + ng-model="$ctrl.files" + accept="{{$ctrl.accept}}"> +
-
-
-
- - info_outline - - - -
-
+
+
+
+ + + + + + +
+
+
+
+
+
+
+
diff --git a/front/core/components/input-file/index.js b/front/core/components/input-file/index.js index d0f93e4f8..3a0066e75 100644 --- a/front/core/components/input-file/index.js +++ b/front/core/components/input-file/index.js @@ -1,15 +1,13 @@ import ngModule from '../../module'; -import Input from '../../lib/input'; +import FormInput from '../form-input'; import './style.scss'; -export default class InputFile extends Input { +export default class InputFile extends FormInput { constructor($element, $scope) { super($element, $scope); - this.element = $element[0]; - this.hasFocus = false; this._multiple = false; this._value = 'Select a file'; - + this.input = this.element.querySelector('input'); this.registerEvents(); } @@ -106,26 +104,12 @@ export default class InputFile extends Input { } } -InputFile.$inject = ['$element', '$scope']; - -ngModule.component('vnInputFile', { +ngModule.vnComponent('vnInputFile', { template: require('./index.html'), controller: InputFile, - transclude: { - leftIcons: '?tLeftIcons', - rightIcons: '?tRightIcons' - }, bindings: { - label: '@?', - name: '@?', - disabled: ' .container { - width: 100%; - position: relative; - padding-bottom: 2px; - display: flex; - - & > .textField { - width: 100%; - display: flex; - align-items: center; - position: relative; - padding-top: 4px; - } - } - - .leftIcons, .rightIcons, .suffix { - display: flex; - color: $color-font-secondary; - - .material-icons { - font-size: 20px !important - } - } - - .suffix vn-icon-button { - padding: 0 - } - - t-left-icons { - padding-right: 0.5em - } - - t-right-icons { - padding-left: 0.5em - } - - .infix { - position: relative; - display: block; - flex: auto; - width: 100%; - min-width: 0; - } - i.clear { - visibility: hidden; - cursor: pointer; - outline: 0; - - &:hover { - color: #222; - } - } - &:hover i.clear { - visibility: visible; - } - i.visible { - visibility: visible; - } - label { - position: absolute; - bottom: 0; - left: 0; - padding: 4px 0!important; - pointer-events: none; - color: $color-font-secondary; - transition-duration: .2s; - transition-timing-function: cubic-bezier(.4,0,.2,1); - } - &.not-empty label{ - bottom: 24px; - color: $color-main; - padding: 0; - font-size: 12px; - } - input { - outline: none; - border: none; - font-family: "Helvetica", "Arial", sans-serif; - display: block; - font-size: 16px; - width: 100%; - background: 0 0; - color: inherit; - padding: 4px; - box-sizing: border-box; - border-bottom: 0!important; - - &[type=number] { - -moz-appearance: textfield; - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - } - &:invalid { - box-shadow: none; - } - } - .underline { - position: absolute; - bottom: 0; - height: 1px; - content: ' '; - pointer-events: none; - width: 100%; - background-color: $color-input-underline; - } - .selected.underline { - background-color: $color-main; - height: 2px; - left: 50%; - width: 0px !important; - transition-duration: 0.2s; - transition-timing-function: cubic-bezier(.4,0,.2,1); - } - - div.selected { - &.container{ - border-bottom: 0px; - } - label { - bottom: 24px; - color: $color-main; - font-size: 12px; - } - .selected.underline{ - left: 0; - width: 100%!important; - } - } - & > div.container > div.textField > div.infix.invalid { - @extend div.selected; - - & > span.mdl-textfield__error { - visibility: visible; - } - & > label { - color: #d50000; - } - } - .infix.invalid + .underline { - background-color: #d50000; - } - - label span:nth-child(2) { - color: $color-alert + input[type=file] { + display: none; } } \ No newline at end of file diff --git a/front/core/components/input-range/index.html b/front/core/components/input-range/index.html deleted file mode 100644 index 649e4de9f..000000000 --- a/front/core/components/input-range/index.html +++ /dev/null @@ -1,9 +0,0 @@ -
- - - - -
\ No newline at end of file diff --git a/front/core/components/input-range/index.js b/front/core/components/input-range/index.js deleted file mode 100644 index 8cfd898c7..000000000 --- a/front/core/components/input-range/index.js +++ /dev/null @@ -1,79 +0,0 @@ -import ngModule from '../../module'; -import Input from '../../lib/input'; -import './style.scss'; - -export default class inputRange extends Input { - constructor($element, $scope) { - super($element, $scope); - this.mdlElement = this.element.querySelector('.mdl-slider'); - componentHandler.upgradeElement(this.mdlElement); - this.mdlElement.addEventListener('change', () => { - this._value = this.input.value; - this.$.$applyAsync(); - if (this._value && this.onChange) - this.emit('change', {value: this._value}); - }); - } - - get value() { - return this._value; - } - - set value(value) { - this._value = value; - this.mdlElement.MaterialSlider.change(value); - } - - get max() { - return this.input.max; - } - - set max(value) { - this.input.max = value; - } - - get min() { - return this.input.min; - } - - set min(value) { - this.input.min = value; - } - - get step() { - return this.input.step; - } - - set step(value) { - this.input.step = value; - } - - get() { - return this._model; - } - - set model(value) { - this._model = value; - } - - set disabled(value) { - this.input.disabled = value; - } -} - -inputRange.$inject = ['$element', '$scope']; - -ngModule.component('vnInputRange', { - template: require('./index.html'), - controller: inputRange, - bindings: { - label: '@?', - disabled: '{{::$ctrl.label}} + + + \ No newline at end of file diff --git a/front/core/components/range/index.js b/front/core/components/range/index.js new file mode 100644 index 000000000..80410875a --- /dev/null +++ b/front/core/components/range/index.js @@ -0,0 +1,50 @@ +import ngModule from '../../module'; +import FormInput from '../form-input'; +import './style.scss'; + +export default class Range extends FormInput { + constructor($element, $scope) { + super($element, $scope); + this.input = this.element.querySelector('input'); + } + + get max() { + return this.input.max; + } + + set max(value) { + this.input.max = value; + } + + get min() { + return this.input.min; + } + + set min(value) { + this.input.min = value; + } + + get step() { + return this.input.step; + } + + set step(value) { + this.input.step = value; + } + + refreshTabIndex() { + this.input.tabIndex = this.disabled ? -1 : this.tabIndex; + } +} + +ngModule.vnComponent('vnRange', { + template: require('./index.html'), + controller: Range, + bindings: { + min: ' label { + font-size: 12px; + + &.main { + color: $color-main; + } + &.min-label { + float: left; + } + &.max-label { + float: right; + } + } + & > input { + cursor: pointer; + height: 30px; + display: block; + width: 100%; + background: transparent; + border-color: transparent; + -webkit-appearance: none; + margin: .2em 0; + + &:focus { + outline: none; + } + &::-moz-focus-outer { + border: 0; + } + @include range( + "-moz-range-thumb", + "-moz-range-track" + ); + @include range( + "-webkit-slider-thumb", + "-webkit-slider-runnable-track" + ); + @include range( + "-ms-thumb", + "-ms-track" + ); + &:disabled { + cursor: initial; + } + } +} diff --git a/front/core/components/scroll-up/scroll-up.html b/front/core/components/scroll-up/scroll-up.html index 3f3b309d5..a3748acc6 100644 --- a/front/core/components/scroll-up/scroll-up.html +++ b/front/core/components/scroll-up/scroll-up.html @@ -1,5 +1,6 @@ - \ No newline at end of file + vn-tooltip="Go up" + class="round"> + \ No newline at end of file diff --git a/front/core/components/scroll-up/style.scss b/front/core/components/scroll-up/style.scss index 0d5cd6c58..1bf7ea982 100644 --- a/front/core/components/scroll-up/style.scss +++ b/front/core/components/scroll-up/style.scss @@ -1,6 +1,6 @@ vn-scroll-up { - top: 5em; - right: 2.5em; + top: 5.5em; + right: 2em; display: none; position: fixed; } \ No newline at end of file diff --git a/front/core/components/searchbar/style.scss b/front/core/components/searchbar/style.scss index b3fa4b1a2..03cc0cd8d 100644 --- a/front/core/components/searchbar/style.scss +++ b/front/core/components/searchbar/style.scss @@ -2,6 +2,7 @@ vn-searchbar { display: block; + width: 100%; } .search-panel { diff --git a/front/core/components/spinner/spinner.html b/front/core/components/spinner/spinner.html index 47b6e42fe..b6a3af8be 100644 --- a/front/core/components/spinner/spinner.html +++ b/front/core/components/spinner/spinner.html @@ -1,2 +1,12 @@ -
+
+ + + +
\ No newline at end of file diff --git a/front/core/components/spinner/spinner.js b/front/core/components/spinner/spinner.js index ca87323d5..aee973aa6 100644 --- a/front/core/components/spinner/spinner.js +++ b/front/core/components/spinner/spinner.js @@ -1,19 +1,18 @@ import ngModule from '../../module'; import Component from '../../lib/component'; -import './style.css'; +import './style.scss'; /** * A spinner to inform the user about loading process. */ export default class Spinner extends Component { constructor($element, $scope) { - super($element); + super($element, $scope); this._enable = false; this.spinner = $element[0].firstChild; - componentHandler.upgradeElement(this.spinner); } /** - * Enables/disables the spinner. + * Activates/deactivates the spinner. * * @param {Boolean} value %true to enable, %false to disable */ @@ -35,14 +34,14 @@ export default class Spinner extends Component { * Activates the spinner. */ start() { - this.spinner.MaterialSpinner.start(); + this.spinner.style.display = 'block'; this._enable = true; } /** * Deactivates the spinner. */ stop() { - this.spinner.MaterialSpinner.stop(); + this.spinner.style.display = 'none'; this._enable = false; } } diff --git a/front/core/components/spinner/spinner.spec.js b/front/core/components/spinner/spinner.spec.js index cb23783f7..437139c8c 100644 --- a/front/core/components/spinner/spinner.spec.js +++ b/front/core/components/spinner/spinner.spec.js @@ -1,7 +1,6 @@ import './spinner.js'; describe('Component vnSpinner', () => { - let $scope; let $element; let controller; @@ -9,53 +8,44 @@ describe('Component vnSpinner', () => { $translateProvider.translations('en', {}); })); - beforeEach(angular.mock.inject(($componentController, $rootScope) => { - $scope = $rootScope.$new(); - $element = angular.element('
'); - controller = $componentController('vnSpinner', {$scope, $element}); + beforeEach(angular.mock.inject(($compile, $rootScope) => { + $element = $compile(``)($rootScope); + controller = $element.controller('vnSpinner'); })); + afterEach(() => { + $element.remove(); + }); + describe('enable()', () => { - it(`should call start() based on a boolean value passed as argument`, () => { + it(`should call start() when enable is set to true`, () => { spyOn(controller, 'start'); - spyOn(controller, 'stop'); controller.enable = true; expect(controller.start).toHaveBeenCalledWith(); - expect(controller.stop).not.toHaveBeenCalledWith(); }); - it(`should call stop() based on a boolean value passed as argument`, () => { - spyOn(controller, 'start'); + it(`should call stop() when enable is set to false`, () => { spyOn(controller, 'stop'); controller.enable = false; - expect(controller.start).not.toHaveBeenCalledWith(); expect(controller.stop).toHaveBeenCalledWith(); }); }); describe('start()', () => { - it(`should call start() on the controller.materialSpinner then set controllers._enable to be truthy`, () => { - controller.spinner = {MaterialSpinner: {start: () => {}}}; - spyOn(controller.spinner.MaterialSpinner, 'start'); - controller._enable = false; + it(`should set enable to true`, () => { controller.start(); - expect(controller.spinner.MaterialSpinner.start).toHaveBeenCalledWith(); - expect(controller._enable).toBeTruthy(); + expect(controller.enable).toBeTruthy(); }); }); describe('stop()', () => { - it(`should call stop() on the controller.materialSpinner then set controllers._enable to be truthy`, () => { - controller.spinner = {MaterialSpinner: {stop: () => {}}}; - spyOn(controller.spinner.MaterialSpinner, 'stop'); - controller._enable = true; + it(`should set enable to false`, () => { controller.stop(); - expect(controller.spinner.MaterialSpinner.stop).toHaveBeenCalledWith(); - expect(controller._enable).toBeFalsy(); + expect(controller.enable).toBeFalsy(); }); }); }); diff --git a/front/core/components/spinner/style.css b/front/core/components/spinner/style.css deleted file mode 100644 index fbcd1a0bf..000000000 --- a/front/core/components/spinner/style.css +++ /dev/null @@ -1,3 +0,0 @@ -vn-spinner { - display: inline-block; -} \ No newline at end of file diff --git a/front/core/components/spinner/style.scss b/front/core/components/spinner/style.scss new file mode 100644 index 000000000..3be908caf --- /dev/null +++ b/front/core/components/spinner/style.scss @@ -0,0 +1,60 @@ +@import "variables"; + +vn-spinner { + display: inline-block; + min-height: 28px; + min-width: 28px; + + & > .loader { + position: relative; + margin: 0 auto; + width: 100%; + height: 100%; + + &:before { + content: ''; + display: block; + padding-top: 100%; + } + & > .circular { + animation: rotate 2s linear infinite; + transform-origin: center center; + height: 100%; + width: 100%; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + + & > .path { + stroke: $color-main; + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + stroke-linecap: square; + stroke-width: 6px; + animation: dash 1.5s ease-in-out infinite; + } + } + } + @keyframes rotate { + 100% { + transform: rotate(360deg); + } + } + @keyframes dash { + 0% { + stroke-dasharray: 1, 200; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -35px; + } + 100% { + stroke-dasharray: 89, 200; + stroke-dashoffset: -124px; + } + } +} \ No newline at end of file diff --git a/front/core/components/step-control/style.scss b/front/core/components/step-control/style.scss index e1c29c9a2..9acc1f314 100644 --- a/front/core/components/step-control/style.scss +++ b/front/core/components/step-control/style.scss @@ -41,11 +41,5 @@ vn-step-control { & > .buttons > .step { display: flex } - & > .buttons > .step > .mdl-button { - line-height: 32px; - font-size: 12px; - padding: 0 12px; - height: 32px - } } } \ No newline at end of file diff --git a/front/core/components/submit/index.js b/front/core/components/submit/index.js new file mode 100644 index 000000000..ced73f0ba --- /dev/null +++ b/front/core/components/submit/index.js @@ -0,0 +1,13 @@ +import ngModule from '../../module'; +import Button from '../button'; + +export default class Controller extends Button { + constructor($element, $scope) { + super($element, $scope); + this.type = 'submit'; + } +} + +ngModule.vnComponent('vnSubmit', { + controller: Controller +}); diff --git a/front/core/components/submit/submit.html b/front/core/components/submit/submit.html deleted file mode 100644 index 6e77e4c16..000000000 --- a/front/core/components/submit/submit.html +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/front/core/components/submit/submit.js b/front/core/components/submit/submit.js deleted file mode 100644 index 41d63cf1d..000000000 --- a/front/core/components/submit/submit.js +++ /dev/null @@ -1,25 +0,0 @@ -import ngModule from '../../module'; -import Input from '../../lib/input'; - -export default class Controller extends Input { - constructor($element, $scope) { - super($element, $scope); - this.$element = $element; - this.input = $element[0].querySelector('input'); - } - - set disabled(value) { - this.input.disabled = value; - } -} - -Controller.$inject = ['$element', '$scope']; - -ngModule.component('vnSubmit', { - template: require('./submit.html'), - controller: Controller, - bindings: { - label: '@?', - disabled: ' span { font-size: $input-font-size; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } & > .btn { position: relative; diff --git a/front/core/components/tooltip/tooltip.js b/front/core/components/tooltip/tooltip.js index e0bc323eb..036ec6958 100644 --- a/front/core/components/tooltip/tooltip.js +++ b/front/core/components/tooltip/tooltip.js @@ -13,7 +13,7 @@ export default class Tooltip extends Component { constructor($element, $scope, $timeout) { super($element, $scope); this.$timeout = $timeout; - $element.addClass('vn-tooltip mdl-shadow--4dp'); + $element.addClass('vn-tooltip vn-shadow'); this.position = 'down'; this.margin = 10; } diff --git a/front/core/directives/acl.js b/front/core/directives/acl.js index f9df740cf..1cebddd42 100644 --- a/front/core/directives/acl.js +++ b/front/core/directives/acl.js @@ -1,110 +1,41 @@ import ngModule from '../module'; +import FormInput from '../components/form-input'; -function vnAcl(aclService, $timeout) { +function vnAcl(aclService) { let acls = []; - function getMaterialType(className) { - let type = ''; - if (className) { - type = className.replace('mdl-', '').replace('__input', ''); - type = type.charAt(0).toUpperCase() + type.slice(1); - } - return type; - } - function updateMaterial(input) { - if (input && input.className) { - let find = input.className.match(/mdl-[\w]+input/g); - if (find && find.length && find[0]) { - let type = getMaterialType(find[0]); - if (type && input.parentNode[`Material${type}`] && input.parentNode[`Material${type}`].updateClasses_) - input.parentNode[`Material${type}`].updateClasses_(); - } - } - } - function getDynamicConditions($attrs) { - let atributes = $attrs.$attr; - let conditions = {}; - - Object.keys(atributes).forEach(atribute => { - if (atribute.startsWith('aclConditionalTo')) { - let role = atributes[atribute].split('-').slice(-1)[0]; - conditions[atribute] = { - role: role - }; - } - }); - return conditions; - } - - function permissionElement($element, action) { - if (!aclService.hasAny(acls)) { - if (action === 'disabled') { - let element = $element[0]; - let selector = 'input, textarea, button, submit, md-checkbox'; - - if (element.$ctrl) { - element.setAttribute('disabled', 'true'); - element.$ctrl.disabled = true; - } - - if (!element.matches(selector)) - element = element.querySelector(selector); - - if (element) { - $timeout(() => { - element.setAttribute('disabled', 'true'); - updateMaterial(element); - }); - $element[0].querySelectorAll('vn-drop-down').forEach(element => { - element.parentNode.removeChild(element); - }); - } - } else - $element.remove(); - } - } - - function updateAcls(role, toAdd) { - let position = acls.indexOf(role); - - if (!toAdd && position > -1) - acls.splice(position, 1); - // XXX: add acl and enabled element if previusly was disabled - } - return { restrict: 'A', priority: -1, - link: function($scope, $element, $attrs) { + link: function(_, $element, $attrs) { acls = $attrs.vnAcl.split(',').map(i => i.trim()); if (acls[0] == '') return; - let action = $attrs.vnAclAction || 'disabled'; - let conditions = getDynamicConditions($attrs); + let action = $attrs.vnAclAction || 'disable'; - permissionElement($element, action); + if (aclService.hasAny(acls)) return; - if (Object.keys(conditions).length) { - let watchConditions = $scope.$watch(() => { - Object.keys(conditions).forEach(attrName => { - let hasPermission = $scope.$eval($attrs[attrName]); - if (!hasPermission) { - updateAcls(conditions[attrName].role, hasPermission); - permissionElement($element, action); - delete conditions[attrName]; - } - }); + if (action === 'disable') { + let element = $element[0]; + let elementToDisable = element.$ctrl; - if (Object.keys(conditions).length === 0) { - // unWacth - watchConditions(); - } - }); - } + if (!(elementToDisable instanceof FormInput)) { + let selector = 'input, textarea, button, submit'; + + if (!element.matches(selector)) + element = element.querySelector(selector); + + elementToDisable = element; + } + + if (elementToDisable) + elementToDisable.disabled = true; + } else + $element.remove(); } }; } -vnAcl.$inject = ['aclService', '$timeout']; +vnAcl.$inject = ['aclService']; ngModule.directive('vnAcl', vnAcl); diff --git a/front/core/directives/specs/acl.spec.js b/front/core/directives/specs/acl.spec.js index 523fb28bd..a7884a12d 100644 --- a/front/core/directives/specs/acl.spec.js +++ b/front/core/directives/specs/acl.spec.js @@ -1,54 +1,97 @@ describe('Directive acl', () => { - let scope; + let $scope; + let $element; let element; let compile; - let $timeout; beforeEach(angular.mock.module('vnCore', $translateProvider => { $translateProvider.translations('en', {}); })); - compile = (hasPermissions, _element) => { - inject(($compile, $rootScope, aclService, _$timeout_) => { - spyOn(aclService, 'hasAny').and.returnValue(hasPermissions); - scope = $rootScope.$new(); - $timeout = _$timeout_; - element = angular.element(_element); - $compile(element)(scope); - scope.$digest(); + beforeEach(inject(($httpBackend, aclService) => { + $httpBackend.whenGET('/api/Accounts/acl') + .respond({ + user: {id: 1, name: 'myUser'}, + roles: [ + {role: {name: 'myRole'}}, + {role: {name: 'myOtherRole'}} + ] + }); + aclService.load(); + $httpBackend.flush(); + })); + + afterEach(() => { + $element.remove(); + $scope.$destroy(); + }); + + compile = html => { + inject(($compile, $rootScope) => { + $scope = $rootScope.$new(); + $element = $compile(html)($scope); + $scope.$digest(); + element = $element[0]; }); }; - it('should not disable the input element as the user has permision', () => { - let html = `
`; - compile(true, html); - let input = element.find('input'); + it('should not disable the input element as the user owns the role', () => { + let html = ` +
+ +
+ `; + compile(html); + let input = element.querySelector('input'); - expect(input).toBeDefined(); - expect(input.attr('disabled')).toBeFalsy(); + expect(input.disabled).toBeFalsy(); }); - it('should delete the element as the user does not have permission and there is no action', () => { - let html = `
`; - compile(false, html); + it('should disable the element as the action is to disable and the user does not own the role', () => { + let html = ` +
+ +
+ `; + compile(html); + let input = element.querySelector('input'); - expect(element.children().length).toEqual(0); + expect(input.disabled).toBeTruthy(); }); - it('should disable the element as the action is to disable it but the user has no permission but present', () => { - let html = `
`; - compile(false, html); - let input = element.find('input'); - $timeout.flush(); + it('should keep the element as the action is to remove and the user owns the role', () => { + let html = ` +
+
+ +
+
+ `; + compile(html); + let div = element.querySelector('div'); - expect(input).toBeDefined(); - expect(input.attr('disabled')).toBeTruthy(); + expect(div).not.toBeNull(); }); - it('should delete any element with the tag vn-drop-down', () => { - let html = `
`; - compile(false, html); + it('should delete the element as the action is to remove and the user does not own the role', () => { + let html = ` +
+
+ +
+
+ `; + compile(html); + let div = element.querySelector('div'); - expect(element.find('vn-drop-down').length).toBe(0); + expect(div).toBeNull(); }); }); diff --git a/front/core/lib/input.js b/front/core/lib/input.js deleted file mode 100644 index b29d3fe37..000000000 --- a/front/core/lib/input.js +++ /dev/null @@ -1,42 +0,0 @@ -import Component from './component'; - -/** - * Component that host an input. - */ -export default class Input extends Component { - constructor($element, $scope) { - super($element, $scope); - this.input = this.element.querySelector('input'); - } - - set disabled(value) { - this.input.disabled = value == true; - this.mdlUpdate(); - } - - get disabled() { - return this.input.disabled; - } - - select() { - this.input.select(); - } - - focus() { - this.input.focus(); - } - - mdlUpdate() { - if (this.mdlElement) - this.mdlElement.updateClasses_(); - } -} -Input.$inject = ['$element', '$scope']; - -export const $options = { - bindings: { - label: '@?', - disabled: '=2.8.0 <3.0.0" - } - }, "angular-translate": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.1.tgz", @@ -83,11 +65,6 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, - "flatpickr": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz", - "integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA==" - }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -97,11 +74,6 @@ "esprima": "^4.0.0" } }, - "material-design-lite": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/material-design-lite/-/material-design-lite-1.3.0.tgz", - "integrity": "sha1-0ATOP+6Zoe63Sni4oyUTSl8RcdM=" - }, "mg-crud": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz", @@ -110,19 +82,6 @@ "angular": "^1.6.1" } }, - "moment": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" - }, - "moment-timezone": { - "version": "0.5.25", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.25.tgz", - "integrity": "sha512-DgEaTyN/z0HFaVcVbSyVCUU6HeFdnNC3vE4c9cgu2dgMTvjBUBdBzWfasTBmAW45u5OIMeCJtU8yNjM22DHucw==", - "requires": { - "moment": ">= 2.9.0" - } - }, "npm": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/npm/-/npm-6.11.3.tgz", diff --git a/front/package.json b/front/package.json index 82798b28c..e17dbd08c 100644 --- a/front/package.json +++ b/front/package.json @@ -12,16 +12,10 @@ "@babel/polyfill": "^7.2.5", "@uirouter/angularjs": "^1.0.20", "angular": "^1.7.5", - "angular-animate": "^1.7.7", - "angular-aria": "^1.7.7", - "angular-moment": "^1.3.0", "angular-translate": "^2.18.1", "angular-translate-loader-partial": "^2.18.1", - "flatpickr": "^4.5.2", "js-yaml": "^3.13.1", - "material-design-lite": "^1.3.0", "mg-crud": "^1.1.2", - "moment-timezone": "^0.5.25", "npm": "^6.11.3", "oclazyload": "^0.6.3", "require-yaml": "0.0.1", diff --git a/front/salix/components/app/style.scss b/front/salix/components/app/style.scss index 29c14fe0b..530524773 100644 --- a/front/salix/components/app/style.scss +++ b/front/salix/components/app/style.scss @@ -1,12 +1,5 @@ @import "variables"; -body { - background-color: $color-bg; - overflow: auto; - height: 100%; - font-family: vn-font; - color: $color-font; -} vn-app { height: inherit; display: block; @@ -104,37 +97,3 @@ vn-app { } } } -form vn-horizontal { - align-items: center; - - & > * { - box-sizing: border-box; - min-height: 2.8em; - padding: 0 $spacing-sm; - - &:first-child { - padding-left: 0; - padding-right: $spacing-xs; - } - &:last-child { - padding-left: $spacing-xs; - padding-right: 0; - } - &:first-child:last-child { - padding: 0; - } - } - - @media screen and (max-width: $mobile-width) { - flex-direction: column; - align-items: initial; - - & > * { - &, - &:first-child, - &:last-child { - padding: 0; - } - } - } -} \ No newline at end of file diff --git a/front/salix/components/descriptor/index.html b/front/salix/components/descriptor/index.html new file mode 100644 index 000000000..a3ee34563 --- /dev/null +++ b/front/salix/components/descriptor/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/front/salix/components/descriptor/index.js b/front/salix/components/descriptor/index.js index 423b033ce..504812b15 100644 --- a/front/salix/components/descriptor/index.js +++ b/front/salix/components/descriptor/index.js @@ -1 +1,12 @@ +import ngModule from '../../module'; import './style.scss'; + +export default class QuickLinks {} + +ngModule.component('vnQuickLinks', { + template: require('./index.html'), + controller: QuickLinks, + bindings: { + links: ' * { - min-width: 1.8em; @extend %clickable; + min-width: 45px; + height: 45px; + box-sizing: border-box; display: flex; align-items: center; justify-content: center; - padding: .5em; color: inherit; & > vn-icon { + padding: 10px; + } + vn-icon { font-size: 1.8em; } } @@ -55,28 +59,25 @@ } } } - & > .quicklinks { + .quicklinks, + vn-quick-links { display: flex; align-items: center; justify-content: center; - padding: 0; & > a { - padding: $spacing-sm; - + padding: 0 $spacing-md; + margin: 0 $spacing-sm; + & > vn-icon { font-size: 1.8em; padding: 0; - - & > i { - line-height: 36px - } } } } } } -vn-popover { +.vn-popover { .vn-descriptor > .header > a:first-child { visibility: hidden; } diff --git a/front/salix/components/home/home.html b/front/salix/components/home/home.html index fa9cd9d67..b6aaeced1 100644 --- a/front/salix/components/home/home.html +++ b/front/salix/components/home/home.html @@ -4,7 +4,7 @@ ng-repeat="mod in ::$ctrl.modules" ui-sref="{{::mod.route.state}}" translate-attr="::{title: mod.name}" - class="mdl-shadow--4dp"> + class="vn-shadow">
diff --git a/front/salix/components/index.js b/front/salix/components/index.js index ca37b21d1..5724231ed 100644 --- a/front/salix/components/index.js +++ b/front/salix/components/index.js @@ -1,11 +1,11 @@ import './app/app'; -import './login/login'; -import './home/home'; -import './main-menu/main-menu'; import './background/background'; -import './side-menu/side-menu'; -import './left-menu/left-menu'; -import './topbar/topbar'; -import './user-popover'; import './descriptor'; +import './home/home'; +import './left-menu/left-menu'; +import './login/login'; +import './main-menu/main-menu'; +import './topbar/topbar'; +import './side-menu/side-menu'; import './summary'; +import './user-popover'; diff --git a/front/salix/components/login/login.html b/front/salix/components/login/login.html index 73154222c..b15714a23 100644 --- a/front/salix/components/login/login.html +++ b/front/salix/components/login/login.html @@ -4,14 +4,12 @@ *:hover { - color: $color-main; + & > * { + transition: color 250ms ease-out; } & > #user { vertical-align: middle; @@ -20,12 +20,16 @@ vn-main-menu { margin-right: .2em; cursor: pointer; } - & > vn-icon-button { - font-size: 2.1em; + & > .vn-button { + font-size: 1.2em; color: inherit; padding: 0; margin-left: .3em; } + & > :hover { + color: $color-main; + opacity: 1; + } } } diff --git a/front/salix/components/summary/style.scss b/front/salix/components/summary/style.scss index c9a2b74ab..9fd85be3c 100644 --- a/front/salix/components/summary/style.scss +++ b/front/salix/components/summary/style.scss @@ -20,6 +20,7 @@ & > vn-horizontal { flex-wrap: wrap; padding: $spacing-md; + overflow: hidden; h4 { margin-bottom: $spacing-md; @@ -28,7 +29,7 @@ line-height: 1; padding: 7px; padding-bottom: 4px; /* Bottom line-height fix */ - font-family: unset; + font-weight: lighter; background-color: $color-main-light; border-bottom: .1em solid $color-main; white-space: nowrap; @@ -38,7 +39,6 @@ & > * { margin: $spacing-sm; min-width: 14em; - overflow: hidden; padding: 0; } & > vn-auto { diff --git a/front/salix/styles/misc.scss b/front/salix/styles/misc.scss index 8066759ac..6dcaab060 100644 --- a/front/salix/styles/misc.scss +++ b/front/salix/styles/misc.scss @@ -1,31 +1,43 @@ @import "./variables"; @import "./effects"; -html, body { - margin: 0; - padding: 0; +form vn-horizontal { + align-items: stretch; + + & > * { + box-sizing: border-box; + min-height: 2.8em; + padding: 0 $spacing-sm; + + &:first-child { + padding-left: 0; + padding-right: $spacing-xs; + } + &:last-child { + padding-left: $spacing-xs; + padding-right: 0; + } + &:first-child:last-child { + padding: 0; + } + } + + @media screen and (max-width: $mobile-width) { + flex-direction: column; + align-items: initial; + + & > * { + &, + &:first-child, + &:last-child { + padding: 0; + } + } + } } -a:focus, -input:focus, -button:focus { - outline: none; -} -button::-moz-focus-inner, -input[type=submit]::-moz-focus-inner, -input[type=button]::-moz-focus-inner, -input[type=reset]::-moz-focus-inner { - border: none; -} -.unselectable { - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; -} -a, .link { + +.link { color: $color-font-link; - text-decoration: none; - outline: 0 } .link { cursor: pointer; @@ -34,6 +46,12 @@ a, .link { text-decoration: underline; } } +.unselectable { + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} vn-bg-title { display: block; text-align: center; @@ -77,9 +95,6 @@ html [pointer], .pointer{ html [noDrop], .noDrop{ cursor: no-drop; } -button { - @extend %clickable; -} vn-button-bar { display: block; margin-top: $spacing-sm; @@ -91,9 +106,6 @@ vn-tool-bar { margin-right: .6em; } } -input[type="submit"]:disabled, button:disabled { - opacity: 0.7; -} html [scrollable] { min-height: 1px; flex: 1; diff --git a/modules/agency/front/index/index.html b/modules/agency/front/index/index.html index cfe39c7f1..c2cd52faa 100644 --- a/modules/agency/front/index/index.html +++ b/modules/agency/front/index/index.html @@ -80,7 +80,8 @@ vn-tooltip="New zone" vn-bind="+" fixed-bottom-right> - diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 65467d349..b502cf020 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -28,16 +28,18 @@ ng-click="$ctrl.showLastTickets($event)" vn-tooltip="Imports ticket lines"> - - + diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html index 24efcc0fb..431989bbd 100644 --- a/modules/claim/front/descriptor/index.html +++ b/modules/claim/front/descriptor/index.html @@ -42,32 +42,9 @@ value="{{$ctrl.claim.ticketFk}}">
- + +
-
- + tabindex="-1" + icon="delete"> +
diff --git a/modules/claim/front/summary/index.html b/modules/claim/front/summary/index.html index 314d71bc9..46600c0da 100644 --- a/modules/claim/front/summary/index.html +++ b/modules/claim/front/summary/index.html @@ -30,16 +30,18 @@ - - +

Detail

diff --git a/modules/client/front/address/create/index.html b/modules/client/front/address/create/index.html index 8c30f9929..30e49590c 100644 --- a/modules/client/front/address/create/index.html +++ b/modules/client/front/address/create/index.html @@ -119,12 +119,10 @@ - + diff --git a/modules/client/front/basic-data/index.html b/modules/client/front/basic-data/index.html index eed8277af..ce80ea5a6 100644 --- a/modules/client/front/basic-data/index.html +++ b/modules/client/front/basic-data/index.html @@ -5,70 +5,68 @@ form="form" save="patch"> -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/client/front/credit-insurance/insurance/create/index.html b/modules/client/front/credit-insurance/insurance/create/index.html index f652f6011..a28fb605b 100644 --- a/modules/client/front/credit-insurance/insurance/create/index.html +++ b/modules/client/front/credit-insurance/insurance/create/index.html @@ -35,9 +35,9 @@ - + + \ No newline at end of file diff --git a/modules/client/front/descriptor/index.html b/modules/client/front/descriptor/index.html index 84f3ca10e..32d785fe3 100644 --- a/modules/client/front/descriptor/index.html +++ b/modules/client/front/descriptor/index.html @@ -63,31 +63,8 @@ ng-class="{bright: $ctrl.client.isTaxDataChecked == false}">
- + +
\ No newline at end of file diff --git a/modules/invoiceOut/front/descriptor/index.html b/modules/invoiceOut/front/descriptor/index.html index 211560d28..3960c3925 100644 --- a/modules/invoiceOut/front/descriptor/index.html +++ b/modules/invoiceOut/front/descriptor/index.html @@ -33,24 +33,9 @@ value="{{$ctrl.invoiceOut.company.code}}">
- + +
- - + + + + diff --git a/modules/item/front/descriptor/index.html b/modules/item/front/descriptor/index.html index cd12c253f..e273b02e4 100644 --- a/modules/item/front/descriptor/index.html +++ b/modules/item/front/descriptor/index.html @@ -64,32 +64,9 @@ ng-class="{bright: $ctrl.item.isActive == false}"> - + +
- +
- + + - +
+ class="colored"> {{$ctrl.category.value}} + class="colored"> {{$ctrl.type.value}} + class="colored"> {{::tag.value}} - +
\ No newline at end of file diff --git a/modules/order/front/filter/style.scss b/modules/order/front/filter/style.scss index 52125ace6..0cac5765f 100644 --- a/modules/order/front/filter/style.scss +++ b/modules/order/front/filter/style.scss @@ -39,10 +39,12 @@ vn-catalog-filter > div { } } .chips { + display: flex; flex-wrap: wrap; padding: $spacing-md; + overflow: hidden; + max-width: 100%; } - vn-autocomplete[vn-id="type"] .list { max-height: 20em } diff --git a/modules/order/front/prices-popover/index.html b/modules/order/front/prices-popover/index.html index 3a7f34462..a88e027ac 100644 --- a/modules/order/front/prices-popover/index.html +++ b/modules/order/front/prices-popover/index.html @@ -1,13 +1,11 @@
- - - + - +
@@ -74,32 +72,9 @@ - + +
- + +
-