adminforth 2.4.0-next.331 → 2.4.0-next.333

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,6 +62,7 @@
62
62
 
63
63
  <ResourceForm
64
64
  v-else-if="coreStore.resource"
65
+ ref="resourceFormRef"
65
66
  :record="editableRecord"
66
67
  :resource="coreStore.resource"
67
68
  :adminUser="coreStore.adminUser"
@@ -93,13 +94,14 @@ import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
93
94
  import { useCoreStore } from '@/stores/core';
94
95
  import { callAdminForthApi, getCustomComponent,checkAcessByAllowedActions, initThreeDotsDropdown } from '@/utils';
95
96
  import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
96
- import { computed, onMounted, ref, type Ref } from 'vue';
97
+ import { computed, onMounted, ref, type Ref, nextTick } from 'vue';
97
98
  import { useRoute, useRouter } from 'vue-router';
98
99
  import { showErrorTost } from '@/composables/useFrontendApi';
99
100
  import ThreeDotsMenu from '@/components/ThreeDotsMenu.vue';
100
101
  import adminforth from '@/adminforth';
101
102
  import { useI18n } from 'vue-i18n';
102
103
  import { type AdminForthComponentDeclarationFull } from '@/types/Common.js';
104
+ import type { AdminForthResourceColumn } from '@/types/Back';
103
105
 
104
106
  const { t } = useI18n();
105
107
  const coreStore = useCoreStore();
@@ -116,6 +118,8 @@ const saving = ref(false);
116
118
 
117
119
  const record: Ref<Record<string, any>> = ref({});
118
120
 
121
+ const resourceFormRef = ref<InstanceType<typeof ResourceForm> | null>(null);
122
+
119
123
  const editSaveButtonInjection = computed<AdminForthComponentDeclarationFull | null>(() => {
120
124
  const raw: any = coreStore.resourceOptions?.pageInjections?.edit?.saveButton as any;
121
125
  if (!raw) return null;
@@ -168,6 +172,8 @@ onMounted(async () => {
168
172
  async function saveRecord(opts?: { confirmationResult?: any }) {
169
173
  if (!isValid.value) {
170
174
  validating.value = true;
175
+ await nextTick();
176
+ scrollToInvalidField();
171
177
  return;
172
178
  } else {
173
179
  validating.value = false;
@@ -223,4 +229,23 @@ async function saveRecord(opts?: { confirmationResult?: any }) {
223
229
  saving.value = false;
224
230
  }
225
231
 
232
+ function scrollToInvalidField() {
233
+ let columnsWithErrors: {column: AdminForthResourceColumn, error: string}[] = [];
234
+ for (const column of resourceFormRef.value?.editableColumns || []) {
235
+ const error = resourceFormRef.value?.columnError(column);
236
+ if (error) {
237
+ columnsWithErrors.push({column, error});
238
+ }
239
+ }
240
+ const errorMessage = t('Failed to save. Please fix errors for the following fields:') + '<ul class="mt-2 list-disc list-inside">' + columnsWithErrors.map(c => `<li><strong>${c.column.label || c.column.name}</strong>: ${c.error}</li>`).join('') + '</ul>';
241
+ adminforth.alert({
242
+ messageHtml: errorMessage,
243
+ variant: 'danger'
244
+ });
245
+ const firstInvalidElement = document.querySelector('.af-invalid-field-message');
246
+ if (firstInvalidElement) {
247
+ firstInvalidElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
248
+ }
249
+ }
250
+
226
251
  </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "2.4.0-next.331",
3
+ "version": "2.4.0-next.333",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",