Skip to content

Commit fc0348a

Browse files
committed
Merge branch 'next'
2 parents 772f22c + aea7e01 commit fc0348a

File tree

23 files changed

+254
-106
lines changed

23 files changed

+254
-106
lines changed

adapters/install-adapters.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter"
2+
ADAPTERS="adminforth-completion-adapter-open-ai-chat-gpt adminforth-email-adapter-aws-ses adminforth-google-oauth-adapter adminforth-github-oauth-adapter adminforth-facebook-oauth-adapter adminforth-keycloak-oauth-adapter adminforth-microsoft-oauth-adapter adminforth-image-generation-adapter-openai"
33

44
# for each
55
install_adapter() {

adminforth/documentation/blog/2024-10-01-ai-blog/index.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ nvm use 20
4040
## Step 1: Create a new AdminForth project
4141

4242
```bash
43-
npx adminforth create-app ai-blog
43+
npx adminforth create-app --app-name ai-blog
4444
```
4545

4646
Add modules:
@@ -440,11 +440,10 @@ export default {
440440
{ originalFilename, originalExtension }: {originalFilename: string, originalExtension: string }
441441
) => `user-avatars/${new Date().getFullYear()}/${randomUUID()}/${originalFilename}.${originalExtension}`,
442442
generation: {
443-
provider: 'openai-dall-e',
443+
provider: 'openai',
444444
countToGenerate: 2,
445445
openAiOptions: {
446-
model: 'dall-e-3',
447-
size: '1024x1024',
446+
model: 'gpt-4o',
448447
apiKey: process.env.OPENAI_API_KEY,
449448
},
450449
},
@@ -562,11 +561,10 @@ export default {
562561
{ originalFilename, originalExtension }: {originalFilename: string, originalExtension: string }
563562
) => `post-previews/${new Date().getFullYear()}/${randomUUID()}/${originalFilename}.${originalExtension}`,
564563
generation: {
565-
provider: 'openai-dall-e',
564+
provider: 'openai',
566565
countToGenerate: 2,
567566
openAiOptions: {
568-
model: 'dall-e-3',
569-
size: '1792x1024',
567+
model: 'gpt-4o',
570568
apiKey: process.env.OPENAI_API_KEY,
571569
},
572570
fieldsForContext: ['title'],

adminforth/documentation/blog/2025-02-19-compose-ec2-deployment-ci-registry/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ When I implmented this solution, I was curious whether it will be faster to buil
3434
First I used results form [deploying AdminForth to EC2 with Terraform without registry](/blog/compose-ec2-deployment-github-actions/) where we built images on EC2. Then I did the same test but with self-hosted registry on EC2 and compared to [deploying AdminForth to EC2 with Amazon ECR](/blog/compose-aws-ec2-ecr-terraform-github-actions/) where we built images on CI and pushed to Amazon ECR.
3535

3636
| Feature | Without Registry (build directly on EC2) | With self-hosted registry | With Amazon ECR |
37-
| --- | --- | --- |
37+
| --- | --- | --- | --- |
3838
| Initial build time\* | 3m 13.541s | 2m 48.412s | 3m 54s |
39-
| Rebuild time (changed `index.ts`)\*| 0m 51.653s | 0m 54.120s |
39+
| Rebuild time (changed `index.ts`)\* | 0m 51.653s | 0m42.131s | 0m 54.120s |
4040

4141
<sub>\* All tests done from local machine (Intel(R) Core(TM) Ultra 9 185H, Docker Desktop/WSL2 64 GB RAM, 300Mbps up/down) up to working state</sub>
4242

adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,30 @@ const coreStore = useCoreStore();
360360
</script>
361361
```
362362

363+
ALso if you want to disable ability to change such fields (but keep them as readonly) you can add `readonlyColumns` to the link:
364+
365+
```html title="./resources/Dashboard.vue
366+
<template>
367+
...
368+
<LinkButton
369+
:to="{
370+
name: 'resource-create',
371+
params: {
372+
resourceId: 'aparts',
373+
},
374+
query: {
375+
values: encodeURIComponent(JSON.stringify({
376+
realtor_id: coreStore?.adminUser.dbUser.id
377+
})),
378+
//diff-add
379+
readonlyColumns: encodeURIComponent(JSON.stringify(['realtor_id'])),
380+
},
381+
}"
382+
>
383+
{{$t('Create new apartment')}}
384+
</LinkButton>
385+
...
386+
```
363387

364388
## Editing
365389

adminforth/documentation/docs/tutorial/05-Plugins/05-upload.md

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -252,28 +252,32 @@ Also you will have to enable static website hosting in your bucket settings and
252252
253253
## Image generation
254254
255-
Upload plugin supports AI generation for images
255+
Upload plugin supports AI generation for images. Yo use it you need to install image generation adapter.
256+
For example for OpenAI models like `gpt-image-1` (or old `DALL-E` models):
257+
258+
```bash
259+
npm i @adminforth/image-generation-adapter-openai
260+
```
261+
262+
256263
257264
```ts title="./index.ts"
265+
import ImageGenerationAdapterOpenAI from '@adminforth/image-generation-adapter-openai';
258266

259267
new UploadPlugin({
260268
...
261269
//diff-add
262270
generation: {
263-
//diff-add
264-
provider: 'openai-dall-e',
265271
//diff-add
266272
countToGenerate: 2, // how much images generate in one shot
267273
//diff-add
268-
openAiOptions: {
269-
//diff-add
270-
model: 'dall-e-3', // one of models from OpenAI docs https://platform.openai.com/docs/api-reference/images/create
271-
//diff-add
272-
size: '1792x1024', // make sure that size is supported by model using OpenAI docs
273-
//diff-add
274-
apiKey: process.env.OPENAI_API_KEY as string,
275-
//diff-add
276-
},
274+
adapter: new ImageGenerationAdapterOpenAI({
275+
//diff-add
276+
openAiApiKey: process.env.OPENAI_API_KEY as string,
277+
//diff-add
278+
model: 'gpt-image-1',
279+
//diff-add
280+
}),
277281
//diff-add
278282
fieldsForContext: ['title'],
279283

@@ -284,6 +288,50 @@ Here is how it works:
284288
285289
![alt text](demoImgGen-1.gif)
286290
291+
You can also pass additional parameters to OpenAI API call
292+
293+
294+
```ts title="./apartments.ts"
295+
new ImageGenerationAdapterOpenAI({
296+
//diff-add
297+
openAiApiKey: process.env.OPENAI_API_KEY as string,
298+
//diff-add
299+
model: 'gpt-image-1',
300+
//diff-add
301+
extraParams: {
302+
//diff-add
303+
moderation: 'low',
304+
//diff-add
305+
quality: 'high',
306+
//diff-add
307+
}),
308+
```
309+
310+
311+
## Images editing or post-processing
312+
313+
You can not only generate images from text, but also edit, post-process or improve existing images. E.g. remove texts, add objects, change colors, etc.
314+
315+
Create a new column `apartment_source` in `apartments` table, and put another instance of `UploadPlugin` in the same resource configuration.
316+
317+
318+
Now tweak the current UploadPlugin configuration in a next way:
319+
320+
321+
```ts title="./apartments.ts"
322+
generation: {
323+
adapter: new ImageGenerationAdapterOpenAI({
324+
openAiApiKey: process.env.OPENAI_API_KEY as string,
325+
}),
326+
327+
attachFiles: ({ record, adminUser }: { record: any; adminUser: AdminUser }) => {
328+
// attach apartment source image to generation, image should be public
329+
return [`https://tmpbucket-adminforth.s3.eu-central-1.amazonaws.com/${record.apartment_source}`];
330+
},
331+
generationPrompt: "Remove text from the image",
332+
countToGenerate: 3,
333+
}
334+
```
287335
288336
### Rate limits
289337
@@ -294,11 +342,11 @@ new UploadPlugin({
294342
...
295343
generation: {
296344
...
297-
//diff-add
298-
rateLimit: {
299-
limit: '5/12h', // up to 5 times per 12 hour
300-
errorMessage: 'You exhausted your image generation limit 5 times per 12 hours, please try again later',
301-
}
345+
//diff-add
346+
rateLimit: {
347+
limit: '5/12h', // up to 5 times per 12 hour
348+
errorMessage: 'You exhausted your image generation limit 5 times per 12 hours, please try again later',
349+
}
302350
...
303351
});
304352
```

adminforth/modules/restApi.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ export async function interpretResource(
2929
source: ActionCheckSource,
3030
adminforth: IAdminForth
3131
): Promise<{allowedActions: AllowedActionsResolved}> {
32-
// if (process.env.HEAVY_DEBUG) {
33-
// console.log('🪲Interpreting resource', resource.resourceId, source, 'adminUser', adminUser);
34-
// }
32+
if (process.env.HEAVY_DEBUG) {
33+
console.log('🪲Interpreting resource', resource.resourceId, source, 'adminUser', adminUser);
34+
}
3535
const allowedActions = {} as AllowedActionsResolved;
3636

3737
// we need to compute only allowed actions for this source:
@@ -56,9 +56,6 @@ export async function interpretResource(
5656
await Promise.all(
5757
Object.entries(resource.options.allowedActions).map(
5858
async ([key, value]: [string, AllowedActionValue]) => {
59-
if (process.env.HEAVY_DEBUG) {
60-
console.log(`🪲🚥${resource.resourceId}: allowed ${key}: ${value}`)
61-
}
6259
if (!neededActions.includes(key as AllowedActionsEnum)) {
6360
allowedActions[key] = false;
6461
return;

adminforth/spa/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adminforth/spa/src/afcl/Dialog.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<slot name="trigger"></slot>
77
</div>
88
<Teleport to="body">
9-
<div ref="modalEl" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
9+
<div ref="modalEl" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-full max-h-full">
1010
<div v-bind="$attrs" class="relative p-4 max-w-2xl max-h-full" :class="$attrs.class?.includes('w-') ? '' : 'w-full'">
1111
<!-- Modal content -->
1212
<div class="relative bg-white rounded-lg shadow-sm dark:bg-gray-700">

adminforth/spa/src/afcl/Dropzone.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949

5050
<script setup lang="ts">
5151
import { humanifySize } from '@/utils';
52-
import { ref, defineExpose, type Ref } from 'vue';
52+
import { ref, type Ref } from 'vue';
5353
import { IconFileSolid } from '@iconify-prerendered/vue-flowbite';
5454
import { watch } from 'vue';
5555
import adminforth from '@/adminforth';

adminforth/spa/src/afcl/Input.vue

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22

3-
<div class="flex z-0">
3+
<div class="flex z-0" :class="{'opacity-50' : readonly}">
44
<span
55
v-if="$slots.prefix || prefix"
66
class="inline-flex items-center px-3 text-sm text-gray-900 bg-gray-200 border border-s-0 border-gray-300 rounded-s-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600">
@@ -18,6 +18,7 @@
1818
class="inline-flex bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-0 focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary
1919
blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white translate-y-0"
2020
:class="{'rounded-l-md': !$slots.prefix && !prefix, 'rounded-r-md': !$slots.suffix && !suffix, 'w-full': fullWidth}"
21+
:disabled="readonly"
2122
>
2223

2324

@@ -34,13 +35,14 @@
3435
3536
import { ref } from 'vue';
3637
37-
const props = defineProps({
38-
type: String,
39-
fullWidth: Boolean,
40-
modelValue: String,
41-
suffix: String,
42-
prefix: String,
43-
})
38+
const props = defineProps<{
39+
type: string,
40+
fullWidth: boolean,
41+
modelValue: string,
42+
suffix: string,
43+
prefix: string,
44+
readonly?: boolean,
45+
}>()
4446
4547
const input = ref<HTMLInputElement | null>(null)
4648

0 commit comments

Comments
 (0)