Rich editor
Under the hood this plugin uses Quill. Quill is a free, open source WYSIWYG editor built for the modern web.
This plugin allows you to use Quill editor in your AdminForth application.
Usage
First, install the plugin:
npm i @adminforth/rich-editor --save
Import plugin:
import RichEditorPlugin from "@adminforth/rich-editor";
Now instantiate the plugin and add it to the configuration:
{
...
resourceId: 'aparts',
columns: [
...
{
name: 'description',
type: AdminForthDataTypes.TEXT, // like plain AdminForthDataTypes.TEXT but renders HTML in show/list views
components: {
show: "@/renderers/RichText.vue",
list: "@/renderers/RichText.vue",
},
...
}
...
],
...
plugins: [
...
new RichEditorPlugin({
htmlFieldName: 'description',
}),
...
],
}
Now you can see Quill editor in the description
field in the edit view:
Multiple editors in one resource
If you need multiple fields in one resource which happens rarely, just add multiple instances of the plugin:
{
...
resourceId: 'promotion',
columns: [
...
{
name: 'short_description',
type: AdminForthDataTypes.TEXT,
components: {
list: "@/renderers/RichText.vue",
show: "@/renderers/RichText.vue",
}
...
},
{
name: 'full_description',
type: AdminForthDataTypes.TEXT,
components: {
list: "@/renderers/RichText.vue",
show: "@/renderers/RichText.vue",
}
...
}
...
],
...
plugins: [
...
new QuillEditorPlugin({
htmlField: 'short_description',
}),
new QuillEditorPlugin({
htmlField: 'full_description',
}),
...
],
}
Completion
First, install the completion adapter:
npm i @adminforth/completion-adapter-open-ai-chat-gpt --save
To get completion suggestions for the text in the editor, you can use the completion
option. This option is an object with the following properties:
import CompletionAdapterOpenAIChatGPT from "@adminforth/completion-adapter-open-ai-chat-gpt";
new RichEditorPlugin({
htmlFieldName: 'description',
completion: {
adapter: new CompletionAdapterOpenAIChatGPT({
openAiApiKey: process.env.OPENAI_API_KEY as string,
model: 'gpt-4o', //gpt-4o-mini is a default (cheapest one)
expert: {
temperature: 0.7 //Model temperature, default 0.7
}
}),
expert: {
debounceTime: 250,
}
}
}),
Imges in Rich editor
First, you need to create resource for images:
model description_image {
id String @id
created_at DateTime
resource_id String
record_id String
image_path String
}
npm run makemigration -- --name add_description_image ; npm run migrate:local
npm i @adminforth/upload --save
npm i @adminforth/storage-adapter-local --save
import AdminForthStorageAdapterLocalFilesystem from "@adminforth/storage-adapter-local";
import { AdminForthResourceInput } from "adminforth";
import UploadPlugin from "@adminforth/upload";
import { v1 as uuid } from "uuid";
export default {
dataSource: "maindb",
table: "description_image",
resourceId: "description_images",
label: "Description images",
columns: [
{
name: "id",
primaryKey: true,
required: false,
fillOnCreate: ({ initialRecord }: any) => uuid(),
showIn: {
create: false,
},
},
{
name: "created_at",
required: false,
fillOnCreate: ({ initialRecord }: any) => new Date().toISOString(),
showIn: {
create: false,
},
},
{ name: "resource_id", required: false },
{ name: "record_id", required: false },
{ name: "image_path", required: false },
],
plugins: [
new UploadPlugin({
pathColumnName: "image_path",
// rich editor plugin supports only 'public-read' ACL images for SEO purposes (instead of presigned URLs which change every time)
storageAdapter: new AdminForthStorageAdapterLocalFilesystem({
fileSystemFolder: "./db/uploads/description_images", // folder where files will be stored on disk
adminServeBaseUrl: "static/source", // the adapter not only stores files, but also serves them for HTTP requests
mode: "public", // public if all files should be accessible from the web, private only if could be accesed by temporary presigned links
signingSecret: process.env.ADMINFORTH_SECRET, // secret used to generate presigned URLs
}),
allowedFileExtensions: [
"jpg",
"jpeg",
"png",
"gif",
"webm",
"exe",
"webp",
],
maxFileSize: 1024 * 1024 * 20, // 5MB
filePath: ({ originalFilename, originalExtension, contentType }) =>
`description_images/${new Date().getFullYear()}/${uuid()}/${originalFilename}.${originalExtension}`,
preview: {
// Used to display preview (if it is image) in list and show views instead of just path
// previewUrl: ({s3Path}) => `https://tmpbucket-adminforth.s3.eu-central-1.amazonaws.com/${s3Path}`,
// show image preview instead of path in list view
// showInList: false,
},
}),
],
} as AdminForthResourceInput;
Next, add new resource to index.ts
:
import descriptionImage from './resources/description_images.js';
...
resources: [
usersResource,
apartments,
descriptionImage
],
Next, add attachments to RichEditor plugin:
import RichEditorPlugin from '@adminforth/rich-editor';
// ... existing resource configuration ...
new RichEditorPlugin({
htmlFieldName: 'description',
attachments: {
attachmentResource: "description_images",
attachmentFieldName: "image_path",
attachmentRecordIdFieldName: "record_id",
attachmentResourceIdFieldName: "resource_id",
}
})