adminforth 2.4.0-next.7 → 2.4.0-next.71
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/commands/callTsProxy.js +14 -4
- package/commands/cli.js +12 -4
- package/commands/createApp/templates/custom/tsconfig.json.hbs +2 -3
- package/commands/createApp/templates/index.ts.hbs +1 -1
- package/commands/createApp/templates/package.json.hbs +1 -1
- package/commands/createApp/utils.js +39 -13
- package/commands/createCustomComponent/configUpdater.js +25 -21
- package/commands/createCustomComponent/fileGenerator.js +1 -1
- package/commands/createCustomComponent/main.js +2 -1
- package/commands/createCustomComponent/templates/login/beforeLogin.vue.hbs +18 -0
- package/dist/dataConnectors/baseConnector.d.ts.map +1 -1
- package/dist/dataConnectors/baseConnector.js +16 -3
- package/dist/dataConnectors/baseConnector.js.map +1 -1
- package/dist/dataConnectors/mongo.d.ts.map +1 -1
- package/dist/dataConnectors/mongo.js +14 -14
- package/dist/dataConnectors/mongo.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -9
- package/dist/index.js.map +1 -1
- package/dist/modules/codeInjector.d.ts.map +1 -1
- package/dist/modules/codeInjector.js +25 -9
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/modules/configValidator.d.ts.map +1 -1
- package/dist/modules/configValidator.js +50 -1
- package/dist/modules/configValidator.js.map +1 -1
- package/dist/modules/restApi.d.ts.map +1 -1
- package/dist/modules/restApi.js +45 -2
- package/dist/modules/restApi.js.map +1 -1
- package/dist/modules/styles.d.ts +42 -0
- package/dist/modules/styles.d.ts.map +1 -1
- package/dist/modules/styles.js +44 -2
- package/dist/modules/styles.js.map +1 -1
- package/dist/spa/index.html +1 -1
- package/dist/spa/src/App.vue +14 -5
- package/dist/spa/src/afcl/Button.vue +4 -4
- package/dist/spa/src/afcl/Checkbox.vue +21 -13
- package/dist/spa/src/afcl/CountryFlag.vue +3 -1
- package/dist/spa/src/afcl/Dropzone.vue +4 -2
- package/dist/spa/src/afcl/Input.vue +5 -3
- package/dist/spa/src/afcl/JsonViewer.vue +25 -0
- package/dist/spa/src/afcl/Link.vue +1 -1
- package/dist/spa/src/afcl/LinkButton.vue +1 -1
- package/dist/spa/src/afcl/Select.vue +44 -15
- package/dist/spa/src/afcl/Table.vue +8 -8
- package/dist/spa/src/afcl/Toggle.vue +32 -0
- package/dist/spa/src/afcl/Tooltip.vue +1 -1
- package/dist/spa/src/afcl/index.ts +2 -2
- package/dist/spa/src/components/AcceptModal.vue +4 -4
- package/dist/spa/src/components/ColumnValueInput.vue +21 -2
- package/dist/spa/src/components/ColumnValueInputWrapper.vue +1 -0
- package/dist/spa/src/components/CustomDatePicker.vue +2 -2
- package/dist/spa/src/components/CustomDateRangePicker.vue +1 -0
- package/dist/spa/src/components/Filters.vue +73 -28
- package/dist/spa/src/components/GroupsTable.vue +3 -3
- package/dist/spa/src/components/ResourceForm.vue +61 -26
- package/dist/spa/src/components/ResourceListTable.vue +34 -36
- package/dist/spa/src/components/ResourceListTableVirtual.vue +23 -25
- package/dist/spa/src/components/ShowTable.vue +11 -6
- package/dist/spa/src/components/ValueRenderer.vue +4 -4
- package/dist/spa/src/controls/BoolToggle.vue +34 -0
- package/dist/spa/src/spa_types/core.ts +7 -0
- package/dist/spa/src/stores/core.ts +1 -1
- package/dist/spa/src/types/Back.ts +46 -12
- package/dist/spa/src/types/Common.ts +10 -1
- package/dist/spa/src/types/adapters/CompletionAdapter.ts +25 -0
- package/dist/spa/src/types/adapters/EmailAdapter.ts +29 -0
- package/dist/spa/src/types/adapters/ImageGenerationAdapter.ts +50 -0
- package/dist/spa/src/types/adapters/OAuth2Adapter.ts +34 -0
- package/dist/spa/src/types/adapters/StorageAdapter.ts +73 -0
- package/dist/spa/src/types/adapters/index.ts +5 -0
- package/dist/spa/src/utils.ts +209 -0
- package/dist/spa/src/views/CreateView.vue +3 -3
- package/dist/spa/src/views/EditView.vue +1 -1
- package/dist/spa/src/views/ListView.vue +2 -2
- package/dist/spa/src/views/LoginView.vue +39 -37
- package/dist/spa/src/views/ResourceParent.vue +1 -1
- package/dist/spa/src/views/ShowView.vue +3 -3
- package/dist/types/Back.d.ts +40 -9
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js.map +1 -1
- package/dist/types/Common.d.ts +9 -0
- package/dist/types/Common.d.ts.map +1 -1
- package/dist/types/Common.js.map +1 -1
- package/dist/types/adapters/CompletionAdapter.d.ts +20 -0
- package/dist/types/adapters/CompletionAdapter.d.ts.map +1 -0
- package/dist/types/adapters/CompletionAdapter.js +2 -0
- package/dist/types/adapters/CompletionAdapter.js.map +1 -0
- package/dist/types/adapters/EmailAdapter.d.ts +21 -0
- package/dist/types/adapters/EmailAdapter.d.ts.map +1 -0
- package/dist/types/adapters/EmailAdapter.js +2 -0
- package/dist/types/adapters/EmailAdapter.js.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts +37 -0
- package/dist/types/adapters/ImageGenerationAdapter.d.ts.map +1 -0
- package/dist/types/adapters/ImageGenerationAdapter.js +2 -0
- package/dist/types/adapters/ImageGenerationAdapter.js.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts +32 -0
- package/dist/types/adapters/OAuth2Adapter.d.ts.map +1 -0
- package/dist/types/adapters/OAuth2Adapter.js +2 -0
- package/dist/types/adapters/OAuth2Adapter.js.map +1 -0
- package/dist/types/adapters/StorageAdapter.d.ts +63 -0
- package/dist/types/adapters/StorageAdapter.d.ts.map +1 -0
- package/dist/types/adapters/StorageAdapter.js +2 -0
- package/dist/types/adapters/StorageAdapter.js.map +1 -0
- package/dist/types/adapters/index.d.ts +6 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/index.js +2 -0
- package/dist/types/adapters/index.js.map +1 -0
- package/package.json +2 -2
- package/dist/spa/src/types/Adapters.ts +0 -213
- package/dist/types/Adapters.d.ts +0 -168
- package/dist/types/Adapters.d.ts.map +0 -1
- package/dist/types/Adapters.js +0 -2
- package/dist/types/Adapters.js.map +0 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<div class="overflow-x-auto shadow-resourseFormShadow dark:shadow-darkResourseFormShadow"
|
|
3
|
+
:class="{'rounded-default' : isRounded}"
|
|
4
|
+
>
|
|
3
5
|
<div v-if="groupName && !noTitle" class="text-md font-semibold px-6 py-3 flex flex-1 items-center dark:border-gray-600 text-gray-700 bg-lightFormHeading dark:bg-gray-700 dark:text-gray-400 rounded-t-lg">
|
|
4
6
|
{{ groupName }}
|
|
5
7
|
</div>
|
|
6
8
|
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 table-fixed">
|
|
7
|
-
<thead v-if="!allColumnsHaveCustomComponent" class="text-gray-700 dark:text-gray-400 bg-lightFormHeading dark:bg-
|
|
9
|
+
<thead v-if="!allColumnsHaveCustomComponent" class="text-gray-700 dark:text-gray-400 bg-lightFormHeading dark:bg-darkFormHeading dark:border-darkFormBorder block md:table-row-group">
|
|
8
10
|
<tr>
|
|
9
11
|
<th scope="col" class="px-6 py-3 text-xs uppercase hidden md:w-52 md:table-cell">
|
|
10
12
|
{{ $t('Field') }}
|
|
@@ -19,7 +21,7 @@
|
|
|
19
21
|
v-for="column in columns"
|
|
20
22
|
:key="column.name"
|
|
21
23
|
class="bg-lightForm border-t border-gray-100
|
|
22
|
-
dark:bg-
|
|
24
|
+
dark:bg-darkForm dark:border-darkFormBorder block md:table-row"
|
|
23
25
|
>
|
|
24
26
|
<component
|
|
25
27
|
v-if="column.components?.showRow"
|
|
@@ -60,7 +62,7 @@
|
|
|
60
62
|
import { getCustomComponent } from '@/utils';
|
|
61
63
|
import { useCoreStore } from '@/stores/core';
|
|
62
64
|
import { computed } from 'vue';
|
|
63
|
-
const props = defineProps<{
|
|
65
|
+
const props = withDefaults(defineProps<{
|
|
64
66
|
columns: Array<{
|
|
65
67
|
name: string;
|
|
66
68
|
label: string;
|
|
@@ -80,8 +82,11 @@
|
|
|
80
82
|
noTitle?: boolean;
|
|
81
83
|
resource: Record<string, any>;
|
|
82
84
|
record: Record<string, any>;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
isRounded?: boolean;
|
|
86
|
+
}>(), {
|
|
87
|
+
isRounded: true
|
|
88
|
+
});
|
|
89
|
+
|
|
85
90
|
const coreStore = useCoreStore();
|
|
86
91
|
const allColumnsHaveCustomComponent = computed(() => {
|
|
87
92
|
return props.columns.every(column => {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
</span>
|
|
28
28
|
|
|
29
29
|
<span v-else-if="column.type === 'boolean'">
|
|
30
|
-
<span v-if="record[column.name] === true" class="bg-green-100 whitespace-nowrap text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-green-400 border border-green-400">{{ $t('Yes') }}</span>
|
|
31
|
-
<span v-else-if="record[column.name] === false" class="bg-red-100 whitespace-nowrap text-red-
|
|
30
|
+
<span v-if="record[column.name] === true" class="af-true-value-icon bg-green-100 whitespace-nowrap text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-green-400 border border-green-400">{{ $t('Yes') }}</span>
|
|
31
|
+
<span v-else-if="record[column.name] === false" class="af-false-value-icon bg-red-100 whitespace-nowrap text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400">{{ $t('No') }}</span>
|
|
32
32
|
<span v-else class="bg-gray-100 whitespace-nowrap text-gray-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-gray-400 border border-gray-400">{{ $t('Unset') }}</span>
|
|
33
33
|
</span>
|
|
34
34
|
<span
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
<span
|
|
40
40
|
v-if="column.isArray.itemType === 'boolean' && arrayItem"
|
|
41
41
|
:key="`${column.name}-${arrayItemIndex}`"
|
|
42
|
-
class="bg-green-100 whitespace-nowrap text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-green-400 border border-green-400">
|
|
42
|
+
class="af-true-value-icon bg-green-100 whitespace-nowrap text-green-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-green-400 border border-green-400">
|
|
43
43
|
{{ $t('Yes') }}
|
|
44
44
|
</span>
|
|
45
45
|
<span
|
|
46
46
|
v-else-if="column.isArray.itemType === 'boolean'"
|
|
47
47
|
:key="`${column.name}-${arrayItemIndex}`"
|
|
48
|
-
class="bg-red-100 whitespace-nowrap text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400">
|
|
48
|
+
class="af-false-value-icon bg-red-100 whitespace-nowrap text-red-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-gray-700 dark:text-red-400 border border-red-400">
|
|
49
49
|
{{ $t('No') }}
|
|
50
50
|
</span>
|
|
51
51
|
<span
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Toggle
|
|
3
|
+
:disabled="readonly"
|
|
4
|
+
@update:modelValue="$emit('update:value', $event)"
|
|
5
|
+
:modelValue="valueFromRecord"
|
|
6
|
+
>
|
|
7
|
+
<p>{{text}}</p>
|
|
8
|
+
</Toggle>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup lang="ts">
|
|
12
|
+
import Toggle from '@/afcl/Toggle.vue';
|
|
13
|
+
import type {
|
|
14
|
+
AdminForthResourceColumnCommon,
|
|
15
|
+
AdminForthResourceCommon,
|
|
16
|
+
AdminUser,
|
|
17
|
+
} from "@/types/Common";
|
|
18
|
+
|
|
19
|
+
const props = defineProps<{
|
|
20
|
+
value: boolean,
|
|
21
|
+
text: string,
|
|
22
|
+
column: AdminForthResourceColumnCommon,
|
|
23
|
+
record: any,
|
|
24
|
+
meta: any,
|
|
25
|
+
resource: AdminForthResourceCommon,
|
|
26
|
+
adminUser: AdminUser,
|
|
27
|
+
readonly: boolean
|
|
28
|
+
}>();
|
|
29
|
+
console.log(JSON.stringify(props));
|
|
30
|
+
console.log("Current mode:", props.meta?.mode)
|
|
31
|
+
defineEmits(['update:value']);
|
|
32
|
+
const valueFromRecord = props.record[props.column.name]
|
|
33
|
+
const editReadOnly = props.column.editReadonly;
|
|
34
|
+
</script>
|
|
@@ -21,6 +21,7 @@ export type ResourceColumns = {
|
|
|
21
21
|
|
|
22
22
|
export type CoreConfig = {
|
|
23
23
|
brandName: string,
|
|
24
|
+
singleTheme?: 'light' | 'dark',
|
|
24
25
|
brandLogo: string,
|
|
25
26
|
title: string,
|
|
26
27
|
datesFormat: string,
|
|
@@ -33,12 +34,18 @@ export type CoreConfig = {
|
|
|
33
34
|
passwordHashField: string,
|
|
34
35
|
loginBackgroundImage: string,
|
|
35
36
|
loginBackgroundPosition: string,
|
|
37
|
+
removeBackgroundBlendMode: boolean,
|
|
36
38
|
userFullnameField: string,
|
|
37
39
|
},
|
|
38
40
|
emptyFieldPlaceholder?: {
|
|
39
41
|
show?: string,
|
|
40
42
|
list?: string,
|
|
41
43
|
} | string,
|
|
44
|
+
|
|
45
|
+
customHeadItems?: {
|
|
46
|
+
tagName: string;
|
|
47
|
+
attributes: { [key: string]: string | boolean };
|
|
48
|
+
}[],
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
|
|
@@ -92,16 +92,16 @@ export interface IExpressHttpServer extends IHttpServer {
|
|
|
92
92
|
* Adds adminUser to request object if user is authorized. Drops request with 401 status if user is not authorized.
|
|
93
93
|
* @param callable : Function which will be called if user is authorized.
|
|
94
94
|
*
|
|
95
|
-
* Example:
|
|
96
95
|
*
|
|
96
|
+
* @example
|
|
97
97
|
* ```ts
|
|
98
|
-
* expressApp.get('/myApi', authorize((req, res) =>
|
|
98
|
+
* expressApp.get('/myApi', authorize((req, res) => {
|
|
99
99
|
* console.log('User is authorized', req.adminUser);
|
|
100
|
-
* res.json(
|
|
101
|
-
*
|
|
102
|
-
*
|
|
100
|
+
* res.json({ message: 'Hello World' });
|
|
101
|
+
* }));
|
|
102
|
+
* ```
|
|
103
103
|
*
|
|
104
|
-
*/
|
|
104
|
+
*/
|
|
105
105
|
authorize(callable: Function): void;
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -336,7 +336,7 @@ export interface IAdminForth {
|
|
|
336
336
|
|
|
337
337
|
createResourceRecord(
|
|
338
338
|
params: { resource: AdminForthResource, record: any, adminUser: AdminUser, extra?: HttpExtra }
|
|
339
|
-
): Promise<{ error?: string, createdRecord?: any }>;
|
|
339
|
+
): Promise<{ error?: string, createdRecord?: any, newRecordId?: any }>;
|
|
340
340
|
|
|
341
341
|
updateResourceRecord(
|
|
342
342
|
params: { resource: AdminForthResource, recordId: any, record: any, oldRecord: any, adminUser: AdminUser, extra?: HttpExtra }
|
|
@@ -474,7 +474,7 @@ export type BeforeDataSourceRequestFunction = (params: {
|
|
|
474
474
|
requestUrl: string,
|
|
475
475
|
},
|
|
476
476
|
adminforth: IAdminForth,
|
|
477
|
-
}) => Promise<{ok: boolean, error?: string}>;
|
|
477
|
+
}) => Promise<{ok: boolean, error?: string, newRecordId?: string}>;
|
|
478
478
|
|
|
479
479
|
/**
|
|
480
480
|
* Modify response to change how data is returned after fetching from database.
|
|
@@ -525,7 +525,7 @@ export type BeforeEditSaveFunction = (params: {
|
|
|
525
525
|
oldRecord: any,
|
|
526
526
|
adminforth: IAdminForth,
|
|
527
527
|
extra?: HttpExtra,
|
|
528
|
-
}) => Promise<{ok: boolean, error?: string}>;
|
|
528
|
+
}) => Promise<{ok: boolean, error?: string | null}>;
|
|
529
529
|
|
|
530
530
|
|
|
531
531
|
|
|
@@ -535,7 +535,7 @@ export type BeforeCreateSaveFunction = (params: {
|
|
|
535
535
|
record: any,
|
|
536
536
|
adminforth: IAdminForth,
|
|
537
537
|
extra?: HttpExtra,
|
|
538
|
-
}) => Promise<{ok: boolean, error?: string}>;
|
|
538
|
+
}) => Promise<{ok: boolean, error?: string | null, newRecordId?: string}>;
|
|
539
539
|
|
|
540
540
|
export type AfterCreateSaveFunction = (params: {
|
|
541
541
|
resource: AdminForthResource,
|
|
@@ -619,6 +619,11 @@ interface AdminForthInputConfigCustomization {
|
|
|
619
619
|
*/
|
|
620
620
|
brandName?: string,
|
|
621
621
|
|
|
622
|
+
/**
|
|
623
|
+
* Whether to use single theme for the app
|
|
624
|
+
*/
|
|
625
|
+
singleTheme?: 'light' | 'dark',
|
|
626
|
+
|
|
622
627
|
/**
|
|
623
628
|
* Whether to show brand name in sidebar
|
|
624
629
|
* default is true
|
|
@@ -747,6 +752,7 @@ interface AdminForthInputConfigCustomization {
|
|
|
747
752
|
*/
|
|
748
753
|
loginPageInjections?: {
|
|
749
754
|
underInputs?: AdminForthComponentDeclaration | Array<AdminForthComponentDeclaration>,
|
|
755
|
+
panelHeader?: AdminForthComponentDeclaration | Array<AdminForthComponentDeclaration>,
|
|
750
756
|
}
|
|
751
757
|
|
|
752
758
|
/**
|
|
@@ -758,6 +764,16 @@ interface AdminForthInputConfigCustomization {
|
|
|
758
764
|
sidebar?: AdminForthComponentDeclaration | Array<AdminForthComponentDeclaration>,
|
|
759
765
|
everyPageBottom?: AdminForthComponentDeclaration | Array<AdminForthComponentDeclaration>,
|
|
760
766
|
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Allows adding custom elements (e.g., <link>, <script>, <meta>) to the <head> of the HTML document.
|
|
770
|
+
* Each item must include a tag name and a set of attributes.
|
|
771
|
+
*/
|
|
772
|
+
customHeadItems?: {
|
|
773
|
+
tagName: string;
|
|
774
|
+
attributes: Record<string, string | boolean>;
|
|
775
|
+
}[];
|
|
776
|
+
|
|
761
777
|
}
|
|
762
778
|
|
|
763
779
|
export interface AdminForthActionInput {
|
|
@@ -934,6 +950,13 @@ export interface AdminForthInputConfig {
|
|
|
934
950
|
*/
|
|
935
951
|
loginBackgroundPosition?: 'over' | '1/2' | '1/3' | '2/3' | '3/4' | '2/5' | '3/5',
|
|
936
952
|
|
|
953
|
+
/**
|
|
954
|
+
* If true, background blend mode will be removed from login background image when position is 'over'
|
|
955
|
+
*
|
|
956
|
+
* Default: false
|
|
957
|
+
*/
|
|
958
|
+
removeBackgroundBlendMode?: boolean,
|
|
959
|
+
|
|
937
960
|
/**
|
|
938
961
|
* Function or functions which will be called before user try to login.
|
|
939
962
|
* Each function will resive User object as an argument
|
|
@@ -1054,6 +1077,7 @@ export interface AdminForthConfigCustomization extends Omit<AdminForthInputConfi
|
|
|
1054
1077
|
|
|
1055
1078
|
loginPageInjections: {
|
|
1056
1079
|
underInputs: Array<AdminForthComponentDeclarationFull>,
|
|
1080
|
+
panelHeader: Array<AdminForthComponentDeclarationFull>,
|
|
1057
1081
|
},
|
|
1058
1082
|
|
|
1059
1083
|
globalInjections: {
|
|
@@ -1062,6 +1086,12 @@ export interface AdminForthConfigCustomization extends Omit<AdminForthInputConfi
|
|
|
1062
1086
|
sidebar: Array<AdminForthComponentDeclarationFull>,
|
|
1063
1087
|
everyPageBottom: Array<AdminForthComponentDeclarationFull>,
|
|
1064
1088
|
},
|
|
1089
|
+
|
|
1090
|
+
customHeadItems?: {
|
|
1091
|
+
tagName: string;
|
|
1092
|
+
attributes: Record<string, string | boolean>;
|
|
1093
|
+
}[];
|
|
1094
|
+
|
|
1065
1095
|
}
|
|
1066
1096
|
|
|
1067
1097
|
export interface AdminForthConfig extends Omit<AdminForthInputConfig, 'customization' | 'resources'> {
|
|
@@ -1316,9 +1346,13 @@ export interface AdminForthResource extends Omit<AdminForthResourceInput, 'optio
|
|
|
1316
1346
|
},
|
|
1317
1347
|
create?: {
|
|
1318
1348
|
/**
|
|
1349
|
+
* Should return `ok: true` to continue saving pipeline and allow creating record in database, and `ok: false` to interrupt pipeline and prevent record creation.
|
|
1350
|
+
* If you need to show error on UI, set `error: \<error message\>` in response.
|
|
1351
|
+
*
|
|
1319
1352
|
* Typical use-cases:
|
|
1320
|
-
* -
|
|
1321
|
-
* -
|
|
1353
|
+
* - Create record by custom code (return `{ ok: false, newRecordId: <id of created record from custom code> }`)
|
|
1354
|
+
* - Validate record before saving to database and interrupt execution if validation failed (return `{ ok: false, error: <validation error> }`), though `allowedActions.create` should be preferred in most cases
|
|
1355
|
+
* - fill-in adminUser as creator of record (set `record.<some field> = x; return \{ ok: true \}`)
|
|
1322
1356
|
* - Attach additional data to record before saving to database (mostly fillOnCreate should be used instead)
|
|
1323
1357
|
*/
|
|
1324
1358
|
beforeSave?: Array<BeforeCreateSaveFunction>,
|
|
@@ -584,6 +584,8 @@ export interface AdminForthForeignResourceCommon {
|
|
|
584
584
|
polymorphicResources?: Array<AdminForthPolymorphicForeignResource>,
|
|
585
585
|
polymorphicOn?: string,
|
|
586
586
|
unsetLabel?: string,
|
|
587
|
+
searchableFields?: string | string[],
|
|
588
|
+
searchIsCaseSensitive?: boolean,
|
|
587
589
|
}
|
|
588
590
|
|
|
589
591
|
export type FillOnCreateFunction = (params: {
|
|
@@ -1055,15 +1057,18 @@ export interface AdminForthConfigForFrontend {
|
|
|
1055
1057
|
usernameFieldName: string,
|
|
1056
1058
|
loginBackgroundImage: string,
|
|
1057
1059
|
loginBackgroundPosition: string,
|
|
1060
|
+
removeBackgroundBlendMode: boolean,
|
|
1058
1061
|
title?: string,
|
|
1059
1062
|
demoCredentials?: string,
|
|
1060
1063
|
loginPromptHTML?: string,
|
|
1061
1064
|
loginPageInjections: {
|
|
1062
1065
|
underInputs: Array<AdminForthComponentDeclaration>,
|
|
1066
|
+
panelHeader: Array<AdminForthComponentDeclaration>,
|
|
1063
1067
|
},
|
|
1064
1068
|
rememberMeDays: number,
|
|
1065
1069
|
showBrandNameInSidebar: boolean,
|
|
1066
1070
|
brandLogo?: string,
|
|
1071
|
+
singleTheme?: 'light' | 'dark',
|
|
1067
1072
|
datesFormat: string,
|
|
1068
1073
|
timeFormat: string,
|
|
1069
1074
|
auth: any,
|
|
@@ -1079,7 +1084,11 @@ export interface AdminForthConfigForFrontend {
|
|
|
1079
1084
|
header: Array<AdminForthComponentDeclarationFull>,
|
|
1080
1085
|
sidebar: Array<AdminForthComponentDeclarationFull>,
|
|
1081
1086
|
everyPageBottom: Array<AdminForthComponentDeclarationFull>,
|
|
1082
|
-
}
|
|
1087
|
+
},
|
|
1088
|
+
customHeadItems?: {
|
|
1089
|
+
tagName: string;
|
|
1090
|
+
attributes: Record<string, string | boolean>;
|
|
1091
|
+
}[],
|
|
1083
1092
|
}
|
|
1084
1093
|
|
|
1085
1094
|
export interface GetBaseConfigResponse {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface CompletionAdapter {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This method is called to validate the configuration of the adapter
|
|
5
|
+
* and should throw a clear user-readbale error if the configuration is invalid.
|
|
6
|
+
*/
|
|
7
|
+
validate(): void;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This method should return a text completion based on the provided content and stop sequence.
|
|
11
|
+
* @param content - The input text to complete
|
|
12
|
+
* @param stop - An array of stop sequences to indicate where to stop the completion
|
|
13
|
+
* @param maxTokens - The maximum number of tokens to generate
|
|
14
|
+
* @returns A promise that resolves to an object containing the completed text and other metadata
|
|
15
|
+
*/
|
|
16
|
+
complete(
|
|
17
|
+
content: string,
|
|
18
|
+
stop: string[],
|
|
19
|
+
maxTokens: number,
|
|
20
|
+
): Promise<{
|
|
21
|
+
content?: string;
|
|
22
|
+
finishReason?: string;
|
|
23
|
+
error?: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface EmailAdapter {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This method is called to validate the configuration of the adapter
|
|
5
|
+
* and should throw a clear user-readbale error if the configuration is invalid.
|
|
6
|
+
*/
|
|
7
|
+
validate(): Promise<void>;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This method should send an email using the adapter
|
|
11
|
+
* @param from - The sender's email address
|
|
12
|
+
* @param to - The recipient's email address
|
|
13
|
+
* @param text - The plain text version of the email
|
|
14
|
+
* @param html - The HTML version of the email
|
|
15
|
+
* @param subject - The subject of the email
|
|
16
|
+
*/
|
|
17
|
+
sendEmail(
|
|
18
|
+
from: string,
|
|
19
|
+
to: string,
|
|
20
|
+
text: string,
|
|
21
|
+
html: string,
|
|
22
|
+
subject: string
|
|
23
|
+
): Promise<{
|
|
24
|
+
error?: string;
|
|
25
|
+
ok?: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { EmailAdapter };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface ImageGenerationAdapter {
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This method is called to validate the configuration of the adapter
|
|
5
|
+
* and should throw a clear user-readbale error if the configuration is invalid.
|
|
6
|
+
*/
|
|
7
|
+
validate(): void;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Return max number of images which model can generate in one request
|
|
11
|
+
*/
|
|
12
|
+
outputImagesMaxCountSupported(): number;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Return the list of supported dimensions in format ["100x500", "200x200"]
|
|
16
|
+
*/
|
|
17
|
+
outputDimensionsSupported(): string[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Input file extension supported
|
|
21
|
+
*/
|
|
22
|
+
inputFileExtensionSupported(): string[];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This method should generate an image based on the provided prompt and input files.
|
|
26
|
+
* @param prompt - The prompt to generate the image
|
|
27
|
+
* @param inputFiles - An array of input file paths (optional)
|
|
28
|
+
* @param n - The number of images to generate (default is 1)
|
|
29
|
+
* @param size - The size of the generated image (default is the lowest dimension supported)
|
|
30
|
+
* @returns A promise that resolves to an object containing the generated image URLs and any error message
|
|
31
|
+
*/
|
|
32
|
+
generate({
|
|
33
|
+
prompt,
|
|
34
|
+
inputFiles,
|
|
35
|
+
n,
|
|
36
|
+
size,
|
|
37
|
+
}: {
|
|
38
|
+
prompt: string,
|
|
39
|
+
inputFiles: string[],
|
|
40
|
+
|
|
41
|
+
// default = lowest dimension supported
|
|
42
|
+
size?: string,
|
|
43
|
+
|
|
44
|
+
// one by default
|
|
45
|
+
n?: number
|
|
46
|
+
}): Promise<{
|
|
47
|
+
imageURLs?: string[];
|
|
48
|
+
error?: string;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This interface is used to implement OAuth2 authentication adapters.
|
|
4
|
+
*/
|
|
5
|
+
export interface OAuth2Adapter {
|
|
6
|
+
/**
|
|
7
|
+
* This method should return navigatable URL to the OAuth2 provider authentication page.
|
|
8
|
+
*/
|
|
9
|
+
getAuthUrl(): string;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This method should return the token from the OAuth2 provider using the provided code and redirect URI.
|
|
13
|
+
* @param code - The authorization code received from the OAuth2 provider
|
|
14
|
+
* @param redirect_uri - The redirect URI used in the authentication request
|
|
15
|
+
* @returns A promise that resolves to an object containing the email address of the authenticated user
|
|
16
|
+
*/
|
|
17
|
+
getTokenFromCode(code: string, redirect_uri: string): Promise<{ email: string }>;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This method should return text (content) of SVG icon which will be used in the UI.
|
|
21
|
+
* Use official SVG icons with simplest possible conent, omit icons which have base64 encoded raster images inside.
|
|
22
|
+
*/
|
|
23
|
+
getIcon(): string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* This method should return the text to be displayed on the button in the UI
|
|
27
|
+
*/
|
|
28
|
+
getButtonText?(): string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* This method should return the name of the adapter
|
|
32
|
+
*/
|
|
33
|
+
getName?(): string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Each storage adapter should support two ways of storing files:
|
|
4
|
+
* - publically (public URL) - the file can be accessed by anyone by HTTP GET / HEAD request with plain URL
|
|
5
|
+
* - privately (presigned URL) - the file can be accessed by anyone by HTTP GET / HEAD request only with presigned URLs, limited by expiration time
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
export interface StorageAdapter {
|
|
9
|
+
/**
|
|
10
|
+
* This method should return the presigned URL for the given key capable of upload (adapter user will call PUT multipart form data to this URL within expiresIn seconds after link generation).
|
|
11
|
+
* By default file which will be uploaded on PUT should be marked for deletion. So if during 24h it is not marked for not deletion, it adapter should delete it forever.
|
|
12
|
+
* The PUT method should fail if the file already exists.
|
|
13
|
+
*
|
|
14
|
+
* Adapter user will always pass next parameters to the method:
|
|
15
|
+
* @param key - The key of the file to be uploaded e.g. "uploads/file.txt"
|
|
16
|
+
* @param expiresIn - The expiration time in seconds for the presigned URL
|
|
17
|
+
* @param contentType - The content type of the file to be uploaded, e.g. "image/png"
|
|
18
|
+
*
|
|
19
|
+
* @returns A promise that resolves to an object containing the upload URL and any extra parameters which should be sent with PUT multipart form data
|
|
20
|
+
*/
|
|
21
|
+
getUploadSignedUrl(key: string, contentType: string, expiresIn?: number): Promise<{
|
|
22
|
+
uploadUrl: string;
|
|
23
|
+
uploadExtraParams?: Record<string, string>;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* This method should return the URL for the given key capable of download (200 GET request with response body or 200 HEAD request without response body).
|
|
28
|
+
* If adapter configured to store objects publically, this method should return the public URL of the file.
|
|
29
|
+
* If adapter configured to no allow public storing of images, this method should return the presigned URL for the file.
|
|
30
|
+
*
|
|
31
|
+
* @param key - The key of the file to be downloaded e.g. "uploads/file.txt"
|
|
32
|
+
* @param expiresIn - The expiration time in seconds for the presigned URL
|
|
33
|
+
*/
|
|
34
|
+
getDownloadUrl(key: string, expiresIn?: number): Promise<string>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* This method should mark the file for deletion.
|
|
38
|
+
* If file is marked for delation and exists more then 24h (since creation date) it should be deleted.
|
|
39
|
+
* This method should work even if the file does not exist yet (e.g. only presigned URL was generated).
|
|
40
|
+
* @param key - The key of the file to be uploaded e.g. "uploads/file.txt"
|
|
41
|
+
*/
|
|
42
|
+
markKeyForDeletation(key: string): Promise<void>;
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* This method should mark the file to not be deleted.
|
|
47
|
+
* This method should be used to cancel the deletion of the file if it was marked for deletion.
|
|
48
|
+
* @param key - The key of the file to be uploaded e.g. "uploads/file.txt"
|
|
49
|
+
*/
|
|
50
|
+
markKeyForNotDeletation(key: string): Promise<void>;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* This method can start needed schedullers, cron jobs, etc. to clean up the storage.
|
|
55
|
+
* @param adapterUserUniqueRepresentation - The unique representation of the plugin instance which
|
|
56
|
+
* wil use this adapter. Might be handy if you need to distinguish between different instances of the same adapter.
|
|
57
|
+
*/
|
|
58
|
+
setupLifecycle(adapterUserUniqueRepresentation: string): Promise<void>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* If adapter is configured to publically, this method should return true.
|
|
62
|
+
*/
|
|
63
|
+
objectCanBeAccesedPublicly(): Promise<boolean>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* This method should return the key as a data URL (base64 encoded string).
|
|
67
|
+
* @param key - The key of the file to be converted to a data URL
|
|
68
|
+
* @returns A promise that resolves to a string containing the data URL
|
|
69
|
+
*/
|
|
70
|
+
getKeyAsDataURL(key: string): Promise<string>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { EmailAdapter } from './EmailAdapter.js';
|
|
2
|
+
export type { CompletionAdapter } from './CompletionAdapter.js';
|
|
3
|
+
export type { ImageGenerationAdapter } from './ImageGenerationAdapter.js';
|
|
4
|
+
export type { OAuth2Adapter } from './OAuth2Adapter.js';
|
|
5
|
+
export type { StorageAdapter } from './StorageAdapter.js';
|