#7346 manualInvoice #793
CHANGELOG.mdcypress.config.jspackage.jsonpnpm-lock.yaml
src
boot
components
CreateBankEntityForm.vueCreateNewPostcodeForm.vueCreateNewProvinceForm.vueCreateThermographForm.vueFilterItemForm.vueFilterTravelForm.vueFormModel.vueFormModelPopup.vueItemsFilterPanel.vueLeftMenu.vueNavBar.vue
VnTable
common
VnBtnSelect.vueVnChangePassword.vueVnComponent.vueVnDate.vueVnDms.vueVnInput.vueVnInputDate.vueVnInputNumber.vueVnInputTime.vueVnLocation.vueVnProgressModal.vueVnRadio.vueVnSelect.vueVnTime.vueVnTitle.vue
ui
composables
css
filters
i18n/locale
layouts
pages
180
CHANGELOG.md
180
CHANGELOG.md
|
@ -1,3 +1,183 @@
|
|||
# Version 24.40 - 2024-10-02
|
||||
|
||||
### Added 🆕
|
||||
|
||||
- chore: refs #4074 admit several acls by:jorgep
|
||||
- chore: refs #4074 drop workerCreate by:jorgep
|
||||
- chore: refs #4074 fix tests by:jorgep
|
||||
- chore: refs #4074 wip replace useRole for useAcl by:jorgep
|
||||
- chore: refs #7155 remove console.log by:alexm
|
||||
- chore: refs #7155 typo by:alexm
|
||||
- chore: refs #7663 add test by:jorgep
|
||||
- chore: refs #7663 create test wip by:jorgep
|
||||
- chore: refs #7663 drop useless code (origin/7663-setWeight) by:jorgep
|
||||
- chore: refs #7828 fix e2e by:jorgep
|
||||
- feat(AccountBasicData): add twoFactorFk by:alexm
|
||||
- feat: add max rule by:Javier Segarra
|
||||
- feat: add shortcut add event in some subSections by:Javier Segarra
|
||||
- feat: add shortcut more buttons (origin/add_shortcut_add_subSections) by:Javier Segarra
|
||||
- feat: add tooltip CustomerNewCustomAgent by:Javier Segarra
|
||||
- feat: apply color when today by:Javier Segarra
|
||||
- feat: change label because its more natural by:Javier Segarra
|
||||
- feat: change order by:Javier Segarra
|
||||
- feat: change QBadge color by:Javier Segarra
|
||||
- feat: change url CustomerList by:Javier Segarra
|
||||
- feat: copy customer countryFk by:Javier Segarra
|
||||
- feat: create VnSelectEnum and add in AccountBasicData and ClaimBasicData by:alexm
|
||||
- feat: CustomerBalance by:Javier Segarra
|
||||
- feat: CustomerConsumptionFilter by:Javier Segarra
|
||||
- feat: customer consumption (origin/7830-customerDesplegables, 7830-customerDesplegables) by:alexm
|
||||
- feat: CustomerCreateTicket by:Javier Segarra
|
||||
- feat: CustomerCredit section by:Javier Segarra
|
||||
- feat: CustomerGreuges by:Javier Segarra
|
||||
- feat: CustomerSample to VnTable by:Javier Segarra
|
||||
- feat: global handler (origin/fix_global_handler, fix_global_handler) by:alexm
|
||||
- feat: goToSupplier by:Javier Segarra
|
||||
- feat: handle newValue by:Javier Segarra
|
||||
- feat: handle same multiple CP by:Javier Segarra
|
||||
- feat: hide menus on small view (origin/hideMenu) by:jorgep
|
||||
- feat: minor changes by:Javier Segarra
|
||||
- feat: orderCreateDialog by:Javier Segarra
|
||||
- feat: refs #4074 drop useless code by:jorgep
|
||||
- feat: refs #4074 useAcl in vnSelectDialog by:jorgep
|
||||
- feat: refs #6346 new wagon type section by:Jon
|
||||
- feat: refs #7404 add m3 and fix detail by:pablone
|
||||
- feat: refs #7404 add some style to the form and reorganize fields by:pablone
|
||||
- feat: refs #7404 add travel m3 to reserves form by:pablone
|
||||
- feat: refs #7404 style dynamic text color by:pablone
|
||||
- feat: refs #7404 travel m3 form by:pablone
|
||||
- feat: refs #7500 added VnImg to show files by:Jon
|
||||
- feat: refs #7663 add setWeight menu opt (wip) by:jorgep
|
||||
- feat: refs #7663 fine tunning by:jorgep
|
||||
- feat: refs #7828 create axios instance which no manage errors (origin/7828-makeCorrectCalls) by:jorgep
|
||||
- feat: refs #7828 useAcl & cherry pick mail data worker by:jorgep
|
||||
- feat: remove cli warnings by:Javier Segarra
|
||||
- feat: show preparation field by:Javier Segarra
|
||||
- feat: stateGroupedFilter by:Javier Segarra
|
||||
- feat: translations fixed by:jgallego
|
||||
- feat(TravelList): add daysOnward by:alexm
|
||||
- feat: travel m3 by:pablone
|
||||
- feat: use disableInifiniteScroll property by:Javier Segarra
|
||||
- feat: VnImg draggable by:Javier Segarra
|
||||
- feat: vnLocation changes by:Javier Segarra
|
||||
- feat: vnSelect exprBuilder by:Javier Segarra
|
||||
- fix: refs #7404 remove some style by:pablone
|
||||
- fix: refs #7404 style non center pop up (origin/7404-fixFront) by:pablone
|
||||
- fix: refs #7404 translates and some minor style fixes by:pablone
|
||||
- fix: styles by:Javier Segarra
|
||||
- perf: improve style by:Javier Segarra
|
||||
|
||||
### Changed 📦
|
||||
|
||||
- perf: CustomerBalance by:Javier Segarra
|
||||
- perf: CustomerBasicData by:Javier Segarra
|
||||
- perf: CustomerBasicData.salesPersonFk by:Javier Segarra
|
||||
- perf: CustomerSummary by:Javier Segarra
|
||||
- perf: customerSummaryTable by:Javier Segarra
|
||||
- perf: disable card option by:Javier Segarra
|
||||
- perf: i18n by:Javier Segarra
|
||||
- perf: improve by:Javier Segarra
|
||||
- perf: improve style by:Javier Segarra
|
||||
- perf: imrpove exprBuilder by:Javier Segarra
|
||||
- perf: minor comments by:Javier Segarra
|
||||
- perf: refs #6346 previous changes by:Jon
|
||||
- perf: sendEmail customerConsumption by:Javier Segarra
|
||||
- perf: solve reload CardSummary component by:Javier Segarra
|
||||
- perf: update CustommerDescriptor by:Javier Segarra
|
||||
- refactor: refs #4074 accept array by:jorgep
|
||||
- refactor: refs #4074 rollback by:jorgep
|
||||
- refactor: refs #4074 use acl & drop useless roles by:jorgep
|
||||
- refactor: refs #4074 useAcl in navigationStore & router by:jorgep
|
||||
- refactor: refs #4074 use fn (origin/4074-useAcls) by:jorgep
|
||||
- refactor: refs #4074 use VnTitle by:jorgep
|
||||
- refactor: refs #6346 deleted front error checking by:Jon
|
||||
- refactor: refs #6346 requested changes by:Jon
|
||||
- refactor: refs #6346 wagons to VnTable by:Jon
|
||||
- refactor: refs #7500 deleted useless code by:Jon
|
||||
- refactor: refs #7500 refactor vnimg when storage is dms by:Jon
|
||||
- refactor: refs #7828 wip by:jorgep
|
||||
|
||||
### Fixed 🛠️
|
||||
|
||||
- chore: refs #4074 fix tests by:jorgep
|
||||
- chore: refs #7828 fix e2e by:jorgep
|
||||
- feat: refs #7404 add m3 and fix detail by:pablone
|
||||
- feat: translations fixed by:jgallego
|
||||
- fix: #5938 grouped filter by:Javier Segarra
|
||||
- fix: #6943 fix customerSummaryTable by:Javier Segarra
|
||||
- fix: #6943 show nickname salesPerson by:Javier Segarra
|
||||
- fix: address-create i18n by:Javier Segarra
|
||||
- fix: comments (origin/6943_fix_customer_module, 6943_fix_customer_module) by:Javier Segarra
|
||||
- fix: CusomerSummary to Address by:Javier Segarra
|
||||
- fix: CustomerAddress mobile by:Javier Segarra
|
||||
- fix: CustomerBillingData by:Javier Segarra
|
||||
- fix: Customerconsumption by:Javier Segarra
|
||||
- fix: customer credit opinion by:alexm
|
||||
- fix: CustomerCreditOpinion workerDescriptor by:Javier Segarra
|
||||
- fix: CustomerDescriptorAccount by:Javier Segarra
|
||||
- fix: CustomerDescriptor.bussinessTypeFk by:Javier Segarra
|
||||
- fix: CustomerFilter by:Javier Segarra
|
||||
- fix: CustomerGreuges by:Javier Segarra
|
||||
- fix: CustomerMandates by:Javier Segarra
|
||||
- fix: Customer module find salesPersons out of first get by:Javier Segarra
|
||||
- fix: CustomerRecovery transalate label by:Javier Segarra
|
||||
- fix: CustomerSamples by:Javier Segarra
|
||||
- fix: customerSummaryToTicketList button by:Javier Segarra
|
||||
- fix: CustomerWebPayment by:Javier Segarra
|
||||
- fix: CustommerSummaryTable Proxy by:Javier Segarra
|
||||
- fix: deleted code by:Jon
|
||||
- fix: duplicate code by:alexm
|
||||
- fix: emit:updateModelValue by:Javier Segarra
|
||||
- fix: fixed wagon tests by:Jon
|
||||
- fix: fix wagon list reload by:Jon
|
||||
- fix: i18n en preparation label by:Javier Segarra
|
||||
- fix: infiniteScroll by:Javier Segarra
|
||||
- fix: isFullMovable checkbox by:Javier Segarra
|
||||
- fix: merge conflicts by:Javier Segarra
|
||||
- fix: merge in dev by:alexm
|
||||
- fix: missing code by:Jon
|
||||
- fix: Options VnSelect properties by:Javier Segarra
|
||||
- fix: refs #4074 await to watch by:jorgep
|
||||
- fix: refs #4074 drop wrong acl by:jorgep
|
||||
- fix: refs #4074 workerCard data-key by:jorgep
|
||||
- fix: refs #6346 fix list and create by:pablone
|
||||
- fix: refs #6943 prevent null (origin/6943-warmfix-preventNull) by:jorgep
|
||||
- fix: refs #7155 remove userParams in watcher (7155-travel_daysOnward) by:alexm
|
||||
- fix: refs #7155 use chip-locale (origin/7155-travel_daysOnward_2, 7155-travel_daysOnward_2) by:alexm
|
||||
- fix: refs #7404 remove console.log by:pablone
|
||||
- fix: refs #7404 remove from test by:pablone
|
||||
- fix: refs #7404 remove some style by:pablone
|
||||
- fix: refs #7404 revert commit prevent production access by:pablone
|
||||
- fix: refs #7404 style non center pop up (origin/7404-fixFront) by:pablone
|
||||
- fix: refs #7404 translates and some minor style fixes by:pablone
|
||||
- fix: refs #7500 fixed e2e test by:Jon
|
||||
- fix: refs #7500 fixed showing images wrongly by:Jon
|
||||
- fix: refs #7830 customer credit by:pablone
|
||||
- fix: refs #7830 remove console.log by:pablone
|
||||
- fix: remove console.log by:pablone
|
||||
- fix: remove FetchData by:Javier Segarra
|
||||
- fix: remove FIXME (origin/6943_fix_customerSummaryTable) by:Javier Segarra
|
||||
- fix: remove print variable by:Javier Segarra
|
||||
- fix: remove promise execution by:Javier Segarra
|
||||
- fix: reset VnTable scroll properties by:Javier Segarra
|
||||
- fix: rule by:Javier Segarra
|
||||
- fix: solve conflicts from master to test by:Javier Segarra
|
||||
- fix: split params (origin/warmfix-addSearchUrl) by:jorgep
|
||||
- fix: state cell by:Javier Segarra
|
||||
- fix: stop call back event hasMoreData by:Javier Segarra
|
||||
- fix: styles by:Javier Segarra
|
||||
- fix: SupplierFiscalData VnLocation (origin/fix_supplierFD_location) by:Javier Segarra
|
||||
- fix: VnLocation test by:Javier Segarra
|
||||
- fix(VnTable): header background-color by:alexm
|
||||
- fix(VnTable): sanitizer value is defined by:carlossa
|
||||
- fix: wagon reload (origin/FixWagonRedirect) by:Jon
|
||||
- fix: workerDms filter workerFk by:alexm
|
||||
- fix(WorkerList): add type email by:alexm
|
||||
- Merge remote-tracking branch 'origin/7830-customerDesplegables' into 6943_fix_customerSummaryTable by:Javier Segarra
|
||||
- refs #7155 scopeDays fix (origin/7155-scopeDays) by:carlossa
|
||||
- revert: vnUSerLink change by:Javier Segarra
|
||||
- test: fix test (7677_vnLocation_perf) by:Javier Segarra
|
||||
|
||||
# Version 24.38 - 2024-09-17
|
||||
|
||||
### Added 🆕
|
||||
|
|
|
@ -11,12 +11,22 @@ module.exports = defineConfig({
|
|||
video: false,
|
||||
specPattern: 'test/cypress/integration/**/*.spec.js',
|
||||
experimentalRunAllSpecs: true,
|
||||
watchForFileChanges: true,
|
||||
reporter: 'cypress-mochawesome-reporter',
|
||||
reporterOptions: {
|
||||
charts: true,
|
||||
reportPageTitle: 'Cypress Inline Reporter',
|
||||
embeddedScreenshots: true,
|
||||
reportDir: 'test/cypress/reports',
|
||||
inlineAssets: true,
|
||||
},
|
||||
component: {
|
||||
componentFolder: 'src',
|
||||
testFiles: '**/*.spec.js',
|
||||
supportFile: 'test/cypress/support/unit.js',
|
||||
},
|
||||
setupNodeEvents(on, config) {
|
||||
require('cypress-mochawesome-reporter/plugin')(on);
|
||||
// implement node event listeners here
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
{
|
||||
"name": "salix-front",
|
||||
"version": "24.42.0",
|
||||
"version": "24.44.0",
|
||||
"description": "Salix frontend",
|
||||
"productName": "Salix",
|
||||
"author": "Verdnatura",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@8.15.1",
|
||||
"scripts": {
|
||||
"resetDatabase": "cd ../salix && gulp docker",
|
||||
"lint": "eslint --ext .js,.vue ./",
|
||||
"format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
|
||||
"test:e2e": "cypress open",
|
||||
"test:e2e:ci": "cd ../salix && gulp docker && cd ../salix-front && cypress run",
|
||||
"test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run",
|
||||
"test": "echo \"See package.json => scripts for available tests.\" && exit 0",
|
||||
"test:unit": "vitest",
|
||||
"test:unit:ci": "vitest run",
|
||||
|
@ -42,6 +43,7 @@
|
|||
"@vue/test-utils": "^2.4.4",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"cypress": "^13.6.6",
|
||||
"cypress-mochawesome-reporter": "^3.8.2",
|
||||
"eslint": "^8.41.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-plugin-cypress": "^2.13.3",
|
||||
|
|
379
pnpm-lock.yaml
379
pnpm-lock.yaml
|
@ -70,6 +70,9 @@ devDependencies:
|
|||
cypress:
|
||||
specifier: ^13.6.6
|
||||
version: 13.6.6
|
||||
cypress-mochawesome-reporter:
|
||||
specifier: ^3.8.2
|
||||
version: 3.8.2(cypress@13.6.6)(mocha@10.7.3)
|
||||
eslint:
|
||||
specifier: ^8.41.0
|
||||
version: 8.56.0
|
||||
|
@ -829,8 +832,8 @@ packages:
|
|||
vue-i18n:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 10.0.0-beta.5
|
||||
'@intlify/shared': 10.0.0-beta.5
|
||||
'@intlify/message-compiler': 10.0.0
|
||||
'@intlify/shared': 10.0.0
|
||||
jsonc-eslint-parser: 1.4.1
|
||||
source-map: 0.6.1
|
||||
vue-i18n: 9.9.1(vue@3.4.19)
|
||||
|
@ -844,11 +847,11 @@ packages:
|
|||
'@intlify/message-compiler': 9.9.1
|
||||
'@intlify/shared': 9.9.1
|
||||
|
||||
/@intlify/message-compiler@10.0.0-beta.5:
|
||||
resolution: {integrity: sha512-hLLchnM1dmtSEruerkzvU9vePsLqBXz3RU85SCx/Vd12fFQiymP+/5Rn9MJ8MyfLmIOLDEx4PRh+/GkIQP6oog==}
|
||||
/@intlify/message-compiler@10.0.0:
|
||||
resolution: {integrity: sha512-OcaWc63NC/9p1cMdgoNKBj4d61BH8sUW1Hfs6YijTd9656ZR4rNqXAlRnBrfS5ABq0vjQjpa8VnyvH9hK49yBw==}
|
||||
engines: {node: '>= 16'}
|
||||
dependencies:
|
||||
'@intlify/shared': 10.0.0-beta.5
|
||||
'@intlify/shared': 10.0.0
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
|
@ -859,8 +862,8 @@ packages:
|
|||
'@intlify/shared': 9.9.1
|
||||
source-map-js: 1.0.2
|
||||
|
||||
/@intlify/shared@10.0.0-beta.5:
|
||||
resolution: {integrity: sha512-g9bq5Y1bOcC9qxtNk4UWtF3sXm6Wh0fGISb7vD5aLyF7yQv7ZFjxQjJzBP2GqG/9+PAGYutqjP1GGadNqFtyAQ==}
|
||||
/@intlify/shared@10.0.0:
|
||||
resolution: {integrity: sha512-6ngLfI7DOTew2dcF9WMJx+NnMWghMBhIiHbGg+wRvngpzD5KZJZiJVuzMsUQE1a5YebEmtpTEfUrDp/NqVGdiw==}
|
||||
engines: {node: '>= 16'}
|
||||
dev: true
|
||||
|
||||
|
@ -884,7 +887,7 @@ packages:
|
|||
optional: true
|
||||
dependencies:
|
||||
'@intlify/bundle-utils': 4.0.0(vue-i18n@9.9.1)
|
||||
'@intlify/shared': 10.0.0-beta.5
|
||||
'@intlify/shared': 10.0.0
|
||||
'@rollup/pluginutils': 4.2.1
|
||||
'@vue/compiler-sfc': 3.4.19
|
||||
debug: 4.3.4(supports-color@8.1.1)
|
||||
|
@ -1999,6 +2002,10 @@ packages:
|
|||
dependencies:
|
||||
fill-range: 7.0.1
|
||||
|
||||
/browser-stdout@1.3.1:
|
||||
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
|
||||
dev: true
|
||||
|
||||
/browserslist@4.23.0:
|
||||
resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
|
@ -2106,6 +2113,16 @@ packages:
|
|||
upper-case: 1.1.3
|
||||
dev: true
|
||||
|
||||
/camelcase@5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/camelcase@6.3.0:
|
||||
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/camelcase@7.0.1:
|
||||
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
@ -2255,6 +2272,22 @@ packages:
|
|||
engines: {node: '>= 10'}
|
||||
dev: true
|
||||
|
||||
/cliui@6.0.0:
|
||||
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 6.2.0
|
||||
dev: true
|
||||
|
||||
/cliui@7.0.4:
|
||||
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 7.0.0
|
||||
dev: true
|
||||
|
||||
/cliui@8.0.1:
|
||||
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
@ -2558,6 +2591,23 @@ packages:
|
|||
/csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
/cypress-mochawesome-reporter@3.8.2(cypress@13.6.6)(mocha@10.7.3):
|
||||
resolution: {integrity: sha512-oJZkNzhNmN9ZD+LmZyFuPb8aWaIijyHyqYh52YOBvR6B6ckfJNCHP3A98a+/nG0H4t46CKTNwo+wNpMa4d2kjA==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
cypress: '>=6.2.0'
|
||||
dependencies:
|
||||
commander: 10.0.1
|
||||
cypress: 13.6.6
|
||||
fs-extra: 10.1.0
|
||||
mochawesome: 7.1.3(mocha@10.7.3)
|
||||
mochawesome-merge: 4.3.0
|
||||
mochawesome-report-generator: 6.2.0
|
||||
transitivePeerDependencies:
|
||||
- mocha
|
||||
dev: true
|
||||
|
||||
/cypress@13.6.6:
|
||||
resolution: {integrity: sha512-S+2S9S94611hXimH9a3EAYt81QM913ZVA03pUmGDfLTFa5gyp85NJ8dJGSlEAEmyRsYkioS1TtnWtbv/Fzt11A==}
|
||||
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
|
||||
|
@ -2627,6 +2677,10 @@ packages:
|
|||
time-zone: 1.0.0
|
||||
dev: true
|
||||
|
||||
/dateformat@4.6.3:
|
||||
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
|
||||
dev: true
|
||||
|
||||
/dayjs@1.11.10:
|
||||
resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
|
||||
dev: true
|
||||
|
@ -2676,6 +2730,29 @@ packages:
|
|||
ms: 2.1.2
|
||||
supports-color: 8.1.1
|
||||
|
||||
/debug@4.3.7(supports-color@8.1.1):
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
supports-color: 8.1.1
|
||||
dev: true
|
||||
|
||||
/decamelize@1.2.0:
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/decamelize@4.0.0:
|
||||
resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/decompress-response@6.0.0:
|
||||
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -2758,6 +2835,11 @@ packages:
|
|||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
|
||||
/diff@5.2.0:
|
||||
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
dev: true
|
||||
|
||||
/doctrine@3.0.0:
|
||||
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -3550,6 +3632,14 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
locate-path: 5.0.0
|
||||
path-exists: 4.0.0
|
||||
dev: true
|
||||
|
||||
/find-up@5.0.0:
|
||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -3646,6 +3736,15 @@ packages:
|
|||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
dev: true
|
||||
|
||||
/fs-extra@10.1.0:
|
||||
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
jsonfile: 6.1.0
|
||||
universalify: 2.0.1
|
||||
dev: true
|
||||
|
||||
/fs-extra@11.2.0:
|
||||
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
|
||||
engines: {node: '>=14.14'}
|
||||
|
@ -3654,6 +3753,15 @@ packages:
|
|||
jsonfile: 6.1.0
|
||||
universalify: 2.0.1
|
||||
|
||||
/fs-extra@7.0.1:
|
||||
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
|
||||
engines: {node: '>=6 <7 || >=8'}
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
jsonfile: 4.0.0
|
||||
universalify: 0.1.2
|
||||
dev: true
|
||||
|
||||
/fs-extra@9.1.0:
|
||||
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -3675,6 +3783,10 @@ packages:
|
|||
dev: true
|
||||
optional: true
|
||||
|
||||
/fsu@1.1.1:
|
||||
resolution: {integrity: sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==}
|
||||
dev: true
|
||||
|
||||
/function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
|
@ -3775,6 +3887,18 @@ packages:
|
|||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
/glob@8.1.0:
|
||||
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
|
||||
engines: {node: '>=12'}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 5.1.6
|
||||
once: 1.4.0
|
||||
dev: true
|
||||
|
||||
/global-directory@4.0.1:
|
||||
resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
@ -4189,6 +4313,11 @@ packages:
|
|||
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/is-plain-obj@2.1.0:
|
||||
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-plain-obj@3.0.0:
|
||||
resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -4361,6 +4490,12 @@ packages:
|
|||
resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==}
|
||||
dev: true
|
||||
|
||||
/jsonfile@4.0.0:
|
||||
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
dev: true
|
||||
|
||||
/jsonfile@6.1.0:
|
||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||
dependencies:
|
||||
|
@ -4452,6 +4587,13 @@ packages:
|
|||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/locate-path@5.0.0:
|
||||
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
p-locate: 4.1.0
|
||||
dev: true
|
||||
|
||||
/locate-path@6.0.0:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -4486,10 +4628,26 @@ packages:
|
|||
resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==}
|
||||
dev: true
|
||||
|
||||
/lodash.isempty@4.4.0:
|
||||
resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==}
|
||||
dev: true
|
||||
|
||||
/lodash.isfunction@3.0.9:
|
||||
resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==}
|
||||
dev: true
|
||||
|
||||
/lodash.isobject@3.0.2:
|
||||
resolution: {integrity: sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==}
|
||||
dev: true
|
||||
|
||||
/lodash.isplainobject@4.0.6:
|
||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||
dev: true
|
||||
|
||||
/lodash.isstring@4.0.1:
|
||||
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||
dev: true
|
||||
|
||||
/lodash.kebabcase@4.1.1:
|
||||
resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==}
|
||||
dev: true
|
||||
|
@ -4552,6 +4710,13 @@ packages:
|
|||
wrap-ansi: 6.2.0
|
||||
dev: true
|
||||
|
||||
/loose-envify@1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/loupe@2.3.7:
|
||||
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
|
||||
dependencies:
|
||||
|
@ -4722,6 +4887,79 @@ packages:
|
|||
ufo: 1.4.0
|
||||
dev: true
|
||||
|
||||
/mocha@10.7.3:
|
||||
resolution: {integrity: sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==}
|
||||
engines: {node: '>= 14.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
ansi-colors: 4.1.3
|
||||
browser-stdout: 1.3.1
|
||||
chokidar: 3.6.0
|
||||
debug: 4.3.7(supports-color@8.1.1)
|
||||
diff: 5.2.0
|
||||
escape-string-regexp: 4.0.0
|
||||
find-up: 5.0.0
|
||||
glob: 8.1.0
|
||||
he: 1.2.0
|
||||
js-yaml: 4.1.0
|
||||
log-symbols: 4.1.0
|
||||
minimatch: 5.1.6
|
||||
ms: 2.1.3
|
||||
serialize-javascript: 6.0.2
|
||||
strip-json-comments: 3.1.1
|
||||
supports-color: 8.1.1
|
||||
workerpool: 6.5.1
|
||||
yargs: 16.2.0
|
||||
yargs-parser: 20.2.9
|
||||
yargs-unparser: 2.0.0
|
||||
dev: true
|
||||
|
||||
/mochawesome-merge@4.3.0:
|
||||
resolution: {integrity: sha512-1roR6g+VUlfdaRmL8dCiVpKiaUhbPVm1ZQYUM6zHX46mWk+tpsKVZR6ba98k2zc8nlPvYd71yn5gyH970pKBSw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
fs-extra: 7.0.1
|
||||
glob: 7.2.3
|
||||
yargs: 15.4.1
|
||||
dev: true
|
||||
|
||||
/mochawesome-report-generator@6.2.0:
|
||||
resolution: {integrity: sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
dateformat: 4.6.3
|
||||
escape-html: 1.0.3
|
||||
fs-extra: 10.1.0
|
||||
fsu: 1.1.1
|
||||
lodash.isfunction: 3.0.9
|
||||
opener: 1.5.2
|
||||
prop-types: 15.8.1
|
||||
tcomb: 3.2.29
|
||||
tcomb-validation: 3.4.1
|
||||
validator: 13.11.0
|
||||
yargs: 17.7.2
|
||||
dev: true
|
||||
|
||||
/mochawesome@7.1.3(mocha@10.7.3):
|
||||
resolution: {integrity: sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==}
|
||||
peerDependencies:
|
||||
mocha: '>=7'
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
diff: 5.2.0
|
||||
json-stringify-safe: 5.0.1
|
||||
lodash.isempty: 4.4.0
|
||||
lodash.isfunction: 3.0.9
|
||||
lodash.isobject: 3.0.2
|
||||
lodash.isstring: 4.0.1
|
||||
mocha: 10.7.3
|
||||
mochawesome-report-generator: 6.2.0
|
||||
strip-ansi: 6.0.1
|
||||
uuid: 8.3.2
|
||||
dev: true
|
||||
|
||||
/ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
|
||||
|
@ -4870,6 +5108,11 @@ packages:
|
|||
is-wsl: 2.2.0
|
||||
dev: false
|
||||
|
||||
/opener@1.5.2:
|
||||
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/optionator@0.9.3:
|
||||
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
@ -4915,6 +5158,13 @@ packages:
|
|||
engines: {node: '>=12.20'}
|
||||
dev: false
|
||||
|
||||
/p-limit@2.3.0:
|
||||
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
p-try: 2.2.0
|
||||
dev: true
|
||||
|
||||
/p-limit@3.1.0:
|
||||
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -4929,6 +5179,13 @@ packages:
|
|||
yocto-queue: 1.0.0
|
||||
dev: true
|
||||
|
||||
/p-locate@4.1.0:
|
||||
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
p-limit: 2.3.0
|
||||
dev: true
|
||||
|
||||
/p-locate@5.0.0:
|
||||
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -4950,6 +5207,11 @@ packages:
|
|||
aggregate-error: 3.1.0
|
||||
dev: true
|
||||
|
||||
/p-try@2.2.0:
|
||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/package-json@8.1.1:
|
||||
resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
@ -5139,6 +5401,14 @@ packages:
|
|||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/prop-types@15.8.1:
|
||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
object-assign: 4.1.1
|
||||
react-is: 16.13.1
|
||||
dev: true
|
||||
|
||||
/proto-list@1.2.4:
|
||||
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
|
||||
|
||||
|
@ -5242,6 +5512,10 @@ packages:
|
|||
strip-json-comments: 2.0.1
|
||||
dev: false
|
||||
|
||||
/react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
dev: true
|
||||
|
||||
/react-is@17.0.2:
|
||||
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
||||
dev: true
|
||||
|
@ -5328,6 +5602,10 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/require-main-filename@2.0.0:
|
||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
||||
dev: true
|
||||
|
||||
/requires-port@1.0.0:
|
||||
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
|
||||
|
||||
|
@ -5573,6 +5851,10 @@ packages:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
dev: true
|
||||
|
||||
/set-function-length@1.2.1:
|
||||
resolution: {integrity: sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
@ -5829,6 +6111,16 @@ packages:
|
|||
readable-stream: 3.6.2
|
||||
dev: true
|
||||
|
||||
/tcomb-validation@3.4.1:
|
||||
resolution: {integrity: sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==}
|
||||
dependencies:
|
||||
tcomb: 3.2.29
|
||||
dev: true
|
||||
|
||||
/tcomb@3.2.29:
|
||||
resolution: {integrity: sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==}
|
||||
dev: true
|
||||
|
||||
/text-extensions@2.4.0:
|
||||
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -6048,6 +6340,11 @@ packages:
|
|||
crypto-random-string: 4.0.0
|
||||
dev: false
|
||||
|
||||
/universalify@0.1.2:
|
||||
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
dev: true
|
||||
|
||||
/universalify@0.2.0:
|
||||
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
@ -6137,7 +6434,6 @@ packages:
|
|||
/validator@13.11.0:
|
||||
resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
||||
|
||||
/vary@1.1.2:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
|
@ -6484,6 +6780,10 @@ packages:
|
|||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/which-module@2.0.1:
|
||||
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
|
||||
dev: true
|
||||
|
||||
/which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -6511,6 +6811,10 @@ packages:
|
|||
resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
|
||||
dev: true
|
||||
|
||||
/workerpool@6.5.1:
|
||||
resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==}
|
||||
dev: true
|
||||
|
||||
/wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -6559,6 +6863,10 @@ packages:
|
|||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
dev: true
|
||||
|
||||
/y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -6584,11 +6892,64 @@ packages:
|
|||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yargs-parser@18.1.3:
|
||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
camelcase: 5.3.1
|
||||
decamelize: 1.2.0
|
||||
dev: true
|
||||
|
||||
/yargs-parser@20.2.9:
|
||||
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/yargs-parser@21.1.1:
|
||||
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/yargs-unparser@2.0.0:
|
||||
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
camelcase: 6.3.0
|
||||
decamelize: 4.0.0
|
||||
flat: 5.0.2
|
||||
is-plain-obj: 2.1.0
|
||||
dev: true
|
||||
|
||||
/yargs@15.4.1:
|
||||
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
cliui: 6.0.0
|
||||
decamelize: 1.2.0
|
||||
find-up: 4.1.0
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
require-main-filename: 2.0.0
|
||||
set-blocking: 2.0.0
|
||||
string-width: 4.2.3
|
||||
which-module: 2.0.1
|
||||
y18n: 4.0.3
|
||||
yargs-parser: 18.1.3
|
||||
dev: true
|
||||
|
||||
/yargs@16.2.0:
|
||||
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
cliui: 7.0.4
|
||||
escalade: 3.1.2
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
string-width: 4.2.3
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 20.2.9
|
||||
dev: true
|
||||
|
||||
/yargs@17.7.2:
|
||||
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
|
||||
engines: {node: '>=12'}
|
||||
|
|
|
@ -2,9 +2,10 @@ import axios from 'axios';
|
|||
import { useSession } from 'src/composables/useSession';
|
||||
import { Router } from 'src/router';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { useStateQueryStore } from 'src/stores/useStateQueryStore';
|
||||
|
||||
let session, notify, stateQuery;
|
||||
|
||||
const session = useSession();
|
||||
const { notify } = useNotify();
|
||||
const baseUrl = '/api/';
|
||||
|
||||
axios.defaults.baseURL = baseUrl;
|
||||
|
@ -15,7 +16,7 @@ const onRequest = (config) => {
|
|||
if (token.length && !config.headers.Authorization) {
|
||||
config.headers.Authorization = token;
|
||||
}
|
||||
|
||||
stateQuery.add(config);
|
||||
return config;
|
||||
};
|
||||
|
||||
|
@ -24,10 +25,10 @@ const onRequestError = (error) => {
|
|||
};
|
||||
|
||||
const onResponse = (response) => {
|
||||
const { method } = response.config;
|
||||
const config = response.config;
|
||||
stateQuery.remove(config);
|
||||
|
||||
const isSaveRequest = method === 'patch';
|
||||
if (isSaveRequest) {
|
||||
if (config.method === 'patch') {
|
||||
notify('globals.dataSaved', 'positive');
|
||||
}
|
||||
|
||||
|
@ -35,37 +36,9 @@ const onResponse = (response) => {
|
|||
};
|
||||
|
||||
const onResponseError = (error) => {
|
||||
let message = '';
|
||||
stateQuery.remove(error.config);
|
||||
|
||||
const response = error.response;
|
||||
const responseData = response && response.data;
|
||||
const responseError = responseData && response.data.error;
|
||||
if (responseError) {
|
||||
message = responseError.message;
|
||||
}
|
||||
|
||||
switch (response?.status) {
|
||||
case 422:
|
||||
if (error.name == 'ValidationError')
|
||||
message +=
|
||||
' "' +
|
||||
responseError.details.context +
|
||||
'.' +
|
||||
Object.keys(responseError.details.codes).join(',') +
|
||||
'"';
|
||||
break;
|
||||
case 500:
|
||||
message = 'errors.statusInternalServerError';
|
||||
break;
|
||||
case 502:
|
||||
message = 'errors.statusBadGateway';
|
||||
break;
|
||||
case 504:
|
||||
message = 'errors.statusGatewayTimeout';
|
||||
break;
|
||||
}
|
||||
|
||||
if (session.isLoggedIn() && response?.status === 401) {
|
||||
if (session.isLoggedIn() && error.response?.status === 401) {
|
||||
session.destroy(false);
|
||||
const hash = window.location.hash;
|
||||
const url = hash.slice(1);
|
||||
|
@ -74,14 +47,18 @@ const onResponseError = (error) => {
|
|||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
notify(message, 'negative');
|
||||
|
||||
return Promise.reject(error);
|
||||
};
|
||||
|
||||
axios.interceptors.request.use(onRequest, onRequestError);
|
||||
axios.interceptors.response.use(onResponse, onResponseError);
|
||||
axiosNoError.interceptors.request.use(onRequest);
|
||||
axiosNoError.interceptors.response.use(onResponse);
|
||||
export function setupAxios() {
|
||||
session = useSession();
|
||||
notify = useNotify().notify;
|
||||
stateQuery = useStateQueryStore();
|
||||
|
||||
axios.interceptors.request.use(onRequest, onRequestError);
|
||||
axios.interceptors.response.use(onResponse, onResponseError);
|
||||
axiosNoError.interceptors.request.use(onRequest);
|
||||
axiosNoError.interceptors.response.use(onResponse);
|
||||
}
|
||||
|
||||
export { onRequest, onResponseError, axiosNoError };
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
import { QInput } from 'quasar';
|
||||
import setDefault from './setDefault';
|
||||
|
||||
setDefault(QInput, 'dense', true);
|
|
@ -0,0 +1,4 @@
|
|||
import { QSelect } from 'quasar';
|
||||
import setDefault from './setDefault';
|
||||
|
||||
setDefault(QSelect, 'dense', true);
|
|
@ -1,38 +0,0 @@
|
|||
import routes from 'src/router/modules';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
let isNotified = false;
|
||||
|
||||
export default {
|
||||
created: function () {
|
||||
const router = useRouter();
|
||||
const keyBindingMap = routes
|
||||
.filter((route) => route.meta.keyBinding)
|
||||
.reduce((map, route) => {
|
||||
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
const { ctrlKey, altKey, code } = event;
|
||||
|
||||
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
|
||||
event.preventDefault();
|
||||
router.push(keyBindingMap[code]);
|
||||
isNotified = true;
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = (event) => {
|
||||
const { ctrlKey, altKey } = event;
|
||||
|
||||
// Resetea la bandera cuando se sueltan las teclas ctrl o alt
|
||||
if (!ctrlKey || !altKey) {
|
||||
isNotified = false;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('keyup', handleKeyUp);
|
||||
},
|
||||
};
|
|
@ -1 +1,3 @@
|
|||
export * from './defaults/qTable';
|
||||
export * from './defaults/qInput';
|
||||
export * from './defaults/qSelect';
|
||||
|
|
|
@ -1,16 +1,53 @@
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import qFormMixin from './qformMixin';
|
||||
import mainShortcutMixin from './mainShortcutMixin';
|
||||
import keyShortcut from './keyShortcut';
|
||||
import { setupAxios } from 'src/boot/axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
import { CanceledError } from 'axios';
|
||||
|
||||
const { notify } = useNotify();
|
||||
|
||||
export default boot(({ app }) => {
|
||||
app.mixin(qFormMixin);
|
||||
app.mixin(mainShortcutMixin);
|
||||
app.directive('shortcut', keyShortcut);
|
||||
app.config.errorHandler = function (err) {
|
||||
console.error(err);
|
||||
notify('globals.error', 'negative', 'error');
|
||||
app.config.errorHandler = (error) => {
|
||||
let message;
|
||||
const response = error.response;
|
||||
const responseData = response?.data;
|
||||
const responseError = responseData && response.data.error;
|
||||
if (responseError) {
|
||||
message = responseError.message;
|
||||
}
|
||||
|
||||
switch (response?.status) {
|
||||
case 422:
|
||||
if (error.name == 'ValidationError')
|
||||
message +=
|
||||
' "' +
|
||||
responseError.details.context +
|
||||
'.' +
|
||||
Object.keys(responseError.details.codes).join(',') +
|
||||
'"';
|
||||
break;
|
||||
case 500:
|
||||
message = 'errors.statusInternalServerError';
|
||||
break;
|
||||
case 502:
|
||||
message = 'errors.statusBadGateway';
|
||||
break;
|
||||
case 504:
|
||||
message = 'errors.statusGatewayTimeout';
|
||||
break;
|
||||
}
|
||||
|
||||
console.error(error);
|
||||
if (error instanceof CanceledError) {
|
||||
const env = process.env.NODE_ENV;
|
||||
if (env && env !== 'development') return;
|
||||
message = 'Duplicate request';
|
||||
}
|
||||
|
||||
notify(message ?? 'globals.error', 'negative', 'error');
|
||||
};
|
||||
setupAxios();
|
||||
});
|
||||
|
|
|
@ -31,8 +31,8 @@ const countriesFilter = {
|
|||
|
||||
const countriesOptions = ref([]);
|
||||
|
||||
const onDataSaved = (formData, requestResponse) => {
|
||||
emit('onDataSaved', formData, requestResponse);
|
||||
const onDataSaved = (...args) => {
|
||||
emit('onDataSaved', ...args);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
|
|
|
@ -79,14 +79,20 @@ async function onProvinceCreated(data) {
|
|||
watch(
|
||||
() => [postcodeFormData.countryFk],
|
||||
async (newCountryFk, oldValueFk) => {
|
||||
if (!!oldValueFk[0] && newCountryFk[0] !== oldValueFk[0]) {
|
||||
if (Array.isArray(newCountryFk)) {
|
||||
newCountryFk = newCountryFk[0];
|
||||
}
|
||||
if (Array.isArray(oldValueFk)) {
|
||||
oldValueFk = oldValueFk[0];
|
||||
}
|
||||
if (!!oldValueFk && newCountryFk !== oldValueFk) {
|
||||
postcodeFormData.provinceFk = null;
|
||||
postcodeFormData.townFk = null;
|
||||
}
|
||||
if ((newCountryFk, newCountryFk !== postcodeFormData.countryFk)) {
|
||||
if (oldValueFk !== newCountryFk) {
|
||||
await provincesFetchDataRef.value.fetch({
|
||||
where: {
|
||||
countryFk: newCountryFk[0],
|
||||
countryFk: newCountryFk,
|
||||
},
|
||||
});
|
||||
await townsFetchDataRef.value.fetch({
|
||||
|
@ -102,10 +108,13 @@ watch(
|
|||
|
||||
watch(
|
||||
() => postcodeFormData.provinceFk,
|
||||
async (newProvinceFk) => {
|
||||
if (newProvinceFk[0] && newProvinceFk[0] !== postcodeFormData.provinceFk) {
|
||||
async (newProvinceFk, oldValueFk) => {
|
||||
if (Array.isArray(newProvinceFk)) {
|
||||
newProvinceFk = newProvinceFk[0];
|
||||
}
|
||||
if (newProvinceFk !== oldValueFk) {
|
||||
await townsFetchDataRef.value.fetch({
|
||||
where: { provinceFk: newProvinceFk[0] },
|
||||
where: { provinceFk: newProvinceFk },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -125,16 +134,20 @@ async function handleCountries(data) {
|
|||
<FetchData
|
||||
ref="provincesFetchDataRef"
|
||||
@on-fetch="handleProvinces"
|
||||
:sort-by="['name ASC']"
|
||||
:limit="30"
|
||||
auto-load
|
||||
url="Provinces/location"
|
||||
/>
|
||||
<FetchData
|
||||
ref="townsFetchDataRef"
|
||||
:sort-by="['name ASC']"
|
||||
:limit="30"
|
||||
@on-fetch="handleTowns"
|
||||
auto-load
|
||||
url="Towns/location"
|
||||
/>
|
||||
<FetchData @on-fetch="handleCountries" auto-load url="Countries" />
|
||||
|
||||
<FormModelPopup
|
||||
url-create="postcodes"
|
||||
model="postcode"
|
||||
|
@ -200,8 +213,10 @@ async function handleCountries(data) {
|
|||
@on-province-created="onProvinceCreated"
|
||||
/>
|
||||
<VnSelect
|
||||
url="Countries"
|
||||
:sort-by="['name ASC']"
|
||||
:label="t('Country')"
|
||||
:options="countriesOptions"
|
||||
@update:options="handleCountries"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
|
|
|
@ -46,6 +46,8 @@ const onDataSaved = (dataSaved, requestResponse) => {
|
|||
},
|
||||
}"
|
||||
url="Autonomies/location"
|
||||
:sort-by="['name ASC']"
|
||||
:limit="30"
|
||||
/>
|
||||
<FormModelPopup
|
||||
:title="t('New province')"
|
||||
|
|
|
@ -38,7 +38,7 @@ const onDataSaved = (dataSaved) => {
|
|||
@on-fetch="(data) => (warehousesOptions = data)"
|
||||
auto-load
|
||||
url="Warehouses"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC', limit: 30 }"
|
||||
:filter="{ fields: ['id', 'name'], order: 'name ASC' }"
|
||||
/>
|
||||
<FetchData
|
||||
@on-fetch="(data) => (temperaturesOptions = data)"
|
||||
|
|
|
@ -50,25 +50,25 @@ const loading = ref(false);
|
|||
|
||||
const tableColumns = computed(() => [
|
||||
{
|
||||
label: t('entry.buys.id'),
|
||||
label: t('globals.id'),
|
||||
name: 'id',
|
||||
field: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('entry.buys.name'),
|
||||
label: t('globals.name'),
|
||||
name: 'name',
|
||||
field: 'name',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('entry.buys.size'),
|
||||
label: t('globals.size'),
|
||||
name: 'size',
|
||||
field: 'size',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('entry.buys.producer'),
|
||||
label: t('globals.producer'),
|
||||
name: 'producerName',
|
||||
field: 'producer',
|
||||
align: 'left',
|
||||
|
@ -152,10 +152,10 @@ const selectItem = ({ id }) => {
|
|||
</span>
|
||||
<h1 class="title">{{ t('Filter item') }}</h1>
|
||||
<VnRow>
|
||||
<VnInput :label="t('entry.buys.name')" v-model="itemFilterParams.name" />
|
||||
<VnInput :label="t('globals.name')" v-model="itemFilterParams.name" />
|
||||
<VnInput :label="t('entry.buys.size')" v-model="itemFilterParams.size" />
|
||||
<VnSelect
|
||||
:label="t('entry.buys.producer')"
|
||||
:label="t('globals.producer')"
|
||||
:options="producersOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
|
@ -163,7 +163,7 @@ const selectItem = ({ id }) => {
|
|||
v-model="itemFilterParams.producerFk"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('entry.buys.type')"
|
||||
:label="t('globals.type')"
|
||||
:options="ItemTypesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
|
|
|
@ -48,13 +48,13 @@ const loading = ref(false);
|
|||
|
||||
const tableColumns = computed(() => [
|
||||
{
|
||||
label: t('entry.basicData.id'),
|
||||
label: t('globals.id'),
|
||||
name: 'id',
|
||||
field: 'id',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('entry.basicData.warehouseOut'),
|
||||
label: t('globals.warehouseOut'),
|
||||
name: 'warehouseOutFk',
|
||||
field: 'warehouseOutFk',
|
||||
align: 'left',
|
||||
|
@ -62,7 +62,7 @@ const tableColumns = computed(() => [
|
|||
warehousesOptions.value.find((warehouse) => warehouse.id === val).name,
|
||||
},
|
||||
{
|
||||
label: t('entry.basicData.warehouseIn'),
|
||||
label: t('globals.warehouseIn'),
|
||||
name: 'warehouseInFk',
|
||||
field: 'warehouseInFk',
|
||||
align: 'left',
|
||||
|
@ -70,14 +70,14 @@ const tableColumns = computed(() => [
|
|||
warehousesOptions.value.find((warehouse) => warehouse.id === val).name,
|
||||
},
|
||||
{
|
||||
label: t('entry.basicData.shipped'),
|
||||
label: t('globals.shipped'),
|
||||
name: 'shipped',
|
||||
field: 'shipped',
|
||||
align: 'left',
|
||||
format: (val) => toDate(val),
|
||||
},
|
||||
{
|
||||
label: t('entry.basicData.landed'),
|
||||
label: t('globals.landed'),
|
||||
name: 'landed',
|
||||
field: 'landed',
|
||||
align: 'left',
|
||||
|
@ -146,7 +146,7 @@ const selectTravel = ({ id }) => {
|
|||
<h1 class="title">{{ t('Filter travels') }}</h1>
|
||||
<VnRow>
|
||||
<VnSelect
|
||||
:label="t('entry.basicData.agency')"
|
||||
:label="t('globals.agency')"
|
||||
:options="agenciesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
|
@ -154,7 +154,7 @@ const selectTravel = ({ id }) => {
|
|||
v-model="travelFilterParams.agencyModeFk"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('entry.basicData.warehouseOut')"
|
||||
:label="t('globals.warehouseOut')"
|
||||
:options="warehousesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
|
@ -162,7 +162,7 @@ const selectTravel = ({ id }) => {
|
|||
v-model="travelFilterParams.warehouseOutFk"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('entry.basicData.warehouseIn')"
|
||||
:label="t('globals.warehouseIn')"
|
||||
:options="warehousesOptions"
|
||||
hide-selected
|
||||
option-label="name"
|
||||
|
@ -170,11 +170,11 @@ const selectTravel = ({ id }) => {
|
|||
v-model="travelFilterParams.warehouseInFk"
|
||||
/>
|
||||
<VnInputDate
|
||||
:label="t('entry.basicData.shipped')"
|
||||
:label="t('globals.shipped')"
|
||||
v-model="travelFilterParams.shipped"
|
||||
/>
|
||||
<VnInputDate
|
||||
:label="t('entry.basicData.landed')"
|
||||
:label="t('globals.landed')"
|
||||
v-model="travelFilterParams.landed"
|
||||
/>
|
||||
</VnRow>
|
||||
|
|
|
@ -217,9 +217,6 @@ async function save() {
|
|||
updateAndEmit('onDataSaved', formData.value, response?.data);
|
||||
if ($props.reload) await arrayData.fetch({});
|
||||
hasChanges.value = false;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
notify('errors.writeRequest', 'negative');
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
@ -275,6 +272,7 @@ defineExpose({
|
|||
hasChanges,
|
||||
reset,
|
||||
fetch,
|
||||
formData,
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
|
|
|
@ -61,6 +61,7 @@ defineExpose({
|
|||
:loading="isLoading"
|
||||
@click="emit('onDataCanceled')"
|
||||
v-close-popup
|
||||
data-cy="FormModelPopup_cancel"
|
||||
/>
|
||||
<QBtn
|
||||
:label="t('globals.save')"
|
||||
|
@ -70,6 +71,7 @@ defineExpose({
|
|||
class="q-ml-sm"
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
data-cy="FormModelPopup_save"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -248,7 +248,7 @@ const removeTag = (index, params, search) => {
|
|||
>
|
||||
<QItemSection class="col">
|
||||
<VnSelect
|
||||
:label="t('components.itemsFilterPanel.tag')"
|
||||
:label="t('globals.tag')"
|
||||
v-model="value.selectedTag"
|
||||
:options="tagOptions"
|
||||
option-label="name"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { onMounted, watch, ref, reactive } from 'vue';
|
||||
import { onMounted, watch, ref, reactive, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { QSeparator, useQuasar } from 'quasar';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
@ -9,6 +9,7 @@ import { toLowerCamel } from 'src/filters';
|
|||
import routes from 'src/router/modules';
|
||||
import LeftMenuItem from './LeftMenuItem.vue';
|
||||
import LeftMenuItemGroup from './LeftMenuItemGroup.vue';
|
||||
import VnInput from './common/VnInput.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
@ -22,7 +23,32 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const items = ref([]);
|
||||
const expansionItemElements = reactive({});
|
||||
const pinnedModules = computed(() => {
|
||||
const map = new Map();
|
||||
items.value.forEach((item) => item.isPinned && map.set(item.name, item));
|
||||
return map;
|
||||
});
|
||||
const search = ref(null);
|
||||
|
||||
const filteredItems = computed(() => {
|
||||
if (!search.value) return items.value;
|
||||
return items.value.filter((item) => {
|
||||
const locale = t(item.title).toLowerCase();
|
||||
return locale.includes(search.value.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
const filteredPinnedModules = computed(() => {
|
||||
if (!search.value) return pinnedModules.value;
|
||||
const map = new Map();
|
||||
for (const [key, pinnedModule] of pinnedModules.value) {
|
||||
const locale = t(pinnedModule.title).toLowerCase();
|
||||
if (locale.includes(search.value.toLowerCase())) map.set(key, pinnedModule);
|
||||
}
|
||||
return map;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
await navigation.fetchPinned();
|
||||
|
@ -66,8 +92,6 @@ function addChildren(module, route, parent) {
|
|||
}
|
||||
}
|
||||
|
||||
const items = ref([]);
|
||||
|
||||
function getRoutes() {
|
||||
if (props.source === 'main') {
|
||||
const modules = Object.assign([], navigation.getModules().value);
|
||||
|
@ -129,15 +153,44 @@ const handleItemExpansion = (itemName) => {
|
|||
<QList padding class="column-max-width">
|
||||
<template v-if="$props.source === 'main'">
|
||||
<template v-if="$route?.matched[1]?.name === 'Dashboard'">
|
||||
<QItem class="header">
|
||||
<QItemSection avatar>
|
||||
<QIcon name="view_module" />
|
||||
</QItemSection>
|
||||
<QItemSection> {{ t('globals.modules') }}</QItemSection>
|
||||
<QItem class="q-pb-md">
|
||||
<VnInput
|
||||
v-model="search"
|
||||
:label="t('Search modules')"
|
||||
class="full-width"
|
||||
filled
|
||||
dense
|
||||
/>
|
||||
</QItem>
|
||||
<QSeparator />
|
||||
<template v-for="item in items" :key="item.name">
|
||||
<template v-if="item.children">
|
||||
<template v-if="filteredPinnedModules.size">
|
||||
<LeftMenuItem
|
||||
v-for="[key, pinnedModule] of filteredPinnedModules"
|
||||
:key="key"
|
||||
:item="pinnedModule"
|
||||
group="modules"
|
||||
>
|
||||
<template #side>
|
||||
<QBtn
|
||||
v-if="pinnedModule.isPinned === true"
|
||||
@click="togglePinned(pinnedModule, $event)"
|
||||
icon="remove_circle"
|
||||
size="xs"
|
||||
flat
|
||||
round
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('components.leftMenu.removeFromPinned') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
</LeftMenuItem>
|
||||
<QSeparator />
|
||||
</template>
|
||||
<template v-for="item in filteredItems" :key="item.name">
|
||||
<template
|
||||
v-if="item.children && !filteredPinnedModules.has(item.name)"
|
||||
>
|
||||
<LeftMenuItem :item="item" group="modules">
|
||||
<template #side>
|
||||
<QBtn
|
||||
|
@ -256,3 +309,7 @@ const handleItemExpansion = (itemName) => {
|
|||
color: var(--vn-label-color);
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
es:
|
||||
Search modules: Buscar módulos
|
||||
</i18n>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { onMounted, ref } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { useStateQueryStore } from 'src/stores/useStateQueryStore';
|
||||
import { useQuasar } from 'quasar';
|
||||
import PinnedModules from './PinnedModules.vue';
|
||||
import UserPanel from 'components/UserPanel.vue';
|
||||
|
@ -12,6 +13,7 @@ import VnAvatar from './ui/VnAvatar.vue';
|
|||
const { t } = useI18n();
|
||||
const stateStore = useStateStore();
|
||||
const quasar = useQuasar();
|
||||
const stateQuery = useStateQueryStore();
|
||||
const state = useState();
|
||||
const user = state.getUser();
|
||||
const appName = 'Lilium';
|
||||
|
@ -50,6 +52,14 @@ const pinnedModulesRef = ref();
|
|||
</QBtn>
|
||||
</RouterLink>
|
||||
<VnBreadcrumbs v-if="$q.screen.gt.sm" />
|
||||
<QSpinner
|
||||
color="primary"
|
||||
class="q-ml-md"
|
||||
:class="{
|
||||
'no-visible': !stateQuery.isLoading().value,
|
||||
}"
|
||||
size="xs"
|
||||
/>
|
||||
<QSpace />
|
||||
<div id="searchbar" class="searchbar"></div>
|
||||
<QSpace />
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { markRaw, computed, defineModel } from 'vue';
|
||||
import { markRaw, computed } from 'vue';
|
||||
import { QIcon, QCheckbox } from 'quasar';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { markRaw, computed, defineModel } from 'vue';
|
||||
import { markRaw, computed } from 'vue';
|
||||
import { QCheckbox } from 'quasar';
|
||||
import { useArrayData } from 'composables/useArrayData';
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ const $props = defineProps({
|
|||
default: 'flex-one',
|
||||
},
|
||||
searchUrl: {
|
||||
type: String,
|
||||
type: [String, Boolean],
|
||||
default: 'table',
|
||||
},
|
||||
isEditable: {
|
||||
|
@ -134,6 +134,7 @@ const splittedColumns = ref({ columns: [] });
|
|||
const columnsVisibilitySkipped = ref();
|
||||
const createForm = ref();
|
||||
const tableFilterRef = ref([]);
|
||||
const tableRef = ref();
|
||||
|
||||
const tableModes = [
|
||||
{
|
||||
|
@ -150,8 +151,8 @@ const tableModes = [
|
|||
},
|
||||
];
|
||||
onBeforeMount(() => {
|
||||
setUserParams(route.query[$props.searchUrl]);
|
||||
hasParams.value = params.value && Object.keys(params.value).length !== 0;
|
||||
const urlParams = route.query[$props.searchUrl];
|
||||
hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -182,7 +183,8 @@ watch(
|
|||
|
||||
watch(
|
||||
() => route.query[$props.searchUrl],
|
||||
(val) => setUserParams(val)
|
||||
(val) => setUserParams(val),
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
||||
|
@ -233,7 +235,7 @@ function splitColumns(columns) {
|
|||
if (col.create) splittedColumns.value.create.push(col);
|
||||
if (col.cardVisible) splittedColumns.value.cardVisible.push(col);
|
||||
if ($props.isEditable && col.disable == null) col.disable = false;
|
||||
if ($props.useModel && col.columnFilter != false)
|
||||
if ($props.useModel && col.columnFilter !== false)
|
||||
col.columnFilter = { inWhere: true, ...col.columnFilter };
|
||||
splittedColumns.value.columns.push(col);
|
||||
}
|
||||
|
||||
|
@ -313,12 +315,34 @@ defineExpose({
|
|||
selected,
|
||||
CrudModelRef,
|
||||
params,
|
||||
tableRef,
|
||||
});
|
||||
|
||||
function handleOnDataSaved(_, res) {
|
||||
function handleOnDataSaved(_) {
|
||||
if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
|
||||
else $props.create.onDataSaved(_);
|
||||
}
|
||||
|
||||
function handleScroll() {
|
||||
const tMiddle = tableRef.value.$el.querySelector('.q-table__middle');
|
||||
const { scrollHeight, scrollTop, clientHeight } = tMiddle;
|
||||
const isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) <= 40;
|
||||
if (isAtBottom) CrudModelRef.value.vnPaginateRef.paginate();
|
||||
}
|
||||
|
||||
function handleSelection({ evt, added, rows: selectedRows }, rows) {
|
||||
if (evt?.shiftKey && added) {
|
||||
const rowIndex = selectedRows[0].$index;
|
||||
const selectedIndexes = new Set(selected.value.map((row) => row.$index));
|
||||
for (const row of rows) {
|
||||
if (row.$index == rowIndex) break;
|
||||
if (!selectedIndexes.has(row.$index)) {
|
||||
selected.value.push(row);
|
||||
selectedIndexes.add(row.$index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<QDrawer
|
||||
|
@ -403,8 +427,10 @@ function handleOnDataSaved(_, res) {
|
|||
</template>
|
||||
<template #body="{ rows }">
|
||||
<QTable
|
||||
ref="tableRef"
|
||||
v-bind="table"
|
||||
class="vnTable"
|
||||
:class="{ 'last-row-sticky': $props.footer }"
|
||||
:columns="splittedColumns.columns"
|
||||
:rows="rows"
|
||||
v-model:selected="selected"
|
||||
|
@ -414,14 +440,10 @@ function handleOnDataSaved(_, res) {
|
|||
flat
|
||||
:style="isTableMode && `max-height: ${tableHeight}`"
|
||||
:virtual-scroll="isTableMode"
|
||||
@virtual-scroll="
|
||||
(event) =>
|
||||
event.index > rows.length - 2 &&
|
||||
($props.crudModel?.paginate ?? true) &&
|
||||
CrudModelRef.vnPaginateRef.paginate()
|
||||
"
|
||||
@virtual-scroll="handleScroll"
|
||||
@row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
|
||||
@update:selected="emit('update:selected', $event)"
|
||||
@selection="(details) => handleSelection(details, rows)"
|
||||
>
|
||||
<template #top-left v-if="!$props.withoutHeader">
|
||||
<slot name="top-left"></slot>
|
||||
|
@ -449,7 +471,11 @@ function handleOnDataSaved(_, res) {
|
|||
/>
|
||||
</template>
|
||||
<template #header-cell="{ col }">
|
||||
<QTh v-if="col.visible ?? true">
|
||||
<QTh
|
||||
v-if="col.visible ?? true"
|
||||
:style="col.headerStyle"
|
||||
:class="col.headerClass"
|
||||
>
|
||||
<div
|
||||
class="column self-start q-ml-xs ellipsis"
|
||||
:class="`text-${col?.align ?? 'left'}`"
|
||||
|
@ -495,6 +521,7 @@ function handleOnDataSaved(_, res) {
|
|||
auto-width
|
||||
class="no-margin q-px-xs"
|
||||
:class="[getColAlign(col), col.columnClass]"
|
||||
:style="col.style"
|
||||
v-if="col.visible ?? true"
|
||||
@click.ctrl="
|
||||
($event) =>
|
||||
|
@ -523,6 +550,7 @@ function handleOnDataSaved(_, res) {
|
|||
:class="getColAlign(col)"
|
||||
class="sticky no-padding"
|
||||
@click="stopEventPropagation($event)"
|
||||
:style="col.style"
|
||||
>
|
||||
<QBtn
|
||||
v-for="(btn, index) of col.actions"
|
||||
|
@ -708,7 +736,7 @@ function handleOnDataSaved(_, res) {
|
|||
icon="add"
|
||||
shortcut="+"
|
||||
/>
|
||||
<QTooltip>
|
||||
<QTooltip self="top right">
|
||||
{{ createForm?.title }}
|
||||
</QTooltip>
|
||||
</QPageSticky>
|
||||
|
@ -807,6 +835,7 @@ es:
|
|||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vnTable {
|
||||
thead tr th {
|
||||
position: sticky;
|
||||
|
@ -845,6 +874,9 @@ es:
|
|||
table tbody th {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.last-row-sticky {
|
||||
tbody:nth-last-child(1) {
|
||||
@extend .bg-header;
|
||||
position: sticky;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<script setup>
|
||||
import VnSelect from './VnSelect.vue';
|
||||
|
||||
defineProps({
|
||||
selectProps: { type: Object, required: true },
|
||||
promise: { type: Function, default: () => {} },
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<QBtnDropdown v-bind="$attrs" color="primary">
|
||||
<VnSelect
|
||||
v-bind="selectProps"
|
||||
hide-selected
|
||||
hide-dropdown-icon
|
||||
focus-on-mount
|
||||
@update:model-value="promise"
|
||||
/>
|
||||
</QBtnDropdown>
|
||||
</template>
|
|
@ -0,0 +1,136 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnRow from '../ui/VnRow.vue';
|
||||
import VnInput from './VnInput.vue';
|
||||
import FetchData from '../FetchData.vue';
|
||||
import useNotify from 'src/composables/useNotify';
|
||||
|
||||
const props = defineProps({
|
||||
submitFn: { type: Function, default: () => {} },
|
||||
askOldPass: { type: Boolean, default: false },
|
||||
});
|
||||
const emit = defineEmits(['onSubmit']);
|
||||
const { t } = useI18n();
|
||||
const { notify } = useNotify();
|
||||
|
||||
const form = ref();
|
||||
const changePassDialog = ref();
|
||||
const passwords = ref({ newPassword: null, repeatPassword: null });
|
||||
const requirements = ref([]);
|
||||
const isLoading = ref(false);
|
||||
|
||||
const validate = async () => {
|
||||
const { newPassword, repeatPassword, oldPassword } = passwords.value;
|
||||
|
||||
if (!newPassword) {
|
||||
notify(t('You must enter a new password'), 'negative');
|
||||
return;
|
||||
}
|
||||
if (newPassword !== repeatPassword) {
|
||||
notify(t("Passwords don't match"), 'negative');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isLoading.value = true;
|
||||
await props.submitFn(newPassword, oldPassword);
|
||||
emit('onSubmit');
|
||||
} catch (e) {
|
||||
notify('errors.writeRequest', 'negative');
|
||||
} finally {
|
||||
changePassDialog.value.hide();
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
defineExpose({ show: () => changePassDialog.value.show() });
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="UserPasswords/findOne"
|
||||
auto-load
|
||||
@on-fetch="(data) => (requirements = data)"
|
||||
/>
|
||||
<QDialog ref="changePassDialog">
|
||||
<QCard style="width: 350px">
|
||||
<QCardSection>
|
||||
<slot name="header">
|
||||
<VnRow class="items-center" style="flex-direction: row">
|
||||
<span class="text-h6" v-text="t('globals.changePass')" />
|
||||
<QIcon
|
||||
class="cursor-pointer"
|
||||
name="close"
|
||||
size="xs"
|
||||
style="flex: 0"
|
||||
v-close-popup
|
||||
/>
|
||||
</VnRow>
|
||||
</slot>
|
||||
</QCardSection>
|
||||
<QForm ref="form">
|
||||
<QCardSection>
|
||||
<VnInput
|
||||
v-if="props.askOldPass"
|
||||
:label="t('Old password')"
|
||||
v-model="passwords.oldPassword"
|
||||
type="password"
|
||||
:required="true"
|
||||
autofocus
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('New password')"
|
||||
v-model="passwords.newPassword"
|
||||
type="password"
|
||||
:required="true"
|
||||
:info="
|
||||
t('passwordRequirements', {
|
||||
length: requirements.length,
|
||||
nAlpha: requirements.nAlpha,
|
||||
nUpper: requirements.nUpper,
|
||||
nDigits: requirements.nDigits,
|
||||
nPunct: requirements.nPunct,
|
||||
})
|
||||
"
|
||||
autofocus
|
||||
/>
|
||||
|
||||
<VnInput
|
||||
:label="t('Repeat password')"
|
||||
v-model="passwords.repeatPassword"
|
||||
type="password"
|
||||
/>
|
||||
</QCardSection>
|
||||
</QForm>
|
||||
<QCardActions>
|
||||
<slot name="actions">
|
||||
<QBtn
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
:label="t('globals.cancel')"
|
||||
class="q-ml-sm"
|
||||
color="primary"
|
||||
flat
|
||||
type="reset"
|
||||
v-close-popup
|
||||
/>
|
||||
<QBtn
|
||||
:disabled="isLoading"
|
||||
:loading="isLoading"
|
||||
:label="t('globals.confirm')"
|
||||
color="primary"
|
||||
@click="validate"
|
||||
/>
|
||||
</slot>
|
||||
</QCardActions>
|
||||
</QCard>
|
||||
</QDialog>
|
||||
</template>
|
||||
|
||||
<i18n>
|
||||
es:
|
||||
New password: Nueva contraseña
|
||||
Repeat password: Repetir contraseña
|
||||
You must enter a new password: Debes introducir la nueva contraseña
|
||||
Passwords don't match: Las contraseñas no coinciden
|
||||
</i18n>
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { computed, defineModel } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const model = defineModel(undefined, { required: true });
|
||||
const $props = defineProps({
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<script setup>
|
||||
const model = defineModel({ type: [String, Number], required: true });
|
||||
</script>
|
||||
<template>
|
||||
<QDate v-model="model" :today-btn="true" :options="$attrs.options" />
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.q-date {
|
||||
width: 245px;
|
||||
min-width: unset;
|
||||
|
||||
:deep(.q-date__calendar) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
:deep(.q-date__view) {
|
||||
min-height: 245px;
|
||||
padding: 8px;
|
||||
}
|
||||
:deep(.q-date__calendar-days-container) {
|
||||
min-height: 160px;
|
||||
height: unset;
|
||||
}
|
||||
|
||||
:deep(.q-date__header) {
|
||||
padding: 2px 2px 5px 12px;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -31,6 +31,10 @@ const $props = defineProps({
|
|||
type: String,
|
||||
default: null,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const warehouses = ref();
|
||||
|
@ -43,7 +47,8 @@ const dms = ref({});
|
|||
onMounted(() => {
|
||||
defaultData();
|
||||
if (!$props.formInitialData)
|
||||
dms.value.description = t($props.model + 'Description', dms.value);
|
||||
dms.value.description =
|
||||
$props.description ?? t($props.model + 'Description', dms.value);
|
||||
});
|
||||
function onFileChange(files) {
|
||||
dms.value.hasFileAttached = !!files;
|
||||
|
@ -54,7 +59,6 @@ function mapperDms(data) {
|
|||
const formData = new FormData();
|
||||
const { files } = data;
|
||||
if (files) formData.append(files?.name, files);
|
||||
delete data.files;
|
||||
|
||||
const dms = {
|
||||
hasFile: !!data.hasFile,
|
||||
|
@ -78,6 +82,7 @@ async function save() {
|
|||
const body = mapperDms(dms.value);
|
||||
const response = await axios.post(getUrl(), body[0], body[1]);
|
||||
emit('onDataSaved', body[1].params, response);
|
||||
delete dms.value.files;
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -158,13 +163,14 @@ function addDefaultData(data) {
|
|||
/>
|
||||
<QFile
|
||||
ref="inputFileRef"
|
||||
:label="t('entry.buys.file')"
|
||||
:label="t('globals.file')"
|
||||
v-model="dms.files"
|
||||
:multiple="false"
|
||||
:accept="allowedContentTypes"
|
||||
@update:model-value="onFileChange(dms.files)"
|
||||
class="required"
|
||||
:display-value="dms.file"
|
||||
data-cy="VnDms_inputFile"
|
||||
>
|
||||
<template #append>
|
||||
<QIcon
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, useAttrs } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits([
|
||||
'update:modelValue',
|
||||
'update:options',
|
||||
|
@ -27,11 +30,11 @@ const $props = defineProps({
|
|||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
emptyToNull: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
const { validations } = useValidator();
|
||||
|
||||
const { t } = useI18n();
|
||||
const requiredFieldRule = (val) => validations().required($attrs.required, val);
|
||||
|
||||
const vnInputRef = ref(null);
|
||||
const value = computed({
|
||||
|
@ -39,6 +42,7 @@ const value = computed({
|
|||
return $props.modelValue;
|
||||
},
|
||||
set(value) {
|
||||
if ($props.emptyToNull && value === '') value = null;
|
||||
emit('update:modelValue', value);
|
||||
},
|
||||
});
|
||||
|
@ -60,8 +64,6 @@ const focus = () => {
|
|||
defineExpose({
|
||||
focus,
|
||||
});
|
||||
import { useAttrs } from 'vue';
|
||||
const $attrs = useAttrs();
|
||||
|
||||
const mixinRules = [
|
||||
requiredFieldRule,
|
||||
|
@ -85,7 +87,7 @@ const mixinRules = [
|
|||
v-model="value"
|
||||
v-bind="{ ...$attrs, ...styleAttrs }"
|
||||
:type="$attrs.type"
|
||||
:class="{ required: $attrs.required }"
|
||||
:class="{ required: isRequired }"
|
||||
@keyup.enter="emit('keyup.enter')"
|
||||
:clearable="false"
|
||||
:rules="mixinRules"
|
||||
|
@ -130,24 +132,4 @@ const mixinRules = [
|
|||
.q-field__append {
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
.q-field__append.q-field__marginal.row.no-wrap.items-center.row {
|
||||
height: 20px;
|
||||
}
|
||||
.q-field--outlined .q-field__append.q-field__marginal.row.no-wrap.items-center.row {
|
||||
height: auto;
|
||||
}
|
||||
.q-field__control {
|
||||
height: unset;
|
||||
}
|
||||
|
||||
.q-field--labeled {
|
||||
.q-field__native,
|
||||
.q-field__prefix,
|
||||
.q-field__suffix,
|
||||
.q-field__input {
|
||||
padding-bottom: 0;
|
||||
min-height: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2,8 +2,14 @@
|
|||
import { onMounted, watch, computed, ref, useAttrs } from 'vue';
|
||||
import { date } from 'quasar';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnDate from './VnDate.vue';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const model = defineModel({ type: [String, Date] });
|
||||
const { t } = useI18n();
|
||||
|
||||
const $props = defineProps({
|
||||
isOutlined: {
|
||||
type: Boolean,
|
||||
|
@ -14,18 +20,13 @@ const $props = defineProps({
|
|||
default: true,
|
||||
},
|
||||
});
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
const { validations } = useValidator();
|
||||
|
||||
const { t } = useI18n();
|
||||
const requiredFieldRule = (val) => validations().required($attrs.required, val);
|
||||
const vnInputDateRef = ref(null);
|
||||
|
||||
const dateFormat = 'DD/MM/YYYY';
|
||||
const isPopupOpen = ref();
|
||||
const hover = ref();
|
||||
const mask = ref();
|
||||
const $attrs = useAttrs();
|
||||
|
||||
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||
|
||||
|
@ -86,6 +87,11 @@ const styleAttrs = computed(() => {
|
|||
}
|
||||
: {};
|
||||
});
|
||||
|
||||
const manageDate = (date) => {
|
||||
formattedDate.value = date;
|
||||
isPopupOpen.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -97,7 +103,7 @@ const styleAttrs = computed(() => {
|
|||
:mask="mask"
|
||||
placeholder="dd/mm/aaaa"
|
||||
v-bind="{ ...$attrs, ...styleAttrs }"
|
||||
:class="{ required: $attrs.required }"
|
||||
:class="{ required: isRequired }"
|
||||
:rules="mixinRules"
|
||||
:clearable="false"
|
||||
@click="isPopupOpen = true"
|
||||
|
@ -128,6 +134,7 @@ const styleAttrs = computed(() => {
|
|||
/>
|
||||
</template>
|
||||
<QMenu
|
||||
v-if="$q.screen.gt.xs"
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
v-model="isPopupOpen"
|
||||
|
@ -136,19 +143,11 @@ const styleAttrs = computed(() => {
|
|||
:no-focus="true"
|
||||
:no-parent-event="true"
|
||||
>
|
||||
<QDate
|
||||
v-model="popupDate"
|
||||
:landscape="true"
|
||||
:today-btn="true"
|
||||
:options="$attrs.options"
|
||||
@update:model-value="
|
||||
(date) => {
|
||||
formattedDate = date;
|
||||
isPopupOpen = false;
|
||||
}
|
||||
"
|
||||
/>
|
||||
<VnDate v-model="popupDate" @update:model-value="manageDate" />
|
||||
</QMenu>
|
||||
<QDialog v-else v-model="isPopupOpen">
|
||||
<VnDate v-model="popupDate" @update:model-value="manageDate" />
|
||||
</QDialog>
|
||||
</QInput>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
<script setup>
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import { ref } from 'vue';
|
||||
import { useAttrs } from 'vue';
|
||||
|
||||
const model = defineModel({ type: [Number, String] });
|
||||
const $attrs = useAttrs();
|
||||
const step = ref($attrs.step || 0.01);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VnInput v-bind="$attrs" v-model.number="model" type="number" />
|
||||
<VnInput v-bind="$attrs" v-model.number="model" type="number" :step="step" />
|
||||
</template>
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
import { computed, ref, useAttrs } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { date } from 'quasar';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
const { validations } = useValidator();
|
||||
import VnTime from './VnTime.vue';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const { t } = useI18n();
|
||||
const model = defineModel({ type: String });
|
||||
const props = defineProps({
|
||||
timeOnly: {
|
||||
|
@ -18,8 +21,6 @@ const props = defineProps({
|
|||
});
|
||||
const vnInputTimeRef = ref(null);
|
||||
const initialDate = ref(model.value ?? Date.vnNew());
|
||||
const { t } = useI18n();
|
||||
const requiredFieldRule = (val) => validations().required($attrs.required, val);
|
||||
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||
const dateFormat = 'HH:mm';
|
||||
const isPopupOpen = ref();
|
||||
|
@ -76,7 +77,7 @@ function dateToTime(newDate) {
|
|||
placeholder="--:--"
|
||||
v-model="formattedTime"
|
||||
v-bind="{ ...$attrs, ...styleAttrs }"
|
||||
:class="{ required: $attrs.required }"
|
||||
:class="{ required: isRequired }"
|
||||
style="min-width: 100px"
|
||||
:rules="mixinRules"
|
||||
@click="isPopupOpen = false"
|
||||
|
@ -107,6 +108,7 @@ function dateToTime(newDate) {
|
|||
/>
|
||||
</template>
|
||||
<QMenu
|
||||
v-if="$q.screen.gt.xs"
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
v-model="isPopupOpen"
|
||||
|
@ -115,8 +117,11 @@ function dateToTime(newDate) {
|
|||
:no-focus="true"
|
||||
:no-parent-event="true"
|
||||
>
|
||||
<QTime v-model="formattedTime" mask="HH:mm" landscape now-btn />
|
||||
<VnTime v-model="formattedTime" />
|
||||
</QMenu>
|
||||
<QDialog v-else v-model="isPopupOpen">
|
||||
<VnTime v-model="formattedTime" />
|
||||
</QDialog>
|
||||
</QInput>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -3,9 +3,12 @@ import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
|
|||
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ref } from 'vue';
|
||||
import { useAttrs } from 'vue';
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['update:model-value', 'update:options']);
|
||||
|
||||
const $attrs = useAttrs();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const props = defineProps({
|
||||
location: {
|
||||
type: Object,
|
||||
|
@ -13,6 +16,7 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const mixinRules = [requiredFieldRule];
|
||||
const locationProperties = [
|
||||
'postcode',
|
||||
(obj) =>
|
||||
|
@ -69,11 +73,13 @@ const handleModelValue = (data) => {
|
|||
:label="t('Location')"
|
||||
:placeholder="t('search_by_postalcode')"
|
||||
:input-debounce="300"
|
||||
:class="{ required: $attrs.required }"
|
||||
:class="{ required: isRequired }"
|
||||
v-bind="$attrs"
|
||||
clearable
|
||||
:emit-value="false"
|
||||
:tooltip="t('Create new location')"
|
||||
:rules="mixinRules"
|
||||
:lazy-rules="true"
|
||||
>
|
||||
<template #form>
|
||||
<CreateNewPostcode
|
||||
|
|
|
@ -9,10 +9,6 @@ const $props = defineProps({
|
|||
type: Number, //Progress value (1.0 > x > 0.0)
|
||||
required: true,
|
||||
},
|
||||
showDialog: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
cancelled: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
@ -24,30 +20,22 @@ const emit = defineEmits(['cancel', 'close']);
|
|||
|
||||
const dialogRef = ref(null);
|
||||
|
||||
const _showDialog = computed({
|
||||
get: () => $props.showDialog,
|
||||
set: (value) => {
|
||||
if (value) dialogRef.value.show();
|
||||
},
|
||||
const showDialog = defineModel('showDialog', {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
});
|
||||
|
||||
const _progress = computed(() => $props.progress);
|
||||
|
||||
const progressLabel = computed(() => `${Math.round($props.progress * 100)}%`);
|
||||
|
||||
const cancel = () => {
|
||||
dialogRef.value.hide();
|
||||
emit('cancel');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QDialog ref="dialogRef" v-model="_showDialog" @hide="onDialogHide">
|
||||
<QDialog ref="dialogRef" v-model="showDialog" @hide="emit('close')">
|
||||
<QCard class="full-width dialog">
|
||||
<QCardSection class="row">
|
||||
<span class="text-h6">{{ t('Progress') }}</span>
|
||||
<QSpace />
|
||||
<QBtn icon="close" flat round dense @click="emit('close')" />
|
||||
<QBtn icon="close" flat round dense v-close-popup />
|
||||
</QCardSection>
|
||||
<QCardSection>
|
||||
<div class="column">
|
||||
|
@ -80,7 +68,7 @@ const cancel = () => {
|
|||
type="button"
|
||||
flat
|
||||
class="text-primary"
|
||||
@click="cancel()"
|
||||
v-close-popup
|
||||
>
|
||||
{{ t('globals.cancel') }}
|
||||
</QBtn>
|
||||
|
|
|
@ -2,5 +2,12 @@
|
|||
const model = defineModel({ type: Boolean, required: true });
|
||||
</script>
|
||||
<template>
|
||||
<QRadio v-model="model" v-bind="$attrs" dense :dark="true" class="q-mr-sm" />
|
||||
<QRadio
|
||||
v-model="model"
|
||||
v-bind="$attrs"
|
||||
dense
|
||||
:dark="true"
|
||||
class="q-mr-sm"
|
||||
size="xs"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
|
||||
import { useRequired } from 'src/composables/useRequired';
|
||||
import dataByOrder from 'src/utils/dataByOrder';
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
|
||||
const $attrs = useAttrs();
|
||||
const { t } = useI18n();
|
||||
const { isRequired, requiredFieldRule } = useRequired($attrs);
|
||||
const $props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Number, Object],
|
||||
|
@ -87,10 +91,7 @@ const $props = defineProps({
|
|||
default: false,
|
||||
},
|
||||
});
|
||||
const { validations } = useValidator();
|
||||
const requiredFieldRule = (val) => validations().required($attrs.required, val);
|
||||
const $attrs = useAttrs();
|
||||
const { t } = useI18n();
|
||||
|
||||
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||
const { optionLabel, optionValue, optionFilter, optionFilterValue, options, modelValue } =
|
||||
toRefs($props);
|
||||
|
@ -120,7 +121,7 @@ watch(options, (newValue) => {
|
|||
});
|
||||
|
||||
watch(modelValue, async (newValue) => {
|
||||
if (!myOptions.value.some((option) => option[optionValue.value] == newValue))
|
||||
if (!myOptions?.value?.some((option) => option[optionValue.value] == newValue))
|
||||
await fetchFilter(newValue);
|
||||
|
||||
if ($props.noOne) myOptions.value.unshift(noOneOpt.value);
|
||||
|
@ -139,8 +140,10 @@ function findKeyInOptions() {
|
|||
}
|
||||
|
||||
function setOptions(data) {
|
||||
data = dataByOrder(data, $props.sortBy);
|
||||
myOptions.value = JSON.parse(JSON.stringify(data));
|
||||
myOptionsOriginal.value = JSON.parse(JSON.stringify(data));
|
||||
emit('update:options', data);
|
||||
}
|
||||
|
||||
function filter(val, options) {
|
||||
|
@ -227,6 +230,8 @@ function nullishToTrue(value) {
|
|||
}
|
||||
|
||||
const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
|
||||
|
||||
defineExpose({ opts: myOptions });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -254,7 +259,7 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
|
|||
:fill-input="nullishToTrue($attrs['fill-input'])"
|
||||
ref="vnSelectRef"
|
||||
lazy-rules
|
||||
:class="{ required: $attrs.required }"
|
||||
:class="{ required: isRequired }"
|
||||
:rules="mixinRules"
|
||||
virtual-scroll-slice-size="options.length"
|
||||
hide-bottom-space
|
||||
|
@ -283,15 +288,4 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
|
|||
.q-field--outlined {
|
||||
max-width: 100%;
|
||||
}
|
||||
.q-field__inner {
|
||||
.q-field__control {
|
||||
min-height: auto !important;
|
||||
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
.q-field__native.row {
|
||||
min-height: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<script setup>
|
||||
const model = defineModel({ type: [String, Number], required: true });
|
||||
</script>
|
||||
<template>
|
||||
<QTime v-model="model" now-btn mask="HH:mm" />
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.q-time {
|
||||
width: 230px;
|
||||
min-width: unset;
|
||||
:deep(.q-time__header) {
|
||||
min-height: unset;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -8,7 +8,7 @@ defineProps({
|
|||
<template>
|
||||
<div :class="$q.screen.gt.md ? 'q-pb-lg' : 'q-pb-md'">
|
||||
<div class="header-link" :style="{ cursor: url ? 'pointer' : 'default' }">
|
||||
<a :href="url" :class="url ? 'link' : 'color-vn-text'">
|
||||
<a :href="url" :class="url ? 'link' : 'color-vn-text'" v-bind="$attrs">
|
||||
{{ text }}
|
||||
<QIcon v-if="url" :name="icon" />
|
||||
</a>
|
||||
|
|
|
@ -167,6 +167,7 @@ const toModule = computed(() =>
|
|||
icon="more_vert"
|
||||
round
|
||||
size="md"
|
||||
data-cy="descriptor-more-opts"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('components.cardDescriptor.moreOptions') }}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
|
|||
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import { isDialogOpened } from 'src/filters';
|
||||
|
||||
const props = defineProps({
|
||||
url: {
|
||||
|
@ -58,22 +59,6 @@ async function fetch() {
|
|||
emit('onFetch', Array.isArray(data) ? data[0] : data);
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
const showRedirectToSummaryIcon = computed(() => {
|
||||
const exist = existSummary(route.matched);
|
||||
return !isSummary.value && route.meta.moduleName && exist;
|
||||
});
|
||||
|
||||
function existSummary(routes) {
|
||||
const hasSummary = routes.some((r) => r.name === `${route.meta.moduleName}Summary`);
|
||||
if (hasSummary) return hasSummary;
|
||||
for (const current of routes) {
|
||||
if (current.path != '/' && current.children) {
|
||||
const exist = existSummary(current.children);
|
||||
if (exist) return exist;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -84,7 +69,7 @@ function existSummary(routes) {
|
|||
<div class="summaryHeader bg-primary q-pa-sm text-weight-bolder">
|
||||
<slot name="header-left">
|
||||
<router-link
|
||||
v-if="showRedirectToSummaryIcon"
|
||||
v-if="isDialogOpened()"
|
||||
class="header link"
|
||||
:to="{
|
||||
name: `${moduleName ?? route.meta.moduleName}Summary`,
|
||||
|
@ -118,6 +103,7 @@ function existSummary(routes) {
|
|||
|
||||
.cardSummary {
|
||||
width: 100%;
|
||||
max-height: 70vh;
|
||||
.summaryHeader {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
|
|
|
@ -31,7 +31,7 @@ const dialog = ref(null);
|
|||
<div class="container order-catalog-item overflow-hidden">
|
||||
<QCard class="card shadow-6">
|
||||
<div class="img-wrapper">
|
||||
<VnImg :id="item.id" class="image" />
|
||||
<VnImg :id="item.id" class="image" zoom-resolution="1600x900" />
|
||||
<div v-if="item.hex && isCatalog" class="item-color-container">
|
||||
<div
|
||||
class="item-color"
|
||||
|
|
|
@ -30,10 +30,11 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
defineEmits(['confirm', ...useDialogPluginComponent.emits]);
|
||||
const emit = defineEmits(['confirm', 'cancel', ...useDialogPluginComponent.emits]);
|
||||
defineExpose({ show: () => dialogRef.value.show(), hide: () => dialogRef.value.hide() });
|
||||
|
||||
const { dialogRef, onDialogOK } = useDialogPluginComponent();
|
||||
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
|
||||
useDialogPluginComponent();
|
||||
|
||||
const title = props.title || t('Confirm');
|
||||
const message =
|
||||
|
@ -53,9 +54,14 @@ async function confirm() {
|
|||
}
|
||||
onDialogOK(props.data);
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
emit('cancel');
|
||||
onDialogCancel();
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<QDialog ref="dialogRef">
|
||||
<QDialog ref="dialogRef" @hide="onDialogHide">
|
||||
<QCard class="q-pa-sm">
|
||||
<QCardSection class="row items-center q-pb-none">
|
||||
<QAvatar
|
||||
|
@ -67,7 +73,14 @@ async function confirm() {
|
|||
/>
|
||||
<span class="text-h6">{{ title }}</span>
|
||||
<QSpace />
|
||||
<QBtn icon="close" :disable="isLoading" flat round dense v-close-popup />
|
||||
<QBtn
|
||||
icon="close"
|
||||
:disable="isLoading"
|
||||
flat
|
||||
round
|
||||
dense
|
||||
@click="cancel()"
|
||||
/>
|
||||
</QCardSection>
|
||||
<QCardSection class="q-pb-none">
|
||||
<span v-if="message !== false" v-html="message" />
|
||||
|
@ -81,7 +94,7 @@ async function confirm() {
|
|||
color="primary"
|
||||
:disable="isLoading"
|
||||
flat
|
||||
v-close-popup
|
||||
@click="cancel()"
|
||||
/>
|
||||
<QBtn
|
||||
:label="t('globals.confirm')"
|
||||
|
@ -90,6 +103,7 @@ async function confirm() {
|
|||
@click="confirm()"
|
||||
unelevated
|
||||
autofocus
|
||||
data-cy="VnConfirm_confirm"
|
||||
/>
|
||||
</QCardActions>
|
||||
</QCard>
|
||||
|
|
|
@ -57,7 +57,6 @@ const $props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
defineExpose({ search, sanitizer });
|
||||
const emit = defineEmits([
|
||||
'update:modelValue',
|
||||
'refresh',
|
||||
|
@ -170,9 +169,29 @@ const tagsList = computed(() => {
|
|||
return tagList;
|
||||
});
|
||||
|
||||
const formatTags = (tags) => {
|
||||
const formattedTags = [];
|
||||
tags.forEach((tag) => {
|
||||
if (tag.label === 'and') {
|
||||
tag.value.forEach((item) => {
|
||||
for (const key in item) {
|
||||
formattedTags.push({ label: key, value: item[key] });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
formattedTags.push(tag);
|
||||
}
|
||||
});
|
||||
return formattedTags;
|
||||
};
|
||||
|
||||
const tags = computed(() => {
|
||||
return tagsList.value.filter((tag) => !($props.customTags || []).includes(tag.label));
|
||||
const filteredTags = tagsList.value.filter(
|
||||
(tag) => !($props.customTags || []).includes(tag.label)
|
||||
);
|
||||
return formatTags(filteredTags);
|
||||
});
|
||||
|
||||
const customTags = computed(() =>
|
||||
tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
|
||||
);
|
||||
|
@ -193,13 +212,20 @@ function formatValue(value) {
|
|||
|
||||
function sanitizer(params) {
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
if (value && typeof value === 'object') {
|
||||
if (key === 'and' && Array.isArray(value)) {
|
||||
value.forEach((item) => {
|
||||
Object.assign(params, item);
|
||||
});
|
||||
delete params[key];
|
||||
} else if (value && typeof value === 'object') {
|
||||
const param = Object.values(value)[0];
|
||||
if (typeof param == 'string') params[key] = param.replaceAll('%', '');
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
defineExpose({ search, sanitizer, userParams });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -58,7 +58,7 @@ defineExpose({
|
|||
:class="{ zoomIn: zoom }"
|
||||
:src="getUrl()"
|
||||
v-bind="$attrs"
|
||||
@click.stop="show = $props.zoom ? true : false"
|
||||
@click.stop="show = $props.zoom"
|
||||
spinner-color="primary"
|
||||
/>
|
||||
<QDialog v-if="$props.zoom" v-model="show">
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<script setup>
|
||||
defineProps({ email: { type: [String], default: null } });
|
||||
</script>
|
||||
<template>
|
||||
<QBtn
|
||||
v-if="email"
|
||||
flat
|
||||
round
|
||||
icon="email"
|
||||
size="sm"
|
||||
color="primary"
|
||||
padding="none"
|
||||
:href="`mailto:${email}`"
|
||||
@click.stop
|
||||
/>
|
||||
</template>
|
|
@ -1,16 +1,56 @@
|
|||
<script setup>
|
||||
defineProps({ phoneNumber: { type: [String, Number], default: null } });
|
||||
import { reactive, useAttrs, onBeforeMount, capitalize } from 'vue';
|
||||
import axios from 'axios';
|
||||
const props = defineProps({
|
||||
phoneNumber: { type: [String, Number], default: null },
|
||||
channel: { type: Number, default: null },
|
||||
});
|
||||
|
||||
const config = reactive({
|
||||
sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
|
||||
'say-simple': {
|
||||
icon: 'vn:saysimple',
|
||||
href: null,
|
||||
channel: props.channel,
|
||||
},
|
||||
});
|
||||
const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
|
||||
|
||||
onBeforeMount(async () => {
|
||||
let url;
|
||||
let { channel } = config[type];
|
||||
|
||||
if (type === 'say-simple') {
|
||||
url = (await axios.get('SaySimpleConfigs/findOne')).data.url;
|
||||
if (!channel)
|
||||
channel = (
|
||||
await axios.get('SaySimpleCountries/findOne', {
|
||||
params: {
|
||||
filter: { fields: ['channel'], where: { countryFk: 0 } },
|
||||
},
|
||||
})
|
||||
).data?.channel;
|
||||
|
||||
config[
|
||||
type
|
||||
].href = `${url}?customerIdentity=%2B${props.phoneNumber}&channelId=${channel}`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<QBtn
|
||||
v-if="phoneNumber"
|
||||
flat
|
||||
round
|
||||
icon="phone"
|
||||
:icon="config[type].icon"
|
||||
size="sm"
|
||||
color="primary"
|
||||
padding="none"
|
||||
:href="`sip:${phoneNumber}`"
|
||||
:href="config[type].href"
|
||||
@click.stop
|
||||
/>
|
||||
>
|
||||
<QTooltip>
|
||||
{{ capitalize(type).replace('-', '') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { ref } from 'vue';
|
||||
import { ref, reactive } from 'vue';
|
||||
import { onBeforeRouteLeave } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useQuasar } from 'quasar';
|
||||
|
@ -12,36 +12,40 @@ import VnPaginate from 'components/ui/VnPaginate.vue';
|
|||
import VnUserLink from 'components/ui/VnUserLink.vue';
|
||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
import VnAvatar from 'components/ui/VnAvatar.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnSelect from 'components/common/VnSelect.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import VnInput from 'components/common/VnInput.vue';
|
||||
|
||||
const $props = defineProps({
|
||||
url: { type: String, default: null },
|
||||
filter: { type: Object, default: () => {} },
|
||||
body: { type: Object, default: () => {} },
|
||||
addNote: { type: Boolean, default: false },
|
||||
selectType: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const state = useState();
|
||||
const quasar = useQuasar();
|
||||
const currentUser = ref(state.getUser());
|
||||
const newNote = ref('');
|
||||
const newNote = reactive({ text: null, observationTypeFk: null });
|
||||
const observationTypes = ref([]);
|
||||
const vnPaginateRef = ref();
|
||||
function handleKeyUp(event) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
if (!event.shiftKey) insert();
|
||||
}
|
||||
}
|
||||
|
||||
async function insert() {
|
||||
if (!newNote.text || ($props.selectType && !newNote.observationTypeFk)) return;
|
||||
|
||||
const body = $props.body;
|
||||
const newBody = { ...body, ...{ text: newNote.value } };
|
||||
const newBody = {
|
||||
...body,
|
||||
...{ text: newNote.text, observationTypeFk: newNote.observationTypeFk },
|
||||
};
|
||||
await axios.post($props.url, newBody);
|
||||
await vnPaginateRef.value.fetch();
|
||||
newNote.value = '';
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to, from, next) => {
|
||||
if (newNote.value)
|
||||
if (newNote.text)
|
||||
quasar.dialog({
|
||||
component: VnConfirm,
|
||||
componentProps: {
|
||||
|
@ -54,6 +58,13 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
v-if="selectType"
|
||||
url="ObservationTypes"
|
||||
:filter="{ fields: ['id', 'description'] }"
|
||||
auto-load
|
||||
@on-fetch="(data) => (observationTypes = data)"
|
||||
/>
|
||||
<QCard class="q-pa-xs q-mb-xl full-width" v-if="$props.addNote">
|
||||
<QCardSection horizontal>
|
||||
<VnAvatar :worker-id="currentUser.id" size="md" />
|
||||
|
@ -62,29 +73,42 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
{{ t('globals.now') }}
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QCardSection class="q-pa-xs q-my-none q-py-none" horizontal>
|
||||
<QInput
|
||||
v-model="newNote"
|
||||
class="full-width"
|
||||
type="textarea"
|
||||
:label="t('Add note here...')"
|
||||
filled
|
||||
size="lg"
|
||||
autogrow
|
||||
autofocus
|
||||
@keyup="handleKeyUp"
|
||||
clearable
|
||||
>
|
||||
<template #append>
|
||||
<QBtn
|
||||
:title="t('Save (Enter)')"
|
||||
icon="save"
|
||||
color="primary"
|
||||
flat
|
||||
@click="insert"
|
||||
/>
|
||||
</template>
|
||||
</QInput>
|
||||
<QCardSection class="q-px-xs q-my-none q-py-none">
|
||||
<VnRow class="full-width">
|
||||
<VnSelect
|
||||
:label="t('Observation type')"
|
||||
v-if="selectType"
|
||||
url="ObservationTypes"
|
||||
v-model="newNote.observationTypeFk"
|
||||
option-label="description"
|
||||
style="flex: 0.15"
|
||||
:required="true"
|
||||
@keyup.enter.stop="insert"
|
||||
/>
|
||||
<VnInput
|
||||
v-model.trim="newNote.text"
|
||||
type="textarea"
|
||||
:label="t('Add note here...')"
|
||||
filled
|
||||
size="lg"
|
||||
autogrow
|
||||
@keyup.enter.stop="insert"
|
||||
clearable
|
||||
:required="true"
|
||||
>
|
||||
<template #append>
|
||||
<QBtn
|
||||
:title="t('Save (Enter)')"
|
||||
icon="save"
|
||||
color="primary"
|
||||
flat
|
||||
@click="insert"
|
||||
class="q-mb-xs"
|
||||
dense
|
||||
/>
|
||||
</template>
|
||||
</VnInput>
|
||||
</VnRow>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<VnPaginate
|
||||
|
@ -98,6 +122,10 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
class="show"
|
||||
v-bind="$attrs"
|
||||
search-url="notes"
|
||||
@on-fetch="
|
||||
newNote.text = '';
|
||||
newNote.observationTypeFk = null;
|
||||
"
|
||||
>
|
||||
<template #body="{ rows }">
|
||||
<TransitionGroup name="list" tag="div" class="column items-center full-width">
|
||||
|
@ -111,13 +139,28 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
:descriptor="false"
|
||||
:worker-id="note.workerFk"
|
||||
size="md"
|
||||
:title="note.worker?.user.nickname"
|
||||
/>
|
||||
<div class="full-width row justify-between q-pa-xs">
|
||||
<VnUserLink
|
||||
:name="`${note.worker.user.nickname}`"
|
||||
:worker-id="note.worker.id"
|
||||
/>
|
||||
{{ toDateHourMin(note.created) }}
|
||||
<div>
|
||||
<VnUserLink
|
||||
:name="`${note.worker.user.nickname}`"
|
||||
:worker-id="note.worker.id"
|
||||
/>
|
||||
<QBadge
|
||||
class="q-ml-xs"
|
||||
outline
|
||||
color="grey"
|
||||
v-if="selectType && note.observationTypeFk"
|
||||
>
|
||||
{{
|
||||
observationTypes.find(
|
||||
(ot) => ot.id === note.observationTypeFk
|
||||
)?.description
|
||||
}}
|
||||
</QBadge>
|
||||
</div>
|
||||
<span v-text="toDateHourMin(note.created)" />
|
||||
</div>
|
||||
</QCardSection>
|
||||
<QCardSection class="q-pa-xs q-my-none q-py-none">
|
||||
|
@ -131,12 +174,6 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
<style lang="scss" scoped>
|
||||
.q-card {
|
||||
width: 90%;
|
||||
@media (max-width: $breakpoint-sm) {
|
||||
width: 100%;
|
||||
}
|
||||
&__section {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
.q-dialog .q-card {
|
||||
width: 400px;
|
||||
|
@ -150,11 +187,28 @@ onBeforeRouteLeave((to, from, next) => {
|
|||
opacity: 0;
|
||||
background-color: $primary;
|
||||
}
|
||||
|
||||
.vn-row > :nth-child(2) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-xs) {
|
||||
.vn-row > :deep(*) {
|
||||
margin-left: 0;
|
||||
}
|
||||
.q-card {
|
||||
width: 100%;
|
||||
|
||||
&__section {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
es:
|
||||
Add note here...: Añadir nota aquí...
|
||||
New note: Nueva nota
|
||||
Save (Enter): Guardar (Intro)
|
||||
|
||||
Observation type: Tipo de observación
|
||||
</i18n>
|
||||
|
|
|
@ -56,7 +56,7 @@ const props = defineProps({
|
|||
},
|
||||
offset: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
default: undefined,
|
||||
},
|
||||
skeleton: {
|
||||
type: Boolean,
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
<script setup>
|
||||
defineProps({ wrap: { type: Boolean, default: false } });
|
||||
</script>
|
||||
<template>
|
||||
<div class="vn-row q-gutter-md q-mb-md">
|
||||
<div class="vn-row q-gutter-md">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.vn-row {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
> :deep(*) {
|
||||
flex: 1;
|
||||
}
|
||||
|
@ -22,6 +18,9 @@ defineProps({ wrap: { type: Boolean, default: false } });
|
|||
&:not(.wrap) {
|
||||
flex-direction: column;
|
||||
}
|
||||
&[fixed] {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<script setup>
|
||||
import { useRoute } from 'vue-router';
|
||||
import { defineProps } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
routeName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
entityId: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const id = props.entityId;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link
|
||||
v-if="route?.name !== routeName"
|
||||
:to="{ name: routeName, params: { id: id } }"
|
||||
class="header link"
|
||||
:href="url"
|
||||
>
|
||||
<QIcon name="open_in_new" color="white" size="sm" />
|
||||
</router-link>
|
||||
</template>
|
|
@ -0,0 +1,55 @@
|
|||
<script setup>
|
||||
import { defineProps, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = defineProps({
|
||||
usesMana: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
manaCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
manaVal: {
|
||||
type: String,
|
||||
default: 'mana',
|
||||
},
|
||||
manaLabel: {
|
||||
type: String,
|
||||
default: 'Promotion mana',
|
||||
},
|
||||
manaClaimVal: {
|
||||
type: String,
|
||||
default: 'manaClaim',
|
||||
},
|
||||
claimLabel: {
|
||||
type: String,
|
||||
default: 'Claim mana',
|
||||
},
|
||||
});
|
||||
|
||||
const manaCode = ref(props.manaCode);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="column q-gutter-y-sm q-mt-sm">
|
||||
<QRadio
|
||||
v-model="manaCode"
|
||||
dense
|
||||
:val="manaVal"
|
||||
:label="t(manaLabel)"
|
||||
:dark="true"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
<QRadio
|
||||
v-model="manaCode"
|
||||
dense
|
||||
:val="manaClaimVal"
|
||||
:label="t(claimLabel)"
|
||||
:dark="true"
|
||||
class="q-mb-sm"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,11 @@
|
|||
import axios from 'axios';
|
||||
import { useRole } from './useRole';
|
||||
|
||||
export async function useAdvancedSummary(model, id, roles = ['hr']) {
|
||||
if (useRole().hasAny(roles)) {
|
||||
const { data } = await axios.get(`${model}/advancedSummary`, {
|
||||
params: { filter: { where: { id } } },
|
||||
});
|
||||
return Array.isArray(data) ? data[0] : data;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ import { useRouter, useRoute } from 'vue-router';
|
|||
import axios from 'axios';
|
||||
import { useArrayDataStore } from 'stores/useArrayDataStore';
|
||||
import { buildFilter } from 'filters/filterPanel';
|
||||
import { isDialogOpened } from 'src/filters';
|
||||
|
||||
const arrayDataStore = useArrayDataStore();
|
||||
|
||||
|
@ -114,8 +115,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
for (const row of response.data) store.data.push(row);
|
||||
} else {
|
||||
store.data = response.data;
|
||||
if (!document.querySelectorAll('[role="dialog"]').length)
|
||||
updateRouter && updateStateParams();
|
||||
if (!isDialogOpened()) updateRouter && updateStateParams();
|
||||
}
|
||||
|
||||
store.isLoading = false;
|
||||
|
@ -248,7 +248,8 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
|
|||
|
||||
function updateStateParams() {
|
||||
const newUrl = { path: route.path, query: { ...(route.query ?? {}) } };
|
||||
newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
|
||||
if (store?.searchUrl)
|
||||
newUrl.query[store.searchUrl] = JSON.stringify(store.currentFilter);
|
||||
|
||||
if (store.navigate) {
|
||||
const { customRouteRedirectName, searchText } = store.navigate;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import { useValidator } from 'src/composables/useValidator';
|
||||
|
||||
export function useRequired($attrs) {
|
||||
const { validations } = useValidator();
|
||||
|
||||
const isRequired = Object.keys($attrs).includes('required');
|
||||
const requiredFieldRule = (val) => validations().required(isRequired, val);
|
||||
|
||||
return {
|
||||
isRequired,
|
||||
requiredFieldRule,
|
||||
};
|
||||
}
|
|
@ -8,9 +8,13 @@ import useNotify from './useNotify';
|
|||
import { useTokenConfig } from './useTokenConfig';
|
||||
const TOKEN_MULTIMEDIA = 'tokenMultimedia';
|
||||
const TOKEN = 'token';
|
||||
|
||||
let router;
|
||||
export default {
|
||||
setup() {
|
||||
router = useRouter();
|
||||
},
|
||||
};
|
||||
export function useSession() {
|
||||
const router = useRouter();
|
||||
const { notify } = useNotify();
|
||||
let isCheckingToken = false;
|
||||
let intervalId = null;
|
||||
|
|
|
@ -288,14 +288,7 @@ input::-webkit-inner-spin-button {
|
|||
color: $info;
|
||||
}
|
||||
}
|
||||
.q-field__inner {
|
||||
.q-field__control {
|
||||
min-height: auto !important;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 2px;
|
||||
.q-field__native.row {
|
||||
min-height: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.no-visible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,19 @@ function parseJSON(str, fallback) {
|
|||
export default function (route, param) {
|
||||
// catch route query params
|
||||
const params = parseJSON(route?.query?.params, {});
|
||||
|
||||
// extract and parse filter from params
|
||||
const { filter: filterStr = '{}' } = params;
|
||||
|
||||
const where = parseJSON(filterStr, {})?.where;
|
||||
if (where && where[param] !== undefined) {
|
||||
|
||||
if (where && !param) {
|
||||
return where;
|
||||
} else if (where && where.and) {
|
||||
const foundParam = where.and.find((p) => p[param]);
|
||||
if (foundParam) {
|
||||
return foundParam[param];
|
||||
}
|
||||
} else if (where && where[param]) {
|
||||
return where[param];
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -12,8 +12,10 @@ import dateRange from './dateRange';
|
|||
import toHour from './toHour';
|
||||
import dashOrCurrency from './dashOrCurrency';
|
||||
import getParamWhere from './getParamWhere';
|
||||
import isDialogOpened from './isDialogOpened';
|
||||
|
||||
export {
|
||||
isDialogOpened,
|
||||
toLowerCase,
|
||||
toLowerCamel,
|
||||
toDate,
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default function isDialogOpened(query = '[role="dialog"]') {
|
||||
return document.querySelectorAll(query).length > 0;
|
||||
}
|
|
@ -59,7 +59,7 @@ globals:
|
|||
downloadCSVSuccess: CSV downloaded successfully
|
||||
reference: Reference
|
||||
agency: Agency
|
||||
wareHouseOut: Warehouse Out
|
||||
warehouseOut: Warehouse Out
|
||||
wareHouseIn: Warehouse In
|
||||
landed: Landed
|
||||
shipped: Shipped
|
||||
|
@ -105,6 +105,30 @@ globals:
|
|||
campaign: Campaign
|
||||
weight: Weight
|
||||
error: Ups! Something went wrong
|
||||
recalc: Recalculate
|
||||
alias: Alias
|
||||
vat: VAT
|
||||
intrastat: Intrastat
|
||||
tags: Tags
|
||||
size: Size
|
||||
producer: Producer
|
||||
origin: Origin
|
||||
state: State
|
||||
subtotal: Subtotal
|
||||
visible: Visible
|
||||
price: Price
|
||||
client: Client
|
||||
country: Country
|
||||
phone: Phone
|
||||
mobile: Mobile
|
||||
postcode: Postcode
|
||||
street: Street
|
||||
tag: Tag
|
||||
ticketId: Ticket ID
|
||||
confirmed: Confirmed
|
||||
small: Small
|
||||
medium: Medium
|
||||
big: Big
|
||||
pageTitles:
|
||||
logIn: Login
|
||||
addressEdit: Update address
|
||||
|
@ -275,6 +299,9 @@ globals:
|
|||
serial: Serial
|
||||
medical: Mutual
|
||||
RouteExtendedList: Router
|
||||
wasteRecalc: Waste recaclulate
|
||||
operator: Operator
|
||||
parking: Parking
|
||||
supplier: Supplier
|
||||
created: Created
|
||||
worker: Worker
|
||||
|
@ -297,9 +324,16 @@ globals:
|
|||
salesPersonFk: Sales person
|
||||
warehouseFk: Warehouse
|
||||
provinceFk: Province
|
||||
from: From
|
||||
To: To
|
||||
stateFk: State
|
||||
email: Email
|
||||
SSN: SSN
|
||||
fi: FI
|
||||
myTeam: My team
|
||||
departmentFk: Department
|
||||
changePass: Change password
|
||||
deleteConfirmTitle: Delete selected elements
|
||||
changeState: Change state
|
||||
raid: 'Raid {daysInForward} days'
|
||||
errors:
|
||||
statusUnauthorized: Access denied
|
||||
statusInternalServerError: An internal server error has ocurred
|
||||
|
@ -319,16 +353,12 @@ login:
|
|||
loginError: Invalid username or password
|
||||
fieldRequired: This field is required
|
||||
twoFactorRequired: Two-factor verification required
|
||||
twoFactor:
|
||||
code: Code
|
||||
twoFactorRequired:
|
||||
validate: Validate
|
||||
insert: Enter the verification code
|
||||
explanation: >-
|
||||
Please, enter the verification code that we have sent to your email in the
|
||||
next 5 minutes
|
||||
verifyEmail:
|
||||
pageTitles:
|
||||
verifyEmail: Email verification
|
||||
recoverPassword:
|
||||
userOrEmail: User or recovery email
|
||||
explanation: >-
|
||||
|
@ -340,15 +370,7 @@ resetPassword:
|
|||
entry:
|
||||
list:
|
||||
newEntry: New entry
|
||||
landed: Landed
|
||||
invoiceNumber: Invoice number
|
||||
supplier: Supplier
|
||||
booked: Booked
|
||||
confirmed: Confirmed
|
||||
ordered: Ordered
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
reference: Reference
|
||||
created: Creation
|
||||
supplierFk: Supplier
|
||||
isBooked: Booked
|
||||
|
@ -357,245 +379,121 @@ entry:
|
|||
companyFk: Company
|
||||
travelFk: Travel
|
||||
isExcludedFromAvailable: Inventory
|
||||
isRaid: Raid
|
||||
invoiceAmount: Import
|
||||
summary:
|
||||
commission: Commission
|
||||
currency: Currency
|
||||
company: Company
|
||||
reference: Reference
|
||||
invoiceNumber: Invoice number
|
||||
ordered: Ordered
|
||||
confirmed: Confirmed
|
||||
booked: Booked
|
||||
raid: Raid
|
||||
excludedFromAvailable: Inventory
|
||||
travelReference: Reference
|
||||
travelAgency: Agency
|
||||
travelShipped: Shipped
|
||||
travelWarehouseOut: Warehouse Out
|
||||
travelDelivered: Delivered
|
||||
travelLanded: Landed
|
||||
travelWarehouseIn: Warehouse In
|
||||
travelReceived: Received
|
||||
buys: Buys
|
||||
quantity: Quantity
|
||||
stickers: Stickers
|
||||
package: Package
|
||||
weight: Weight
|
||||
packing: Packing
|
||||
grouping: Grouping
|
||||
buyingValue: Buying value
|
||||
import: Import
|
||||
pvp: PVP
|
||||
item: Item
|
||||
basicData:
|
||||
supplier: Supplier
|
||||
travel: Travel
|
||||
reference: Reference
|
||||
invoiceNumber: Invoice number
|
||||
company: Company
|
||||
currency: Currency
|
||||
commission: Commission
|
||||
observation: Observation
|
||||
ordered: Ordered
|
||||
confirmed: Confirmed
|
||||
booked: Booked
|
||||
raid: Raid
|
||||
excludedFromAvailable: Inventory
|
||||
agency: Agency
|
||||
warehouseOut: Warehouse Out
|
||||
warehouseIn: Warehouse In
|
||||
shipped: Shipped
|
||||
landed: Landed
|
||||
id: ID
|
||||
buys:
|
||||
groupingPrice: Grouping price
|
||||
packingPrice: Packing price
|
||||
reference: Reference
|
||||
observations: Observations
|
||||
item: Item
|
||||
size: Size
|
||||
packing: Packing
|
||||
grouping: Grouping
|
||||
buyingValue: Buying value
|
||||
packagingFk: Box
|
||||
file: File
|
||||
name: Name
|
||||
producer: Producer
|
||||
type: Type
|
||||
color: Color
|
||||
id: ID
|
||||
printedStickers: Printed stickers
|
||||
notes:
|
||||
observationType: Observation type
|
||||
descriptor:
|
||||
agency: Agency
|
||||
landed: Landed
|
||||
warehouseOut: Warehouse Out
|
||||
latestBuys:
|
||||
tableVisibleColumns:
|
||||
image: Picture
|
||||
itemFk: Item ID
|
||||
packing: Packing
|
||||
grouping: Grouping
|
||||
quantity: Quantity
|
||||
size: Size
|
||||
tags: Tags
|
||||
type: Type
|
||||
intrastat: Intrastat
|
||||
origin: Origin
|
||||
weightByPiece: Weight/Piece
|
||||
isActive: Active
|
||||
family: Family
|
||||
entryFk: Entry
|
||||
buyingValue: Buying value
|
||||
freightValue: Freight value
|
||||
comissionValue: Commission value
|
||||
description: Description
|
||||
packageValue: Package value
|
||||
isIgnored: Is ignored
|
||||
price2: Grouping
|
||||
price3: Packing
|
||||
minPrice: Min
|
||||
ektFk: Ekt
|
||||
weight: Weight
|
||||
packagingFk: Package
|
||||
packingOut: Package out
|
||||
landing: Landing
|
||||
isExcludedFromAvailable: Es inventory
|
||||
isRaid: Raid
|
||||
ticket:
|
||||
pageTitles:
|
||||
tickets: Tickets
|
||||
list: List
|
||||
ticketCreate: New ticket
|
||||
summary: Summary
|
||||
basicData: Basic Data
|
||||
boxing: Boxing
|
||||
sms: Sms
|
||||
notes: Notes
|
||||
sale: Sale
|
||||
dms: File management
|
||||
volume: Volume
|
||||
observation: Notes
|
||||
ticketAdvance: Advance tickets
|
||||
futureTickets: Future tickets
|
||||
purchaseRequest: Purchase request
|
||||
weeklyTickets: Weekly tickets
|
||||
list:
|
||||
nickname: Nickname
|
||||
state: State
|
||||
shipped: Shipped
|
||||
landed: Landed
|
||||
salesPerson: Sales person
|
||||
total: Total
|
||||
card:
|
||||
ticketId: Ticket ID
|
||||
state: State
|
||||
customerId: Customer ID
|
||||
salesPerson: Sales person
|
||||
agency: Agency
|
||||
shipped: Shipped
|
||||
warehouse: Warehouse
|
||||
customerCard: Customer card
|
||||
alias: Alias
|
||||
ticketList: Ticket List
|
||||
newOrder: New Order
|
||||
boxing:
|
||||
expedition: Expedition
|
||||
item: Item
|
||||
created: Created
|
||||
worker: Worker
|
||||
selectTime: 'Select time:'
|
||||
selectVideo: 'Select video:'
|
||||
notFound: No videos available
|
||||
summary:
|
||||
state: State
|
||||
salesPerson: Sales person
|
||||
agency: Agency
|
||||
zone: Zone
|
||||
warehouse: Warehouse
|
||||
collection: Collection
|
||||
route: Route
|
||||
invoice: Invoice
|
||||
shipped: Shipped
|
||||
landed: Landed
|
||||
consigneePhone: Consignee phone
|
||||
consigneeMobile: Consignee mobile
|
||||
consigneeAddress: Consignee address
|
||||
clientPhone: Client phone
|
||||
clientMobile: Client mobile
|
||||
consignee: Consignee
|
||||
subtotal: Subtotal
|
||||
vat: VAT
|
||||
total: Total
|
||||
saleLines: Line items
|
||||
item: Item
|
||||
visible: Visible
|
||||
available: Available
|
||||
quantity: Quantity
|
||||
price: Price
|
||||
discount: Discount
|
||||
packing: Packing
|
||||
hasComponentLack: Component lack
|
||||
itemShortage: Not visible
|
||||
claim: Claim
|
||||
reserved: Reserved
|
||||
created: Created
|
||||
package: Package
|
||||
taxClass: Tax class
|
||||
services: Services
|
||||
changeState: Change state
|
||||
requester: Requester
|
||||
atender: Atender
|
||||
request: Request
|
||||
weight: Weight
|
||||
goTo: Go to
|
||||
summaryAmount: Summary
|
||||
purchaseRequest: Purchase request
|
||||
service: Service
|
||||
description: Description
|
||||
attender: Attender
|
||||
ok: Ok
|
||||
create:
|
||||
client: Client
|
||||
address: Address
|
||||
landed: Landed
|
||||
warehouse: Warehouse
|
||||
agency: Agency
|
||||
invoiceOut:
|
||||
list:
|
||||
ref: Reference
|
||||
issued: Issued
|
||||
shortIssued: Issued
|
||||
client: Client
|
||||
created: Created
|
||||
shortCreated: Created
|
||||
company: Company
|
||||
dued: Due date
|
||||
shortDued: Due date
|
||||
amount: Amount
|
||||
card:
|
||||
issued: Issued
|
||||
client: Client
|
||||
company: Company
|
||||
customerCard: Customer card
|
||||
summary:
|
||||
issued: Issued
|
||||
created: Created
|
||||
dued: Due
|
||||
booked: Booked
|
||||
company: Company
|
||||
taxBreakdown: Tax breakdown
|
||||
type: Type
|
||||
taxableBase: Taxable base
|
||||
rate: Rate
|
||||
fee: Fee
|
||||
tickets: Tickets
|
||||
ticketId: Ticket id
|
||||
nickname: Alias
|
||||
shipped: Shipped
|
||||
totalWithVat: Amount
|
||||
globalInvoices:
|
||||
errors:
|
||||
|
@ -610,22 +508,14 @@ invoiceOut:
|
|||
criticalInvoiceError: 'Critical invoicing error, process stopped'
|
||||
invalidSerialTypeForAll: The serial type must be global when invoicing all clients
|
||||
table:
|
||||
client: Client
|
||||
addressId: Address id
|
||||
streetAddress: Street
|
||||
statusCard:
|
||||
percentageText: '{getPercentage}% {getAddressNumber} of {getNAddresses}'
|
||||
pdfsNumberText: '{nPdfs} of {totalPdfs} PDFs'
|
||||
negativeBases:
|
||||
from: From
|
||||
to: To
|
||||
company: Company
|
||||
country: Country
|
||||
clientId: Client Id
|
||||
client: Client
|
||||
amount: Amount
|
||||
base: Base
|
||||
ticketId: Ticket Id
|
||||
active: Active
|
||||
hasToInvoice: Has to Invoice
|
||||
verifiedData: Verified Data
|
||||
|
@ -638,77 +528,39 @@ shelving:
|
|||
priority: Priority
|
||||
newShelving: New Shelving
|
||||
summary:
|
||||
code: Code
|
||||
parking: Parking
|
||||
priority: Priority
|
||||
worker: Worker
|
||||
recyclable: Recyclable
|
||||
basicData:
|
||||
code: Code
|
||||
parking: Parking
|
||||
priority: Priority
|
||||
recyclable: Recyclable
|
||||
parking:
|
||||
pickingOrder: Picking order
|
||||
sector: Sector
|
||||
row: Row
|
||||
column: Column
|
||||
pageTitles:
|
||||
parking: Parking
|
||||
searchBar:
|
||||
info: You can search by parking code
|
||||
label: Search parking...
|
||||
order:
|
||||
field:
|
||||
salesPersonFk: Sales Person
|
||||
clientFk: Client
|
||||
isConfirmed: Confirmed
|
||||
created: Created
|
||||
landed: Landed
|
||||
hour: Hour
|
||||
agency: Agency
|
||||
total: Total
|
||||
form:
|
||||
clientFk: Client
|
||||
addressFk: Address
|
||||
landed: Landed
|
||||
agencyModeFk: Agency
|
||||
list:
|
||||
newOrder: New Order
|
||||
summary:
|
||||
basket: Basket
|
||||
nickname: Nickname
|
||||
company: Company
|
||||
confirmed: Confirmed
|
||||
notConfirmed: Not confirmed
|
||||
created: Created
|
||||
landed: Landed
|
||||
phone: Phone
|
||||
createdFrom: Created From
|
||||
address: Address
|
||||
notes: Notes
|
||||
subtotal: Subtotal
|
||||
total: Total
|
||||
vat: VAT
|
||||
state: State
|
||||
alias: Alias
|
||||
items: Items
|
||||
orderTicketList: Order Ticket List
|
||||
details: Details
|
||||
item: Item
|
||||
quantity: Quantity
|
||||
price: Price
|
||||
amount: Amount
|
||||
confirm: Confirm
|
||||
confirmLines: Confirm lines
|
||||
department:
|
||||
pageTitles:
|
||||
basicData: Basic data
|
||||
department: Department
|
||||
summary: Summary
|
||||
name: Name
|
||||
code: Code
|
||||
chat: Chat
|
||||
bossDepartment: Boss Department
|
||||
email: Email
|
||||
selfConsumptionCustomer: Self-consumption customer
|
||||
telework: Telework
|
||||
notifyOnErrors: Notify on errors
|
||||
|
@ -717,46 +569,11 @@ department:
|
|||
hasToSendMail: Send check-ins by email
|
||||
departmentRemoved: Department removed
|
||||
worker:
|
||||
pageTitles:
|
||||
workers: Workers
|
||||
list: List
|
||||
basicData: Basic data
|
||||
summary: Summary
|
||||
notifications: Notifications
|
||||
workerCreate: New worker
|
||||
department: Department
|
||||
pda: PDA
|
||||
notes: Notas
|
||||
dms: My documentation
|
||||
pbx: Private Branch Exchange
|
||||
log: Log
|
||||
calendar: Calendar
|
||||
timeControl: Time control
|
||||
locker: Locker
|
||||
balance: Balance
|
||||
medical: Medical
|
||||
list:
|
||||
name: Name
|
||||
email: Email
|
||||
phone: Phone
|
||||
mobile: Mobile
|
||||
active: Active
|
||||
department: Department
|
||||
schedule: Schedule
|
||||
newWorker: New worker
|
||||
card:
|
||||
workerId: Worker ID
|
||||
user: User
|
||||
name: Name
|
||||
email: Email
|
||||
phone: Phone
|
||||
mobile: Mobile
|
||||
active: Active
|
||||
warehouse: Warehouse
|
||||
agency: Agency
|
||||
salesPerson: Sales person
|
||||
summary:
|
||||
basicData: Basic data
|
||||
boss: Boss
|
||||
phoneExtension: Phone extension
|
||||
entPhone: Enterprise phone
|
||||
|
@ -788,40 +605,30 @@ worker:
|
|||
serialNumber: Serial number
|
||||
removePDA: Deallocate PDA
|
||||
create:
|
||||
name: Name
|
||||
lastName: Last name
|
||||
birth: Birth
|
||||
fi: Fi
|
||||
code: Worker code
|
||||
phone: Phone
|
||||
postcode: Postcode
|
||||
province: Province
|
||||
city: City
|
||||
street: Street
|
||||
webUser: Web user
|
||||
personalEmail: Personal email
|
||||
company: Company
|
||||
boss: Boss
|
||||
payMethods: Pay method
|
||||
iban: IBAN
|
||||
bankEntity: Swift / BIC
|
||||
formation:
|
||||
tableVisibleColumns:
|
||||
course: Curso
|
||||
startDate: Fecha Inicio
|
||||
endDate: Fecha Fin
|
||||
center: Centro Formación
|
||||
invoice: Factura
|
||||
amount: Importe
|
||||
remark: Bonficado
|
||||
hasDiploma: Diploma
|
||||
course: Course
|
||||
startDate: Start date
|
||||
endDate: End date
|
||||
center: Training center
|
||||
invoice: Invoice
|
||||
remark: Remark
|
||||
hasDiploma: Has diploma
|
||||
medical:
|
||||
tableVisibleColumns:
|
||||
date: Date
|
||||
time: Hour
|
||||
center: Formation Center
|
||||
invoice: Invoice
|
||||
amount: Amount
|
||||
isFit: Fit
|
||||
remark: Observations
|
||||
imageNotFound: Image not found
|
||||
|
@ -832,19 +639,20 @@ worker:
|
|||
debit: Debt
|
||||
credit: Have
|
||||
concept: Concept
|
||||
operator:
|
||||
numberOfWagons: Number of wagons
|
||||
train: Train
|
||||
itemPackingType: Item packing type
|
||||
warehouse: Warehouse
|
||||
sector: Sector
|
||||
labeler: Printer
|
||||
linesLimit: Lines limit
|
||||
volumeLimit: Volume limit
|
||||
sizeLimit: Size limit
|
||||
isOnReservationMode: Reservation mode
|
||||
machine: Machine
|
||||
wagon:
|
||||
pageTitles:
|
||||
wagons: Wagons
|
||||
wagonsList: Wagons List
|
||||
wagonCreate: Create wagon
|
||||
wagonEdit: Edit wagon
|
||||
typesList: Types List
|
||||
typeCreate: Create type
|
||||
typeEdit: Edit type
|
||||
wagonCounter: Trolley counter
|
||||
wagonTray: Tray List
|
||||
type:
|
||||
name: Name
|
||||
submit: Submit
|
||||
reset: Reset
|
||||
trayColor: Tray color
|
||||
|
@ -852,13 +660,10 @@ wagon:
|
|||
list:
|
||||
plate: Plate
|
||||
volume: Volume
|
||||
type: Type
|
||||
remove: Remove
|
||||
removeItem: Wagon removed successfully
|
||||
create:
|
||||
plate: Plate
|
||||
volume: Volume
|
||||
type: Type
|
||||
label: Label
|
||||
warnings:
|
||||
noData: No data available
|
||||
|
@ -875,26 +680,17 @@ wagon:
|
|||
supplier:
|
||||
list:
|
||||
payMethod: Pay method
|
||||
payDeadline: Pay deadline
|
||||
payDay: Pay day
|
||||
account: Account
|
||||
newSupplier: New supplier
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
name: Name
|
||||
nif: NIF/CIF
|
||||
nickname: Alias
|
||||
account: Account
|
||||
payMethod: Pay Method
|
||||
payDay: Pay Day
|
||||
country: Country
|
||||
summary:
|
||||
responsible: Responsible
|
||||
notes: Notes
|
||||
verified: Verified
|
||||
isActive: Is active
|
||||
billingData: Billing data
|
||||
payMethod: Pay method
|
||||
payDeadline: Pay deadline
|
||||
payDay: Pay day
|
||||
account: Account
|
||||
|
@ -907,20 +703,16 @@ supplier:
|
|||
fiscalAddress: Fiscal address
|
||||
socialName: Social name
|
||||
taxNumber: Tax number
|
||||
street: Street
|
||||
city: City
|
||||
postCode: Postcode
|
||||
province: Province
|
||||
country: Country
|
||||
create:
|
||||
supplierName: Supplier name
|
||||
basicData:
|
||||
alias: Alias
|
||||
workerFk: Responsible
|
||||
isSerious: Verified
|
||||
isActive: Active
|
||||
isPayMethodChecked: PayMethod checked
|
||||
note: Notes
|
||||
size: Size
|
||||
fiscalData:
|
||||
name: Social name *
|
||||
nif: Tax number *
|
||||
|
@ -929,36 +721,18 @@ supplier:
|
|||
sageWithholdingFk: Sage withholding
|
||||
sageTransactionTypeFk: Sage transaction type
|
||||
supplierActivityFk: Supplier activity
|
||||
healthRegister: Health register
|
||||
street: Street
|
||||
postcode: Postcode
|
||||
city: City *
|
||||
provinceFk: Province
|
||||
country: Country
|
||||
isTrucker: Trucker
|
||||
isVies: Vies
|
||||
billingData:
|
||||
payMethodFk: Billing data
|
||||
payDemFk: Payment deadline
|
||||
payDay: Pay day
|
||||
accounts:
|
||||
iban: Iban
|
||||
bankEntity: Bank entity
|
||||
beneficiary: Beneficiary
|
||||
contacts:
|
||||
name: Name
|
||||
phone: Phone
|
||||
mobile: Mobile
|
||||
email: Email
|
||||
observation: Notes
|
||||
addresses:
|
||||
street: Street
|
||||
postcode: Postcode
|
||||
phone: Phone
|
||||
name: Name
|
||||
city: City
|
||||
province: Province
|
||||
mobile: Mobile
|
||||
agencyTerms:
|
||||
agencyFk: Agency
|
||||
minimumM3: Minimum M3
|
||||
|
@ -970,25 +744,16 @@ supplier:
|
|||
addRow: Add row
|
||||
consumption:
|
||||
entry: Entry
|
||||
date: Date
|
||||
reference: Reference
|
||||
travel:
|
||||
travelList:
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
ref: Reference
|
||||
agency: Agency
|
||||
shipped: Shipped
|
||||
landed: Landed
|
||||
shipHour: Shipment Hour
|
||||
landHour: Landing Hour
|
||||
warehouseIn: Warehouse in
|
||||
warehouseOut: Warehouse out
|
||||
totalEntries: Total entries
|
||||
totalEntriesTooltip: Total entries
|
||||
daysOnward: Landed days onwards
|
||||
summary:
|
||||
confirmed: Confirmed
|
||||
entryId: Entry Id
|
||||
freight: Freight
|
||||
package: Package
|
||||
|
@ -1001,66 +766,30 @@ travel:
|
|||
AddEntry: Add entry
|
||||
thermographs: Thermographs
|
||||
hb: HB
|
||||
variables:
|
||||
search: Id/Reference
|
||||
agencyModeFk: Agency
|
||||
warehouseInFk: ' Warehouse In'
|
||||
warehouseOutFk: Warehouse Out
|
||||
landedFrom: Landed from
|
||||
landedTo: Landed to
|
||||
continent: Continent out
|
||||
totalEntries: Total entries
|
||||
basicData:
|
||||
reference: Reference
|
||||
agency: Agency
|
||||
shipped: Shipped
|
||||
landed: Landed
|
||||
warehouseOut: Warehouse Out
|
||||
warehouseIn: Warehouse In
|
||||
delivered: Delivered
|
||||
received: Received
|
||||
daysInForward: Days in forward
|
||||
thermographs:
|
||||
code: Code
|
||||
temperature: Temperature
|
||||
state: State
|
||||
destination: Destination
|
||||
created: Created
|
||||
thermograph: Thermograph
|
||||
reference: Reference
|
||||
type: Type
|
||||
company: Company
|
||||
warehouse: Warehouse
|
||||
travelFileDescription: 'Travel id { travelId }'
|
||||
file: File
|
||||
item:
|
||||
descriptor:
|
||||
item: Item
|
||||
buyer: Buyer
|
||||
color: Color
|
||||
category: Category
|
||||
stems: Stems
|
||||
visible: Visible
|
||||
available: Available
|
||||
warehouseText: 'Calculated on the warehouse of { warehouseName }'
|
||||
itemDiary: Item diary
|
||||
producer: Producer
|
||||
list:
|
||||
id: Identifier
|
||||
grouping: Grouping
|
||||
packing: Packing
|
||||
description: Description
|
||||
stems: Stems
|
||||
category: Category
|
||||
typeName: Type
|
||||
intrastat: Intrastat
|
||||
isActive: Active
|
||||
size: Size
|
||||
origin: Origin
|
||||
userName: Buyer
|
||||
weightByPiece: Weight/Piece
|
||||
stemMultiplier: Multiplier
|
||||
producer: Producer
|
||||
landed: Landed
|
||||
fixedPrice:
|
||||
itemFk: Item ID
|
||||
groupingPrice: Grouping price
|
||||
|
@ -1069,81 +798,57 @@ item:
|
|||
minPrice: Min price
|
||||
started: Started
|
||||
ended: Ended
|
||||
warehouse: Warehouse
|
||||
create:
|
||||
name: Name
|
||||
tag: Tag
|
||||
priority: Priority
|
||||
type: Type
|
||||
intrastat: Intrastat
|
||||
origin: Origin
|
||||
buyRequest:
|
||||
ticketId: 'Ticket ID'
|
||||
shipped: 'Shipped'
|
||||
requester: 'Requester'
|
||||
requested: 'Requested'
|
||||
price: 'Price'
|
||||
attender: 'Atender'
|
||||
item: 'Item'
|
||||
achieved: 'Achieved'
|
||||
concept: 'Concept'
|
||||
state: 'State'
|
||||
requester: Requester
|
||||
requested: Requested
|
||||
attender: Atender
|
||||
achieved: Achieved
|
||||
concept: Concept
|
||||
summary:
|
||||
basicData: 'Basic data'
|
||||
otherData: 'Other data'
|
||||
description: 'Description'
|
||||
tax: 'Tax'
|
||||
tags: 'Tags'
|
||||
botanical: 'Botanical'
|
||||
barcode: 'Barcode'
|
||||
name: 'Nombre'
|
||||
completeName: 'Nombre completo'
|
||||
family: 'Familia'
|
||||
size: 'Medida'
|
||||
origin: 'Origen'
|
||||
stems: 'Tallos'
|
||||
multiplier: 'Multiplicador'
|
||||
buyer: 'Comprador'
|
||||
doPhoto: 'Do photo'
|
||||
intrastatCode: 'Código intrastat'
|
||||
intrastat: 'Intrastat'
|
||||
ref: 'Referencia'
|
||||
relevance: 'Relevancia'
|
||||
weight: 'Peso (gramos)/tallo'
|
||||
units: 'Unidades/caja'
|
||||
expense: 'Gasto'
|
||||
generic: 'Genérico'
|
||||
recycledPlastic: 'Plástico reciclado'
|
||||
nonRecycledPlastic: 'Plástico no reciclado'
|
||||
minSalesQuantity: 'Cantidad mínima de venta'
|
||||
genus: 'Genus'
|
||||
specie: 'Specie'
|
||||
otherData: Other data
|
||||
tax: Tax
|
||||
botanical: Botanical
|
||||
barcode: Barcode
|
||||
completeName: Complete name
|
||||
family: Familiy
|
||||
stems: Stems
|
||||
multiplier: Multiplier
|
||||
buyer: Buyer
|
||||
doPhoto: Do photo
|
||||
intrastatCode: Intrastat code
|
||||
ref: Reference
|
||||
relevance: Relevance
|
||||
weight: Weight (gram)/stem
|
||||
units: Units/box
|
||||
expense: Expense
|
||||
generic: Generic
|
||||
recycledPlastic: Recycled plastic
|
||||
nonRecycledPlastic: Non recycled plastic
|
||||
minSalesQuantity: Min sales quantity
|
||||
genus: Genus
|
||||
specie: Specie
|
||||
components:
|
||||
topbar: {}
|
||||
itemsFilterPanel:
|
||||
typeFk: Type
|
||||
tag: Tag
|
||||
value: Value
|
||||
# ItemFixedPriceFilter
|
||||
buyerFk: Buyer
|
||||
warehouseFk: Warehouse
|
||||
started: From
|
||||
ended: To
|
||||
mine: For me
|
||||
hasMinPrice: Minimum price
|
||||
# LatestBuysFilter
|
||||
salesPersonFk: Buyer
|
||||
supplierFk: Supplier
|
||||
from: From
|
||||
to: To
|
||||
active: Is active
|
||||
visible: Is visible
|
||||
floramondo: Is floramondo
|
||||
showBadDates: Show future items
|
||||
userPanel:
|
||||
copyToken: Token copied to clipboard
|
||||
settings: Settings
|
||||
logOut: Log Out
|
||||
localWarehouse: Local warehouse
|
||||
localBank: Local bank
|
||||
localCompany: Local company
|
||||
|
@ -1151,7 +856,6 @@ components:
|
|||
userCompany: User company
|
||||
smartCard:
|
||||
downloadFile: Download file
|
||||
clone: Clone
|
||||
openCard: View
|
||||
openSummary: Summary
|
||||
viewSummary: Summary
|
||||
|
|
|
@ -58,8 +58,8 @@ globals:
|
|||
downloadCSVSuccess: Descarga de CSV exitosa
|
||||
reference: Referencia
|
||||
agency: Agencia
|
||||
wareHouseOut: Alm. salida
|
||||
wareHouseIn: Alm. entrada
|
||||
warehouseOut: Alm. salida
|
||||
warehouseIn: Alm. entrada
|
||||
landed: F. entrega
|
||||
shipped: F. envío
|
||||
totalEntries: Ent. totales
|
||||
|
@ -107,6 +107,30 @@ globals:
|
|||
campaign: Campaña
|
||||
weight: Peso
|
||||
error: ¡Ups! Algo salió mal
|
||||
recalc: Recalcular
|
||||
alias: Alias
|
||||
vat: IVA
|
||||
intrastat: Intrastat
|
||||
tags: Etiquetas
|
||||
size: Medida
|
||||
producer: Productor
|
||||
origin: Origen
|
||||
state: Estado
|
||||
subtotal: Subtotal
|
||||
visible: Visible
|
||||
price: Precio
|
||||
client: Cliente
|
||||
country: País
|
||||
phone: Teléfono
|
||||
mobile: Móvil
|
||||
postcode: Código postal
|
||||
street: Dirección
|
||||
tag: Etiqueta
|
||||
ticketId: ID ticket
|
||||
confirmed: Confirmado
|
||||
small: Pequeño/a
|
||||
medium: Mediano/a
|
||||
big: Grande
|
||||
pageTitles:
|
||||
logIn: Inicio de sesión
|
||||
addressEdit: Modificar consignatario
|
||||
|
@ -279,6 +303,9 @@ globals:
|
|||
clientsActionsMonitor: Clientes y acciones
|
||||
serial: Facturas por serie
|
||||
medical: Mutua
|
||||
wasteRecalc: Recalcular mermas
|
||||
operator: Operario
|
||||
parking: Parking
|
||||
supplier: Proveedor
|
||||
created: Fecha creación
|
||||
worker: Trabajador
|
||||
|
@ -301,9 +328,16 @@ globals:
|
|||
salesPersonFk: Comercial
|
||||
warehouseFk: Almacén
|
||||
provinceFk: Provincia
|
||||
from: Desde
|
||||
To: Hasta
|
||||
stateFk: Estado
|
||||
departmentFk: Departamento
|
||||
email: Correo
|
||||
SSN: NSS
|
||||
fi: NIF
|
||||
myTeam: Mi equipo
|
||||
changePass: Cambiar contraseña
|
||||
deleteConfirmTitle: Eliminar los elementos seleccionados
|
||||
changeState: Cambiar estado
|
||||
raid: 'Redada {daysInForward} días'
|
||||
errors:
|
||||
statusUnauthorized: Acceso denegado
|
||||
statusInternalServerError: Ha ocurrido un error interno del servidor
|
||||
|
@ -324,13 +358,9 @@ login:
|
|||
fieldRequired: Este campo es obligatorio
|
||||
twoFactorRequired: Verificación de doble factor requerida
|
||||
twoFactor:
|
||||
code: Código
|
||||
validate: Validar
|
||||
insert: Introduce el código de verificación
|
||||
explanation: Por favor introduce el código de verificación que te hemos enviado a tu email en los próximos 5 minutos
|
||||
verifyEmail:
|
||||
pageTitles:
|
||||
verifyEmail: Verificación de correo
|
||||
recoverPassword:
|
||||
userOrEmail: Usuario o correo de recuperación
|
||||
explanation: >-
|
||||
|
@ -342,15 +372,7 @@ resetPassword:
|
|||
entry:
|
||||
list:
|
||||
newEntry: Nueva entrada
|
||||
landed: F. entrega
|
||||
invoiceNumber: Núm. factura
|
||||
supplier: Proveedor
|
||||
booked: Asentado
|
||||
confirmed: Confirmado
|
||||
ordered: Pedida
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
reference: Referencia
|
||||
created: Creación
|
||||
supplierFk: Proveedor
|
||||
isBooked: Asentado
|
||||
|
@ -359,18 +381,13 @@ entry:
|
|||
companyFk: Empresa
|
||||
travelFk: Envio
|
||||
isExcludedFromAvailable: Inventario
|
||||
isRaid: Redada
|
||||
invoiceAmount: Importe
|
||||
summary:
|
||||
commission: Comisión
|
||||
currency: Moneda
|
||||
company: Empresa
|
||||
reference: Referencia
|
||||
invoiceNumber: Núm. factura
|
||||
ordered: Pedida
|
||||
confirmed: Confirmada
|
||||
booked: Contabilizada
|
||||
raid: Redada
|
||||
excludedFromAvailable: Inventario
|
||||
travelReference: Referencia
|
||||
travelAgency: Agencia
|
||||
|
@ -378,233 +395,108 @@ entry:
|
|||
travelWarehouseOut: Alm. salida
|
||||
travelDelivered: Enviada
|
||||
travelLanded: F. entrega
|
||||
travelWarehouseIn: Alm. entrada
|
||||
travelReceived: Recibida
|
||||
buys: Compras
|
||||
quantity: Cantidad
|
||||
stickers: Etiquetas
|
||||
package: Embalaje
|
||||
weight: Peso
|
||||
packing: Packing
|
||||
grouping: Grouping
|
||||
buyingValue: Coste
|
||||
import: Importe
|
||||
pvp: PVP
|
||||
item: Artículo
|
||||
basicData:
|
||||
supplier: Proveedor
|
||||
travel: Envío
|
||||
reference: Referencia
|
||||
invoiceNumber: Núm. factura
|
||||
company: Empresa
|
||||
currency: Moneda
|
||||
observation: Observación
|
||||
commission: Comisión
|
||||
ordered: Pedida
|
||||
confirmed: Confirmado
|
||||
booked: Asentado
|
||||
raid: Redada
|
||||
excludedFromAvailable: Inventario
|
||||
agency: Agencia
|
||||
warehouseOut: Alm. salida
|
||||
warehouseIn: Alm. entrada
|
||||
shipped: F. envío
|
||||
landed: F. entrega
|
||||
id: ID
|
||||
buys:
|
||||
groupingPrice: Precio grouping
|
||||
packingPrice: Precio packing
|
||||
reference: Referencia
|
||||
observations: Observaciónes
|
||||
item: Artículo
|
||||
size: Medida
|
||||
packing: Packing
|
||||
grouping: Grouping
|
||||
buyingValue: Coste
|
||||
packagingFk: Embalaje
|
||||
file: Fichero
|
||||
name: Nombre
|
||||
producer: Productor
|
||||
type: Tipo
|
||||
color: Color
|
||||
id: ID
|
||||
printedStickers: Etiquetas impresas
|
||||
notes:
|
||||
observationType: Tipo de observación
|
||||
descriptor:
|
||||
agency: Agencia
|
||||
landed: F. entrega
|
||||
warehouseOut: Alm. salida
|
||||
latestBuys:
|
||||
tableVisibleColumns:
|
||||
image: Foto
|
||||
itemFk: Id Artículo
|
||||
packing: packing
|
||||
grouping: Grouping
|
||||
quantity: Cantidad
|
||||
size: Medida
|
||||
tags: Etiquetas
|
||||
type: Tipo
|
||||
intrastat: Intrastat
|
||||
origin: Origen
|
||||
weightByPiece: Peso (gramos)/tallo
|
||||
isActive: Activo
|
||||
family: Familia
|
||||
entryFk: Entrada
|
||||
buyingValue: Coste
|
||||
freightValue: Porte
|
||||
comissionValue: Comisión
|
||||
description: Descripción
|
||||
packageValue: Embalaje
|
||||
isIgnored: Ignorado
|
||||
price2: Grouping
|
||||
price3: Packing
|
||||
minPrice: Min
|
||||
ektFk: Ekt
|
||||
weight: Peso
|
||||
packagingFk: Embalaje
|
||||
packingOut: Embalaje envíos
|
||||
landing: Llegada
|
||||
isExcludedFromAvailable: Es inventario
|
||||
isRaid: Redada
|
||||
ticket:
|
||||
pageTitles:
|
||||
tickets: Tickets
|
||||
list: Listado
|
||||
ticketCreate: Nuevo ticket
|
||||
summary: Resumen
|
||||
basicData: Datos básicos
|
||||
boxing: Encajado
|
||||
sms: Sms
|
||||
notes: Notas
|
||||
sale: Lineas del pedido
|
||||
dms: Gestión documental
|
||||
volume: Volumen
|
||||
observation: Notas
|
||||
ticketAdvance: Adelantar tickets
|
||||
futureTickets: Tickets a futuro
|
||||
expedition: Expedición
|
||||
purchaseRequest: Petición de compra
|
||||
weeklyTickets: Tickets programados
|
||||
saleTracking: Líneas preparadas
|
||||
services: Servicios
|
||||
tracking: Estados
|
||||
components: Componentes
|
||||
pictures: Fotos
|
||||
packages: Embalajes
|
||||
list:
|
||||
nickname: Alias
|
||||
state: Estado
|
||||
shipped: Enviado
|
||||
landed: Entregado
|
||||
salesPerson: Comercial
|
||||
total: Total
|
||||
card:
|
||||
ticketId: ID ticket
|
||||
state: Estado
|
||||
customerId: ID cliente
|
||||
salesPerson: Comercial
|
||||
agency: Agencia
|
||||
shipped: Enviado
|
||||
warehouse: Almacén
|
||||
customerCard: Ficha del cliente
|
||||
alias: Alias
|
||||
ticketList: Listado de tickets
|
||||
newOrder: Nuevo pedido
|
||||
boxing:
|
||||
expedition: Expedición
|
||||
item: Artículo
|
||||
created: Creado
|
||||
worker: Trabajador
|
||||
selectTime: 'Seleccionar hora:'
|
||||
selectVideo: 'Seleccionar vídeo:'
|
||||
notFound: No hay vídeos disponibles
|
||||
summary:
|
||||
state: Estado
|
||||
salesPerson: Comercial
|
||||
agency: Agencia
|
||||
zone: Zona
|
||||
warehouse: Almacén
|
||||
collection: Colección
|
||||
route: Ruta
|
||||
invoice: Factura
|
||||
shipped: Enviado
|
||||
landed: Entregado
|
||||
consigneePhone: Tel. consignatario
|
||||
consigneeMobile: Móv. consignatario
|
||||
consigneeAddress: Dir. consignatario
|
||||
clientPhone: Tel. cliente
|
||||
clientMobile: Móv. cliente
|
||||
consignee: Consignatario
|
||||
subtotal: Subtotal
|
||||
vat: IVA
|
||||
total: Total
|
||||
saleLines: Líneas del pedido
|
||||
item: Artículo
|
||||
visible: Visible
|
||||
available: Disponible
|
||||
quantity: Cantidad
|
||||
price: Precio
|
||||
discount: Descuento
|
||||
packing: Encajado
|
||||
hasComponentLack: Faltan componentes
|
||||
itemShortage: No visible
|
||||
claim: Reclamación
|
||||
reserved: Reservado
|
||||
created: Fecha creación
|
||||
package: Embalaje
|
||||
taxClass: Tipo IVA
|
||||
services: Servicios
|
||||
changeState: Cambiar estado
|
||||
requester: Solicitante
|
||||
atender: Comprador
|
||||
request: Petición de compra
|
||||
weight: Peso
|
||||
goTo: Ir a
|
||||
summaryAmount: Resumen
|
||||
purchaseRequest: Petición de compra
|
||||
service: Servicio
|
||||
description: Descripción
|
||||
attender: Consignatario
|
||||
create:
|
||||
client: Cliente
|
||||
address: Dirección
|
||||
landed: F. entrega
|
||||
warehouse: Almacén
|
||||
agency: Agencia
|
||||
invoiceOut:
|
||||
list:
|
||||
ref: Referencia
|
||||
issued: Fecha emisión
|
||||
shortIssued: F. emisión
|
||||
client: Cliente
|
||||
created: Fecha creación
|
||||
shortCreated: F. creación
|
||||
company: Empresa
|
||||
dued: Fecha vencimineto
|
||||
shortDued: F. vencimiento
|
||||
amount: Importe
|
||||
card:
|
||||
issued: Fecha emisión
|
||||
client: Cliente
|
||||
company: Empresa
|
||||
customerCard: Ficha del cliente
|
||||
ticketList: Listado de tickets
|
||||
summary:
|
||||
issued: Fecha
|
||||
created: Fecha creación
|
||||
dued: Vencimiento
|
||||
booked: Contabilizada
|
||||
company: Empresa
|
||||
taxBreakdown: Desglose impositivo
|
||||
type: Tipo
|
||||
taxableBase: Base imp.
|
||||
rate: Tarifa
|
||||
fee: Cuota
|
||||
tickets: Tickets
|
||||
ticketId: Id ticket
|
||||
nickname: Alias
|
||||
shipped: F. envío
|
||||
totalWithVat: Importe
|
||||
globalInvoices:
|
||||
errors:
|
||||
|
@ -619,20 +511,14 @@ invoiceOut:
|
|||
criticalInvoiceError: Error crítico en la facturación proceso detenido
|
||||
invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
|
||||
table:
|
||||
client: Cliente
|
||||
addressId: Id dirección
|
||||
streetAddress: Dirección fiscal
|
||||
statusCard:
|
||||
percentageText: '{getPercentage}% {getAddressNumber} de {getNAddresses}'
|
||||
pdfsNumberText: '{nPdfs} de {totalPdfs} PDFs'
|
||||
negativeBases:
|
||||
company: Empresa
|
||||
country: País
|
||||
clientId: Id cliente
|
||||
client: Cliente
|
||||
amount: Importe
|
||||
base: Base
|
||||
ticketId: Id ticket
|
||||
active: Activo
|
||||
hasToInvoice: Facturar
|
||||
verifiedData: Datos comprobados
|
||||
|
@ -642,79 +528,44 @@ invoiceOut:
|
|||
order:
|
||||
field:
|
||||
salesPersonFk: Comercial
|
||||
clientFk: Cliente
|
||||
isConfirmed: Confirmada
|
||||
created: Creado
|
||||
landed: F. entrega
|
||||
hour: Hora
|
||||
agency: Agencia
|
||||
total: Total
|
||||
form:
|
||||
clientFk: Cliente
|
||||
addressFk: Dirección
|
||||
landed: F. entrega
|
||||
agencyModeFk: Agencia
|
||||
list:
|
||||
newOrder: Nuevo Pedido
|
||||
summary:
|
||||
basket: Cesta
|
||||
nickname: Alias
|
||||
company: Empresa
|
||||
confirmed: Confirmada
|
||||
notConfirmed: No confirmada
|
||||
created: Creado
|
||||
landed: F. entrega
|
||||
phone: Teléfono
|
||||
createdFrom: Creado desde
|
||||
address: Dirección
|
||||
notes: Notas
|
||||
subtotal: Subtotal
|
||||
total: Total
|
||||
vat: IVA
|
||||
state: Estado
|
||||
alias: Alias
|
||||
items: Items
|
||||
items: Artículos
|
||||
orderTicketList: Tickets del pedido
|
||||
details: Detalles
|
||||
item: Item
|
||||
quantity: Cantidad
|
||||
price: Precio
|
||||
amount: Monto
|
||||
confirm: Confirmar
|
||||
confirmLines: Confirmar lineas
|
||||
shelving:
|
||||
list:
|
||||
parking: Parking
|
||||
priority: Prioridad
|
||||
newShelving: Nuevo Carro
|
||||
summary:
|
||||
code: Código
|
||||
parking: Parking
|
||||
priority: Prioridad
|
||||
worker: Trabajador
|
||||
recyclable: Reciclable
|
||||
basicData:
|
||||
code: Código
|
||||
parking: Parking
|
||||
priority: Prioridad
|
||||
recyclable: Reciclable
|
||||
parking:
|
||||
pickingOrder: Orden de recogida
|
||||
row: Fila
|
||||
column: Columna
|
||||
pageTitles:
|
||||
parking: Parking
|
||||
searchBar:
|
||||
info: Puedes buscar por código de parking
|
||||
label: Buscar parking...
|
||||
department:
|
||||
pageTitles:
|
||||
basicData: Basic data
|
||||
department: Departamentos
|
||||
summary: Resumen
|
||||
name: Nombre
|
||||
code: Código
|
||||
chat: Chat
|
||||
bossDepartment: Jefe de departamento
|
||||
email: Email
|
||||
selfConsumptionCustomer: Cliente autoconsumo
|
||||
telework: Teletrabaja
|
||||
notifyOnErrors: Notificar errores
|
||||
|
@ -723,47 +574,11 @@ department:
|
|||
hasToSendMail: Enviar fichadas por mail
|
||||
departmentRemoved: Departamento eliminado
|
||||
worker:
|
||||
pageTitles:
|
||||
workers: Trabajadores
|
||||
list: Listado
|
||||
basicData: Datos básicos
|
||||
summary: Resumen
|
||||
notifications: Notificaciones
|
||||
workerCreate: Nuevo trabajador
|
||||
department: Departamentos
|
||||
pda: PDA
|
||||
notes: Notas
|
||||
dms: Mi documentación
|
||||
pbx: Centralita
|
||||
log: Historial
|
||||
calendar: Calendario
|
||||
timeControl: Control de horario
|
||||
locker: Taquilla
|
||||
balance: Balance
|
||||
formation: Formación
|
||||
medical: Mutua
|
||||
list:
|
||||
name: Nombre
|
||||
email: Email
|
||||
phone: Teléfono
|
||||
mobile: Móvil
|
||||
active: Activo
|
||||
department: Departamento
|
||||
schedule: Horario
|
||||
newWorker: Nuevo trabajador
|
||||
card:
|
||||
workerId: ID Trabajador
|
||||
user: Usuario
|
||||
name: Nombre
|
||||
email: Correo personal
|
||||
phone: Teléfono
|
||||
mobile: Móvil
|
||||
active: Activo
|
||||
warehouse: Almacén
|
||||
agency: Empresa
|
||||
salesPerson: Comercial
|
||||
summary:
|
||||
basicData: Datos básicos
|
||||
boss: Jefe
|
||||
phoneExtension: Extensión de teléfono
|
||||
entPhone: Teléfono de empresa
|
||||
|
@ -786,19 +601,12 @@ worker:
|
|||
serialNumber: Número de serie
|
||||
removePDA: Desasignar PDA
|
||||
create:
|
||||
name: Nombre
|
||||
lastName: Apellido
|
||||
birth: Fecha de nacimiento
|
||||
fi: DNI/NIF/NIE
|
||||
code: Código de trabajador
|
||||
phone: Teléfono
|
||||
postcode: Código postal
|
||||
province: Provincia
|
||||
city: Población
|
||||
street: Dirección
|
||||
webUser: Usuario Web
|
||||
personalEmail: Correo personal
|
||||
company: Empresa
|
||||
boss: Jefe
|
||||
payMethods: Método de pago
|
||||
iban: IBAN
|
||||
|
@ -810,16 +618,13 @@ worker:
|
|||
endDate: Fecha Fin
|
||||
center: Centro Formación
|
||||
invoice: Factura
|
||||
amount: Importe
|
||||
remark: Bonficado
|
||||
hasDiploma: Diploma
|
||||
medical:
|
||||
tableVisibleColumns:
|
||||
date: Fecha
|
||||
time: Hora
|
||||
center: Centro de Formación
|
||||
invoice: Factura
|
||||
amount: Importe
|
||||
isFit: Apto
|
||||
remark: Observaciones
|
||||
imageNotFound: No se ha encontrado la imagen
|
||||
|
@ -830,19 +635,21 @@ worker:
|
|||
debit: Debe
|
||||
credit: Haber
|
||||
concept: Concepto
|
||||
operator:
|
||||
numberOfWagons: Número de vagones
|
||||
train: tren
|
||||
itemPackingType: Tipo de embalaje
|
||||
warehouse: Almacén
|
||||
sector: Sector
|
||||
labeler: Impresora
|
||||
linesLimit: Líneas límite
|
||||
volumeLimit: Volumen límite
|
||||
sizeLimit: Tamaño límite
|
||||
isOnReservationMode: Modo de reserva
|
||||
machine: Máquina
|
||||
|
||||
wagon:
|
||||
pageTitles:
|
||||
wagons: Vagones
|
||||
wagonsList: Listado vagones
|
||||
wagonCreate: Crear tipo
|
||||
wagonEdit: Editar tipo
|
||||
typesList: Listado tipos
|
||||
typeCreate: Crear tipo
|
||||
typeEdit: Editar tipo
|
||||
wagonCounter: Contador de carros
|
||||
wagonTray: Listado bandejas
|
||||
type:
|
||||
name: Nombre
|
||||
submit: Guardar
|
||||
reset: Deshacer cambios
|
||||
trayColor: Color de la bandeja
|
||||
|
@ -850,13 +657,9 @@ wagon:
|
|||
list:
|
||||
plate: Matrícula
|
||||
volume: Volumen
|
||||
type: Tipo
|
||||
remove: Borrar
|
||||
removeItem: Vagón borrado correctamente
|
||||
create:
|
||||
plate: Matrícula
|
||||
volume: Volumen
|
||||
type: Tipo
|
||||
label: Etiqueta
|
||||
warnings:
|
||||
noData: Sin datos disponibles
|
||||
|
@ -872,26 +675,16 @@ wagon:
|
|||
supplier:
|
||||
list:
|
||||
payMethod: Método de pago
|
||||
payDeadline: Plazo de pago
|
||||
payDay: Día de pago
|
||||
account: Cuenta
|
||||
newSupplier: Nuevo proveedor
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
name: Nombre
|
||||
nif: NIF/CIF
|
||||
nickname: Alias
|
||||
account: Cuenta
|
||||
payMethod: Método de pago
|
||||
payDay: Dia de pago
|
||||
country: País
|
||||
summary:
|
||||
responsible: Responsable
|
||||
notes: Notas
|
||||
verified: Verificado
|
||||
isActive: Está activo
|
||||
billingData: Forma de pago
|
||||
payMethod: Método de pago
|
||||
payDeadline: Plazo de pago
|
||||
payDay: Día de pago
|
||||
account: Cuenta
|
||||
|
@ -904,20 +697,17 @@ supplier:
|
|||
fiscalAddress: Dirección fiscal
|
||||
socialName: Razón social
|
||||
taxNumber: NIF/CIF
|
||||
street: Dirección
|
||||
city: Población
|
||||
postCode: Código postal
|
||||
province: Provincia
|
||||
country: País
|
||||
create:
|
||||
supplierName: Nombre del proveedor
|
||||
basicData:
|
||||
alias: Alias
|
||||
workerFk: Responsable
|
||||
isSerious: Verificado
|
||||
isActive: Activo
|
||||
isPayMethodChecked: Método de pago validado
|
||||
note: Notas
|
||||
size: Tamaño
|
||||
fiscalData:
|
||||
name: Razón social *
|
||||
nif: NIF/CIF *
|
||||
|
@ -926,36 +716,17 @@ supplier:
|
|||
sageWithholdingFk: Retención sage
|
||||
sageTransactionTypeFk: Tipo de transacción sage
|
||||
supplierActivityFk: Actividad proveedor
|
||||
healthRegister: Pasaporte sanitario
|
||||
street: Calle
|
||||
postcode: Código postal
|
||||
city: Población *
|
||||
provinceFk: Provincia
|
||||
country: País
|
||||
isTrucker: Transportista
|
||||
isVies: Vies
|
||||
billingData:
|
||||
payMethodFk: Forma de pago
|
||||
payDemFk: Plazo de pago
|
||||
payDay: Día de pago
|
||||
accounts:
|
||||
iban: Iban
|
||||
bankEntity: Entidad bancaria
|
||||
beneficiary: Beneficiario
|
||||
contacts:
|
||||
name: Nombre
|
||||
phone: Teléfono
|
||||
mobile: Móvil
|
||||
email: Email
|
||||
observation: Notas
|
||||
addresses:
|
||||
street: Dirección
|
||||
postcode: Código postal
|
||||
phone: Teléfono
|
||||
name: Nombre
|
||||
city: Población
|
||||
province: Provincia
|
||||
mobile: Móvil
|
||||
agencyTerms:
|
||||
agencyFk: Agencia
|
||||
minimumM3: M3 mínimos
|
||||
|
@ -967,25 +738,16 @@ supplier:
|
|||
addRow: Añadir fila
|
||||
consumption:
|
||||
entry: Entrada
|
||||
date: Fecha
|
||||
reference: Referencia
|
||||
travel:
|
||||
travelList:
|
||||
tableVisibleColumns:
|
||||
id: Id
|
||||
ref: Referencia
|
||||
agency: Agencia
|
||||
shipped: F.envío
|
||||
shipHour: Hora de envío
|
||||
landHour: Hora de llegada
|
||||
landed: F.entrega
|
||||
warehouseIn: Alm.salida
|
||||
warehouseOut: Alm.entrada
|
||||
totalEntries: ∑
|
||||
totalEntriesTooltip: Entradas totales
|
||||
daysOnward: Días de llegada en adelante
|
||||
summary:
|
||||
confirmed: Confirmado
|
||||
entryId: Id entrada
|
||||
freight: Porte
|
||||
package: Embalaje
|
||||
|
@ -998,66 +760,30 @@ travel:
|
|||
AddEntry: Añadir entrada
|
||||
thermographs: Termógrafos
|
||||
hb: HB
|
||||
variables:
|
||||
search: Id/Referencia
|
||||
agencyModeFk: Agencia
|
||||
warehouseInFk: Alm. entrada
|
||||
warehouseOutFk: ' Alm. salida'
|
||||
landedFrom: Llegada desde
|
||||
landedTo: Llegada hasta
|
||||
continent: Cont. Salida
|
||||
totalEntries: Ent. totales
|
||||
basicData:
|
||||
reference: Referencia
|
||||
agency: Agencia
|
||||
shipped: F. Envío
|
||||
landed: F. entrega
|
||||
warehouseOut: Alm. salida
|
||||
warehouseIn: Alm. entrada
|
||||
delivered: Enviada
|
||||
received: Recibida
|
||||
daysInForward: Días redada
|
||||
thermographs:
|
||||
code: Código
|
||||
temperature: Temperatura
|
||||
state: Estado
|
||||
destination: Destino
|
||||
created: Fecha creación
|
||||
thermograph: Termógrafo
|
||||
reference: Referencia
|
||||
type: Tipo
|
||||
company: Empresa
|
||||
warehouse: Almacén
|
||||
travelFileDescription: 'Id envío { travelId }'
|
||||
file: Fichero
|
||||
item:
|
||||
descriptor:
|
||||
item: Artículo
|
||||
buyer: Comprador
|
||||
color: Color
|
||||
category: Categoría
|
||||
stems: Tallos
|
||||
visible: Visible
|
||||
available: Disponible
|
||||
warehouseText: 'Calculado sobre el almacén de { warehouseName }'
|
||||
itemDiary: Registro de compra-venta
|
||||
producer: Productor
|
||||
list:
|
||||
id: Identificador
|
||||
grouping: Grouping
|
||||
packing: Packing
|
||||
description: Descripción
|
||||
stems: Tallos
|
||||
category: Reino
|
||||
typeName: Tipo
|
||||
intrastat: Intrastat
|
||||
isActive: Activo
|
||||
size: Medida
|
||||
origin: Origen
|
||||
weightByPiece: Peso (gramos)/tallo
|
||||
userName: Comprador
|
||||
stemMultiplier: Multiplicador
|
||||
producer: Productor
|
||||
landed: F. entrega
|
||||
fixedPrice:
|
||||
itemFk: ID Artículo
|
||||
groupingPrice: Precio grouping
|
||||
|
@ -1066,79 +792,56 @@ item:
|
|||
minPrice: Precio min
|
||||
started: Inicio
|
||||
ended: Fin
|
||||
warehouse: Almacén
|
||||
create:
|
||||
name: Nombre
|
||||
tag: Etiqueta
|
||||
priority: Prioridad
|
||||
type: Tipo
|
||||
intrastat: Intrastat
|
||||
origin: Origen
|
||||
summary:
|
||||
basicData: 'Datos básicos'
|
||||
otherData: 'Otros datos'
|
||||
description: 'Descripción'
|
||||
tax: 'IVA'
|
||||
tags: 'Etiquetas'
|
||||
botanical: 'Botánico'
|
||||
barcode: 'Código de barras'
|
||||
name: 'Nombre'
|
||||
completeName: 'Nombre completo'
|
||||
family: 'Familia'
|
||||
size: 'Medida'
|
||||
origin: 'Origen'
|
||||
stems: 'Tallos'
|
||||
multiplier: 'Multiplicador'
|
||||
buyer: 'Comprador'
|
||||
doPhoto: 'Hacer foto'
|
||||
intrastatCode: 'Código intrastat'
|
||||
intrastat: 'Intrastat'
|
||||
ref: 'Referencia'
|
||||
relevance: 'Relevancia'
|
||||
weight: 'Peso (gramos)/tallo'
|
||||
units: 'Unidades/caja'
|
||||
expense: 'Gasto'
|
||||
generic: 'Genérico'
|
||||
recycledPlastic: 'Plástico reciclado'
|
||||
nonRecycledPlastic: 'Plástico no reciclado'
|
||||
minSalesQuantity: 'Cantidad mínima de venta'
|
||||
genus: 'Genus'
|
||||
specie: 'Specie'
|
||||
otherData: Otros datos
|
||||
tax: IVA
|
||||
botanical: Botánico
|
||||
barcode: Código de barras
|
||||
completeName: Nombre completo
|
||||
family: Familia
|
||||
stems: Tallos
|
||||
multiplier: Multiplicador
|
||||
buyer: Comprador
|
||||
doPhoto: Hacer foto
|
||||
intrastatCode: Código intrastat
|
||||
ref: Referencia
|
||||
relevance: Relevancia
|
||||
weight: Peso (gramos)/tallo
|
||||
units: Unidades/caja
|
||||
expense: Gasto
|
||||
generic: Genérico
|
||||
recycledPlastic: Plástico reciclado
|
||||
nonRecycledPlastic: Plástico no reciclado
|
||||
minSalesQuantity: Cantidad mínima de venta
|
||||
genus: Genus
|
||||
specie: Specie
|
||||
buyRequest:
|
||||
ticketId: 'ID Ticket'
|
||||
shipped: 'F. envío'
|
||||
requester: 'Solicitante'
|
||||
requested: 'Solicitado'
|
||||
price: 'Precio'
|
||||
attender: 'Comprador'
|
||||
item: 'Artículo'
|
||||
achieved: 'Conseguido'
|
||||
concept: 'Concepto'
|
||||
state: 'Estado'
|
||||
requester: Solicitante
|
||||
requested: Solicitado
|
||||
attender: Comprador
|
||||
achieved: Conseguido
|
||||
concept: Concepto
|
||||
components:
|
||||
topbar: {}
|
||||
itemsFilterPanel:
|
||||
typeFk: Tipo
|
||||
tag: Etiqueta
|
||||
value: Valor
|
||||
# ItemFixedPriceFilter
|
||||
buyerFk: Comprador
|
||||
warehouseFk: Almacén
|
||||
started: Desde
|
||||
ended: Hasta
|
||||
mine: Para mi
|
||||
hasMinPrice: Precio mínimo
|
||||
# LatestBuysFilter
|
||||
salesPersonFk: Comprador
|
||||
supplierFk: Proveedor
|
||||
active: Activo
|
||||
visible: Visible
|
||||
floramondo: Floramondo
|
||||
showBadDates: Ver items a futuro
|
||||
userPanel:
|
||||
copyToken: Token copiado al portapapeles
|
||||
settings: Configuración
|
||||
logOut: Cerrar sesión
|
||||
localWarehouse: Almacén local
|
||||
localBank: Banco local
|
||||
localCompany: Empresa local
|
||||
|
@ -1146,7 +849,6 @@ components:
|
|||
userCompany: Empresa del usuario
|
||||
smartCard:
|
||||
downloadFile: Descargar archivo
|
||||
clone: Clonar
|
||||
openCard: Ficha
|
||||
openSummary: Detalles
|
||||
viewSummary: Vista previa
|
||||
|
|
|
@ -1,7 +1,44 @@
|
|||
<script setup>
|
||||
import { useQuasar } from 'quasar';
|
||||
import Navbar from 'src/components/NavBar.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import routes from 'src/router/modules';
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
const quasar = useQuasar();
|
||||
|
||||
onMounted(() => {
|
||||
let isNotified = false;
|
||||
|
||||
const router = useRouter();
|
||||
const keyBindingMap = routes
|
||||
.filter((route) => route.meta.keyBinding)
|
||||
.reduce((map, route) => {
|
||||
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
const { ctrlKey, altKey, code } = event;
|
||||
|
||||
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
|
||||
event.preventDefault();
|
||||
router.push(keyBindingMap[code]);
|
||||
isNotified = true;
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = (event) => {
|
||||
const { ctrlKey, altKey } = event;
|
||||
|
||||
if (!ctrlKey || !altKey) {
|
||||
isNotified = false;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('keyup', handleKeyUp);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -9,6 +9,8 @@ import { useQuasar } from 'quasar';
|
|||
import VnTable from 'components/VnTable/VnTable.vue';
|
||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||
import FetchData from 'src/components/FetchData.vue';
|
||||
import { useValidator } from 'src/composables/useValidator';
|
||||
|
||||
defineProps({
|
||||
id: {
|
||||
|
@ -23,11 +25,18 @@ const stateStore = useStateStore();
|
|||
const quasar = useQuasar();
|
||||
|
||||
const tableRef = ref();
|
||||
|
||||
const roles = ref();
|
||||
const validationsStore = useValidator();
|
||||
const { models } = validationsStore;
|
||||
const exprBuilder = (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return { model: { like: `%${value}%` } };
|
||||
return {
|
||||
or: [
|
||||
{ model: { like: `%${value}%` } },
|
||||
{ property: { like: `%${value}%` } },
|
||||
],
|
||||
};
|
||||
default:
|
||||
return { [param]: value };
|
||||
}
|
||||
|
@ -47,6 +56,13 @@ const columns = computed(() => [
|
|||
label: t('model'),
|
||||
cardVisible: true,
|
||||
create: true,
|
||||
columnCreate: {
|
||||
label: t('model'),
|
||||
component: 'select',
|
||||
attrs: {
|
||||
options: Object.keys(models),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -55,9 +71,10 @@ const columns = computed(() => [
|
|||
cardVisible: true,
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'VnRoles',
|
||||
options: roles,
|
||||
optionLabel: 'name',
|
||||
optionValue: 'name',
|
||||
inputDebounce: 0,
|
||||
},
|
||||
create: true,
|
||||
},
|
||||
|
@ -130,6 +147,11 @@ const deleteAcl = async ({ id }) => {
|
|||
/>
|
||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||
</QDrawer>
|
||||
<FetchData
|
||||
url="VnRoles?fields=['name']"
|
||||
auto-load
|
||||
@on-fetch="(data) => (roles = data)"
|
||||
/>
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="AccountAcls"
|
||||
|
|
|
@ -37,7 +37,7 @@ const redirectToAccountBasicData = (_, { id }) => {
|
|||
<div class="column q-gutter-sm">
|
||||
<VnInput
|
||||
v-model="data.name"
|
||||
:label="t('account.create.name')"
|
||||
:label="t('globals.name')"
|
||||
:rules="validate('VnUser.name')"
|
||||
/>
|
||||
<VnInput
|
||||
|
@ -47,12 +47,12 @@ const redirectToAccountBasicData = (_, { id }) => {
|
|||
/>
|
||||
<VnInput
|
||||
v-model="data.email"
|
||||
:label="t('account.create.email')"
|
||||
:label="t('globals.params.email')"
|
||||
type="email"
|
||||
:rules="validate('VnUser.email')"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('account.create.role')"
|
||||
:label="t('account.card.role')"
|
||||
v-model="data.roleFk"
|
||||
:options="rolesOptions"
|
||||
option-value="id"
|
||||
|
@ -63,7 +63,7 @@ const redirectToAccountBasicData = (_, { id }) => {
|
|||
/>
|
||||
<VnInput
|
||||
v-model="data.password"
|
||||
:label="t('account.create.password')"
|
||||
:label="t('ldap.password')"
|
||||
type="password"
|
||||
:rules="validate('VnUser.password')"
|
||||
/>
|
||||
|
|
|
@ -33,6 +33,7 @@ const rolesOptions = ref([]);
|
|||
:search-button="true"
|
||||
:hidden-tags="['search']"
|
||||
:redirect="false"
|
||||
search-url="table"
|
||||
>
|
||||
<template #tags="{ tag, formatFn }">
|
||||
<div class="q-gutter-x-xs">
|
||||
|
@ -44,7 +45,7 @@ const rolesOptions = ref([]);
|
|||
<QItem class="q-my-sm">
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
:label="t('account.card.name')"
|
||||
:label="t('globals.name')"
|
||||
v-model="params.name"
|
||||
lazy-rules
|
||||
is-outlined
|
||||
|
|
|
@ -102,11 +102,11 @@ onMounted(async () => await getInitialLdapConfig());
|
|||
<QBtn
|
||||
class="q-ml-none"
|
||||
color="primary"
|
||||
:label="t('ldap.testConnection')"
|
||||
:label="t('account.card.testConnection')"
|
||||
@click="onTestConection()"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('ldap.testConnection') }}
|
||||
{{ t('account.card.testConnection') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
|
@ -114,7 +114,7 @@ onMounted(async () => await getInitialLdapConfig());
|
|||
<VnRow class="row q-gutter-md">
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('ldap.enableSync')"
|
||||
:label="t('account.card.enableSync')"
|
||||
v-model="data.hasData"
|
||||
@update:model-value="($event) => (hasData = $event)"
|
||||
:toggle-indeterminate="false"
|
||||
|
@ -146,7 +146,7 @@ onMounted(async () => await getInitialLdapConfig());
|
|||
/>
|
||||
<VnInput :label="t('ldap.userDN')" clearable v-model="data.userDn" />
|
||||
<VnInput
|
||||
:label="t('ldap.groupDN')"
|
||||
:label="t('account.card.groupDN')"
|
||||
clearable
|
||||
v-model="data.groupDn"
|
||||
/>
|
||||
|
|
|
@ -5,7 +5,8 @@ import VnTable from 'components/VnTable/VnTable.vue';
|
|||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||
import AccountSummary from './Card/AccountSummary.vue';
|
||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||
|
||||
import AccountFilter from './AccountFilter.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
const { t } = useI18n();
|
||||
const { viewSummary } = useSummaryDialog();
|
||||
const tableRef = ref();
|
||||
|
@ -20,14 +21,6 @@ const columns = computed(() => [
|
|||
isId: true,
|
||||
field: 'id',
|
||||
cardVisible: true,
|
||||
columnFilter: {
|
||||
component: 'select',
|
||||
name: 'search',
|
||||
attrs: {
|
||||
url: 'VnUsers/preview',
|
||||
fields: ['id', 'name'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
@ -53,9 +46,6 @@ const columns = computed(() => [
|
|||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
columnFilter: {
|
||||
inWhere: true,
|
||||
},
|
||||
cardVisible: true,
|
||||
create: true,
|
||||
},
|
||||
|
@ -67,9 +57,6 @@ const columns = computed(() => [
|
|||
columnField: {
|
||||
component: null,
|
||||
},
|
||||
columnFilter: {
|
||||
inWhere: true,
|
||||
},
|
||||
cardVisible: true,
|
||||
create: true,
|
||||
},
|
||||
|
@ -87,7 +74,7 @@ const columns = computed(() => [
|
|||
name: 'tableActions',
|
||||
actions: [
|
||||
{
|
||||
title: t('View Summary'),
|
||||
title: t('components.smartCard.viewSummary'),
|
||||
icon: 'preview',
|
||||
action: (row) => viewSummary(row.id, AccountSummary),
|
||||
isPrimary: true,
|
||||
|
@ -123,6 +110,11 @@ const exprBuilder = (param, value) => {
|
|||
:info="t('account.searchInfo')"
|
||||
:filter="filter"
|
||||
/>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
<AccountFilter data-key="AccountUsers" />
|
||||
</template>
|
||||
</RightMenu>
|
||||
<VnTable
|
||||
ref="tableRef"
|
||||
data-key="AccountUsers"
|
||||
|
@ -133,6 +125,8 @@ const exprBuilder = (param, value) => {
|
|||
default-mode="table"
|
||||
redirect="account"
|
||||
:use-model="true"
|
||||
:right-search="false"
|
||||
auto-load
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -110,12 +110,12 @@ onMounted(async () => await getInitialSambaConfig());
|
|||
<QBtn
|
||||
class="q-ml-none"
|
||||
color="primary"
|
||||
:label="t('samba.testConnection')"
|
||||
:label="t('account.card.testConnection')"
|
||||
:disable="formModel.hasChanges"
|
||||
@click="onTestConection()"
|
||||
>
|
||||
<QTooltip>
|
||||
{{ t('samba.testConnection') }}
|
||||
{{ t('account.card.testConnection') }}
|
||||
</QTooltip>
|
||||
</QBtn>
|
||||
</template>
|
||||
|
@ -123,7 +123,7 @@ onMounted(async () => await getInitialSambaConfig());
|
|||
<VnRow class="row q-gutter-md">
|
||||
<div class="col">
|
||||
<QCheckbox
|
||||
:label="t('samba.enableSync')"
|
||||
:label="t('account.card.enableSync')"
|
||||
v-model="data.hasData"
|
||||
@update:model-value="($event) => (hasData = $event)"
|
||||
:toggle-indeterminate="false"
|
||||
|
|
|
@ -36,15 +36,12 @@ const onDataSaved = ({ id }) => {
|
|||
<template #form-inputs="{ data }">
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput v-model="data.alias" :label="t('mailAlias.name')" />
|
||||
<VnInput v-model="data.alias" :label="t('globals.name')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="data.description"
|
||||
:label="t('mailAlias.description')"
|
||||
/>
|
||||
<VnInput v-model="data.description" :label="t('role.description')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
</template>
|
||||
|
|
|
@ -11,8 +11,8 @@ const { t } = useI18n();
|
|||
<FormModel model="Alias">
|
||||
<template #form="{ data }">
|
||||
<div class="column q-gutter-y-md">
|
||||
<VnInput v-model="data.alias" :label="t('mailAlias.name')" />
|
||||
<VnInput v-model="data.description" :label="t('mailAlias.description')" />
|
||||
<VnInput v-model="data.alias" :label="t('globals.name')" />
|
||||
<VnInput v-model="data.description" :label="t('role.description')" />
|
||||
<QCheckbox :label="t('mailAlias.isPublic')" v-model="data.isPublic" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -71,7 +71,7 @@ const removeAlias = () => {
|
|||
</QItem>
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv :label="t('mailAlias.description')" :value="entity.description" />
|
||||
<VnLv :label="t('role.description')" :value="entity.description" />
|
||||
</template>
|
||||
</CardDescriptor>
|
||||
</template>
|
||||
|
|
|
@ -42,8 +42,8 @@ const entityId = computed(() => $props.id || route.params.id);
|
|||
<QIcon name="open_in_new" />
|
||||
</router-link>
|
||||
</QCardSection>
|
||||
<VnLv :label="t('mailAlias.id')" :value="alias.id" />
|
||||
<VnLv :label="t('mailAlias.description')" :value="alias.description" />
|
||||
<VnLv :label="t('role.id')" :value="alias.id" />
|
||||
<VnLv :label="t('role.description')" :value="alias.description" />
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
|
|
|
@ -46,13 +46,9 @@ const columns = computed(() => [
|
|||
]);
|
||||
|
||||
const deleteAlias = async (row) => {
|
||||
try {
|
||||
await axios.delete(`${urlPath.value}/${row.id}`);
|
||||
notify(t('User removed'), 'positive');
|
||||
fetchAliases();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
await axios.delete(`${urlPath.value}/${row.id}`);
|
||||
notify(t('User removed'), 'positive');
|
||||
fetchAliases();
|
||||
};
|
||||
|
||||
watch(
|
||||
|
|
|
@ -36,7 +36,7 @@ watch(
|
|||
<div class="q-gutter-y-sm">
|
||||
<VnInput v-model="data.name" :label="t('account.card.nickname')" />
|
||||
<VnInput v-model="data.nickname" :label="t('account.card.alias')" />
|
||||
<VnInput v-model="data.email" :label="t('account.card.email')" />
|
||||
<VnInput v-model="data.email" :label="t('globals.params.email')" />
|
||||
<VnSelect
|
||||
url="Languages"
|
||||
v-model="data.lang"
|
||||
|
|
|
@ -10,10 +10,7 @@ const { t } = useI18n();
|
|||
<VnCard
|
||||
data-key="Account"
|
||||
:descriptor="AccountDescriptor"
|
||||
search-data-key="AccountUsers"
|
||||
:filter="{
|
||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||
}"
|
||||
search-data-key="AccountList"
|
||||
:searchbar-props="{
|
||||
url: 'VnUsers/preview',
|
||||
label: t('account.search'),
|
||||
|
|
|
@ -54,7 +54,7 @@ const hasAccount = ref(false);
|
|||
</template>
|
||||
<template #before>
|
||||
<!-- falla id :id="entityId.value" collection="user" size="160x160" -->
|
||||
<VnImg :id="entityId" collection="user" resolution="160x160" class="photo">
|
||||
<VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
|
||||
<template #error>
|
||||
<div
|
||||
class="absolute-full picture text-center q-pa-md flex flex-center"
|
||||
|
|
|
@ -4,9 +4,12 @@ import { computed, ref, toRefs } from 'vue';
|
|||
import { useI18n } from 'vue-i18n';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useAcl } from 'src/composables/useAcl';
|
||||
import { useArrayData } from 'src/composables/useArrayData';
|
||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
||||
const $props = defineProps({
|
||||
hasAccount: {
|
||||
type: Boolean,
|
||||
|
@ -62,6 +65,19 @@ async function sync() {
|
|||
}
|
||||
</script>
|
||||
<template>
|
||||
<VnChangePassword
|
||||
ref="changePassRef"
|
||||
:ask-old-pass="true"
|
||||
:submit-fn="
|
||||
async (newPassword, oldPassword) => {
|
||||
await axios.patch(`Accounts/change-password`, {
|
||||
userId: entityId,
|
||||
newPassword,
|
||||
oldPassword,
|
||||
});
|
||||
}
|
||||
"
|
||||
/>
|
||||
<VnConfirm
|
||||
v-model="showSyncDialog"
|
||||
:message="t('account.card.actions.sync.message')"
|
||||
|
@ -92,6 +108,17 @@ async function sync() {
|
|||
/>
|
||||
</template>
|
||||
</VnConfirm>
|
||||
<QItem
|
||||
v-if="
|
||||
entityId == account.id &&
|
||||
useAcl().hasAny([{ model: 'Account', props: '*', accessType: 'WRITE' }])
|
||||
"
|
||||
v-ripple
|
||||
clickable
|
||||
@click="$refs.changePassRef.show()"
|
||||
>
|
||||
<QItemSection>{{ t('globals.changePass') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-if="account.hasAccount"
|
||||
v-ripple
|
||||
|
@ -138,6 +165,5 @@ async function sync() {
|
|||
<QItem v-ripple clickable @click="showSyncDialog = true">
|
||||
<QItemSection>{{ t('account.card.actions.sync.name') }}</QItemSection>
|
||||
</QItem>
|
||||
|
||||
<QSeparator />
|
||||
</template>
|
||||
|
|
|
@ -61,23 +61,15 @@ const fetchAccountExistence = async () => {
|
|||
};
|
||||
|
||||
const deleteMailAlias = async (row) => {
|
||||
try {
|
||||
await axios.delete(`${urlPath}/${row.id}`);
|
||||
fetchMailAliases();
|
||||
notify(t('Unsubscribed from alias!'), 'positive');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
await axios.delete(`${urlPath}/${row.id}`);
|
||||
fetchMailAliases();
|
||||
notify(t('Unsubscribed from alias!'), 'positive');
|
||||
};
|
||||
|
||||
const createMailAlias = async (mailAliasFormData) => {
|
||||
try {
|
||||
await axios.post(urlPath, mailAliasFormData);
|
||||
notify(t('Subscribed to alias!'), 'positive');
|
||||
fetchMailAliases();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
await axios.post(urlPath, mailAliasFormData);
|
||||
notify(t('Subscribed to alias!'), 'positive');
|
||||
fetchMailAliases();
|
||||
};
|
||||
|
||||
const fetchMailAliases = async () => {
|
||||
|
|
|
@ -54,7 +54,7 @@ const columns = computed(() => [
|
|||
name: 'tableActions',
|
||||
actions: [
|
||||
{
|
||||
title: t('View Summary'),
|
||||
title: t('components.smartCard.viewSummary'),
|
||||
icon: 'preview',
|
||||
action: (row) => viewSummary(row.id, RoleSummary),
|
||||
isPrimary: true,
|
||||
|
|
|
@ -29,7 +29,7 @@ const props = defineProps({
|
|||
<QItem class="q-my-sm">
|
||||
<QItemSection>
|
||||
<VnInput
|
||||
:label="t('role.name')"
|
||||
:label="t('globals.name')"
|
||||
v-model="params.name"
|
||||
lazy-rules
|
||||
is-outlined
|
||||
|
|
|
@ -12,15 +12,12 @@ const { t } = useI18n();
|
|||
<template #form="{ data }">
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput v-model="data.name" :label="t('role.card.name')" />
|
||||
<VnInput v-model="data.name" :label="t('globals.name')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="data.description"
|
||||
:label="t('role.card.description')"
|
||||
/>
|
||||
<VnInput v-model="data.description" :label="t('role.description')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
</template>
|
||||
|
|
|
@ -58,7 +58,7 @@ const removeRole = async () => {
|
|||
</QItem>
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv :label="t('role.card.description')" :value="entity.description" />
|
||||
<VnLv :label="t('role.description')" :value="entity.description" />
|
||||
</template>
|
||||
</CardDescriptor>
|
||||
</template>
|
||||
|
|
|
@ -22,15 +22,12 @@ const { t } = useI18n();
|
|||
<template #form-inputs="{ data }">
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput v-model="data.name" :label="t('role.card.name')" />
|
||||
<VnInput v-model="data.name" :label="t('globals.name')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow>
|
||||
<div class="col">
|
||||
<VnInput
|
||||
v-model="data.description"
|
||||
:label="t('role.card.description')"
|
||||
/>
|
||||
<VnInput v-model="data.description" :label="t('role.description')" />
|
||||
</div>
|
||||
</VnRow>
|
||||
</template>
|
||||
|
|
|
@ -44,9 +44,9 @@ const filter = {
|
|||
<QIcon name="open_in_new" />
|
||||
</a>
|
||||
</QCardSection>
|
||||
<VnLv :label="t('role.card.id')" :value="role.id" />
|
||||
<VnLv :label="t('role.card.name')" :value="role.name" />
|
||||
<VnLv :label="t('role.card.description')" :value="role.description" />
|
||||
<VnLv :label="t('role.id')" :value="role.id" />
|
||||
<VnLv :label="t('globals.name')" :value="role.name" />
|
||||
<VnLv :label="t('role.description')" :value="role.description" />
|
||||
</QCard>
|
||||
</template>
|
||||
</CardSummary>
|
||||
|
|
|
@ -46,29 +46,15 @@ const columns = computed(() => [
|
|||
]);
|
||||
|
||||
const deleteSubRole = async (row) => {
|
||||
try {
|
||||
await axios.delete(`${urlPath.value}/${row.id}`);
|
||||
fetchSubRoles();
|
||||
notify(
|
||||
t('Role removed. Changes will take a while to fully propagate.'),
|
||||
'positive'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
await axios.delete(`${urlPath.value}/${row.id}`);
|
||||
fetchSubRoles();
|
||||
notify(t('Role removed. Changes will take a while to fully propagate.'), 'positive');
|
||||
};
|
||||
|
||||
const createSubRole = async (subRoleFormData) => {
|
||||
try {
|
||||
await axios.post(urlPath.value, subRoleFormData);
|
||||
notify(
|
||||
t('Role added! Changes will take a while to fully propagate.'),
|
||||
'positive'
|
||||
);
|
||||
fetchSubRoles();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
await axios.post(urlPath.value, subRoleFormData);
|
||||
notify(t('Role added! Changes will take a while to fully propagate.'), 'positive');
|
||||
fetchSubRoles();
|
||||
};
|
||||
|
||||
watch(
|
||||
|
|
|
@ -1,32 +1,15 @@
|
|||
account:
|
||||
pageTitles:
|
||||
users: Users
|
||||
list: Users
|
||||
roles: Roles
|
||||
alias: Mail aliasses
|
||||
accounts: Accounts
|
||||
ldap: LDAP
|
||||
samba: Samba
|
||||
acls: ACLs
|
||||
connections: Connections
|
||||
inheritedRoles: Inherited Roles
|
||||
subRoles: Sub Roles
|
||||
newRole: New role
|
||||
privileges: Privileges
|
||||
mailAlias: Mail Alias
|
||||
mailForwarding: Mail Forwarding
|
||||
accountCreate: New user
|
||||
aliasUsers: Users
|
||||
card:
|
||||
name: Name
|
||||
nickname: User
|
||||
role: Role
|
||||
email: Email
|
||||
alias: Alias
|
||||
lang: Language
|
||||
roleFk: Role
|
||||
newUser: New user
|
||||
ticketTracking: Ticket tracking
|
||||
enableSync: Habilitar sincronización
|
||||
groupDN: DN grupos
|
||||
testConnection: Probar conexión
|
||||
privileges:
|
||||
delegate: Can delegate privileges
|
||||
enabled: Account enabled!
|
||||
|
@ -74,11 +57,7 @@ account:
|
|||
search: Search user
|
||||
searchInfo: You can search by id, name or nickname
|
||||
create:
|
||||
name: Name
|
||||
nickname: Nickname
|
||||
email: Email
|
||||
role: Role
|
||||
password: Password
|
||||
active: Active
|
||||
mailForwarding:
|
||||
forwardingMail: Forward email
|
||||
|
@ -86,50 +65,30 @@ account:
|
|||
enableMailForwarding: Enable mail forwarding
|
||||
mailInputInfo: All emails will be forwarded to the specified address.
|
||||
role:
|
||||
pageTitles:
|
||||
inheritedRoles: Inherited Roles
|
||||
subRoles: Sub Roles
|
||||
card:
|
||||
description: Description
|
||||
id: Id
|
||||
name: Name
|
||||
newRole: New role
|
||||
searchRoles: Search role
|
||||
searchInfo: Search role by id or name
|
||||
name: Name
|
||||
description: Description
|
||||
id: Id
|
||||
mailAlias:
|
||||
pageTitles:
|
||||
aliasUsers: Users
|
||||
search: Search mail alias
|
||||
searchInfo: Search alias by id or name
|
||||
alias: Alias
|
||||
description: Description
|
||||
id: Id
|
||||
newAlias: New alias
|
||||
name: Name
|
||||
isPublic: Public
|
||||
ldap:
|
||||
enableSync: Enable synchronization
|
||||
server: Server
|
||||
rdn: RDN
|
||||
userDN: User DN
|
||||
filter: Filter
|
||||
groupDN: Group DN
|
||||
testConnection: Test connection
|
||||
success: LDAP connection established!
|
||||
password: Password
|
||||
samba:
|
||||
enableSync: Enable synchronization
|
||||
domainController: Domain controller
|
||||
domainAD: AD domain
|
||||
userAD: AD user
|
||||
groupDN: Group DN
|
||||
passwordAD: AD password
|
||||
domainPart: User DN (without domain part)
|
||||
verifyCertificate: Verify certificate
|
||||
testConnection: Test connection
|
||||
success: Samba connection established!
|
||||
accounts:
|
||||
homedir: Homedir base
|
||||
|
@ -147,8 +106,6 @@ connections:
|
|||
created: Created
|
||||
killSession: Kill session
|
||||
acls:
|
||||
role: Role
|
||||
accessType: Access type
|
||||
permissions: Permission
|
||||
search: Search acls
|
||||
searchInfo: Search acls by model name
|
||||
|
|
|
@ -1,27 +1,7 @@
|
|||
account:
|
||||
pageTitles:
|
||||
users: Usuarios
|
||||
list: Usuarios
|
||||
roles: Roles
|
||||
alias: Alias de correo
|
||||
accounts: Cuentas
|
||||
ldap: LDAP
|
||||
samba: Samba
|
||||
acls: ACLs
|
||||
connections: Conexiones
|
||||
inheritedRoles: Roles heredados
|
||||
newRole: Nuevo rol
|
||||
subRoles: Subroles
|
||||
privileges: Privilegios
|
||||
mailAlias: Alias de correo
|
||||
mailForwarding: Reenvío de correo
|
||||
accountCreate: Nuevo usuario
|
||||
aliasUsers: Usuarios
|
||||
card:
|
||||
nickname: Usuario
|
||||
name: Nombre
|
||||
role: Rol
|
||||
email: Mail
|
||||
alias: Alias
|
||||
lang: Idioma
|
||||
roleFk: Rol
|
||||
|
@ -33,6 +13,9 @@ account:
|
|||
deactivated: ¡Usuario desactivado!
|
||||
newUser: Nuevo usuario
|
||||
twoFactor: Doble factor
|
||||
enableSync: Habilitar sincronización
|
||||
groupDN: DN grupos
|
||||
testConnection: Probar conexión
|
||||
privileges:
|
||||
delegate: Puede delegar privilegios
|
||||
actions:
|
||||
|
@ -73,11 +56,7 @@ account:
|
|||
search: Buscar usuario
|
||||
searchInfo: Puedes buscar por id, nombre o usuario
|
||||
create:
|
||||
name: Nombre
|
||||
nickname: Nombre mostrado
|
||||
email: Email
|
||||
role: Rol
|
||||
password: Contraseña
|
||||
active: Activo
|
||||
mailForwarding:
|
||||
forwardingMail: Dirección de reenvío
|
||||
|
@ -85,51 +64,30 @@ account:
|
|||
enableMailForwarding: Habilitar redirección de correo
|
||||
mailInputInfo: Todos los correos serán reenviados a la dirección especificada, no se mantendrá copia de los mismos en el buzón del usuario.
|
||||
role:
|
||||
pageTitles:
|
||||
inheritedRoles: Roles heredados
|
||||
subRoles: Subroles
|
||||
newRole: Nuevo rol
|
||||
card:
|
||||
description: Descripción
|
||||
id: Id
|
||||
name: Nombre
|
||||
newRole: Nuevo rol
|
||||
searchRoles: Buscar roles
|
||||
searchInfo: Buscar rol por id o nombre
|
||||
name: Nombre
|
||||
description: Descripción
|
||||
id: Id
|
||||
mailAlias:
|
||||
pageTitles:
|
||||
aliasUsers: Usuarios
|
||||
search: Buscar alias de correo
|
||||
searchInfo: Buscar alias por id o nombre
|
||||
alias: Alias
|
||||
description: Descripción
|
||||
id: Id
|
||||
newAlias: Nuevo alias
|
||||
name: Nombre
|
||||
isPublic: Público
|
||||
ldap:
|
||||
password: Contraseña
|
||||
enableSync: Habilitar sincronización
|
||||
server: Servidor
|
||||
rdn: RDN
|
||||
userDN: DN usuarios
|
||||
filter: Filtro
|
||||
groupDN: DN grupos
|
||||
testConnection: Probar conexión
|
||||
success: ¡Conexión con LDAP establecida!
|
||||
samba:
|
||||
enableSync: Habilitar sincronización
|
||||
domainController: Controlador de dominio
|
||||
domainAD: Dominio AD
|
||||
groupDN: DN grupos
|
||||
userAD: Usuario AD
|
||||
passwordAD: Contraseña AD
|
||||
domainPart: DN usuarios (sin la parte del dominio)
|
||||
verifyCertificate: Verificar certificado
|
||||
testConnection: Probar conexión
|
||||
success: ¡Conexión con Samba establecida!
|
||||
accounts:
|
||||
homedir: Directorio base para carpetas de usuario
|
||||
|
@ -147,8 +105,6 @@ connections:
|
|||
created: Creado
|
||||
killSession: Matar sesión
|
||||
acls:
|
||||
role: Rol
|
||||
accessType: Tipo de acceso
|
||||
permissions: Permiso
|
||||
search: Buscar acls
|
||||
searchInfo: Buscar acls por nombre
|
||||
|
|
|
@ -204,7 +204,7 @@ function claimUrl(section) {
|
|||
top
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
:label="t('globals.changeState')"
|
||||
>
|
||||
<QList>
|
||||
<QVirtualScroll
|
||||
|
|
|
@ -27,7 +27,7 @@ const addressFilter = {
|
|||
'isLogifloraAllowed',
|
||||
'postalCode',
|
||||
],
|
||||
order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'],
|
||||
order: ['isDefaultAddress DESC', 'isActive DESC', 'id DESC', 'nickname ASC'],
|
||||
include: [
|
||||
{
|
||||
relation: 'observations',
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useRoute } from 'vue-router';
|
|||
import { useAcl } from 'src/composables/useAcl';
|
||||
import axios from 'axios';
|
||||
import { useQuasar } from 'quasar';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import { getClientRisk } from '../composables/getClientRisk';
|
||||
|
||||
import { toCurrency, toDate, toDateHourMin } from 'src/filters';
|
||||
import { useState } from 'composables/useState';
|
||||
|
@ -16,7 +16,7 @@ import { useVnConfirm } from 'composables/useVnConfirm';
|
|||
import VnTable from 'components/VnTable/VnTable.vue';
|
||||
import VnInput from 'components/common/VnInput.vue';
|
||||
import VnSubToolbar from 'components/ui/VnSubToolbar.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnFilter from 'components/VnTable/VnFilter.vue';
|
||||
|
||||
import CustomerNewPayment from 'src/pages/Customer/components/CustomerNewPayment.vue';
|
||||
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
|
||||
|
@ -25,7 +25,7 @@ const { openConfirmationModal } = useVnConfirm();
|
|||
const { sendEmail, openReport } = usePrintService();
|
||||
const { t } = useI18n();
|
||||
const { hasAny } = useAcl();
|
||||
const currentBalance = ref({});
|
||||
|
||||
const quasar = useQuasar();
|
||||
const route = useRoute();
|
||||
const state = useState();
|
||||
|
@ -33,28 +33,53 @@ const stateStore = useStateStore();
|
|||
const user = state.getUser();
|
||||
|
||||
const clientRisk = ref([]);
|
||||
const companies = ref([]);
|
||||
const tableRef = ref();
|
||||
const companyId = ref(user.value.companyFk);
|
||||
const companyId = ref();
|
||||
const companyUser = ref(user.value.companyFk);
|
||||
const balances = ref([]);
|
||||
const vnFilterRef = ref({});
|
||||
const filter = computed(() => {
|
||||
return {
|
||||
clientId: route.params.id,
|
||||
companyId: companyId.value ?? user.value.companyFk,
|
||||
companyId: companyId.value ?? companyUser.value,
|
||||
};
|
||||
});
|
||||
|
||||
const companyFilterColumn = {
|
||||
align: 'left',
|
||||
name: 'companyId',
|
||||
label: t('Company'),
|
||||
component: 'select',
|
||||
attrs: {
|
||||
url: 'Companies',
|
||||
optionLabel: 'code',
|
||||
optionValue: 'id',
|
||||
sortBy: 'code',
|
||||
},
|
||||
columnFilter: {
|
||||
event: {
|
||||
remove: () => (companyId.value = null),
|
||||
'update:modelValue': (newCompanyFk) => {
|
||||
if (!newCompanyFk) return;
|
||||
vnFilterRef.value.addFilter(newCompanyFk);
|
||||
companyUser.value = newCompanyFk;
|
||||
},
|
||||
blur: () => !companyId.value && (companyId.value = companyUser.value),
|
||||
},
|
||||
},
|
||||
visible: false,
|
||||
};
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'right',
|
||||
align: 'left',
|
||||
name: 'payed',
|
||||
label: t('Date'),
|
||||
format: ({ payed }) => toDate(payed),
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
align: 'left',
|
||||
name: 'created',
|
||||
label: t('Creation date'),
|
||||
format: ({ created }) => toDateHourMin(created),
|
||||
|
@ -65,7 +90,12 @@ const columns = computed(() => [
|
|||
label: t('Employee'),
|
||||
columnField: {
|
||||
component: 'userLink',
|
||||
attrs: ({ row }) => ({ workerId: row.workerFk, name: row.userName }),
|
||||
attrs: ({ row }) => {
|
||||
return {
|
||||
workerId: row.workerFk,
|
||||
name: row.userName,
|
||||
};
|
||||
},
|
||||
},
|
||||
cardVisible: true,
|
||||
},
|
||||
|
@ -77,13 +107,13 @@ const columns = computed(() => [
|
|||
class: 'extend',
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
align: 'left',
|
||||
name: 'bankFk',
|
||||
label: t('Bank'),
|
||||
cardVisible: true,
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
align: 'left',
|
||||
name: 'debit',
|
||||
label: t('Debit'),
|
||||
format: ({ debit }) => debit && toCurrency(debit),
|
||||
|
@ -136,20 +166,37 @@ const columns = computed(() => [
|
|||
|
||||
onBeforeMount(() => {
|
||||
stateStore.rightDrawer = true;
|
||||
companyId.value = companyUser.value;
|
||||
});
|
||||
|
||||
async function getCurrentBalance(data) {
|
||||
currentBalance.value[companyId.value] = {
|
||||
amount: 0,
|
||||
code: companies.value.find((c) => c.id === companyId.value)?.code,
|
||||
async function getClientRisks() {
|
||||
const filter = {
|
||||
where: { clientFk: route.params.id, companyFk: companyUser.value },
|
||||
};
|
||||
const { data } = await getClientRisk(filter);
|
||||
clientRisk.value = data;
|
||||
return clientRisk.value;
|
||||
}
|
||||
|
||||
for (const balance of data) {
|
||||
currentBalance.value[balance.companyFk] = {
|
||||
code: balance.company.code,
|
||||
amount: balance.amount,
|
||||
};
|
||||
async function getCurrentBalance() {
|
||||
const currentBalance = (await getClientRisks()).find((balance) => {
|
||||
return balance.companyFk === companyId.value;
|
||||
});
|
||||
return currentBalance && currentBalance.amount;
|
||||
}
|
||||
|
||||
async function onFetch(data) {
|
||||
balances.value = [];
|
||||
for (const [index, balance] of data.entries()) {
|
||||
if (index === 0) {
|
||||
balance.balance = await getCurrentBalance();
|
||||
continue;
|
||||
}
|
||||
const previousBalance = data[index - 1];
|
||||
balance.balance =
|
||||
previousBalance?.balance - (previousBalance?.debit - previousBalance?.credit);
|
||||
}
|
||||
balances.value = data;
|
||||
}
|
||||
|
||||
const showNewPaymentDialog = () => {
|
||||
|
@ -169,43 +216,25 @@ const showBalancePdf = ({ id }) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="Companies"
|
||||
auto-load
|
||||
@on-fetch="(data) => (companies = data)"
|
||||
></FetchData>
|
||||
<FetchData
|
||||
v-if="companies.length > 0"
|
||||
url="clientRisks"
|
||||
:filter="{
|
||||
include: { relation: 'company', scope: { fields: ['code'] } },
|
||||
where: { clientFk: route.params.id },
|
||||
}"
|
||||
auto-load
|
||||
@on-fetch="getCurrentBalance"
|
||||
></FetchData>
|
||||
|
||||
<VnSubToolbar class="q-mb-md">
|
||||
<template #st-data>
|
||||
<div class="column justify-center q-px-md q-py-sm">
|
||||
<span class="text-bold">{{ t('Total by company') }}</span>
|
||||
<div class="row justify-center">
|
||||
{{ currentBalance[companyId]?.code }}:
|
||||
{{ toCurrency(currentBalance[companyId]?.amount) }}
|
||||
<div class="row justify-center" v-if="clientRisk?.length">
|
||||
{{ clientRisk[0].company.code }}:
|
||||
{{ toCurrency(clientRisk[0].amount) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #st-actions>
|
||||
<div>
|
||||
<VnSelect
|
||||
:label="t('Company')"
|
||||
<VnFilter
|
||||
ref="vnFilterRef"
|
||||
v-model="companyId"
|
||||
data-key="CustomerBalance"
|
||||
:options="companies"
|
||||
option-label="code"
|
||||
option-value="id"
|
||||
></VnSelect>
|
||||
:column="companyFilterColumn"
|
||||
search-url="balance"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</VnSubToolbar>
|
||||
|
@ -219,6 +248,7 @@ const showBalancePdf = ({ id }) => {
|
|||
:right-search="false"
|
||||
:is-editable="false"
|
||||
:column-search="false"
|
||||
@on-fetch="onFetch"
|
||||
:disable-option="{ card: true }"
|
||||
auto-load
|
||||
>
|
||||
|
|
|
@ -55,7 +55,7 @@ const exprBuilder = (param, value) => {
|
|||
/>
|
||||
<VnSelect
|
||||
:input-debounce="0"
|
||||
:label="t('customer.basicData.businessType')"
|
||||
:label="t('customer.summary.businessType')"
|
||||
:options="businessTypes"
|
||||
:rules="validate('client.businessTypeFk')"
|
||||
emit-value
|
||||
|
@ -67,13 +67,13 @@ const exprBuilder = (param, value) => {
|
|||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('customer.basicData.contact')"
|
||||
:label="t('customer.summary.contact')"
|
||||
:rules="validate('client.contact')"
|
||||
clearable
|
||||
v-model="data.contact"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('customer.basicData.email')"
|
||||
:label="t('globals.params.email')"
|
||||
:rules="validate('client.email')"
|
||||
clearable
|
||||
type="email"
|
||||
|
@ -90,13 +90,13 @@ const exprBuilder = (param, value) => {
|
|||
</VnRow>
|
||||
<VnRow>
|
||||
<VnInput
|
||||
:label="t('customer.basicData.phone')"
|
||||
:label="t('customer.extendedList.tableVisibleColumns.phone')"
|
||||
:rules="validate('client.phone')"
|
||||
clearable
|
||||
v-model="data.phone"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('customer.basicData.mobile')"
|
||||
:label="t('customer.summary.mobile')"
|
||||
:rules="validate('client.mobile')"
|
||||
clearable
|
||||
v-model="data.mobile"
|
||||
|
@ -106,7 +106,7 @@ const exprBuilder = (param, value) => {
|
|||
<VnSelect
|
||||
url="Workers/search"
|
||||
v-model="data.salesPersonFk"
|
||||
:label="t('customer.basicData.salesPerson')"
|
||||
:label="t('customer.summary.salesPerson')"
|
||||
:params="{
|
||||
departmentCodes: ['VT', 'shopping'],
|
||||
}"
|
||||
|
@ -144,7 +144,7 @@ const exprBuilder = (param, value) => {
|
|||
option-value="id"
|
||||
option-label="name"
|
||||
emit-value
|
||||
:label="t('customer.basicData.contactChannel')"
|
||||
:label="t('customer.summary.contactChannel')"
|
||||
map-options
|
||||
:rules="validate('client.contactChannelFk')"
|
||||
:input-debounce="0"
|
||||
|
|
|
@ -49,7 +49,9 @@ const columns = computed(() => [
|
|||
name: 'credit',
|
||||
create: true,
|
||||
visible: false,
|
||||
attrs: {
|
||||
columnCreate: {
|
||||
component: 'number',
|
||||
required: true,
|
||||
autofocus: true,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -53,11 +53,17 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
<CustomerDescriptorMenu :customer="entity" />
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv :label="t('customer.card.payMethod')" :value="entity.payMethod.name" />
|
||||
|
||||
<VnLv :label="t('customer.card.credit')" :value="toCurrency(entity.credit)" />
|
||||
<VnLv
|
||||
:label="t('customer.card.securedCredit')"
|
||||
:label="t('customer.summary.payMethod')"
|
||||
:value="entity.payMethod.name"
|
||||
/>
|
||||
|
||||
<VnLv
|
||||
:label="t('customer.summary.credit')"
|
||||
:value="toCurrency(entity.credit)"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('customer.summary.securedCredit')"
|
||||
:value="toCurrency(entity.creditInsurance)"
|
||||
/>
|
||||
|
||||
|
@ -66,7 +72,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
:value="toCurrency(entity.debt)"
|
||||
:info="t('customer.summary.riskInfo')"
|
||||
/>
|
||||
<VnLv :label="t('customer.card.salesPerson')">
|
||||
<VnLv :label="t('customer.summary.salesPerson')">
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
v-if="entity.salesPersonUser"
|
||||
|
@ -77,7 +83,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
:label="t('customer.card.businessTypeFk')"
|
||||
:label="t('customer.extendedList.tableVisibleColumns.businessTypeFk')"
|
||||
:value="entity.businessType.description"
|
||||
/>
|
||||
</template>
|
||||
|
@ -150,7 +156,7 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
</QCardActions>
|
||||
</template>
|
||||
<template #actions="{ entity }">
|
||||
<QCardActions class="flex justify-center">
|
||||
<QCardActions class="flex justify-center" style="padding-inline: 0">
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'TicketList',
|
||||
|
@ -168,6 +174,23 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
>
|
||||
<QTooltip>{{ t('Customer ticket list') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'TicketList',
|
||||
query: {
|
||||
table: JSON.stringify({
|
||||
clientFk: entity.id,
|
||||
}),
|
||||
createForm: JSON.stringify({ clientId: entity.id }),
|
||||
},
|
||||
}"
|
||||
size="md"
|
||||
color="primary"
|
||||
target="_blank"
|
||||
icon="vn:ticketAdd"
|
||||
>
|
||||
<QTooltip>{{ t('New ticket') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'InvoiceOutList',
|
||||
|
@ -179,6 +202,23 @@ const setData = (entity) => (data.value = useCardDescription(entity?.name, entit
|
|||
>
|
||||
<QTooltip>{{ t('Customer invoice out list') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'OrderList',
|
||||
query: {
|
||||
table: JSON.stringify({
|
||||
clientFk: entity.id,
|
||||
}),
|
||||
createForm: JSON.stringify({ clientFk: entity.id }),
|
||||
},
|
||||
}"
|
||||
size="md"
|
||||
target="_blank"
|
||||
icon="vn:basketadd"
|
||||
color="primary"
|
||||
>
|
||||
<QTooltip>{{ t('New order') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
:to="{
|
||||
name: 'AccountSummary',
|
||||
|
@ -215,6 +255,8 @@ es:
|
|||
Go to module index: Ir al índice del módulo
|
||||
Customer ticket list: Listado de tickets del cliente
|
||||
Customer invoice out list: Listado de facturas del cliente
|
||||
New order: Nuevo pedido
|
||||
New ticket: Nuevo ticket
|
||||
Go to user: Ir al usuario
|
||||
Go to supplier: Ir al proveedor
|
||||
Customer unpaid: Cliente impago
|
||||
|
|
|
@ -8,9 +8,6 @@ import { useQuasar } from 'quasar';
|
|||
import useNotify from 'src/composables/useNotify';
|
||||
|
||||
import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
|
||||
import TicketCreateDialog from 'src/pages/Ticket/TicketCreateDialog.vue';
|
||||
import OrderCreateDialog from 'src/pages/Order/Card/OrderCreateDialog.vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const $props = defineProps({
|
||||
customer: {
|
||||
|
@ -28,7 +25,7 @@ const showSmsDialog = () => {
|
|||
quasar.dialog({
|
||||
component: VnSmsDialog,
|
||||
componentProps: {
|
||||
phone: $props.customer.phone || $props.customer.mobile,
|
||||
phone: $props.customer.mobile || $props.customer.phone,
|
||||
promise: sendSms,
|
||||
},
|
||||
});
|
||||
|
@ -43,34 +40,9 @@ const sendSms = async (payload) => {
|
|||
notify(error.message, 'positive');
|
||||
}
|
||||
};
|
||||
|
||||
const ticketCreateFormDialog = ref(null);
|
||||
const openTicketCreateForm = () => {
|
||||
ticketCreateFormDialog.value.show();
|
||||
};
|
||||
const orderCreateFormDialog = ref(null);
|
||||
const openOrderCreateForm = () => {
|
||||
orderCreateFormDialog.value.show();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QItem v-ripple clickable @click="openTicketCreateForm()">
|
||||
<QItemSection>
|
||||
{{ t('globals.pageTitles.createTicket') }}
|
||||
<QDialog ref="ticketCreateFormDialog">
|
||||
<TicketCreateDialog />
|
||||
</QDialog>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-ripple clickable @click="openOrderCreateForm()">
|
||||
<QItemSection>
|
||||
{{ t('globals.pageTitles.createOrder') }}
|
||||
<QDialog ref="orderCreateFormDialog">
|
||||
<OrderCreateDialog :client-fk="customer.id" />
|
||||
</QDialog>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
<QItem v-ripple clickable>
|
||||
<QItemSection @click="showSmsDialog()">{{ t('Send SMS') }}</QItemSection>
|
||||
</QItem>
|
||||
|
|
|
@ -53,11 +53,11 @@ function handleLocation(data, location) {
|
|||
</QIcon>
|
||||
</template>
|
||||
</VnInput>
|
||||
<VnInput :label="t('Tax number')" clearable v-model="data.fi" />
|
||||
<VnInput :label="t('Tax number')" clearable v-model="data.fi" required />
|
||||
</VnRow>
|
||||
|
||||
<VnRow>
|
||||
<VnInput :label="t('Street')" clearable v-model="data.street" />
|
||||
<VnInput :label="t('Street')" clearable v-model="data.street" required />
|
||||
</VnRow>
|
||||
|
||||
<VnRow>
|
||||
|
@ -68,6 +68,7 @@ function handleLocation(data, location) {
|
|||
option-label="vat"
|
||||
option-value="id"
|
||||
v-model="data.sageTaxTypeFk"
|
||||
:required="data.isTaxDataChecked"
|
||||
/>
|
||||
<VnSelect
|
||||
:label="t('Sage transaction type')"
|
||||
|
@ -76,6 +77,7 @@ function handleLocation(data, location) {
|
|||
option-label="transaction"
|
||||
option-value="id"
|
||||
v-model="data.sageTransactionTypeFk"
|
||||
:required="data.isTaxDataChecked"
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
|
@ -96,6 +98,7 @@ function handleLocation(data, location) {
|
|||
:roles-allowed-to-create="['deliveryAssistant', 'administrative']"
|
||||
:acls="[{ model: 'Town', props: '*', accessType: 'WRITE' }]"
|
||||
:location="data"
|
||||
:required="true"
|
||||
@update:model-value="(location) => handleLocation(data, location)"
|
||||
/>
|
||||
</VnRow>
|
||||
|
|
|
@ -80,6 +80,11 @@ const columns = computed(() => [
|
|||
align: 'left',
|
||||
name: 'amount',
|
||||
label: t('Amount'),
|
||||
columnCreate: {
|
||||
component: 'number',
|
||||
autofocus: true,
|
||||
required: true,
|
||||
},
|
||||
format: ({ amount }) => toCurrency(amount),
|
||||
create: true,
|
||||
},
|
||||
|
|
|
@ -22,5 +22,6 @@ const noteFilter = computed(() => {
|
|||
:filter="noteFilter"
|
||||
:body="{ clientFk: route.params.id }"
|
||||
style="overflow-y: auto"
|
||||
:select-type="true"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -56,6 +56,7 @@ const columns = computed(() => [
|
|||
label: t('Period'),
|
||||
create: true,
|
||||
...componentColumn('number'),
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||
|
||||
import { toCurrency, toPercentage, toDate } from 'src/filters';
|
||||
import CardSummary from 'components/ui/CardSummary.vue';
|
||||
import { getUrl } from 'src/composables/getUrl';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
||||
import VnLinkMail from 'src/components/ui/VnLinkMail.vue';
|
||||
import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
|
||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||
import VnRow from 'src/components/ui/VnRow.vue';
|
||||
|
@ -25,6 +27,11 @@ const $props = defineProps({
|
|||
const entityId = computed(() => $props.id || route.params.id);
|
||||
const customer = computed(() => summary.value.entity);
|
||||
const summary = ref();
|
||||
const clientUrl = ref();
|
||||
|
||||
onMounted(async () => {
|
||||
clientUrl.value = (await getUrl('client/')) + entityId.value + '/';
|
||||
});
|
||||
|
||||
const balanceDue = computed(() => {
|
||||
return (
|
||||
|
@ -67,6 +74,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
ref="summary"
|
||||
:url="`Clients/${entityId}/summary`"
|
||||
data-key="CustomerSummary"
|
||||
module-name="Customer"
|
||||
>
|
||||
<template #body="{ entity }">
|
||||
<QCard class="vn-one">
|
||||
|
@ -79,7 +87,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
<VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
|
||||
<VnLv :value="entity.phone">
|
||||
<template #label>
|
||||
{{ t('customer.summary.phone') }}
|
||||
{{ t('customer.extendedList.tableVisibleColumns.phone') }}
|
||||
<VnLinkPhone :phone-number="entity.phone" />
|
||||
</template>
|
||||
</VnLv>
|
||||
|
@ -87,9 +95,19 @@ const sumRisk = ({ clientRisks }) => {
|
|||
<template #label>
|
||||
{{ t('customer.summary.mobile') }}
|
||||
<VnLinkPhone :phone-number="entity.mobile" />
|
||||
<VnLinkPhone
|
||||
say-simple
|
||||
:phone-number="entity.mobile"
|
||||
:channel="entity.country?.saySimpleCountry?.channel"
|
||||
class="q-ml-xs"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('customer.summary.email')" :value="entity.email" copy />
|
||||
<VnLv :value="entity.email" copy
|
||||
><template #label>
|
||||
{{ t('globals.params.email') }}
|
||||
<VnLinkMail email="entity.email"></VnLinkMail> </template
|
||||
></VnLv>
|
||||
<VnLv
|
||||
:label="t('customer.summary.salesPerson')"
|
||||
:value="entity?.salesPersonUser?.name"
|
||||
|
@ -130,7 +148,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
<VnLv
|
||||
v-if="entity.country"
|
||||
:label="t('customer.summary.country')"
|
||||
:value="entity.country.country"
|
||||
:value="entity.country.name"
|
||||
/>
|
||||
<VnLv :label="t('customer.summary.street')" :value="entity.street" />
|
||||
</QCard>
|
||||
|
@ -166,7 +184,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
<QCard class="vn-one">
|
||||
<VnTitle
|
||||
:url="`#/customer/${entityId}/billing-data`"
|
||||
:text="t('customer.summary.payMethodFk')"
|
||||
:text="t('customer.summary.billingData')"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('customer.summary.payMethod')"
|
||||
|
@ -201,7 +219,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
:value="entity.defaultAddress.city"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('customer.summary.addressStreet')"
|
||||
:label="t('customer.summary.street')"
|
||||
:value="entity.defaultAddress.street"
|
||||
/>
|
||||
</QCard>
|
||||
|
@ -222,6 +240,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
</QCard>
|
||||
<QCard class="vn-one" v-if="entity.account">
|
||||
<VnTitle
|
||||
target="_blank"
|
||||
:url="`${grafanaUrl}/d/adjlxzv5yjt34d/analisis-de-clientes-7c-crm?orgId=1&var-clientFk=${entityId}`"
|
||||
:text="t('customer.summary.businessData')"
|
||||
icon="vn:grafana"
|
||||
|
@ -235,6 +254,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
:value="toCurrency(entity?.mana?.mana)"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="entity.claimsRatio"
|
||||
:label="t('customer.summary.priceIncreasingRate')"
|
||||
:value="toPercentage(priceIncreasingRate)"
|
||||
/>
|
||||
|
@ -243,12 +263,14 @@ const sumRisk = ({ clientRisks }) => {
|
|||
:value="toCurrency(entity?.averageInvoiced?.invoiced)"
|
||||
/>
|
||||
<VnLv
|
||||
v-if="entity.claimsRatio"
|
||||
:label="t('customer.summary.claimRate')"
|
||||
:value="toPercentage(claimRate)"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-one" v-if="entity.account">
|
||||
<VnTitle
|
||||
target="_blank"
|
||||
:url="`${grafanaUrl}/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`"
|
||||
:text="t('customer.summary.payMethodFk')"
|
||||
icon="vn:grafana"
|
||||
|
@ -268,10 +290,12 @@ const sumRisk = ({ clientRisks }) => {
|
|||
/>
|
||||
|
||||
<VnLv
|
||||
v-if="entity.creditInsurance"
|
||||
:label="t('customer.summary.securedCredit')"
|
||||
:value="toCurrency(entity.creditInsurance)"
|
||||
:info="t('customer.summary.securedCreditInfo')"
|
||||
/>
|
||||
|
||||
<VnLv
|
||||
:label="t('customer.summary.balance')"
|
||||
:value="toCurrency(sumRisk(entity)) || toCurrency(0)"
|
||||
|
@ -301,7 +325,7 @@ const sumRisk = ({ clientRisks }) => {
|
|||
:value="entity.recommendedCredit"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard>
|
||||
<QCard class="vn-one">
|
||||
<VnTitle :text="t('Latest tickets')" />
|
||||
<CustomerSummaryTable />
|
||||
</QCard>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Estava ficat aixina pq si li fiques false es pq no vols q se puga filtrar la columna. Pero null/undefined es pq si