adminforth 1.1.69 → 1.1.70

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.
Files changed (47) hide show
  1. package/auth.ts +1 -3
  2. package/dist/auth.js +1 -2
  3. package/dist/spa/index.html +4 -4
  4. package/dist/spa/package-lock.json +5 -206
  5. package/dist/spa/package.json +2 -8
  6. package/dist/spa/public/favicon.ico +0 -0
  7. package/dist/spa/spa/public/favicon.ico +0 -0
  8. package/dist/spa/spa/src/views/HomeView.vue +8 -0
  9. package/dist/spa/spa/src/views/LoginView.vue +0 -2
  10. package/dist/spa/src/App.vue +72 -171
  11. package/dist/spa/src/assets/logo.svg +1 -19
  12. package/dist/spa/src/components/AcceptModal.vue +10 -3
  13. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  14. package/dist/spa/src/components/CustomDatePicker.vue +6 -19
  15. package/dist/spa/src/components/CustomDateRangePicker.vue +5 -14
  16. package/dist/spa/src/components/Dropdown.vue +5 -19
  17. package/dist/spa/src/components/Filters.vue +37 -91
  18. package/dist/spa/src/components/MenuLink.vue +2 -2
  19. package/dist/spa/src/components/ResourceForm.vue +103 -163
  20. package/dist/spa/src/components/ValueRenderer.vue +6 -22
  21. package/dist/spa/src/main.ts +1 -1
  22. package/dist/spa/src/router/index.ts +19 -30
  23. package/dist/spa/src/stores/core.ts +59 -65
  24. package/dist/spa/src/stores/modal.ts +3 -13
  25. package/dist/spa/src/utils.ts +8 -65
  26. package/dist/spa/src/views/CreateView.vue +16 -76
  27. package/dist/spa/src/views/EditView.vue +14 -76
  28. package/dist/spa/src/views/HomeView.vue +8 -0
  29. package/dist/spa/src/views/ListView.vue +360 -88
  30. package/dist/spa/src/views/LoginView.vue +5 -17
  31. package/dist/spa/src/views/ResourceParent.vue +1 -1
  32. package/dist/spa/src/views/ShowView.vue +19 -114
  33. package/dist/spa/tailwind.config.js +2 -5
  34. package/dist/spa/vite.config.ts +0 -6
  35. package/dist/types.js +30 -0
  36. package/package.json +1 -1
  37. package/spa/src/views/LoginView.vue +0 -2
  38. package/dist/spa/public/assets/favicon.png +0 -0
  39. package/dist/spa/src/components/CustomRangePicker.vue +0 -148
  40. package/dist/spa/src/components/ResourceListTable.vue +0 -419
  41. package/dist/spa/src/components/Toast.vue +0 -66
  42. package/dist/spa/src/composables/useFrontendApi.ts +0 -26
  43. package/dist/spa/src/composables/useStores.ts +0 -113
  44. package/dist/spa/src/spa_types/core.ts +0 -51
  45. package/dist/spa/src/stores/filters.ts +0 -22
  46. package/dist/spa/src/stores/toast.ts +0 -15
  47. package/dist/spa/src/stores/user.ts +0 -54
@@ -1,24 +1,23 @@
1
1
  import { createRouter, createWebHistory } from 'vue-router'
2
+ import HomeView from '../views/HomeView.vue'
2
3
  import ResourceParent from '@/views/ResourceParent.vue'
3
- import { useUserStore } from '@/stores/user'
4
- /* IMPORTANT:ADMINFORTH ROUTES IMPORTS */
4
+ import ListView from '@/views/ListView.vue'
5
+ import ShowView from '@/views/ShowView.vue'
6
+ import EditView from '@/views/EditView.vue'
7
+ import CreateView from '@/views/CreateView.vue'
5
8
 
6
9
  const router = createRouter({
7
10
  history: createWebHistory(import.meta.env.BASE_URL),
8
11
  routes: [
12
+ {
13
+ path: '/',
14
+ name: 'home',
15
+ component: HomeView
16
+ },
9
17
  {
10
18
  path: '/login',
11
19
  name: 'login',
12
- component: () => import('@/views/LoginView.vue'),
13
- meta: { title: 'login' },
14
- beforeEnter: async (to, from, next) => {
15
- const userStore = useUserStore()
16
- if(localStorage.getItem('isAuthorized') === 'true'){
17
- next({name: 'home'})
18
- } else {
19
- next()
20
- }
21
- }
20
+ component: () => import('@/views/LoginView.vue')
22
21
  },
23
22
  {
24
23
  path: '/resource/:resourceId',
@@ -27,29 +26,23 @@ const router = createRouter({
27
26
  children: [
28
27
  {
29
28
  path: '',
30
- component: () => import('@/views/ListView.vue'),
31
- name: 'resource-list',
32
- meta: { title: 'list',type: 'list' }
29
+ component: ListView,
30
+ name: 'resource-list'
33
31
  },
34
32
  {
35
33
  path: 'show/:primaryKey',
36
- component: () => import('@/views/ShowView.vue'),
37
- name: 'resource-show',
38
- meta: { title: 'show', type: 'show'}
39
-
34
+ component: ShowView,
35
+ name: 'resource-show'
40
36
  },
41
37
  {
42
38
  path: 'edit/:primaryKey',
43
- component: () => import('@/views/EditView.vue'),
44
- name: 'resource-edit',
45
- meta: { title: 'edit', type: 'edit'}
39
+ component: EditView,
40
+ name: 'resource-edit'
46
41
  },
47
42
  {
48
43
  path: 'create',
49
- component: () => import('@/views/CreateView.vue'),
50
- name: 'resource-create',
51
- meta: { title: 'create', type: 'create'}
52
-
44
+ component: CreateView,
45
+ name: 'resource-create'
53
46
  },
54
47
  ]
55
48
  },
@@ -57,8 +50,4 @@ const router = createRouter({
57
50
  ]
58
51
  })
59
52
 
60
-
61
-
62
-
63
-
64
53
  export default router
@@ -1,105 +1,96 @@
1
1
  import { ref, computed } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
3
  import { callAdminForthApi } from '@/utils';
4
- import type { AdminForthResource, AdminForthResourceColumn } from '@/types/AdminForthConfig';
5
- import type { Ref } from 'vue'
4
+ import router from '@/router';
5
+
6
+ async function findHomepage(menu) {
7
+ for (const item of menu) {
8
+ if (item.homepage) {
9
+ return item;
10
+ }
11
+ if (item.children) {
12
+ const res = findHomepage(item.children);
13
+ if (res) {
14
+ return res;
15
+ }
16
+ }
17
+ }
18
+ return null;
19
+ }
6
20
 
7
21
  export const useCoreStore = defineStore('core', () => {
8
- const resourceById: Ref<Object> = ref({});
22
+ const resourceById = ref([]);
9
23
  const menu = ref([]);
10
24
  const config = ref({});
11
- const record: Ref<any | null> = ref({});
12
- const resource: Ref<AdminForthResource | null> = ref(null);
13
-
14
- const resourceColumnsWithFilters = computed(() => {
15
- if (!resource.value) {
16
- return [];
17
- }
18
- return resource.value.columns.filter((col: AdminForthResourceColumn) => col.showIn?.includes('filter'));
19
- })
20
-
21
- const resourceOptions = ref(null);
25
+ const record = ref({});
26
+ const resourceColumns = ref(null);
22
27
  const resourceColumnsError = ref('');
23
28
  const resourceColumnsId = ref(null);
24
- const adminUser = ref(null);
29
+ const user = ref(null);
25
30
 
26
31
  async function fetchMenuAndResource() {
27
32
  const resp = await callAdminForthApi({
28
33
  path: '/get_base_config',
29
34
  method: 'GET',
30
35
  });
31
- if(!resp){
32
- return
33
- }
34
36
  menu.value = resp.menu;
35
- resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
37
+ resourceById.value = resp.resources.reduce((acc, resource) => {
36
38
  acc[resource.resourceId] = resource;
37
39
  return acc;
38
40
  }, {});
39
41
  config.value = resp.config;
40
- adminUser.value = resp.user;
41
- console.log('🌍 AdminForth v', resp.version);
42
+ user.value = resp.user;
43
+
44
+ // find homepage:true in menu recuresively
45
+ if (import.meta.env.DEV){
46
+ return
47
+ } else {
48
+ const homepage = await findHomepage(menu.value);
49
+ if (homepage) {
50
+ if (homepage.resourceId) {
51
+ // redirect to homepage
52
+ router.push({ name: 'resource-list', params: { resourceId: homepage.resourceId } });
53
+ } else {
54
+ // redirect to path
55
+ router.push(homepage.path);
56
+ }
57
+ }
58
+ }
42
59
  }
43
60
 
44
61
  async function fetchRecord({ resourceId, primaryKey }) {
45
62
  record.value = null;
46
-
47
- if (!resource.value) {
48
- throw new Error('Columns not fetched yet');
49
- }
50
63
 
51
- const respData = await callAdminForthApi({
52
- path: '/get_resource_data',
64
+ record.value = await callAdminForthApi({
65
+ path: '/get_record',
53
66
  method: 'POST',
54
67
  body: {
55
- source: 'show',
56
68
  resourceId: resourceId,
57
- filters: [
58
- {
59
- field: resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey).name,
60
- operator: 'eq',
61
- value: primaryKey
62
- }
63
- ],
64
- sort: [],
65
- limit: 1,
66
- offset: 0
69
+ primaryKey: primaryKey,
67
70
  }
68
71
  });
69
-
70
- if (respData.error) {
71
- window.adminforth.alert({
72
- message: respData.error,
73
- variant: 'danger',
74
- timeout: 'unlimited'
75
- });
76
- record.value = {};
77
- } else {
78
- record.value = respData.data[0];
79
- }
80
-
81
72
  }
82
73
 
83
- async function fetchResourceFull({ resourceId }: { resourceId: string }) {
84
- if (resourceColumnsId.value === resourceId && resource.value) {
74
+ async function fetchColumns({ resourceId }) {
75
+ if (resourceColumnsId.value === resourceId && resourceColumns.value) {
85
76
  // already fetched
86
77
  return;
87
78
  }
88
79
  resourceColumnsId.value = resourceId;
80
+ resourceColumns.value = null;
89
81
  resourceColumnsError.value = '';
90
82
  const res = await callAdminForthApi({
91
- path: '/get_resource',
83
+ path: '/get_resource_columns',
92
84
  method: 'POST',
93
85
  body: {
94
86
  resourceId,
95
87
  }
96
- });
88
+ }
89
+ );
97
90
  if (res.error) {
98
91
  resourceColumnsError.value = res.error;
99
92
  } else {
100
- resourceById.value[resourceId] = res.resource;
101
- resource.value = res.resource;
102
- resourceOptions.value = res.resource.options;
93
+ resourceColumns.value = res.resource.columns;
103
94
  }
104
95
  }
105
96
 
@@ -111,16 +102,21 @@ export const useCoreStore = defineStore('core', () => {
111
102
  config.value = {...config.value, ...res};
112
103
  }
113
104
 
114
-
105
+ async function logout() {
106
+ await callAdminForthApi({
107
+ path: '/logout',
108
+ method: 'POST',
109
+ });
110
+ }
115
111
 
116
112
  const username = computed(() => {
117
113
  const usernameField = config.value.usernameField;
118
- return adminUser.value && adminUser.value[usernameField];
114
+ return user.value && user.value[usernameField];
119
115
  });
120
116
 
121
117
  const userFullname = computed(() => {
122
118
  const userFullnameField = config.value.userFullnameField;
123
- return adminUser.value && adminUser.value[userFullnameField];
119
+ return user.value && user.value[userFullnameField];
124
120
  })
125
121
 
126
122
 
@@ -134,11 +130,9 @@ export const useCoreStore = defineStore('core', () => {
134
130
  fetchMenuAndResource,
135
131
  fetchRecord,
136
132
  record,
137
- fetchResourceFull,
133
+ resourceColumns,
134
+ fetchColumns,
138
135
  resourceColumnsError,
139
- resourceOptions,
140
- resource,
141
- adminUser,
142
- resourceColumnsWithFilters
136
+ logout
143
137
  }
144
138
  })
@@ -1,12 +1,6 @@
1
1
  import { ref } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
-
4
- type ModalContentType = {
5
- title?: string;
6
- content?: string;
7
- acceptText?: string;
8
- cancelText?: string;
9
- }
3
+ import { callAdminForthApi } from '@/utils';
10
4
 
11
5
 
12
6
  export const useModalStore = defineStore('modal', () => {
@@ -18,17 +12,13 @@ export const useModalStore = defineStore('modal', () => {
18
12
  });
19
13
  const isOpened = ref(false);
20
14
  const onAcceptFunction: any = ref(()=>{});
21
- const onCancelFunction: any = ref(()=>{});
22
15
  function togleModal() {
23
16
  isOpened.value = !isOpened.value;
24
17
  }
25
18
  function setOnAcceptFunction(func: Function) {
26
19
  onAcceptFunction.value = func;
27
20
  }
28
- function setOnCancelFunction(func: Function) {
29
- onCancelFunction.value = func;
30
- }
31
- function setModalContent(content: ModalContentType) {
21
+ function setModalContent(content: string) {
32
22
  modalContent.value = content;
33
23
  }
34
24
  function resetmodalState() {
@@ -43,6 +33,6 @@ export const useModalStore = defineStore('modal', () => {
43
33
 
44
34
  }
45
35
 
46
- return {isOpened, setModalContent,onCancelFunction, togleModal,modalContent, setOnAcceptFunction, onAcceptFunction,resetmodalState,setOnCancelFunction}
36
+ return {isOpened, setModalContent, togleModal,modalContent, setOnAcceptFunction, onAcceptFunction,resetmodalState}
47
37
 
48
38
  })
@@ -1,10 +1,6 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
- import type { CoreConfig } from './spa_types/core';
3
2
 
4
3
  import router from "./router";
5
- import { useRouter } from 'vue-router';
6
- import { useCoreStore } from './stores/core';
7
- import { useUserStore } from './stores/user';
8
4
 
9
5
  export async function callApi({path, method, body=undefined} ) {
10
6
  const options = {
@@ -17,18 +13,14 @@ export async function callApi({path, method, body=undefined} ) {
17
13
  const fullPath = `${import.meta.env.VITE_ADMINFORTH_PUBLIC_PATH || ''}${path}`;
18
14
  const r = await fetch(fullPath, options);
19
15
  if (r.status == 401) {
20
- useUserStore().unauthorize();
21
- router.push({ name: 'login' });
16
+ console.log('router', router);
17
+ router.push({name: 'login'});
22
18
  return null;
23
- }
19
+ }
24
20
  return await r.json();
25
21
  }
26
22
 
27
- export async function callAdminForthApi({ path, method, body=undefined }: {
28
- path: string,
29
- method: 'GET' | 'POST' | 'PUT' | 'DELETE',
30
- body?: any
31
- }) {
23
+ export async function callAdminForthApi({ path, method, body=undefined }) {
32
24
  try {
33
25
  return callApi({path: `/adminapi/v1${path}`, method, body} );
34
26
  } catch (e) {
@@ -37,11 +29,9 @@ export async function callAdminForthApi({ path, method, body=undefined }: {
37
29
  }
38
30
  }
39
31
 
40
- export function getCustomComponent({ file, meta }: { file: string, meta: any }) {
41
- const name = file.replace(/@/g, '').replace(/\./g, '').replace(/\//g, '');
42
- console.log('resolving name', name);
43
- return resolveComponent(name);
44
- }
32
+
33
+
34
+
45
35
 
46
36
  export function getIcon(icon: string) {
47
37
  // icon format is "feather:icon-name". We need to get IconName in pascal case
@@ -51,51 +41,4 @@ export function getIcon(icon: string) {
51
41
  const [iconSet, iconName] = icon.split(':');
52
42
  const compName = 'Icon' + iconName.split('-').map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join('');
53
43
  return resolveComponent(compName);
54
- }
55
-
56
- export const loadFile = (file: string) => {
57
- if (file.startsWith('http')) {
58
- return file;
59
- }
60
- let path;
61
- let baseUrl = '';
62
- if (file.startsWith('@/')) {
63
- path = file.replace('@/', '');
64
- baseUrl = new URL(`./${path}`, import.meta.url).href;
65
- } else if (file.startsWith('@@/')) {
66
- path = file.replace('@@/', '');
67
- baseUrl = new URL(`./custom/${path}`, import.meta.url).href;
68
- } else {
69
- baseUrl = new URL(`./${file}`, import.meta.url).href;
70
- }
71
- return baseUrl;
72
- }
73
-
74
- export function checkEmptyValues(value: any, viewType:'show' | 'list' ) {
75
- const config: CoreConfig | {} = useCoreStore().config;
76
- let emptyFieldPlaceholder = '';
77
- if (config.emptyFieldPlaceholder) {
78
- if(typeof config.emptyFieldPlaceholder === 'string') {
79
- emptyFieldPlaceholder = config.emptyFieldPlaceholder;
80
- } else {
81
- emptyFieldPlaceholder = config.emptyFieldPlaceholder?.[viewType] || '';
82
- }
83
- if (value === null || value === undefined || value === '') {
84
- return emptyFieldPlaceholder;
85
- }
86
- }
87
- return value;
88
- }
89
-
90
- export function checkAcessByAllowedActions(allowedActions:any, action:any ) {
91
- if (!allowedActions) {
92
- console.warn('allowedActions not set');
93
- return;
94
- }
95
- if(allowedActions[action] === false) {
96
- console.warn(`Action ${action} is not allowed`);
97
- router.back();
98
- }
99
- }
100
-
101
-
44
+ }
@@ -1,25 +1,16 @@
1
1
  <template>
2
2
  <div class="relative">
3
3
 
4
- <component
5
- v-for="c in coreStore?.resourceOptions?.pageInjections?.create?.beforeBreadcrumbs || []"
6
- :is="getCustomComponent(c)"
7
- :meta="c.meta"
8
- :record="coreStore.record"
9
- :resource="coreStore.resource"
10
- :adminUser="coreStore.adminUser"
11
- />
12
-
13
4
  <BreadcrumbsWithButtons>
14
5
  <!-- save and cancle -->
15
6
  <button @click="$router.back()"
16
- class="flex items-center py-1 px-3 me-2 text-sm font-medium rounded-default text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
7
+ class="flex items-center py-1 px-3 me-2 mb-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
17
8
  >
18
9
  Cancel
19
10
  </button>
20
11
 
21
12
  <button @click="saveRecord"
22
- class="flex items-center py-1 px-3 text-sm font-medium rounded-default text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50"
13
+ class="flex items-center py-1 px-3 mb-2 text-sm font-medium text-red-600 focus:outline-none bg-white rounded border border-gray-300 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-red-500 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-50"
23
14
  :disabled="saving || (validating && !isValid)"
24
15
  >
25
16
  <svg v-if="saving" x
@@ -31,55 +22,32 @@
31
22
 
32
23
  </BreadcrumbsWithButtons>
33
24
 
34
- <component
35
- v-for="c in coreStore?.resourceOptions?.pageInjections?.create?.afterBreadcrumbs || []"
36
- :is="getCustomComponent(c)"
37
- :meta="c.meta"
38
- :record="coreStore.record"
39
- :resource="coreStore.resource"
40
- :adminUser="coreStore.adminUser"
41
- />
42
-
43
25
  <SingleSkeletLoader v-if="loading"></SingleSkeletLoader>
44
-
45
26
 
46
27
  <ResourceForm
47
28
  v-else
48
- :record="record"
49
- :resource="coreStore.resource"
29
+ :record="{}"
30
+ :resourceColumns="coreStore.resourceColumns"
50
31
  @update:record="onUpdateRecord"
51
32
  @update:isValid="isValid = $event"
52
33
  :validating="validating"
53
- :customComponentsPerColumn="createComponentsPerColumn"
54
34
  >
55
35
  </ResourceForm>
56
36
 
57
- <component
58
- v-for="c in coreStore?.resourceOptions?.pageInjections?.create?.bottom || []"
59
- :is="getCustomComponent(c)"
60
- :meta="c.meta"
61
- :record="coreStore.record"
62
- :resource="coreStore.resource"
63
- :adminUser="coreStore.adminUser"
64
- />
65
-
66
37
  </div>
67
38
  </template>
68
39
 
69
40
 
70
41
  <script setup>
71
42
 
72
- import BreadcrumbsWithButtons from '@/components/BreadcrumbsWithButtons.vue';
73
- import ResourceForm from '@/components/ResourceForm.vue';
74
- import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
43
+ import { ref, computed, onMounted } from 'vue';
44
+ import { useRoute, useRouter } from 'vue-router';
75
45
  import { useCoreStore } from '@/stores/core';
76
- import { callAdminForthApi, getCustomComponent,checkAcessByAllowedActions } from '@/utils';
46
+ import { callAdminForthApi } from '@/utils';
47
+ import ResourceForm from '@/components/ResourceForm.vue';
48
+ import BreadcrumbsWithButtons from '@/components/BreadcrumbsWithButtons.vue';
77
49
  import { IconFloppyDiskSolid } from '@iconify-prerendered/vue-flowbite';
78
- import { onMounted, ref, watch } from 'vue';
79
- import { useRoute, useRouter } from 'vue-router';
80
- import { computed } from 'vue';
81
- import { showErrorTost } from '@/composables/useFrontendApi';
82
-
50
+ import SingleSkeletLoader from '@/components/SingleSkeletLoader.vue';
83
51
 
84
52
  const isValid = ref(false);
85
53
  const validating = ref(false);
@@ -91,19 +59,9 @@ const route = useRoute();
91
59
  const router = useRouter();
92
60
 
93
61
  const record = ref({});
94
- let createComponentsPerColumn = {};
95
62
 
96
63
  const coreStore = useCoreStore();
97
64
 
98
- const initalValues = computed(() => {
99
- if (!route.query.values) {
100
- return {};
101
- }
102
- return JSON.parse(decodeURIComponent(route.query.values));
103
- });
104
-
105
-
106
-
107
65
  async function onUpdateRecord(newRecord) {
108
66
  console.log('newRecord', newRecord);
109
67
  record.value = newRecord;
@@ -111,18 +69,10 @@ async function onUpdateRecord(newRecord) {
111
69
 
112
70
  onMounted(async () => {
113
71
  loading.value = true;
114
- record.value = initalValues.value;
115
- await coreStore.fetchResourceFull({
72
+ coreStore.fetchColumns({
116
73
  resourceId: route.params.resourceId
117
74
  });
118
- createComponentsPerColumn = coreStore.resource.columns.reduce((acc, column) => {
119
- if (column.components?.create) {
120
- acc[column.name] = getCustomComponent(column.components.create);
121
- }
122
- return acc;
123
- }, {});
124
75
  loading.value = false;
125
- checkAcessByAllowedActions(coreStore.resourceOptions.allowedActions,'create');
126
76
  });
127
77
 
128
78
  async function saveRecord() {
@@ -141,22 +91,12 @@ async function saveRecord() {
141
91
  record: record.value,
142
92
  },
143
93
  });
144
- if (response.error) {
145
- showErrorTost(response.error);
146
-
147
- }
148
94
  saving.value = false;
149
- if (route.query.returnTo) {
150
- router.push(route.query.returnTo);
151
- } else {
152
- router.push({
153
- name: 'resource-show',
154
- params: {
155
- resourceId: route.params.resourceId,
156
- primaryKey: response.newRecordId
157
- }
158
- });
159
- }
95
+ router.push({ name: 'resource-show', params: {
96
+ resourceId: route.params.resourceId,
97
+ primaryKey: response.newRecordId
98
+
99
+ } });
160
100
  }
161
101
 
162
102