diff --git a/src/boot/mainShortcutMixin.js b/src/boot/mainShortcutMixin.js
new file mode 100644
index 000000000..481077e37
--- /dev/null
+++ b/src/boot/mainShortcutMixin.js
@@ -0,0 +1,36 @@
+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;
+ if (!ctrlKey || !altKey) {
+ isNotified = false;
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('keyup', handleKeyUp);
+ },
+};
diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js
index fc7852369..8a75e1af7 100644
--- a/src/boot/qformMixin.js
+++ b/src/boot/qformMixin.js
@@ -1,30 +1,52 @@
-import { getCurrentInstance } from 'vue';
-
+function focusFirstInput(input) {
+ input.focus();
+ return;
+}
export default {
mounted: function () {
- const vm = getCurrentInstance();
- if (vm.type.name === 'QForm') {
- if (!['searchbarForm', 'filterPanelForm'].includes(this.$el?.id)) {
- // TODO: AUTOFOCUS IS NOT FOCUSING
- const that = this;
- this.$el.addEventListener('keyup', function (evt) {
- if (evt.key === 'Enter') {
- const input = evt.target;
- if (input.type == 'textarea' && evt.shiftKey) {
- evt.preventDefault();
- let { selectionStart, selectionEnd } = input;
- input.value =
- input.value.substring(0, selectionStart) +
- '\n' +
- input.value.substring(selectionEnd);
- selectionStart = selectionEnd = selectionStart + 1;
- return;
- }
- evt.preventDefault();
- that.onSubmit();
- }
- });
+ const that = this;
+
+ const form = document.querySelector('.q-form#formModel');
+ if (!form) return;
+ try {
+ const inputsFormCard = form.querySelectorAll(
+ `input:not([disabled]):not([type="checkbox"])`
+ );
+ if (inputsFormCard.length) {
+ focusFirstInput(inputsFormCard[0]);
}
+ const textareas = document.querySelectorAll(
+ 'textarea:not([disabled]), [contenteditable]:not([disabled])'
+ );
+ if (textareas.length) {
+ focusFirstInput(textareas[textareas.length - 1]);
+ }
+ const inputs = document.querySelectorAll(
+ 'form#formModel input:not([disabled]):not([type="checkbox"])'
+ );
+ const input = inputs[0];
+ if (!input) return;
+
+ focusFirstInput(input);
+ } catch (error) {
+ console.error(error);
}
+ form.addEventListener('keyup', function (evt) {
+ if (evt.key === 'Enter') {
+ const input = evt.target;
+ if (input.type == 'textarea' && evt.shiftKey) {
+ evt.preventDefault();
+ let { selectionStart, selectionEnd } = input;
+ input.value =
+ input.value.substring(0, selectionStart) +
+ '\n' +
+ input.value.substring(selectionEnd);
+ selectionStart = selectionEnd = selectionStart + 1;
+ return;
+ }
+ evt.preventDefault();
+ that.onSubmit();
+ }
+ });
},
};
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 01fe68d8b..d375c2f69 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -3,11 +3,16 @@ import qFormMixin from './qformMixin';
import keyShortcut from './keyShortcut';
import useNotify from 'src/composables/useNotify.js';
import { CanceledError } from 'axios';
+import { QForm } from 'quasar';
+import { QLayout } from 'quasar';
+import mainShortcutMixin from './mainShortcutMixin';
const { notify } = useNotify();
export default boot(({ app }) => {
- app.mixin(qFormMixin);
+ QForm.mixins = [qFormMixin];
+ QLayout.mixins = [mainShortcutMixin];
+
app.directive('shortcut', keyShortcut);
app.config.errorHandler = (error) => {
let message;
diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index ab2931dfd..31ad9ebed 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -177,6 +177,7 @@ function normalize(text) {
class="full-width"
filled
dense
+ autofocus
/>
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 754b084fc..2a84e5aa1 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -1,50 +1,10 @@
-
-
+
diff --git a/src/pages/Worker/Card/WorkerPda.vue b/src/pages/Worker/Card/WorkerPda.vue
index 94f4e0d95..3ceee2493 100644
--- a/src/pages/Worker/Card/WorkerPda.vue
+++ b/src/pages/Worker/Card/WorkerPda.vue
@@ -133,6 +133,7 @@ function reloadData() {
option-value="id"
id="deviceProductionFk"
hide-selected
+ data-cy="pda-dialog-select"
>
diff --git a/src/pages/Zone/Card/ZoneBasicData.vue b/src/pages/Zone/Card/ZoneBasicData.vue
index 535f2393d..731e03ba7 100644
--- a/src/pages/Zone/Card/ZoneBasicData.vue
+++ b/src/pages/Zone/Card/ZoneBasicData.vue
@@ -32,7 +32,12 @@ const agencyOptions = ref([]);
-
+
diff --git a/test/cypress/integration/worker/workerPda.spec.js b/test/cypress/integration/worker/workerPda.spec.js
index fe8efa834..dc1ca6224 100644
--- a/test/cypress/integration/worker/workerPda.spec.js
+++ b/test/cypress/integration/worker/workerPda.spec.js
@@ -1,6 +1,5 @@
describe('WorkerPda', () => {
- const deviceProductionField =
- '.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
+ const select = '[data-cy="pda-dialog-select"]';
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('developer');
@@ -9,7 +8,8 @@ describe('WorkerPda', () => {
it('assign pda', () => {
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
- cy.get(deviceProductionField).type('{downArrow}{enter}');
+ cy.get(select).click();
+ cy.get(select).type('{downArrow}{enter}');
cy.get('.q-notification__message').should('have.text', 'Data created');
});
diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js
index c6151a49b..de85dac94 100644
--- a/test/cypress/integration/zone/zoneBasicData.spec.js
+++ b/test/cypress/integration/zone/zoneBasicData.spec.js
@@ -8,7 +8,7 @@ describe('ZoneBasicData', () => {
});
it('should throw an error if the name is empty', () => {
- cy.get('.q-card > :nth-child(1)').clear();
+ cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', "can't be blank");
});