adminforth 1.3.55-next.0 → 1.3.55

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 (63) hide show
  1. package/dist/spa/.eslintrc.cjs +14 -0
  2. package/dist/spa/README.md +39 -0
  3. package/dist/spa/env.d.ts +1 -0
  4. package/dist/spa/index.html +23 -0
  5. package/dist/spa/package-lock.json +4659 -0
  6. package/dist/spa/package.json +52 -0
  7. package/dist/spa/postcss.config.js +6 -0
  8. package/dist/spa/public/assets/favicon.png +0 -0
  9. package/dist/spa/src/App.vue +418 -0
  10. package/dist/spa/src/assets/base.css +2 -0
  11. package/dist/spa/src/assets/logo.svg +19 -0
  12. package/dist/spa/src/components/AcceptModal.vue +45 -0
  13. package/dist/spa/src/components/Breadcrumbs.vue +41 -0
  14. package/dist/spa/src/components/BreadcrumbsWithButtons.vue +26 -0
  15. package/dist/spa/src/components/CustomDatePicker.vue +176 -0
  16. package/dist/spa/src/components/CustomDateRangePicker.vue +218 -0
  17. package/dist/spa/src/components/CustomRangePicker.vue +156 -0
  18. package/dist/spa/src/components/Dropdown.vue +168 -0
  19. package/dist/spa/src/components/Filters.vue +222 -0
  20. package/dist/spa/src/components/HelloWorld.vue +17 -0
  21. package/dist/spa/src/components/MenuLink.vue +27 -0
  22. package/dist/spa/src/components/ResourceForm.vue +325 -0
  23. package/dist/spa/src/components/ResourceListTable.vue +466 -0
  24. package/dist/spa/src/components/SingleSkeletLoader.vue +13 -0
  25. package/dist/spa/src/components/SkeleteLoader.vue +23 -0
  26. package/dist/spa/src/components/ThreeDotsMenu.vue +43 -0
  27. package/dist/spa/src/components/Toast.vue +78 -0
  28. package/dist/spa/src/components/ValueRenderer.vue +141 -0
  29. package/dist/spa/src/components/icons/IconCalendar.vue +5 -0
  30. package/dist/spa/src/components/icons/IconCommunity.vue +7 -0
  31. package/dist/spa/src/components/icons/IconDocumentation.vue +7 -0
  32. package/dist/spa/src/components/icons/IconEcosystem.vue +7 -0
  33. package/dist/spa/src/components/icons/IconSupport.vue +7 -0
  34. package/dist/spa/src/components/icons/IconTime.vue +5 -0
  35. package/dist/spa/src/components/icons/IconTooling.vue +19 -0
  36. package/dist/spa/src/composables/useFrontendApi.ts +26 -0
  37. package/dist/spa/src/composables/useStores.ts +131 -0
  38. package/dist/spa/src/index.scss +31 -0
  39. package/dist/spa/src/main.ts +18 -0
  40. package/dist/spa/src/renderers/CompactUUID.vue +48 -0
  41. package/dist/spa/src/renderers/CountryFlag.vue +69 -0
  42. package/dist/spa/src/router/index.ts +59 -0
  43. package/dist/spa/src/spa_types/core.ts +53 -0
  44. package/dist/spa/src/stores/core.ts +148 -0
  45. package/dist/spa/src/stores/filters.ts +27 -0
  46. package/dist/spa/src/stores/modal.ts +48 -0
  47. package/dist/spa/src/stores/toast.ts +31 -0
  48. package/dist/spa/src/stores/user.ts +72 -0
  49. package/dist/spa/src/types/AdminForthConfig.ts +1762 -0
  50. package/dist/spa/src/types/FrontendAPI.ts +143 -0
  51. package/dist/spa/src/utils.ts +160 -0
  52. package/dist/spa/src/views/CreateView.vue +167 -0
  53. package/dist/spa/src/views/EditView.vue +170 -0
  54. package/dist/spa/src/views/ListView.vue +352 -0
  55. package/dist/spa/src/views/LoginView.vue +192 -0
  56. package/dist/spa/src/views/ResourceParent.vue +17 -0
  57. package/dist/spa/src/views/ShowView.vue +194 -0
  58. package/dist/spa/tailwind.config.js +17 -0
  59. package/dist/spa/tsconfig.app.json +14 -0
  60. package/dist/spa/tsconfig.json +11 -0
  61. package/dist/spa/tsconfig.node.json +19 -0
  62. package/dist/spa/vite.config.ts +56 -0
  63. package/package.json +2 -2
@@ -0,0 +1,148 @@
1
+ import { ref, computed } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+ import { callAdminForthApi } from '@/utils';
4
+ import type { AdminForthResource, AdminForthResourceColumn } from '@/types/AdminForthConfig';
5
+ import type { Ref } from 'vue'
6
+
7
+ export const useCoreStore = defineStore('core', () => {
8
+ const resourceById: Ref<Object> = ref({});
9
+ const menu = ref([]);
10
+ 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);
22
+ const resourceColumnsError = ref('');
23
+ const resourceColumnsId = ref(null);
24
+ const adminUser = ref(null);
25
+
26
+ async function fetchMenuAndResource() {
27
+ const resp = await callAdminForthApi({
28
+ path: '/get_base_config',
29
+ method: 'GET',
30
+ });
31
+ if(!resp){
32
+ return
33
+ }
34
+ menu.value = resp.menu;
35
+ resourceById.value = resp.resources.reduce((acc: Object, resource: AdminForthResource) => {
36
+ acc[resource.resourceId] = resource;
37
+ return acc;
38
+ }, {});
39
+ config.value = resp.config;
40
+ adminUser.value = resp.user;
41
+ console.log('🌍 AdminForth v', resp.version);
42
+ }
43
+
44
+ async function fetchRecord({ resourceId, primaryKey }) {
45
+ record.value = null;
46
+
47
+ if (!resource.value) {
48
+ throw new Error('Columns not fetched yet');
49
+ }
50
+ const col = resource.value.columns.find((col: AdminForthResourceColumn) => col.primaryKey);
51
+ if (!col) {
52
+ throw new Error(`Primary key not found in resource ${resourceId}`);
53
+ }
54
+
55
+ const respData = await callAdminForthApi({
56
+ path: '/get_resource_data',
57
+ method: 'POST',
58
+ body: {
59
+ source: 'show',
60
+ resourceId: resourceId,
61
+ filters: [
62
+ {
63
+ field: col.name,
64
+ operator: 'eq',
65
+ value: primaryKey
66
+ }
67
+ ],
68
+ sort: [],
69
+ limit: 1,
70
+ offset: 0
71
+ }
72
+ });
73
+
74
+ if (respData.error) {
75
+ window.adminforth.alert({
76
+ message: respData.error,
77
+ variant: 'danger',
78
+ timeout: 30,
79
+ });
80
+ record.value = {};
81
+ } else {
82
+ record.value = respData.data[0];
83
+ }
84
+
85
+ }
86
+
87
+ async function fetchResourceFull({ resourceId }: { resourceId: string }) {
88
+ if (resourceColumnsId.value === resourceId && resource.value) {
89
+ // already fetched
90
+ return;
91
+ }
92
+ resourceColumnsId.value = resourceId;
93
+ resourceColumnsError.value = '';
94
+ const res = await callAdminForthApi({
95
+ path: '/get_resource',
96
+ method: 'POST',
97
+ body: {
98
+ resourceId,
99
+ }
100
+ });
101
+ if (res.error) {
102
+ resourceColumnsError.value = res.error;
103
+ } else {
104
+ resourceById.value[resourceId] = res.resource;
105
+ resource.value = res.resource;
106
+ resourceOptions.value = res.resource.options;
107
+ }
108
+ }
109
+
110
+ async function getPublicConfig() {
111
+ const res = await callAdminForthApi({
112
+ path: '/get_public_config',
113
+ method: 'GET',
114
+ });
115
+ config.value = {...config.value, ...res};
116
+ }
117
+
118
+
119
+
120
+ const username = computed(() => {
121
+ const usernameField = config.value.usernameField;
122
+ return adminUser.value && adminUser.value[usernameField];
123
+ });
124
+
125
+ const userFullname = computed(() => {
126
+ const userFullnameField = config.value.userFullnameField;
127
+ return adminUser.value && adminUser.value[userFullnameField];
128
+ })
129
+
130
+
131
+ return {
132
+ config,
133
+ resourceById,
134
+ menu,
135
+ username,
136
+ userFullname,
137
+ getPublicConfig,
138
+ fetchMenuAndResource,
139
+ fetchRecord,
140
+ record,
141
+ fetchResourceFull,
142
+ resourceColumnsError,
143
+ resourceOptions,
144
+ resource,
145
+ adminUser,
146
+ resourceColumnsWithFilters
147
+ }
148
+ })
@@ -0,0 +1,27 @@
1
+ import { ref, type Ref } from 'vue';
2
+ import { defineStore } from 'pinia';
3
+
4
+ export const useFiltersStore = defineStore('filters', () => {
5
+ const filters: Ref<any[]> = ref([]);
6
+ const sort: Ref<any> = ref({});
7
+
8
+ const setSort = (s: any) => {
9
+ sort.value = s;
10
+ }
11
+ const getSort = () => {
12
+ return sort.value;
13
+ }
14
+ const setFilter = (filter: any) => {
15
+ filters.value.push(filter);
16
+ }
17
+ const setFilters = (f: any) => {
18
+ filters.value = f;
19
+ }
20
+ const getFilters = () => {
21
+ return filters.value;
22
+ }
23
+ const clearFilters = () => {
24
+ filters.value = [];
25
+ }
26
+ return {setFilter, getFilters, clearFilters, filters, setFilters, setSort, getSort}
27
+ })
@@ -0,0 +1,48 @@
1
+ import { ref } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+
4
+ type ModalContentType = {
5
+ title?: string;
6
+ content?: string;
7
+ acceptText?: string;
8
+ cancelText?: string;
9
+ }
10
+
11
+
12
+ export const useModalStore = defineStore('modal', () => {
13
+ const modalContent = ref({
14
+ title: 'title',
15
+ content: 'content',
16
+ acceptText: 'acceptText',
17
+ cancelText: 'cancelText',
18
+ });
19
+ const isOpened = ref(false);
20
+ const onAcceptFunction: any = ref(()=>{});
21
+ const onCancelFunction: any = ref(()=>{});
22
+ function togleModal() {
23
+ isOpened.value = !isOpened.value;
24
+ }
25
+ function setOnAcceptFunction(func: Function) {
26
+ onAcceptFunction.value = func;
27
+ }
28
+ function setOnCancelFunction(func: Function) {
29
+ onCancelFunction.value = func;
30
+ }
31
+ function setModalContent(content: ModalContentType) {
32
+ modalContent.value = content;
33
+ }
34
+ function resetmodalState() {
35
+ isOpened.value = false;
36
+ modalContent.value = {
37
+ title: 'title',
38
+ content: 'content',
39
+ acceptText: 'acceptText',
40
+ cancelText: 'cancelText',
41
+ };
42
+ setOnAcceptFunction(()=>{});
43
+
44
+ }
45
+
46
+ return {isOpened, setModalContent,onCancelFunction, togleModal,modalContent, setOnAcceptFunction, onAcceptFunction,resetmodalState,setOnCancelFunction}
47
+
48
+ })
@@ -0,0 +1,31 @@
1
+ import { ref, watch, type Ref } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+ import { v1 as uuid } from 'uuid';
4
+ import { useRoute } from 'vue-router';
5
+
6
+
7
+
8
+ export const useToastStore = defineStore('toast', () => {
9
+ const toasts: Ref<any[]> = ref([]);
10
+ const route = useRoute();
11
+
12
+ watch(route, () => {
13
+ console.log('route changed 121');
14
+ // on route change clear all toasts older then 5 seconds
15
+ const now = +new Date();
16
+ toasts.value = toasts.value.filter((t) => now - t.createdAt < 5000);
17
+ });
18
+
19
+ const addToast = (toast: { message: string; variant: string }) => {
20
+ const toastId = uuid();
21
+ toasts.value.push({
22
+ ...toast,
23
+ id: toastId,
24
+ createdAt: +new Date(),
25
+ });
26
+ };
27
+ const removeToast = (toast: { id: string }) => {
28
+ toasts.value = toasts.value.filter((t) => t.id !== toast.id);
29
+ };
30
+ return { toasts, addToast, removeToast };
31
+ });
@@ -0,0 +1,72 @@
1
+ import { ref } from 'vue';
2
+ import { defineStore } from 'pinia';
3
+ import { callAdminForthApi } from '@/utils';
4
+ import { initFlowbite } from 'flowbite'
5
+ import { useRouter } from 'vue-router';
6
+ import { useCoreStore } from './core';
7
+ import router from '@/router';
8
+
9
+
10
+
11
+ export const useUserStore = defineStore('user', () => {
12
+ const isAuthorized = ref(false);
13
+
14
+ function authorize() {
15
+ isAuthorized.value = true;
16
+ localStorage.setItem('isAuthorized', 'true');
17
+ }
18
+
19
+ function unauthorize() {
20
+ isAuthorized.value = false;
21
+ localStorage.setItem('isAuthorized', 'false');
22
+ }
23
+
24
+ async function finishLogin() {
25
+ const coreStore = useCoreStore();
26
+ authorize(); // TODO not sure we need this approach with localStorage
27
+ await router.push('/');
28
+ await router.isReady();
29
+ await coreStore.fetchMenuAndResource();
30
+ setTimeout(() => {
31
+ initFlowbite();
32
+ });
33
+ }
34
+
35
+ async function logout() {
36
+ await callAdminForthApi({
37
+ path: '/logout',
38
+ method: 'POST',
39
+ });
40
+ unauthorize();
41
+ }
42
+
43
+ // async function checkAuth( skipApiCall = false){
44
+ // console.log('checkAuth', isAuthorized.value, skipApiCall)
45
+ // if(isAuthorized.value) {
46
+ // return true}
47
+ // else {
48
+ // if(skipApiCall) return false;
49
+ // const resp = await callAdminForthApi({
50
+ // path: '/check_auth',
51
+ // method: 'POST',
52
+ // });
53
+ // if (resp.status !== 401) {
54
+ // authorize();
55
+ // return true;
56
+ // }
57
+ // else {
58
+ // unauthorize();
59
+ // return false;}
60
+ // }
61
+
62
+ // }
63
+
64
+ return {
65
+ isAuthorized,
66
+ authorize,
67
+ unauthorize,
68
+ logout,
69
+ finishLogin
70
+ }
71
+
72
+ });