adminforth 1.1.48 → 1.1.50

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 (46) hide show
  1. package/dist/spa/index.html +2 -2
  2. package/dist/spa/package-lock.json +17 -4
  3. package/dist/spa/package.json +2 -1
  4. package/dist/spa/spa/src/App.vue +2 -2
  5. package/dist/spa/spa/src/views/ResourceParent.vue +1 -2
  6. package/dist/spa/spa/tailwind.config.js +3 -1
  7. package/dist/spa/src/App.vue +125 -45
  8. package/dist/spa/src/assets/logo.svg +19 -1
  9. package/dist/spa/src/components/AcceptModal.vue +2 -9
  10. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +1 -1
  11. package/dist/spa/src/components/CustomDatePicker.vue +16 -3
  12. package/dist/spa/src/components/CustomDateRangePicker.vue +11 -2
  13. package/dist/spa/src/components/Dropdown.vue +6 -1
  14. package/dist/spa/src/components/Filters.vue +40 -19
  15. package/dist/spa/src/components/ResourceForm.vue +26 -24
  16. package/dist/spa/src/components/ResourceListTable.vue +419 -0
  17. package/dist/spa/src/components/Toast.vue +66 -0
  18. package/dist/spa/src/components/ValueRenderer.vue +14 -8
  19. package/dist/spa/src/composables/useFrontendApi.ts +26 -0
  20. package/dist/spa/src/composables/useStores.ts +113 -0
  21. package/dist/spa/src/main.ts +1 -1
  22. package/dist/spa/src/router/index.ts +30 -20
  23. package/dist/spa/src/spa_types/core.ts +51 -0
  24. package/dist/spa/src/stores/core.ts +48 -31
  25. package/dist/spa/src/stores/filters.ts +22 -0
  26. package/dist/spa/src/stores/modal.ts +13 -3
  27. package/dist/spa/src/stores/toast.ts +15 -0
  28. package/dist/spa/src/stores/user.ts +54 -0
  29. package/dist/spa/src/utils.ts +62 -7
  30. package/dist/spa/src/views/CreateView.vue +67 -15
  31. package/dist/spa/src/views/EditView.vue +45 -11
  32. package/dist/spa/src/views/ListView.vue +82 -366
  33. package/dist/spa/src/views/LoginView.vue +16 -4
  34. package/dist/spa/src/views/ShowView.vue +105 -21
  35. package/dist/spa/tailwind.config.js +1 -1
  36. package/dist/spa/vite.config.ts +6 -0
  37. package/package.json +1 -1
  38. package/spa/src/App.vue +2 -2
  39. package/spa/src/views/ResourceParent.vue +1 -2
  40. package/spa/tailwind.config.js +3 -1
  41. package/dist/plugins/AccessControl/index.js +0 -66
  42. package/dist/plugins/AccessControl/types.js +0 -1
  43. package/dist/spa/public/favicon.ico +0 -0
  44. package/dist/spa/spa/public/favicon.ico +0 -0
  45. package/dist/types.js +0 -30
  46. /package/dist/spa/{spa/public → public/assets}/favicon.png +0 -0
@@ -0,0 +1,113 @@
1
+ import type { FrontendAPIInterface, ConfirmParams, AlertParams, FilterParams,Operator } from '../types/FrontendAPI';
2
+ import { useToastStore } from '../stores/toast';
3
+ import { useModalStore } from '../stores/modal';
4
+ import { useCoreStore } from '@/stores/core';
5
+ import { useFiltersStore } from '@/stores/filters';
6
+ import router from '@/router'
7
+ import type { AdminForthResourceColumn } from '@/types/AdminForthConfig';
8
+
9
+
10
+
11
+
12
+
13
+ declare global {
14
+ interface Window {
15
+ adminforth: {
16
+ confirm: (params: ConfirmParams) => Promise<void>;
17
+ alert: (params: AlertParams) => void;
18
+ setListFilter: (filter: any) => void;
19
+ updateListFilter: (filter: any) => void;
20
+ clearListFilters: () => void;
21
+ };
22
+ }
23
+ }
24
+
25
+ export class FrontendAPI implements FrontendAPIInterface {
26
+ private validOperators: Operator[] = ['lte', 'gte', 'in','ilike'];
27
+ private toastStore:any
28
+ private modalStore:any
29
+ private filtersStore:any
30
+ private coreStore:any
31
+ init() {
32
+ if (window.adminforth) {
33
+ throw new Error('adminforth already initialized');
34
+ }
35
+ this.toastStore = useToastStore();
36
+ this.modalStore = useModalStore();
37
+ console.log(this.toastStore, this.modalStore,'init of adminforth frontend api')
38
+ window.adminforth = {
39
+ confirm: this.confirm.bind(this),
40
+ alert: this.alert.bind(this),
41
+ setListFilter: this.setListFilter.bind(this),
42
+ updateListFilter: this.updateListFilter.bind(this),
43
+ clearListFilters: this.clearListFilters.bind(this),
44
+ }
45
+ }
46
+
47
+ confirm(params: ConfirmParams): Promise<void> {
48
+ return new Promise((resolve, reject) => {
49
+ this.modalStore.setModalContent({ content: params.message, acceptText: params.yes, cancelText: params.no })
50
+ this.modalStore.onAcceptFunction = resolve
51
+ this.modalStore.onCancelFunction = reject
52
+ this.modalStore.togleModal()
53
+ })
54
+ }
55
+
56
+ alert(params: AlertParams): void {
57
+ this.toastStore.addToast({
58
+ message: params.message,
59
+ variant: params.variant,
60
+ timeout: params.timeout
61
+ })
62
+ }
63
+
64
+ listFilterValidation(filter: FilterParams): boolean {
65
+ if(router.currentRoute.value.meta.type !== 'list'){
66
+ throw new Error(`Cannot use ${this.setListFilter.name} filter on a list page`)
67
+ } else {
68
+ if(!this.coreStore) this.coreStore = useCoreStore()
69
+ console.log(this.coreStore.resourceColumnsWithFilters,'core store')
70
+ const filterField = this.coreStore.resourceColumnsWithFilters.find((col: AdminForthResourceColumn) => col.name === filter.field)
71
+ if(!filterField){
72
+ throw new Error(`Field ${filter.field} is not available for filtering`)
73
+ }
74
+ if(filterField) {
75
+ if(!this.validOperators.includes(filter.operator)){
76
+ throw new Error(`Operator ${filter.operator} is not valid`)
77
+ }
78
+ }
79
+ }
80
+ return true
81
+ }
82
+
83
+ setListFilter(filter: FilterParams): void {
84
+ if(this.listFilterValidation(filter)){
85
+ this.filtersStore = useFiltersStore()
86
+ if(this.filtersStore.filters.some((f) => {return f.field === filter.field && f.operator === filter.operator})){
87
+ throw new Error(`Filter ${filter.field} with operator ${filter.operator} already exists`)
88
+ } else {
89
+ this.filtersStore.setFilter(filter)
90
+ }
91
+ }
92
+ }
93
+
94
+ clearListFilters(): void {
95
+ this.filtersStore = useFiltersStore()
96
+ this.filtersStore.clearFilters()
97
+ }
98
+
99
+ updateListFilter(filter: FilterParams): void {
100
+ if(this.listFilterValidation(filter)){
101
+ this.filtersStore = useFiltersStore()
102
+ const index = this.filtersStore.filters.findIndex((f: FilterParams) => f.field === filter.field)
103
+ if(index === -1) {
104
+ this.filtersStore.setFilter(filter)
105
+ } else {
106
+ this.filtersStore.setFilters([...this.filtersStore.filters.slice(0, index), filter, ...this.filtersStore.filters.slice(index + 1)])
107
+ }
108
+ }
109
+ }
110
+
111
+
112
+
113
+ }
@@ -9,7 +9,7 @@ import router from './router'
9
9
  const app = createApp(App)
10
10
  /* IMPORTANT:ADMINFORTH COMPONENT REGISTRATIONS */
11
11
 
12
-
12
+
13
13
  app.use(createPinia())
14
14
  app.use(router)
15
15
 
@@ -1,24 +1,24 @@
1
1
  import { createRouter, createWebHistory } from 'vue-router'
2
2
  import ResourceParent from '@/views/ResourceParent.vue'
3
- import ListView from '@/views/ListView.vue'
4
- import ShowView from '@/views/ShowView.vue'
5
- import EditView from '@/views/EditView.vue'
6
- import CreateView from '@/views/CreateView.vue'
3
+ import { useUserStore } from '@/stores/user'
4
+ /* IMPORTANT:ADMINFORTH ROUTES IMPORTS */
7
5
 
8
6
  const router = createRouter({
9
7
  history: createWebHistory(import.meta.env.BASE_URL),
10
8
  routes: [
11
- {
12
- path: '/',
13
- name: 'home',
14
- //redirect to login
15
- /* IMPORTANT:ADMINFORTH REDIRECT */
16
-
17
- },
18
9
  {
19
10
  path: '/login',
20
11
  name: 'login',
21
- component: () => import('@/views/LoginView.vue')
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
+ }
22
22
  },
23
23
  {
24
24
  path: '/resource/:resourceId',
@@ -27,23 +27,29 @@ const router = createRouter({
27
27
  children: [
28
28
  {
29
29
  path: '',
30
- component: ListView,
31
- name: 'resource-list'
30
+ component: () => import('@/views/ListView.vue'),
31
+ name: 'resource-list',
32
+ meta: { title: 'list',type: 'list' }
32
33
  },
33
34
  {
34
35
  path: 'show/:primaryKey',
35
- component: ShowView,
36
- name: 'resource-show'
36
+ component: () => import('@/views/ShowView.vue'),
37
+ name: 'resource-show',
38
+ meta: { title: 'show', type: 'show'}
39
+
37
40
  },
38
41
  {
39
42
  path: 'edit/:primaryKey',
40
- component: EditView,
41
- name: 'resource-edit'
43
+ component: () => import('@/views/EditView.vue'),
44
+ name: 'resource-edit',
45
+ meta: { title: 'edit', type: 'edit'}
42
46
  },
43
47
  {
44
48
  path: 'create',
45
- component: CreateView,
46
- name: 'resource-create'
49
+ component: () => import('@/views/CreateView.vue'),
50
+ name: 'resource-create',
51
+ meta: { title: 'create', type: 'create'}
52
+
47
53
  },
48
54
  ]
49
55
  },
@@ -51,4 +57,8 @@ const router = createRouter({
51
57
  ]
52
58
  })
53
59
 
60
+
61
+
62
+
63
+
54
64
  export default router
@@ -0,0 +1,51 @@
1
+ import type { AdminForthResource, AdminForthResourceColumn } from '../types/AdminForthConfig';
2
+
3
+ export type resourceById = {
4
+ [key: string]: AdminForthResource;
5
+ }
6
+
7
+ export type Menu = {
8
+ label: string,
9
+ icon: string,
10
+ resourceId: string,
11
+ children?: Array<Menu>,
12
+ }
13
+
14
+ export type Record = {
15
+ [key: string]: any;
16
+ }
17
+
18
+ export type ResourceColumns = {
19
+ [key: string]: Array<AdminForthResourceColumn>;
20
+ }
21
+
22
+ export type CoreConfig = {
23
+ brandName: string,
24
+ brandLogo: string,
25
+ title: string,
26
+ datesFormat: string,
27
+ usernameField: string,
28
+ usernameFieldName?: string,
29
+ deleteConfirmation?: boolean,
30
+ auth?: {
31
+ resourceId: string,
32
+ usernameField: string,
33
+ passwordHashField: string,
34
+ loginBackgroundImage: string,
35
+ userFullnameField: string,
36
+ },
37
+ emptyFieldPlaceholder?: {
38
+ show: string,
39
+ list: string,
40
+
41
+ } | string,
42
+ }
43
+
44
+
45
+ export type AllowedActions = {
46
+ show: boolean,
47
+ create: boolean,
48
+ edit: boolean,
49
+ delete: boolean,
50
+ }
51
+
@@ -1,39 +1,50 @@
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
6
 
5
7
  export const useCoreStore = defineStore('core', () => {
6
- const resourceById = ref([]);
8
+ const resourceById: Ref<Object> = ref({});
7
9
  const menu = ref([]);
8
10
  const config = ref({});
9
- const record = ref({});
10
- const resourceColumns = ref(null);
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);
11
22
  const resourceColumnsError = ref('');
12
23
  const resourceColumnsId = ref(null);
13
- const user = ref(null);
24
+ const adminUser = ref(null);
14
25
 
15
26
  async function fetchMenuAndResource() {
16
27
  const resp = await callAdminForthApi({
17
28
  path: '/get_base_config',
18
29
  method: 'GET',
19
30
  });
31
+ if(!resp){
32
+ return
33
+ }
20
34
  menu.value = resp.menu;
21
- resourceById.value = resp.resources.reduce((acc, resource) => {
35
+ resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
22
36
  acc[resource.resourceId] = resource;
23
37
  return acc;
24
38
  }, {});
25
39
  config.value = resp.config;
26
- user.value = resp.user;
40
+ adminUser.value = resp.user;
27
41
  console.log('🌍 AdminForth v', resp.version);
28
-
29
- // find homepage:true in menu recuresively
30
-
31
42
  }
32
43
 
33
44
  async function fetchRecord({ resourceId, primaryKey }) {
34
45
  record.value = null;
35
46
 
36
- if (!resourceColumns.value) {
47
+ if (!resource.value) {
37
48
  throw new Error('Columns not fetched yet');
38
49
  }
39
50
 
@@ -45,7 +56,7 @@ export const useCoreStore = defineStore('core', () => {
45
56
  resourceId: resourceId,
46
57
  filters: [
47
58
  {
48
- field: resourceColumns.value.find((col) => col.primaryKey).name,
59
+ field: resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey).name,
49
60
  operator: 'eq',
50
61
  value: primaryKey
51
62
  }
@@ -56,30 +67,39 @@ export const useCoreStore = defineStore('core', () => {
56
67
  }
57
68
  });
58
69
 
59
- console.log('📦 record', respData);
60
- record.value = respData.data[0];
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
+
61
81
  }
62
82
 
63
- async function fetchColumns({ resourceId }) {
64
- if (resourceColumnsId.value === resourceId && resourceColumns.value) {
83
+ async function fetchResourceFull({ resourceId }: { resourceId: string }) {
84
+ if (resourceColumnsId.value === resourceId && resource.value) {
65
85
  // already fetched
66
86
  return;
67
87
  }
68
88
  resourceColumnsId.value = resourceId;
69
- resourceColumns.value = null;
70
89
  resourceColumnsError.value = '';
71
90
  const res = await callAdminForthApi({
72
- path: '/get_resource_columns',
91
+ path: '/get_resource',
73
92
  method: 'POST',
74
93
  body: {
75
94
  resourceId,
76
95
  }
77
- }
78
- );
96
+ });
79
97
  if (res.error) {
80
98
  resourceColumnsError.value = res.error;
81
99
  } else {
82
- resourceColumns.value = res.resource.columns;
100
+ resourceById.value[resourceId] = res.resource;
101
+ resource.value = res.resource;
102
+ resourceOptions.value = res.resource.options;
83
103
  }
84
104
  }
85
105
 
@@ -91,21 +111,16 @@ export const useCoreStore = defineStore('core', () => {
91
111
  config.value = {...config.value, ...res};
92
112
  }
93
113
 
94
- async function logout() {
95
- await callAdminForthApi({
96
- path: '/logout',
97
- method: 'POST',
98
- });
99
- }
114
+
100
115
 
101
116
  const username = computed(() => {
102
117
  const usernameField = config.value.usernameField;
103
- return user.value && user.value[usernameField];
118
+ return adminUser.value && adminUser.value[usernameField];
104
119
  });
105
120
 
106
121
  const userFullname = computed(() => {
107
122
  const userFullnameField = config.value.userFullnameField;
108
- return user.value && user.value[userFullnameField];
123
+ return adminUser.value && adminUser.value[userFullnameField];
109
124
  })
110
125
 
111
126
 
@@ -119,9 +134,11 @@ export const useCoreStore = defineStore('core', () => {
119
134
  fetchMenuAndResource,
120
135
  fetchRecord,
121
136
  record,
122
- resourceColumns,
123
- fetchColumns,
137
+ fetchResourceFull,
124
138
  resourceColumnsError,
125
- logout
139
+ resourceOptions,
140
+ resource,
141
+ adminUser,
142
+ resourceColumnsWithFilters
126
143
  }
127
144
  })
@@ -0,0 +1,22 @@
1
+ import { ref } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+ import { callAdminForthApi } from '@/utils';
4
+
5
+ export const useFiltersStore = defineStore('filters', () => {
6
+ const filters = ref([]);
7
+ const setFilter = (filter: any) => {
8
+ filters.value = [...filters.value, filter];
9
+ }
10
+ const setFilters = (f: any) => {
11
+ filters.value = [...f];
12
+ }
13
+ const getFilters = () => {
14
+ return filters.value;
15
+ }
16
+ const clearFilters = () => {
17
+ filters.value = [];
18
+ }
19
+ return {setFilter, getFilters,clearFilters, filters,setFilters}
20
+ })
21
+
22
+
@@ -1,6 +1,12 @@
1
1
  import { ref } from 'vue'
2
2
  import { defineStore } from 'pinia'
3
- import { callAdminForthApi } from '@/utils';
3
+
4
+ type ModalContentType = {
5
+ title?: string;
6
+ content?: string;
7
+ acceptText?: string;
8
+ cancelText?: string;
9
+ }
4
10
 
5
11
 
6
12
  export const useModalStore = defineStore('modal', () => {
@@ -12,13 +18,17 @@ export const useModalStore = defineStore('modal', () => {
12
18
  });
13
19
  const isOpened = ref(false);
14
20
  const onAcceptFunction: any = ref(()=>{});
21
+ const onCancelFunction: any = ref(()=>{});
15
22
  function togleModal() {
16
23
  isOpened.value = !isOpened.value;
17
24
  }
18
25
  function setOnAcceptFunction(func: Function) {
19
26
  onAcceptFunction.value = func;
20
27
  }
21
- function setModalContent(content: string) {
28
+ function setOnCancelFunction(func: Function) {
29
+ onCancelFunction.value = func;
30
+ }
31
+ function setModalContent(content: ModalContentType) {
22
32
  modalContent.value = content;
23
33
  }
24
34
  function resetmodalState() {
@@ -33,6 +43,6 @@ export const useModalStore = defineStore('modal', () => {
33
43
 
34
44
  }
35
45
 
36
- return {isOpened, setModalContent, togleModal,modalContent, setOnAcceptFunction, onAcceptFunction,resetmodalState}
46
+ return {isOpened, setModalContent,onCancelFunction, togleModal,modalContent, setOnAcceptFunction, onAcceptFunction,resetmodalState,setOnCancelFunction}
37
47
 
38
48
  })
@@ -0,0 +1,15 @@
1
+ import { ref, computed } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+ import { callAdminForthApi } from '@/utils';
4
+ import { v1 as uuid } from 'uuid';
5
+
6
+ export const useToastStore = defineStore('toast', () => {
7
+ const toasts = ref([]);
8
+ const addToast = (toast) => {
9
+ toasts.value.push({...toast, id: uuid()});
10
+ };
11
+ const removeToast = (toast) => {
12
+ toasts.value = toasts.value.filter((t) => t.id !== toast.id);
13
+ };
14
+ return { toasts, addToast, removeToast };
15
+ });
@@ -0,0 +1,54 @@
1
+ import {ref} from 'vue';
2
+ import {defineStore} from 'pinia';
3
+ import { callAdminForthApi } from '@/utils';
4
+
5
+ export const useUserStore = defineStore('user', () => {
6
+ const isAuthorized = ref(false);
7
+
8
+ function authorize() {
9
+ isAuthorized.value = true;
10
+ localStorage.setItem('isAuthorized', 'true');
11
+ }
12
+
13
+ function unauthorize() {
14
+ isAuthorized.value = false;
15
+ localStorage.setItem('isAuthorized', 'false');
16
+ }
17
+
18
+ async function logout() {
19
+ await callAdminForthApi({
20
+ path: '/logout',
21
+ method: 'POST',
22
+ });
23
+ unauthorize();
24
+ }
25
+
26
+ // async function checkAuth( skipApiCall = false){
27
+ // console.log('checkAuth', isAuthorized.value, skipApiCall)
28
+ // if(isAuthorized.value) {
29
+ // return true}
30
+ // else {
31
+ // if(skipApiCall) return false;
32
+ // const resp = await callAdminForthApi({
33
+ // path: '/check_auth',
34
+ // method: 'POST',
35
+ // });
36
+ // if (resp.status !== 401) {
37
+ // authorize();
38
+ // return true;
39
+ // }
40
+ // else {
41
+ // unauthorize();
42
+ // return false;}
43
+ // }
44
+
45
+ // }
46
+
47
+ return {
48
+ isAuthorized,
49
+ authorize,
50
+ unauthorize,
51
+ logout
52
+ }
53
+
54
+ });
@@ -1,6 +1,10 @@
1
1
  import { onMounted, ref, resolveComponent } from 'vue';
2
+ import type { CoreConfig } from './spa_types/core';
2
3
 
3
4
  import router from "./router";
5
+ import { useRouter } from 'vue-router';
6
+ import { useCoreStore } from './stores/core';
7
+ import { useUserStore } from './stores/user';
4
8
 
5
9
  export async function callApi({path, method, body=undefined} ) {
6
10
  const options = {
@@ -13,14 +17,18 @@ export async function callApi({path, method, body=undefined} ) {
13
17
  const fullPath = `${import.meta.env.VITE_ADMINFORTH_PUBLIC_PATH || ''}${path}`;
14
18
  const r = await fetch(fullPath, options);
15
19
  if (r.status == 401) {
16
- console.log('router', router);
17
- router.push({name: 'login'});
20
+ useUserStore().unauthorize();
21
+ router.push({ name: 'login' });
18
22
  return null;
19
- }
23
+ }
20
24
  return await r.json();
21
25
  }
22
26
 
23
- export async function callAdminForthApi({ path, method, body=undefined }) {
27
+ export async function callAdminForthApi({ path, method, body=undefined }: {
28
+ path: string,
29
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE',
30
+ body?: any
31
+ }) {
24
32
  try {
25
33
  return callApi({path: `/adminapi/v1${path}`, method, body} );
26
34
  } catch (e) {
@@ -29,8 +37,8 @@ export async function callAdminForthApi({ path, method, body=undefined }) {
29
37
  }
30
38
  }
31
39
 
32
- export function getCustomComponent(filePath: string) {
33
- const name = filePath.replace(/@/g, '').replace(/\./g, '').replace(/\//g, '');
40
+ export function getCustomComponent({ file, meta }: { file: string, meta: any }) {
41
+ const name = file.replace(/@/g, '').replace(/\./g, '').replace(/\//g, '');
34
42
  console.log('resolving name', name);
35
43
  return resolveComponent(name);
36
44
  }
@@ -43,4 +51,51 @@ export function getIcon(icon: string) {
43
51
  const [iconSet, iconName] = icon.split(':');
44
52
  const compName = 'Icon' + iconName.split('-').map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join('');
45
53
  return resolveComponent(compName);
46
- }
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
+