adminforth 1.6.2-next.2 → 1.6.2-next.3
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.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/spa/.eslintrc.cjs +0 -14
- package/dist/spa/README.md +0 -39
- package/dist/spa/env.d.ts +0 -1
- package/dist/spa/index.html +0 -23
- package/dist/spa/package-lock.json +0 -5062
- package/dist/spa/package.json +0 -58
- package/dist/spa/postcss.config.js +0 -6
- package/dist/spa/public/assets/favicon.png +0 -0
- package/dist/spa/src/App.vue +0 -432
- package/dist/spa/src/adminforth.ts +0 -160
- package/dist/spa/src/afcl/AreaChart.vue +0 -160
- package/dist/spa/src/afcl/BarChart.vue +0 -170
- package/dist/spa/src/afcl/Button.vue +0 -27
- package/dist/spa/src/afcl/Checkbox.vue +0 -24
- package/dist/spa/src/afcl/Dropzone.vue +0 -128
- package/dist/spa/src/afcl/Input.vue +0 -41
- package/dist/spa/src/afcl/Link.vue +0 -17
- package/dist/spa/src/afcl/LinkButton.vue +0 -25
- package/dist/spa/src/afcl/PieChart.vue +0 -175
- package/dist/spa/src/afcl/ProgressBar.vue +0 -57
- package/dist/spa/src/afcl/Select.vue +0 -246
- package/dist/spa/src/afcl/Skeleton.vue +0 -26
- package/dist/spa/src/afcl/Spinner.vue +0 -9
- package/dist/spa/src/afcl/Table.vue +0 -116
- package/dist/spa/src/afcl/Tooltip.vue +0 -43
- package/dist/spa/src/afcl/VerticalTabs.vue +0 -49
- package/dist/spa/src/afcl/index.ts +0 -20
- package/dist/spa/src/assets/base.css +0 -2
- package/dist/spa/src/assets/logo.svg +0 -19
- package/dist/spa/src/components/AcceptModal.vue +0 -44
- package/dist/spa/src/components/Breadcrumbs.vue +0 -41
- package/dist/spa/src/components/BreadcrumbsWithButtons.vue +0 -25
- package/dist/spa/src/components/CustomDatePicker.vue +0 -180
- package/dist/spa/src/components/CustomDateRangePicker.vue +0 -218
- package/dist/spa/src/components/CustomRangePicker.vue +0 -156
- package/dist/spa/src/components/Filters.vue +0 -232
- package/dist/spa/src/components/GroupsTable.vue +0 -218
- package/dist/spa/src/components/HelloWorld.vue +0 -17
- package/dist/spa/src/components/MenuLink.vue +0 -41
- package/dist/spa/src/components/ResourceForm.vue +0 -260
- package/dist/spa/src/components/ResourceListTable.vue +0 -486
- package/dist/spa/src/components/ShowTable.vue +0 -81
- package/dist/spa/src/components/SingleSkeletLoader.vue +0 -13
- package/dist/spa/src/components/SkeleteLoader.vue +0 -18
- package/dist/spa/src/components/ThreeDotsMenu.vue +0 -43
- package/dist/spa/src/components/Toast.vue +0 -78
- package/dist/spa/src/components/ValueRenderer.vue +0 -141
- package/dist/spa/src/components/icons/IconCalendar.vue +0 -5
- package/dist/spa/src/components/icons/IconCommunity.vue +0 -7
- package/dist/spa/src/components/icons/IconDocumentation.vue +0 -7
- package/dist/spa/src/components/icons/IconEcosystem.vue +0 -7
- package/dist/spa/src/components/icons/IconSupport.vue +0 -7
- package/dist/spa/src/components/icons/IconTime.vue +0 -5
- package/dist/spa/src/components/icons/IconTooling.vue +0 -19
- package/dist/spa/src/composables/useFrontendApi.ts +0 -28
- package/dist/spa/src/i18n.ts +0 -54
- package/dist/spa/src/index.scss +0 -34
- package/dist/spa/src/main.ts +0 -22
- package/dist/spa/src/renderers/CompactField.vue +0 -46
- package/dist/spa/src/renderers/CompactUUID.vue +0 -46
- package/dist/spa/src/renderers/CountryFlag.vue +0 -65
- package/dist/spa/src/renderers/HumanNumber.vue +0 -58
- package/dist/spa/src/renderers/RelativeTime.vue +0 -42
- package/dist/spa/src/renderers/URL.vue +0 -18
- package/dist/spa/src/router/index.ts +0 -70
- package/dist/spa/src/spa_types/core.ts +0 -51
- package/dist/spa/src/stores/core.ts +0 -228
- package/dist/spa/src/stores/filters.ts +0 -27
- package/dist/spa/src/stores/modal.ts +0 -48
- package/dist/spa/src/stores/toast.ts +0 -30
- package/dist/spa/src/stores/user.ts +0 -79
- package/dist/spa/src/types/Adapters.ts +0 -26
- package/dist/spa/src/types/Back.ts +0 -1344
- package/dist/spa/src/types/Common.ts +0 -940
- package/dist/spa/src/types/FrontendAPI.ts +0 -189
- package/dist/spa/src/utils.ts +0 -184
- package/dist/spa/src/views/CreateView.vue +0 -167
- package/dist/spa/src/views/EditView.vue +0 -171
- package/dist/spa/src/views/ListView.vue +0 -442
- package/dist/spa/src/views/LoginView.vue +0 -199
- package/dist/spa/src/views/PageNotFound.vue +0 -20
- package/dist/spa/src/views/ResourceParent.vue +0 -50
- package/dist/spa/src/views/ShowView.vue +0 -209
- package/dist/spa/src/websocket.ts +0 -129
- package/dist/spa/tailwind.config.js +0 -19
- package/dist/spa/tsconfig.app.json +0 -14
- package/dist/spa/tsconfig.json +0 -11
- package/dist/spa/tsconfig.node.json +0 -19
- package/dist/spa/vite.config.ts +0 -52
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Tooltip>
|
|
3
|
-
{{ relativeTime }}
|
|
4
|
-
<template #tooltip v-if="relativeTime">
|
|
5
|
-
{{ fullTime }}
|
|
6
|
-
</template>
|
|
7
|
-
</Tooltip>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script setup>
|
|
11
|
-
import { computed, ref, onMounted } from 'vue';
|
|
12
|
-
import Tooltip from '@/afcl/Tooltip.vue';
|
|
13
|
-
import en from 'javascript-time-ago/locale/en';
|
|
14
|
-
import TimeAgo from 'javascript-time-ago';
|
|
15
|
-
import dayjs from 'dayjs';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const id = ref();
|
|
19
|
-
|
|
20
|
-
TimeAgo.addLocale(en);
|
|
21
|
-
|
|
22
|
-
const props = defineProps(['column', 'record', 'meta', 'resource', 'adminUser']);
|
|
23
|
-
|
|
24
|
-
const userLocale = ref(navigator.language || 'en-US');
|
|
25
|
-
const timeAgoFormatter = new TimeAgo(userLocale.value);
|
|
26
|
-
const relativeTime = computed(() => {
|
|
27
|
-
const value = props.record[props.column.name];
|
|
28
|
-
const date = new Date(value);
|
|
29
|
-
return timeAgoFormatter.format(date);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const fullTime = computed(() => {
|
|
33
|
-
const value = props.record[props.column.name];
|
|
34
|
-
const date = dayjs(new Date(value));
|
|
35
|
-
return date.format('DD MMM HH:mm');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
onMounted(async () => {
|
|
39
|
-
id.value = Math.random().toString(36).substring(7);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
</script>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<a v-if='record[column.name]' :href="record[column.name]"
|
|
3
|
-
class="text-blue-500 hover:underline overflow-ellipsis overflow-hidden whitespace-nowrap inline-block max-w-full"
|
|
4
|
-
>{{ record[column.name] }}</a>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup>
|
|
8
|
-
|
|
9
|
-
defineProps({
|
|
10
|
-
record: Object,
|
|
11
|
-
resource: Object,
|
|
12
|
-
adminUser: Object,
|
|
13
|
-
meta: Object,
|
|
14
|
-
column: Object
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</script>
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { createRouter, createWebHistory } from 'vue-router';
|
|
2
|
-
import ResourceParent from '@/views/ResourceParent.vue';
|
|
3
|
-
import PageNotFound from '@/views/PageNotFound.vue';
|
|
4
|
-
|
|
5
|
-
/* IMPORTANT:ADMINFORTH ROUTES IMPORTS */
|
|
6
|
-
|
|
7
|
-
const router = createRouter({
|
|
8
|
-
history: createWebHistory(import.meta.env.BASE_URL),
|
|
9
|
-
routes: [
|
|
10
|
-
{
|
|
11
|
-
path: '/login',
|
|
12
|
-
name: 'login',
|
|
13
|
-
component: () => import('@/views/LoginView.vue'),
|
|
14
|
-
meta: {
|
|
15
|
-
title: 'Login',
|
|
16
|
-
customLayout: true
|
|
17
|
-
},
|
|
18
|
-
// beforeEnter: async (to, from, next) => {
|
|
19
|
-
// if(localStorage.getItem('isAuthorized') === 'true') {
|
|
20
|
-
// // check if url has next=... and redirect to it
|
|
21
|
-
// console.log('to.query', to.query)
|
|
22
|
-
// if (to.query.next) {
|
|
23
|
-
// next(to.query.next.toString())
|
|
24
|
-
// } else {
|
|
25
|
-
// next({name: 'home'});
|
|
26
|
-
// }
|
|
27
|
-
// } else {
|
|
28
|
-
// next()
|
|
29
|
-
// }
|
|
30
|
-
// }
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
path: '/resource/:resourceId',
|
|
34
|
-
component: ResourceParent,
|
|
35
|
-
name: 'resource',
|
|
36
|
-
children: [
|
|
37
|
-
{
|
|
38
|
-
path: '',
|
|
39
|
-
component: () => import('@/views/ListView.vue'),
|
|
40
|
-
name: 'resource-list',
|
|
41
|
-
meta: { title: 'list',type: 'list' }
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
path: 'show/:primaryKey',
|
|
45
|
-
component: () => import('@/views/ShowView.vue'),
|
|
46
|
-
name: 'resource-show',
|
|
47
|
-
meta: { title: 'show', type: 'show'}
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
path: 'edit/:primaryKey',
|
|
52
|
-
component: () => import('@/views/EditView.vue'),
|
|
53
|
-
name: 'resource-edit',
|
|
54
|
-
meta: { title: 'edit', type: 'edit'}
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
path: 'create',
|
|
58
|
-
component: () => import('@/views/CreateView.vue'),
|
|
59
|
-
name: 'resource-create',
|
|
60
|
-
meta: { title: 'create', type: 'create'}
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
/* IMPORTANT:ADMINFORTH ROUTES */
|
|
66
|
-
{ path: "/:pathMatch(.*)*", component: PageNotFound },
|
|
67
|
-
]
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
export default router
|
|
@@ -1,51 +0,0 @@
|
|
|
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
|
-
timeFormat: string,
|
|
28
|
-
usernameField: string,
|
|
29
|
-
usernameFieldName?: string,
|
|
30
|
-
auth?: {
|
|
31
|
-
resourceId: string,
|
|
32
|
-
usernameField: string,
|
|
33
|
-
passwordHashField: string,
|
|
34
|
-
loginBackgroundImage: string,
|
|
35
|
-
loginBackgroundPosition: string,
|
|
36
|
-
userFullnameField: string,
|
|
37
|
-
},
|
|
38
|
-
emptyFieldPlaceholder?: {
|
|
39
|
-
show?: string,
|
|
40
|
-
list?: string,
|
|
41
|
-
} | string,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export type AllowedActions = {
|
|
46
|
-
show: boolean,
|
|
47
|
-
create: boolean,
|
|
48
|
-
edit: boolean,
|
|
49
|
-
delete: boolean,
|
|
50
|
-
}
|
|
51
|
-
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { ref, computed } from 'vue'
|
|
2
|
-
import { defineStore } from 'pinia'
|
|
3
|
-
import { callAdminForthApi } from '@/utils';
|
|
4
|
-
import websocket from '@/websocket';
|
|
5
|
-
import adminforth from '@/adminforth';
|
|
6
|
-
|
|
7
|
-
import type { AdminForthResourceCommon, AdminForthResourceColumnCommon, GetBaseConfigResponse, ResourceVeryShort, AdminUser, UserData, AdminForthConfigMenuItem, AdminForthConfigForFrontend } from '@/types/Common';
|
|
8
|
-
import type { Ref } from 'vue'
|
|
9
|
-
|
|
10
|
-
export const useCoreStore = defineStore('core', () => {
|
|
11
|
-
const resourceById: Ref<Record<string, ResourceVeryShort>> = ref({});
|
|
12
|
-
const theme: Ref<'light'| 'dark'> = ref(window.localStorage.getItem('af__theme') as ('light'|'dark') || 'light');
|
|
13
|
-
|
|
14
|
-
const menu: Ref<AdminForthConfigMenuItem[]> = ref([]);
|
|
15
|
-
const config: Ref<AdminForthConfigForFrontend | null> = ref(null);
|
|
16
|
-
const record: Ref<any | null> = ref({});
|
|
17
|
-
const resource: Ref<AdminForthResourceCommon | null> = ref(null);
|
|
18
|
-
const userData: Ref<UserData | null> = ref(null);
|
|
19
|
-
|
|
20
|
-
const resourceColumnsWithFilters = computed(() => {
|
|
21
|
-
if (!resource.value) {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
return resource.value.columns.filter((col: AdminForthResourceColumnCommon) => col.showIn?.includes('filter'));
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const resourceOptions: Ref<AdminForthResourceCommon['options'] | null> = ref(null);
|
|
28
|
-
const resourceColumnsError: Ref<string> = ref('');
|
|
29
|
-
const resourceColumnsId: Ref<string | null> = ref(null);
|
|
30
|
-
const adminUser: Ref<null | AdminUser> = ref(null);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
async function resetAdminUser() {
|
|
34
|
-
adminUser.value = null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function toggleTheme() {
|
|
38
|
-
theme.value = theme.value === 'light' ? 'dark' : 'light';
|
|
39
|
-
if (theme.value === 'light') {
|
|
40
|
-
document.documentElement.classList.remove('dark');
|
|
41
|
-
} else {
|
|
42
|
-
document.documentElement.classList.add('dark');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
document.documentElement.setAttribute('data-theme', theme.value);
|
|
46
|
-
theme.value = theme.value;
|
|
47
|
-
window.localStorage.setItem('af__theme', theme.value);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function fetchMenuAndResource() {
|
|
51
|
-
const resp: GetBaseConfigResponse = await callAdminForthApi({
|
|
52
|
-
path: '/get_base_config',
|
|
53
|
-
method: 'GET',
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
if(!resp){
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
menu.value = resp.menu;
|
|
60
|
-
resourceById.value = resp.resources.reduce((acc: Record<string, ResourceVeryShort>, resource: ResourceVeryShort) => {
|
|
61
|
-
acc[resource.resourceId] = resource;
|
|
62
|
-
return acc;
|
|
63
|
-
}, {});
|
|
64
|
-
config.value = resp.config;
|
|
65
|
-
adminUser.value = resp.adminUser;
|
|
66
|
-
userData.value = resp.user;
|
|
67
|
-
console.log('🌍 AdminForth v', resp.version);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function findItemWithId(items: AdminForthConfigMenuItem[], itemId: string): AdminForthConfigMenuItem | undefined {
|
|
71
|
-
for (const item of items) {
|
|
72
|
-
if (item.itemId === itemId) {
|
|
73
|
-
return item;
|
|
74
|
-
}
|
|
75
|
-
if (item.children) {
|
|
76
|
-
const found = findItemWithId(item.children, itemId);
|
|
77
|
-
if (found) {
|
|
78
|
-
return found;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async function subscribeToMenuBadges() {
|
|
84
|
-
const processItem = (mi: AdminForthConfigMenuItem) => {
|
|
85
|
-
if (mi.badge) {
|
|
86
|
-
websocket.subscribe(`/opentopic/update-menu-badge/${mi.itemId}`, ({ badge }) => {
|
|
87
|
-
mi.badge = badge;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
menu.value.forEach((mi) => {
|
|
93
|
-
processItem(mi);
|
|
94
|
-
if (mi.children) {
|
|
95
|
-
mi.children.forEach((child) => {
|
|
96
|
-
processItem(child);
|
|
97
|
-
})
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
async function fetchMenuBadges() {
|
|
102
|
-
const resp: Record<string, string> = await callAdminForthApi({
|
|
103
|
-
path: '/get_menu_badges',
|
|
104
|
-
method: 'GET',
|
|
105
|
-
});
|
|
106
|
-
if (!resp) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
Object.entries(resp).forEach(([itemId, badge]: [string, string]) => {
|
|
110
|
-
const item: AdminForthConfigMenuItem | undefined = findItemWithId(menu.value, itemId);
|
|
111
|
-
if (item) {
|
|
112
|
-
item.badge = badge;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
subscribeToMenuBadges();
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
async function fetchRecord({ resourceId, primaryKey, source }: { resourceId: string, primaryKey: string, source: string }) {
|
|
122
|
-
record.value = null;
|
|
123
|
-
|
|
124
|
-
if (!resource.value) {
|
|
125
|
-
throw new Error('Columns not fetched yet');
|
|
126
|
-
}
|
|
127
|
-
const col = resource.value.columns.find((col: AdminForthResourceColumnCommon) => col.primaryKey);
|
|
128
|
-
if (!col) {
|
|
129
|
-
throw new Error(`Primary key not found in resource ${resourceId}`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const respData = await callAdminForthApi({
|
|
133
|
-
path: '/get_resource_data',
|
|
134
|
-
method: 'POST',
|
|
135
|
-
body: {
|
|
136
|
-
source: source,
|
|
137
|
-
resourceId: resourceId,
|
|
138
|
-
filters: [
|
|
139
|
-
{
|
|
140
|
-
field: col.name,
|
|
141
|
-
operator: 'eq',
|
|
142
|
-
value: primaryKey
|
|
143
|
-
}
|
|
144
|
-
],
|
|
145
|
-
sort: [],
|
|
146
|
-
limit: 1,
|
|
147
|
-
offset: 0
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
if (respData.error) {
|
|
152
|
-
adminforth.alert({
|
|
153
|
-
message: respData.error,
|
|
154
|
-
variant: 'danger',
|
|
155
|
-
timeout: 30,
|
|
156
|
-
});
|
|
157
|
-
record.value = {};
|
|
158
|
-
} else {
|
|
159
|
-
record.value = respData.data[0];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
async function fetchResourceFull({ resourceId }: { resourceId: string }) {
|
|
165
|
-
if (resourceColumnsId.value === resourceId && resource.value) {
|
|
166
|
-
// already fetched
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
resourceColumnsId.value = resourceId;
|
|
170
|
-
resourceColumnsError.value = '';
|
|
171
|
-
const res = await callAdminForthApi({
|
|
172
|
-
path: '/get_resource',
|
|
173
|
-
method: 'POST',
|
|
174
|
-
body: {
|
|
175
|
-
resourceId,
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
if (res.error) {
|
|
179
|
-
resourceColumnsError.value = res.error;
|
|
180
|
-
} else {
|
|
181
|
-
resourceById.value[resourceId] = res.resource;
|
|
182
|
-
resource.value = res.resource;
|
|
183
|
-
resourceOptions.value = res.resource.options;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async function getPublicConfig() {
|
|
188
|
-
const res = await callAdminForthApi({
|
|
189
|
-
path: '/get_public_config',
|
|
190
|
-
method: 'GET',
|
|
191
|
-
});
|
|
192
|
-
config.value = {...config.value, ...res};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const username = computed(() => {
|
|
197
|
-
const usernameField = config.value?.usernameField;
|
|
198
|
-
return userData.value && usernameField && userData.value[usernameField];
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const userFullname = computed(() => {
|
|
202
|
-
const userFullnameField = config.value?.userFullnameField;
|
|
203
|
-
return userData.value && userFullnameField && userData.value[userFullnameField];
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
return {
|
|
208
|
-
config,
|
|
209
|
-
resourceById,
|
|
210
|
-
menu,
|
|
211
|
-
username,
|
|
212
|
-
userFullname,
|
|
213
|
-
getPublicConfig,
|
|
214
|
-
fetchMenuAndResource,
|
|
215
|
-
fetchRecord,
|
|
216
|
-
record,
|
|
217
|
-
fetchResourceFull,
|
|
218
|
-
resourceColumnsError,
|
|
219
|
-
resourceOptions,
|
|
220
|
-
resource,
|
|
221
|
-
adminUser,
|
|
222
|
-
resourceColumnsWithFilters,
|
|
223
|
-
toggleTheme,
|
|
224
|
-
theme,
|
|
225
|
-
fetchMenuBadges,
|
|
226
|
-
resetAdminUser,
|
|
227
|
-
}
|
|
228
|
-
})
|
|
@@ -1,27 +0,0 @@
|
|
|
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
|
-
})
|
|
@@ -1,48 +0,0 @@
|
|
|
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
|
-
})
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|
-
// on route change clear all toasts older then 5 seconds
|
|
14
|
-
const now = +new Date();
|
|
15
|
-
toasts.value = toasts.value.filter((t) => now - t.createdAt < 5000);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const addToast = (toast: { message: string; variant: string }) => {
|
|
19
|
-
const toastId = uuid();
|
|
20
|
-
toasts.value.push({
|
|
21
|
-
...toast,
|
|
22
|
-
id: toastId,
|
|
23
|
-
createdAt: +new Date(),
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
const removeToast = (toast: { id: string }) => {
|
|
27
|
-
toasts.value = toasts.value.filter((t) => t.id !== toast.id);
|
|
28
|
-
};
|
|
29
|
-
return { toasts, addToast, removeToast };
|
|
30
|
-
});
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { ref } from 'vue';
|
|
2
|
-
import { defineStore } from 'pinia';
|
|
3
|
-
import { callAdminForthApi } from '@/utils';
|
|
4
|
-
import { useCoreStore } from './core';
|
|
5
|
-
import router from '@/router';
|
|
6
|
-
import { reconnect } from '@/websocket';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export const useUserStore = defineStore('user', () => {
|
|
10
|
-
const isAuthorized = ref(false);
|
|
11
|
-
|
|
12
|
-
function authorize() {
|
|
13
|
-
// syncing isAuthorized allows us to use navigation guards without waiting for user api response
|
|
14
|
-
isAuthorized.value = true;
|
|
15
|
-
localStorage.setItem('isAuthorized', 'true');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function unauthorize() {
|
|
19
|
-
isAuthorized.value = false;
|
|
20
|
-
localStorage.setItem('isAuthorized', 'false');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async function finishLogin() {
|
|
24
|
-
const coreStore = useCoreStore();
|
|
25
|
-
authorize();
|
|
26
|
-
reconnect();
|
|
27
|
-
// if next param in route, redirect to it
|
|
28
|
-
if (router.currentRoute.value.query.next) {
|
|
29
|
-
await router.push(router.currentRoute.value.query.next.toString());
|
|
30
|
-
} else {
|
|
31
|
-
await router.push('/');
|
|
32
|
-
}
|
|
33
|
-
await router.isReady();
|
|
34
|
-
await coreStore.fetchMenuAndResource();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function logout() {
|
|
38
|
-
const coreStore = useCoreStore();
|
|
39
|
-
|
|
40
|
-
await callAdminForthApi({
|
|
41
|
-
path: '/logout',
|
|
42
|
-
method: 'POST',
|
|
43
|
-
});
|
|
44
|
-
reconnect();
|
|
45
|
-
coreStore.resetAdminUser();
|
|
46
|
-
unauthorize();
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// async function checkAuth( skipApiCall = false){
|
|
51
|
-
// console.log('checkAuth', isAuthorized.value, skipApiCall)
|
|
52
|
-
// if(isAuthorized.value) {
|
|
53
|
-
// return true}
|
|
54
|
-
// else {
|
|
55
|
-
// if(skipApiCall) return false;
|
|
56
|
-
// const resp = await callAdminForthApi({
|
|
57
|
-
// path: '/check_auth',
|
|
58
|
-
// method: 'POST',
|
|
59
|
-
// });
|
|
60
|
-
// if (resp.status !== 401) {
|
|
61
|
-
// authorize();
|
|
62
|
-
// return true;
|
|
63
|
-
// }
|
|
64
|
-
// else {
|
|
65
|
-
// unauthorize();
|
|
66
|
-
// return false;}
|
|
67
|
-
// }
|
|
68
|
-
|
|
69
|
-
// }
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
isAuthorized,
|
|
73
|
-
authorize,
|
|
74
|
-
unauthorize,
|
|
75
|
-
logout,
|
|
76
|
-
finishLogin
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export interface EmailAdapter {
|
|
2
|
-
validate(): Promise<void>;
|
|
3
|
-
|
|
4
|
-
sendEmail(
|
|
5
|
-
from: string,
|
|
6
|
-
to: string,
|
|
7
|
-
text: string,
|
|
8
|
-
html: string,
|
|
9
|
-
subject: string
|
|
10
|
-
): Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface CompletionAdapter {
|
|
14
|
-
|
|
15
|
-
validate(): void;
|
|
16
|
-
|
|
17
|
-
complete(
|
|
18
|
-
content: string,
|
|
19
|
-
stop: string[],
|
|
20
|
-
maxTokens: number,
|
|
21
|
-
): Promise<{
|
|
22
|
-
content?: string;
|
|
23
|
-
finishReason?: string;
|
|
24
|
-
error?: string;
|
|
25
|
-
}>;
|
|
26
|
-
}
|